Ignore:
File:
1 edited

Legend:

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

    r7feb86e6 r69cf3a4  
    11/*
    22 * Copyright (c) 2009 Jiri Svoboda
    3  * Copyright (c) 2012 Martin Sucha
    43 * All rights reserved.
    54 *
     
    5049
    5150#include "sheet.h"
    52 #include "search.h"
    5351
    5452enum redraw_flags {
     
    8583         */
    8684        int ideal_column;
    87        
    88         char *previous_search;
    8985} pane_t;
    9086
     
    144140static void delete_char_after(void);
    145141static void caret_update(void);
    146 static void caret_move_relative(int drow, int dcolumn, enum dir_spec align_dir, bool select);
    147 static void caret_move_absolute(int row, int column, enum dir_spec align_dir, bool select);
    148 static void caret_move(spt_t spt, bool select, bool update_ideal_column);
    149 static void caret_move_word_left(bool select);
    150 static void caret_move_word_right(bool select);
     142static void caret_move(int drow, int dcolumn, enum dir_spec align_dir);
     143static void caret_move_word_left(void);
     144static void caret_move_word_right(void);
     145static void caret_move_to_line(int row);
    151146static void caret_go_to_line_ask(void);
    152147
     
    154149static void selection_sel_all(void);
    155150static void selection_sel_range(spt_t pa, spt_t pb);
     151static void selection_sel_prev_word(void);
     152static void selection_sel_next_word(void);
    156153static void selection_get_points(spt_t *pa, spt_t *pb);
    157154static void selection_delete(void);
    158155static void selection_copy(void);
    159156static void insert_clipboard_data(void);
    160 
    161 static void search(void);
    162 static void search_forward(char *pattern);
    163 static void search_repeat(void);
    164157
    165158static void pt_get_sof(spt_t *pt);
     
    170163static bool pt_is_delimiter(spt_t *pt);
    171164static bool pt_is_punctuation(spt_t *pt);
    172 static spt_t pt_find_word_left(spt_t spt);
    173 static spt_t pt_find_word_left(spt_t spt);
    174 
    175165static int tag_cmp(tag_t const *a, tag_t const *b);
    176166static int spt_cmp(spt_t const *a, spt_t const *b);
     
    183173{
    184174        kbd_event_t ev;
     175        coord_t coord;
    185176        bool new_file;
    186177        int rc;
     178
     179        spt_t pt;
    187180
    188181        con = console_init(stdin, stdout);
     
    204197
    205198        /* Place caret at the beginning of file. */
    206         spt_t sof;
    207         pt_get_sof(&sof);
    208         sheet_place_tag(doc.sh, &sof, &pane.caret_pos);
    209         pane.ideal_column = 1;
     199        coord.row = coord.column = 1;
     200        sheet_get_cell_pt(doc.sh, &coord, dir_before, &pt);
     201        sheet_place_tag(doc.sh, &pt, &pane.caret_pos);
     202        pane.ideal_column = coord.column;
    210203
    211204        if (argc == 2) {
     
    223216                new_file = true;
    224217
     218        /* Move to beginning of file. */
     219        caret_move(-ED_INFTY, -ED_INFTY, dir_before);
     220
    225221        /* Place selection start tag. */
    226         sheet_place_tag(doc.sh, &sof, &pane.sel_start);
    227 
    228         /* Move to beginning of file. */
    229         pt_get_sof(&sof);
    230         caret_move(sof, true, true);
     222        tag_get_pt(&pane.caret_pos, &pt);
     223        sheet_place_tag(doc.sh, &pt, &pane.sel_start);
    231224
    232225        /* Initial display */
     
    407400                selection_sel_all();
    408401                break;
     402        case KC_W:
     403                if (selection_active())
     404                        break;
     405                selection_sel_prev_word();
     406                selection_delete();
     407                break;
    409408        case KC_RIGHT:
    410                 caret_move_word_right(false);
     409                caret_move_word_right();
    411410                break;
    412411        case KC_LEFT:
    413                 caret_move_word_left(false);
     412                caret_move_word_left();
    414413                break;
    415414        case KC_L:
    416415                caret_go_to_line_ask();
    417416                break;
    418         case KC_F:
    419                 search();
    420                 break;
    421         case KC_N:
    422                 search_repeat();
    423                 break;
    424417        default:
    425418                break;
     
    431424        switch(ev->key) {
    432425        case KC_LEFT:
    433                 caret_move_word_left(true);
     426                selection_sel_prev_word();
    434427                break;
    435428        case KC_RIGHT:
    436                 caret_move_word_right(true);
     429                selection_sel_next_word();
    437430                break;
    438431        default:
     
    442435
    443436/** Move caret while preserving or resetting selection. */
    444 static void caret_move(spt_t new_caret_pt, bool select, bool update_ideal_column)
    445 {
    446         spt_t old_caret_pt, old_sel_pt;
     437static void caret_movement(int drow, int dcolumn, enum dir_spec align_dir,
     438    bool select)
     439{
     440        spt_t pt;
     441        spt_t caret_pt;
    447442        coord_t c_old, c_new;
    448443        bool had_sel;
    449444
    450445        /* Check if we had selection before. */
    451         tag_get_pt(&pane.caret_pos, &old_caret_pt);
    452         tag_get_pt(&pane.sel_start, &old_sel_pt);
    453         had_sel = !spt_equal(&old_caret_pt, &old_sel_pt);
    454 
    455         /* Place tag of the caret */
    456         sheet_remove_tag(doc.sh, &pane.caret_pos);
    457         sheet_place_tag(doc.sh, &new_caret_pt, &pane.caret_pos);
     446        tag_get_pt(&pane.caret_pos, &caret_pt);
     447        tag_get_pt(&pane.sel_start, &pt);
     448        had_sel = !spt_equal(&caret_pt, &pt);
     449
     450        caret_move(drow, dcolumn, align_dir);
    458451
    459452        if (select == false) {
    460453                /* Move sel_start to the same point as caret. */
    461454                sheet_remove_tag(doc.sh, &pane.sel_start);
    462                 sheet_place_tag(doc.sh, &new_caret_pt, &pane.sel_start);
    463         }
    464 
    465         spt_get_coord(&new_caret_pt, &c_new);
     455                tag_get_pt(&pane.caret_pos, &pt);
     456                sheet_place_tag(doc.sh, &pt, &pane.sel_start);
     457        }
     458
    466459        if (select) {
    467                 spt_get_coord(&old_caret_pt, &c_old);
     460                tag_get_pt(&pane.caret_pos, &pt);
     461                spt_get_coord(&caret_pt, &c_old);
     462                spt_get_coord(&pt, &c_new);
    468463
    469464                if (c_old.row == c_new.row)
     
    476471                pane.rflags |= REDRAW_TEXT;
    477472        }
    478        
    479         if (update_ideal_column)
    480                 pane.ideal_column = c_new.column;
    481        
    482         caret_update();
    483473}
    484474
     
    487477        switch (key) {
    488478        case KC_LEFT:
    489                 caret_move_relative(0, -1, dir_before, select);
     479                caret_movement(0, -1, dir_before, select);
    490480                break;
    491481        case KC_RIGHT:
    492                 caret_move_relative(0, 0, dir_after, select);
     482                caret_movement(0, 0, dir_after, select);
    493483                break;
    494484        case KC_UP:
    495                 caret_move_relative(-1, 0, dir_before, select);
     485                caret_movement(-1, 0, dir_before, select);
    496486                break;
    497487        case KC_DOWN:
    498                 caret_move_relative(+1, 0, dir_before, select);
     488                caret_movement(+1, 0, dir_before, select);
    499489                break;
    500490        case KC_HOME:
    501                 caret_move_relative(0, -ED_INFTY, dir_after, select);
     491                caret_movement(0, -ED_INFTY, dir_before, select);
    502492                break;
    503493        case KC_END:
    504                 caret_move_relative(0, +ED_INFTY, dir_before, select);
     494                caret_movement(0, +ED_INFTY, dir_before, select);
    505495                break;
    506496        case KC_PAGE_UP:
    507                 caret_move_relative(-pane.rows, 0, dir_before, select);
     497                caret_movement(-pane.rows, 0, dir_before, select);
    508498                break;
    509499        case KC_PAGE_DOWN:
    510                 caret_move_relative(+pane.rows, 0, dir_before, select);
     500                caret_movement(+pane.rows, 0, dir_before, select);
    511501                break;
    512502        default:
     
    10221012}
    10231013
    1024 /** Relatively move caret position.
     1014/** Change the caret position.
    10251015 *
    10261016 * Moves caret relatively to the current position. Looking at the first
     
    10281018 * to a new character cell, and thus a new character. Then we either go to the
    10291019 * point before the the character or after it, depending on @a align_dir.
    1030  *
    1031  * @param select true if the selection tag should stay where it is
    10321020 */
    1033 static void caret_move_relative(int drow, int dcolumn, enum dir_spec align_dir,
    1034     bool select)
     1021static void caret_move(int drow, int dcolumn, enum dir_spec align_dir)
    10351022{
    10361023        spt_t pt;
     
    10681055         */
    10691056        sheet_get_cell_pt(doc.sh, &coord, align_dir, &pt);
     1057        sheet_remove_tag(doc.sh, &pane.caret_pos);
     1058        sheet_place_tag(doc.sh, &pt, &pane.caret_pos);
    10701059
    10711060        /* For non-vertical movement set the new value for @c ideal_column. */
    1072         caret_move(pt, select, !pure_vertical);
    1073 }
    1074 
    1075 /** Absolutely move caret position.
    1076  *
    1077  * Moves caret to a specified position. We get to a new character cell, and
    1078  * thus a new character. Then we either go to the point before the the character
    1079  * or after it, depending on @a align_dir.
    1080  *
    1081  * @param select true if the selection tag should stay where it is
     1061        if (!pure_vertical) {
     1062                spt_get_coord(&pt, &coord);
     1063                pane.ideal_column = coord.column;
     1064        }
     1065
     1066        caret_update();
     1067}
     1068
     1069static void caret_move_word_left(void)
     1070{
     1071        spt_t pt;
     1072
     1073        do {
     1074                caret_move(0, -1, dir_before);
     1075
     1076                tag_get_pt(&pane.caret_pos, &pt);
     1077
     1078                sheet_remove_tag(doc.sh, &pane.sel_start);
     1079                sheet_place_tag(doc.sh, &pt, &pane.sel_start);
     1080        } while (!pt_is_word_beginning(&pt));
     1081
     1082        pane.rflags |= REDRAW_TEXT;
     1083}
     1084
     1085static void caret_move_word_right(void)
     1086{
     1087        spt_t pt;
     1088
     1089        do {
     1090                caret_move(0, 0, dir_after);
     1091
     1092                tag_get_pt(&pane.caret_pos, &pt);
     1093
     1094                sheet_remove_tag(doc.sh, &pane.sel_start);
     1095                sheet_place_tag(doc.sh, &pt, &pane.sel_start);
     1096        } while (!pt_is_word_beginning(&pt));
     1097
     1098        pane.rflags |= REDRAW_TEXT;
     1099}
     1100
     1101/** Change the caret position to a beginning of a given line
    10821102 */
    1083 static void caret_move_absolute(int row, int column, enum dir_spec align_dir,
    1084     bool select)
    1085 {
     1103static void caret_move_to_line(int row)
     1104{
     1105        spt_t pt;
    10861106        coord_t coord;
    1087         coord.row = row;
    1088         coord.column = column;
    1089        
    1090         spt_t pt;
    1091         sheet_get_cell_pt(doc.sh, &coord, align_dir, &pt);
    1092        
    1093         caret_move(pt, select, true);
    1094 }
    1095 
    1096 /** Find beginning of a word to the left of spt */
    1097 static spt_t pt_find_word_left(spt_t spt)
    1098 {
    1099         do {
    1100                 spt_prev_char(spt, &spt);
    1101         } while (!pt_is_word_beginning(&spt));
    1102         return spt;
    1103 }
    1104 
    1105 /** Find beginning of a word to the right of spt */
    1106 static spt_t pt_find_word_right(spt_t spt)
    1107 {
    1108         do {
    1109                 spt_next_char(spt, &spt);
    1110         } while (!pt_is_word_beginning(&spt));
    1111         return spt;
    1112 }
    1113 
    1114 static void caret_move_word_left(bool select)
    1115 {
    1116         spt_t pt;
     1107
    11171108        tag_get_pt(&pane.caret_pos, &pt);
    1118         spt_t word_left = pt_find_word_left(pt);
    1119         caret_move(word_left, select, true);
    1120 }
    1121 
    1122 static void caret_move_word_right(bool select)
    1123 {
    1124         spt_t pt;
    1125         tag_get_pt(&pane.caret_pos, &pt);
    1126         spt_t word_right = pt_find_word_right(pt);
    1127         caret_move(word_right, select, true);
     1109        spt_get_coord(&pt, &coord);
     1110
     1111        caret_movement(row - coord.row, 0, dir_before, false);
    11281112}
    11291113
     
    11421126        int line = strtol(sline, &endptr, 10);
    11431127        if (*endptr != '\0') {
    1144                 free(sline);
    11451128                status_display("Invalid number entered.");
    11461129                return;
    11471130        }
    1148         free(sline);
    11491131       
    1150         caret_move_absolute(line, pane.ideal_column, dir_before, false);
    1151 }
    1152 
    1153 /* Search operations */
    1154 static int search_spt_producer(void *data, wchar_t *ret)
    1155 {
    1156         assert(data != NULL);
    1157         assert(ret != NULL);
    1158         spt_t *spt = data;
    1159         *ret = spt_next_char(*spt, spt);
    1160         return EOK;
    1161 }
    1162 
    1163 static int search_spt_mark(void *data, void **mark)
    1164 {
    1165         assert(data != NULL);
    1166         assert(mark != NULL);
    1167         spt_t *spt = data;
    1168         spt_t *new = calloc(1, sizeof(spt_t));
    1169         *mark = new;
    1170         if (new == NULL)
    1171                 return ENOMEM;
    1172         *new = *spt;
    1173         return EOK;
    1174 }
    1175 
    1176 static void search_spt_mark_free(void *data)
    1177 {
    1178         free(data);
    1179 }
    1180 
    1181 static search_ops_t search_spt_ops = {
    1182         .equals = char_exact_equals,
    1183         .producer = search_spt_producer,
    1184         .mark = search_spt_mark,
    1185         .mark_free = search_spt_mark_free,
    1186 };
    1187 
    1188 /** Ask for line and go to it. */
    1189 static void search(void)
    1190 {
    1191         char *pattern;
    1192        
    1193         const char *default_value = "";
    1194         if (pane.previous_search)
    1195                 default_value = pane.previous_search;
    1196        
    1197         pattern = prompt("Search for", default_value);
    1198         if (pattern == NULL) {
    1199                 status_display("Search cancelled.");
    1200                 return;
    1201         }
    1202        
    1203         if (pane.previous_search)
    1204                 free(pane.previous_search);
    1205         pane.previous_search = pattern;
    1206        
    1207         search_forward(pattern);
    1208 }
    1209 
    1210 static void search_repeat(void)
    1211 {
    1212         if (pane.previous_search == NULL) {
    1213                 status_display("No previous search to repeat.");
    1214                 return;
    1215         }
    1216        
    1217         search_forward(pane.previous_search);
    1218 }
    1219 
    1220 static void search_forward(char *pattern)
    1221 {
    1222         status_display("Searching...");
    1223        
    1224         spt_t sp, producer_pos;
    1225         tag_get_pt(&pane.caret_pos, &sp);
    1226        
    1227         /* Start searching on the position after caret */
    1228         spt_next_char(sp, &sp);
    1229         producer_pos = sp;
    1230        
    1231         search_t *search = search_init(pattern, &producer_pos, search_spt_ops);
    1232         if (search == NULL) {
    1233                 status_display("Failed initializing search.");
    1234                 return;
    1235         }
    1236        
    1237         match_t match;
    1238         int rc = search_next_match(search, &match);
    1239         if (rc != EOK) {
    1240                 status_display("Failed searching.");
    1241                 search_fini(search);
    1242         }
    1243        
    1244         if (match.end) {
    1245                 status_display("Match found.");
    1246                 assert(match.end != NULL);
    1247                 spt_t *end = match.end;
    1248                 caret_move(*end, false, true);
    1249                 while (match.length > 0) {
    1250                         match.length--;
    1251                         spt_prev_char(*end, end);
    1252                 }
    1253                 caret_move(*end, true, true);
    1254                 free(end);
    1255         }
    1256         else {
    1257                 status_display("Not found.");
    1258         }
    1259        
    1260         search_fini(search);
    1261 }
     1132        caret_move_to_line(line);
     1133}
     1134
    12621135
    12631136/** Check for non-empty selection. */
     
    13291202        pane.rflags |= REDRAW_TEXT;
    13301203        caret_update();
     1204}
     1205
     1206/** Add the previous word to the selection */
     1207static void selection_sel_prev_word(void)
     1208{
     1209        spt_t cpt, wpt, spt, ept;
     1210
     1211        selection_get_points(&spt, &ept);
     1212
     1213        tag_get_pt(&pane.caret_pos, &cpt);
     1214        caret_move_word_left();
     1215        tag_get_pt(&pane.caret_pos, &wpt);
     1216
     1217        if (spt_cmp(&spt, &cpt) == 0)
     1218                selection_sel_range(ept, wpt);
     1219        else
     1220                selection_sel_range(spt, wpt);
     1221}
     1222
     1223/** Add the next word to the selection */
     1224static void selection_sel_next_word(void)
     1225{
     1226        spt_t cpt, wpt, spt, ept;
     1227
     1228        selection_get_points(&spt, &ept);
     1229
     1230        tag_get_pt(&pane.caret_pos, &cpt);
     1231        caret_move_word_right();
     1232        tag_get_pt(&pane.caret_pos, &wpt);
     1233
     1234        if (spt_cmp(&ept, &cpt) == 0)
     1235                selection_sel_range(spt, wpt);
     1236        else
     1237                selection_sel_range(ept, wpt);
    13311238}
    13321239
Note: See TracChangeset for help on using the changeset viewer.