~martin-decky/helenos/rcu

« back to all changes in this revision

Viewing changes to uspace/app/edit/edit.c

  • Committer: Vojtech Horky
  • Date: 2012-05-23 12:03:26 UTC
  • mfrom: (1443.1.19 misc)
  • mto: This revision was merged to the branch mainline in revision 1479.
  • Revision ID: vojtechhorky@users.sourceforge.net-20120523120326-jv50stjymxmh598s
Merge GSOC-originated patches 

Merge from lp:~vojtech-horky/helenos/misc.

The merge includes:
 * Switching to previous directory with `cd -' in Bdsh
 * Interactive mode for cp module in Bdsh
 * Implementation of sleep command
 * printf and echo for Bdsh
 * Rewrite of the mkdir module
 * Ctrl-arrow jumps over words in the editor
 * The scripts work with Python 3

Show diffs side-by-side

added added

removed removed

Lines of Context:
117
117
static void key_handle_unmod(kbd_event_t const *ev);
118
118
static void key_handle_ctrl(kbd_event_t const *ev);
119
119
static void key_handle_shift(kbd_event_t const *ev);
 
120
static void key_handle_shift_ctrl(kbd_event_t const *ev);
120
121
static void key_handle_movement(unsigned int key, bool shift);
121
122
 
122
123
static int file_save(char const *fname);
138
139
static void delete_char_after(void);
139
140
static void caret_update(void);
140
141
static void caret_move(int drow, int dcolumn, enum dir_spec align_dir);
 
142
static void caret_move_word_left(void);
 
143
static void caret_move_word_right(void);
141
144
 
142
145
static bool selection_active(void);
143
146
static void selection_sel_all(void);
 
147
static void selection_sel_range(spt_t pa, spt_t pb);
 
148
static void selection_sel_prev_word(void);
 
149
static void selection_sel_next_word(void);
144
150
static void selection_get_points(spt_t *pa, spt_t *pb);
145
151
static void selection_delete(void);
146
152
static void selection_copy(void);
148
154
 
149
155
static void pt_get_sof(spt_t *pt);
150
156
static void pt_get_eof(spt_t *pt);
 
157
static void pt_get_sol(spt_t *cpt, spt_t *spt);
 
158
static void pt_get_eol(spt_t *cpt, spt_t *ept);
 
159
static bool pt_is_word_beginning(spt_t *pt);
 
160
static bool pt_is_delimiter(spt_t *pt);
 
161
static bool pt_is_punctuation(spt_t *pt);
151
162
static int tag_cmp(tag_t const *a, tag_t const *b);
152
163
static int spt_cmp(spt_t const *a, spt_t const *b);
153
164
static int coord_cmp(coord_t const *a, coord_t const *b);
231
242
                            ((ev.mods & KM_CTRL) == 0) &&
232
243
                             (ev.mods & KM_SHIFT) != 0) {
233
244
                                key_handle_shift(&ev);
 
245
                        } else if (((ev.mods & KM_ALT) == 0) &&
 
246
                            ((ev.mods & KM_CTRL) != 0) &&
 
247
                             (ev.mods & KM_SHIFT) != 0) {
 
248
                                key_handle_shift_ctrl(&ev);
234
249
                        } else if ((ev.mods & (KM_CTRL | KM_ALT | KM_SHIFT)) == 0) {
235
250
                                key_handle_unmod(&ev);
236
251
                        }
376
391
        case KC_A:
377
392
                selection_sel_all();
378
393
                break;
 
394
        case KC_W:
 
395
                if (selection_active())
 
396
                        break;
 
397
                selection_sel_prev_word();
 
398
                selection_delete();
 
399
                break;
 
400
        case KC_RIGHT:
 
401
                caret_move_word_right();
 
402
                break;
 
403
        case KC_LEFT:
 
404
                caret_move_word_left();
 
405
                break;
 
406
        default:
 
407
                break;
 
408
        }
 
409
}
 
410
 
 
411
static void key_handle_shift_ctrl(kbd_event_t const *ev)
 
412
{
 
413
        switch(ev->key) {
 
414
        case KC_LEFT:
 
415
                selection_sel_prev_word();
 
416
                break;
 
417
        case KC_RIGHT:
 
418
                selection_sel_next_word();
 
419
                break;
379
420
        default:
380
421
                break;
381
422
        }
969
1010
 
970
1011
        /* Clamp coordinates. */
971
1012
        if (drow < 0 && coord.row < 1) coord.row = 1;
972
 
        if (dcolumn < 0 && coord.column < 1) coord.column = 1;
 
1013
        if (dcolumn < 0 && coord.column < 1) {
 
1014
                if (coord.row < 2)
 
1015
                        coord.column = 1;
 
1016
                else {
 
1017
                        coord.row--;
 
1018
                        sheet_get_row_width(&doc.sh, coord.row, &coord.column);
 
1019
                }
 
1020
        }
973
1021
        if (drow > 0) {
974
1022
                sheet_get_num_rows(&doc.sh, &num_rows);
975
1023
                if (coord.row > num_rows) coord.row = num_rows;
997
1045
        caret_update();
998
1046
}
999
1047
 
 
1048
static void caret_move_word_left(void) 
 
1049
{
 
1050
        spt_t pt;
 
1051
 
 
1052
        do {
 
1053
                caret_move(0, -1, dir_before);
 
1054
 
 
1055
                tag_get_pt(&pane.caret_pos, &pt);
 
1056
 
 
1057
                sheet_remove_tag(&doc.sh, &pane.sel_start);
 
1058
                sheet_place_tag(&doc.sh, &pt, &pane.sel_start);
 
1059
        } while (!pt_is_word_beginning(&pt));
 
1060
 
 
1061
        pane.rflags |= REDRAW_TEXT;
 
1062
}
 
1063
 
 
1064
static void caret_move_word_right(void) 
 
1065
{
 
1066
        spt_t pt;
 
1067
 
 
1068
        do {
 
1069
                caret_move(0, 0, dir_after);
 
1070
 
 
1071
                tag_get_pt(&pane.caret_pos, &pt);
 
1072
 
 
1073
                sheet_remove_tag(&doc.sh, &pane.sel_start);
 
1074
                sheet_place_tag(&doc.sh, &pt, &pane.sel_start);
 
1075
        } while (!pt_is_word_beginning(&pt));
 
1076
 
 
1077
        pane.rflags |= REDRAW_TEXT;
 
1078
}
 
1079
 
1000
1080
/** Check for non-empty selection. */
1001
1081
static bool selection_active(void)
1002
1082
{
1044
1124
                pane.rflags |= REDRAW_TEXT;
1045
1125
}
1046
1126
 
 
1127
/** Select all text in the editor */
1047
1128
static void selection_sel_all(void)
1048
1129
{
1049
1130
        spt_t spt, ept;
1050
1131
 
1051
1132
        pt_get_sof(&spt);
1052
1133
        pt_get_eof(&ept);
 
1134
 
 
1135
        selection_sel_range(spt, ept);
 
1136
}
 
1137
 
 
1138
/** Select select all text in a given range with the given direction */
 
1139
static void selection_sel_range(spt_t pa, spt_t pb)
 
1140
{
1053
1141
        sheet_remove_tag(&doc.sh, &pane.sel_start);
1054
 
        sheet_place_tag(&doc.sh, &spt, &pane.sel_start);
 
1142
        sheet_place_tag(&doc.sh, &pa, &pane.sel_start);
1055
1143
        sheet_remove_tag(&doc.sh, &pane.caret_pos);
1056
 
        sheet_place_tag(&doc.sh, &ept, &pane.caret_pos);
 
1144
        sheet_place_tag(&doc.sh, &pb, &pane.caret_pos);
1057
1145
 
1058
1146
        pane.rflags |= REDRAW_TEXT;
1059
1147
        caret_update();
1060
1148
}
1061
1149
 
 
1150
/** Add the previous word to the selection */
 
1151
static void selection_sel_prev_word(void)
 
1152
{
 
1153
        spt_t cpt, wpt, spt, ept;
 
1154
 
 
1155
        selection_get_points(&spt, &ept);
 
1156
 
 
1157
        tag_get_pt(&pane.caret_pos, &cpt);
 
1158
        caret_move_word_left();
 
1159
        tag_get_pt(&pane.caret_pos, &wpt);
 
1160
 
 
1161
        if (spt_cmp(&spt, &cpt) == 0)
 
1162
                selection_sel_range(ept, wpt);
 
1163
        else
 
1164
                selection_sel_range(spt, wpt);
 
1165
}
 
1166
 
 
1167
/** Add the next word to the selection */
 
1168
static void selection_sel_next_word(void)
 
1169
{
 
1170
        spt_t cpt, wpt, spt, ept;
 
1171
 
 
1172
        selection_get_points(&spt, &ept);
 
1173
 
 
1174
        tag_get_pt(&pane.caret_pos, &cpt);
 
1175
        caret_move_word_right();
 
1176
        tag_get_pt(&pane.caret_pos, &wpt);
 
1177
 
 
1178
        if (spt_cmp(&ept, &cpt) == 0)
 
1179
                selection_sel_range(spt, wpt);
 
1180
        else
 
1181
                selection_sel_range(ept, wpt);
 
1182
}
 
1183
 
1062
1184
static void selection_copy(void)
1063
1185
{
1064
1186
        spt_t pa, pb;
1118
1240
        sheet_get_cell_pt(&doc.sh, &coord, dir_after, pt);
1119
1241
}
1120
1242
 
 
1243
/** Get start-of-line s-point for given s-point cpt */
 
1244
static void pt_get_sol(spt_t *cpt, spt_t *spt)
 
1245
{
 
1246
        coord_t coord;
 
1247
 
 
1248
        spt_get_coord(cpt, &coord);
 
1249
        coord.column = 1;
 
1250
 
 
1251
        sheet_get_cell_pt(&doc.sh, &coord, dir_before, spt);
 
1252
}
 
1253
 
 
1254
/** Get end-of-line s-point for given s-point cpt */
 
1255
static void pt_get_eol(spt_t *cpt, spt_t *ept)
 
1256
{
 
1257
        coord_t coord;
 
1258
        int row_width;
 
1259
 
 
1260
        spt_get_coord(cpt, &coord);
 
1261
        sheet_get_row_width(&doc.sh, coord.row, &row_width);
 
1262
        coord.column = row_width - 1;
 
1263
 
 
1264
        sheet_get_cell_pt(&doc.sh, &coord, dir_after, ept);
 
1265
}
 
1266
 
 
1267
/** Check whether the spt is at a beginning of a word */
 
1268
static bool pt_is_word_beginning(spt_t *pt)
 
1269
{
 
1270
        spt_t lp, sfp, efp, slp, elp;
 
1271
        coord_t coord;
 
1272
 
 
1273
        pt_get_sof(&sfp);
 
1274
        pt_get_eof(&efp);
 
1275
        pt_get_sol(pt, &slp);
 
1276
        pt_get_eol(pt, &elp);
 
1277
 
 
1278
        /* the spt is at the beginning or end of the file or line */
 
1279
        if ((spt_cmp(&sfp, pt) == 0) || (spt_cmp(&efp, pt) == 0)
 
1280
            || (spt_cmp(&slp, pt) == 0) || (spt_cmp(&elp, pt) == 0))
 
1281
                return true;
 
1282
 
 
1283
        /* the spt is a delimiter */
 
1284
        if (pt_is_delimiter(pt))
 
1285
                return false;
 
1286
 
 
1287
        spt_get_coord(pt, &coord);
 
1288
 
 
1289
        coord.column -= 1;
 
1290
        sheet_get_cell_pt(&doc.sh, &coord, dir_before, &lp);
 
1291
 
 
1292
        return pt_is_delimiter(&lp)
 
1293
            || (pt_is_punctuation(pt) && !pt_is_punctuation(&lp))
 
1294
            || (pt_is_punctuation(&lp) && !pt_is_punctuation(pt));
 
1295
}
 
1296
 
 
1297
static wchar_t get_first_wchar(const char *str)
 
1298
{
 
1299
        size_t offset = 0;
 
1300
        return str_decode(str, &offset, str_size(str));
 
1301
}
 
1302
 
 
1303
static bool pt_is_delimiter(spt_t *pt)
 
1304
{
 
1305
        spt_t rp;
 
1306
        coord_t coord;
 
1307
        char *ch = NULL;
 
1308
 
 
1309
        spt_get_coord(pt, &coord);
 
1310
 
 
1311
        coord.column += 1;
 
1312
        sheet_get_cell_pt(&doc.sh, &coord, dir_after, &rp);
 
1313
 
 
1314
        ch = range_get_str(pt, &rp);
 
1315
        if (ch == NULL)
 
1316
                return false;
 
1317
 
 
1318
        wchar_t first_char = get_first_wchar(ch);
 
1319
        switch(first_char) {
 
1320
        case ' ':
 
1321
        case '\t':
 
1322
        case '\n':
 
1323
                return true;
 
1324
        default:
 
1325
                return false;
 
1326
        }
 
1327
}
 
1328
 
 
1329
static bool pt_is_punctuation(spt_t *pt)
 
1330
{
 
1331
        spt_t rp;
 
1332
        coord_t coord;
 
1333
        char *ch = NULL;
 
1334
 
 
1335
        spt_get_coord(pt, &coord);
 
1336
 
 
1337
        coord.column += 1;
 
1338
        sheet_get_cell_pt(&doc.sh, &coord, dir_after, &rp);
 
1339
 
 
1340
        ch = range_get_str(pt, &rp);
 
1341
        if (ch == NULL)
 
1342
                return false;
 
1343
 
 
1344
        wchar_t first_char = get_first_wchar(ch);
 
1345
        switch(first_char) {
 
1346
        case ',':
 
1347
        case '.':
 
1348
        case ';':
 
1349
        case ':':
 
1350
        case '/':
 
1351
        case '?':
 
1352
        case '\\':
 
1353
        case '|':
 
1354
        case '_':
 
1355
        case '+':
 
1356
        case '-':
 
1357
        case '*':
 
1358
        case '=':
 
1359
        case '<':
 
1360
        case '>':
 
1361
                return true;
 
1362
        default:
 
1363
                return false;
 
1364
        }
 
1365
}
 
1366
 
1121
1367
/** Compare tags. */
1122
1368
static int tag_cmp(tag_t const *a, tag_t const *b)
1123
1369
{