Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 8f6bffdd in mainline


Ignore:
Timestamp:
2012-05-13T11:33:47Z (9 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
master
Children:
c4b0317
Parents:
4b82445
git-author:
Tobias Börtitz <> (2012-05-13 11:33:47)
git-committer:
Vojtech Horky <vojtechhorky@…> (2012-05-13 11:33:47)
Message:

Jumping over words in edit with ctrl+arrow (thx Tobias Börtitz)

This patch implements

  • deleting a word before the caret with shortcut Ctrl-W (vim-like)
  • moving caret word by word using by the shortcuts Ctrl-left (right), also stopping at the beginning and end of a line
  • selecting individual words by using the shortcuts Ctrl-Shift-arrow
Location:
uspace/app/edit
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/edit/edit.c

    r4b82445 r8f6bffdd  
    118118static void key_handle_ctrl(kbd_event_t const *ev);
    119119static void key_handle_shift(kbd_event_t const *ev);
     120static void key_handle_shift_ctrl(kbd_event_t const *ev);
    120121static void key_handle_movement(unsigned int key, bool shift);
    121122
     
    139140static void caret_update(void);
    140141static void caret_move(int drow, int dcolumn, enum dir_spec align_dir);
     142static void caret_move_word_left(void);
     143static void caret_move_word_right(void);
    141144
    142145static bool selection_active(void);
    143146static void selection_sel_all(void);
     147static void selection_sel_range(spt_t pa, spt_t pb);
     148static void selection_sel_prev_word(void);
     149static void selection_sel_next_word(void);
    144150static void selection_get_points(spt_t *pa, spt_t *pb);
    145151static void selection_delete(void);
     
    149155static void pt_get_sof(spt_t *pt);
    150156static void pt_get_eof(spt_t *pt);
     157static void pt_get_sol(spt_t *cpt, spt_t *spt);
     158static void pt_get_eol(spt_t *cpt, spt_t *ept);
     159static bool pt_is_word_beginning(spt_t *pt);
     160static bool pt_is_delimiter(spt_t *pt);
     161static bool pt_is_punctuation(spt_t *pt);
    151162static int tag_cmp(tag_t const *a, tag_t const *b);
    152163static int spt_cmp(spt_t const *a, spt_t const *b);
     
    232243                             (ev.mods & KM_SHIFT) != 0) {
    233244                                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);
    234249                        } else if ((ev.mods & (KM_CTRL | KM_ALT | KM_SHIFT)) == 0) {
    235250                                key_handle_unmod(&ev);
     
    376391        case KC_A:
    377392                selection_sel_all();
     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
     411static 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();
    378419                break;
    379420        default:
     
    9701011        /* Clamp coordinates. */
    9711012        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        }
    9731021        if (drow > 0) {
    9741022                sheet_get_num_rows(&doc.sh, &num_rows);
     
    9981046}
    9991047
     1048static 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
     1064static 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
    10001080/** Check for non-empty selection. */
    10011081static bool selection_active(void)
     
    10451125}
    10461126
     1127/** Select all text in the editor */
    10471128static void selection_sel_all(void)
    10481129{
     
    10511132        pt_get_sof(&spt);
    10521133        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 */
     1139static void selection_sel_range(spt_t pa, spt_t pb)
     1140{
    10531141        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);
    10551143        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);
    10571145
    10581146        pane.rflags |= REDRAW_TEXT;
    10591147        caret_update();
     1148}
     1149
     1150/** Add the previous word to the selection */
     1151static 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 */
     1168static 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);
    10601182}
    10611183
     
    11171239
    11181240        sheet_get_cell_pt(&doc.sh, &coord, dir_after, pt);
     1241}
     1242
     1243/** Get start-of-line s-point for given s-point cpt */
     1244static 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 */
     1255static 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 */
     1268static 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
     1297static 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
     1303static 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
     1329static 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        }
    11191365}
    11201366
  • uspace/app/edit/sheet.c

    r4b82445 r8f6bffdd  
    264264        sheet_get_cell_pt(sh, &coord, dir_before, &pt);
    265265        spt_get_coord(&pt, &coord);
    266         *length = coord.column - 1;
     266        *length = coord.column;
    267267}
    268268
Note: See TracChangeset for help on using the changeset viewer.