Changes in uspace/app/edit/edit.c [8312577:69cf3a4] in mainline


Ignore:
File:
1 edited

Legend:

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

    r8312577 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;
    89         bool previous_search_reverse;
    9085} pane_t;
    9186
     
    145140static void delete_char_after(void);
    146141static void caret_update(void);
    147 static void caret_move_relative(int drow, int dcolumn, enum dir_spec align_dir, bool select);
    148 static void caret_move_absolute(int row, int column, enum dir_spec align_dir, bool select);
    149 static void caret_move(spt_t spt, bool select, bool update_ideal_column);
    150 static void caret_move_word_left(bool select);
    151 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);
    152146static void caret_go_to_line_ask(void);
    153147
     
    155149static void selection_sel_all(void);
    156150static void selection_sel_range(spt_t pa, spt_t pb);
     151static void selection_sel_prev_word(void);
     152static void selection_sel_next_word(void);
    157153static void selection_get_points(spt_t *pa, spt_t *pb);
    158154static void selection_delete(void);
    159155static void selection_copy(void);
    160156static void insert_clipboard_data(void);
    161 
    162 static void search(char *pattern, bool reverse);
    163 static void search_prompt(bool reverse);
    164 static void search_repeat(void);
    165157
    166158static void pt_get_sof(spt_t *pt);
     
    171163static bool pt_is_delimiter(spt_t *pt);
    172164static bool pt_is_punctuation(spt_t *pt);
    173 static spt_t pt_find_word_left(spt_t spt);
    174 static spt_t pt_find_word_left(spt_t spt);
    175 
    176165static int tag_cmp(tag_t const *a, tag_t const *b);
    177166static int spt_cmp(spt_t const *a, spt_t const *b);
     
    184173{
    185174        kbd_event_t ev;
     175        coord_t coord;
    186176        bool new_file;
    187177        int rc;
     178
     179        spt_t pt;
    188180
    189181        con = console_init(stdin, stdout);
     
    205197
    206198        /* Place caret at the beginning of file. */
    207         spt_t sof;
    208         pt_get_sof(&sof);
    209         sheet_place_tag(doc.sh, &sof, &pane.caret_pos);
    210         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;
    211203
    212204        if (argc == 2) {
     
    224216                new_file = true;
    225217
     218        /* Move to beginning of file. */
     219        caret_move(-ED_INFTY, -ED_INFTY, dir_before);
     220
    226221        /* Place selection start tag. */
    227         sheet_place_tag(doc.sh, &sof, &pane.sel_start);
    228 
    229         /* Move to beginning of file. */
    230         pt_get_sof(&sof);
    231         caret_move(sof, true, true);
     222        tag_get_pt(&pane.caret_pos, &pt);
     223        sheet_place_tag(doc.sh, &pt, &pane.sel_start);
    232224
    233225        /* Initial display */
     
    408400                selection_sel_all();
    409401                break;
     402        case KC_W:
     403                if (selection_active())
     404                        break;
     405                selection_sel_prev_word();
     406                selection_delete();
     407                break;
    410408        case KC_RIGHT:
    411                 caret_move_word_right(false);
     409                caret_move_word_right();
    412410                break;
    413411        case KC_LEFT:
    414                 caret_move_word_left(false);
     412                caret_move_word_left();
    415413                break;
    416414        case KC_L:
    417415                caret_go_to_line_ask();
    418416                break;
    419         case KC_F:
    420                 search_prompt(false);
    421                 break;
    422         case KC_N:
    423                 search_repeat();
    424                 break;
    425417        default:
    426418                break;
     
    432424        switch(ev->key) {
    433425        case KC_LEFT:
    434                 caret_move_word_left(true);
     426                selection_sel_prev_word();
    435427                break;
    436428        case KC_RIGHT:
    437                 caret_move_word_right(true);
    438                 break;
    439         case KC_F:
    440                 search_prompt(true);
     429                selection_sel_next_word();
    441430                break;
    442431        default:
     
    446435
    447436/** Move caret while preserving or resetting selection. */
    448 static void caret_move(spt_t new_caret_pt, bool select, bool update_ideal_column)
    449 {
    450         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;
    451442        coord_t c_old, c_new;
    452443        bool had_sel;
    453444
    454445        /* Check if we had selection before. */
    455         tag_get_pt(&pane.caret_pos, &old_caret_pt);
    456         tag_get_pt(&pane.sel_start, &old_sel_pt);
    457         had_sel = !spt_equal(&old_caret_pt, &old_sel_pt);
    458 
    459         /* Place tag of the caret */
    460         sheet_remove_tag(doc.sh, &pane.caret_pos);
    461         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);
    462451
    463452        if (select == false) {
    464453                /* Move sel_start to the same point as caret. */
    465454                sheet_remove_tag(doc.sh, &pane.sel_start);
    466                 sheet_place_tag(doc.sh, &new_caret_pt, &pane.sel_start);
    467         }
    468 
    469         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
    470459        if (select) {
    471                 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);
    472463
    473464                if (c_old.row == c_new.row)
     
    480471                pane.rflags |= REDRAW_TEXT;
    481472        }
    482        
    483         if (update_ideal_column)
    484                 pane.ideal_column = c_new.column;
    485        
    486         caret_update();
    487473}
    488474
     
    491477        switch (key) {
    492478        case KC_LEFT:
    493                 caret_move_relative(0, -1, dir_before, select);
     479                caret_movement(0, -1, dir_before, select);
    494480                break;
    495481        case KC_RIGHT:
    496                 caret_move_relative(0, 0, dir_after, select);
     482                caret_movement(0, 0, dir_after, select);
    497483                break;
    498484        case KC_UP:
    499                 caret_move_relative(-1, 0, dir_before, select);
     485                caret_movement(-1, 0, dir_before, select);
    500486                break;
    501487        case KC_DOWN:
    502                 caret_move_relative(+1, 0, dir_before, select);
     488                caret_movement(+1, 0, dir_before, select);
    503489                break;
    504490        case KC_HOME:
    505                 caret_move_relative(0, -ED_INFTY, dir_after, select);
     491                caret_movement(0, -ED_INFTY, dir_before, select);
    506492                break;
    507493        case KC_END:
    508                 caret_move_relative(0, +ED_INFTY, dir_before, select);
     494                caret_movement(0, +ED_INFTY, dir_before, select);
    509495                break;
    510496        case KC_PAGE_UP:
    511                 caret_move_relative(-pane.rows, 0, dir_before, select);
     497                caret_movement(-pane.rows, 0, dir_before, select);
    512498                break;
    513499        case KC_PAGE_DOWN:
    514                 caret_move_relative(+pane.rows, 0, dir_before, select);
     500                caret_movement(+pane.rows, 0, dir_before, select);
    515501                break;
    516502        default:
     
    10261012}
    10271013
    1028 /** Relatively move caret position.
     1014/** Change the caret position.
    10291015 *
    10301016 * Moves caret relatively to the current position. Looking at the first
     
    10321018 * to a new character cell, and thus a new character. Then we either go to the
    10331019 * point before the the character or after it, depending on @a align_dir.
    1034  *
    1035  * @param select true if the selection tag should stay where it is
    10361020 */
    1037 static void caret_move_relative(int drow, int dcolumn, enum dir_spec align_dir,
    1038     bool select)
     1021static void caret_move(int drow, int dcolumn, enum dir_spec align_dir)
    10391022{
    10401023        spt_t pt;
     
    10721055         */
    10731056        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);
    10741059
    10751060        /* For non-vertical movement set the new value for @c ideal_column. */
    1076         caret_move(pt, select, !pure_vertical);
    1077 }
    1078 
    1079 /** Absolutely move caret position.
    1080  *
    1081  * Moves caret to a specified position. We get to a new character cell, and
    1082  * thus a new character. Then we either go to the point before the the character
    1083  * or after it, depending on @a align_dir.
    1084  *
    1085  * @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
    10861102 */
    1087 static void caret_move_absolute(int row, int column, enum dir_spec align_dir,
    1088     bool select)
    1089 {
     1103static void caret_move_to_line(int row)
     1104{
     1105        spt_t pt;
    10901106        coord_t coord;
    1091         coord.row = row;
    1092         coord.column = column;
    1093        
    1094         spt_t pt;
    1095         sheet_get_cell_pt(doc.sh, &coord, align_dir, &pt);
    1096        
    1097         caret_move(pt, select, true);
    1098 }
    1099 
    1100 /** Find beginning of a word to the left of spt */
    1101 static spt_t pt_find_word_left(spt_t spt)
    1102 {
    1103         do {
    1104                 spt_prev_char(spt, &spt);
    1105         } while (!pt_is_word_beginning(&spt));
    1106         return spt;
    1107 }
    1108 
    1109 /** Find beginning of a word to the right of spt */
    1110 static spt_t pt_find_word_right(spt_t spt)
    1111 {
    1112         do {
    1113                 spt_next_char(spt, &spt);
    1114         } while (!pt_is_word_beginning(&spt));
    1115         return spt;
    1116 }
    1117 
    1118 static void caret_move_word_left(bool select)
    1119 {
    1120         spt_t pt;
     1107
    11211108        tag_get_pt(&pane.caret_pos, &pt);
    1122         spt_t word_left = pt_find_word_left(pt);
    1123         caret_move(word_left, select, true);
    1124 }
    1125 
    1126 static void caret_move_word_right(bool select)
    1127 {
    1128         spt_t pt;
    1129         tag_get_pt(&pane.caret_pos, &pt);
    1130         spt_t word_right = pt_find_word_right(pt);
    1131         caret_move(word_right, select, true);
     1109        spt_get_coord(&pt, &coord);
     1110
     1111        caret_movement(row - coord.row, 0, dir_before, false);
    11321112}
    11331113
     
    11461126        int line = strtol(sline, &endptr, 10);
    11471127        if (*endptr != '\0') {
    1148                 free(sline);
    11491128                status_display("Invalid number entered.");
    11501129                return;
    11511130        }
    1152         free(sline);
    11531131       
    1154         caret_move_absolute(line, pane.ideal_column, dir_before, false);
    1155 }
    1156 
    1157 /* Search operations */
    1158 static int search_spt_producer(void *data, wchar_t *ret)
    1159 {
    1160         assert(data != NULL);
    1161         assert(ret != NULL);
    1162         spt_t *spt = data;
    1163         *ret = spt_next_char(*spt, spt);
    1164         return EOK;
    1165 }
    1166 
    1167 static int search_spt_reverse_producer(void *data, wchar_t *ret)
    1168 {
    1169         assert(data != NULL);
    1170         assert(ret != NULL);
    1171         spt_t *spt = data;
    1172         *ret = spt_prev_char(*spt, spt);
    1173         return EOK;
    1174 }
    1175 
    1176 static int search_spt_mark(void *data, void **mark)
    1177 {
    1178         assert(data != NULL);
    1179         assert(mark != NULL);
    1180         spt_t *spt = data;
    1181         spt_t *new = calloc(1, sizeof(spt_t));
    1182         *mark = new;
    1183         if (new == NULL)
    1184                 return ENOMEM;
    1185         *new = *spt;
    1186         return EOK;
    1187 }
    1188 
    1189 static void search_spt_mark_free(void *data)
    1190 {
    1191         free(data);
    1192 }
    1193 
    1194 static search_ops_t search_spt_ops = {
    1195         .equals = char_exact_equals,
    1196         .producer = search_spt_producer,
    1197         .mark = search_spt_mark,
    1198         .mark_free = search_spt_mark_free,
    1199 };
    1200 
    1201 static search_ops_t search_spt_reverse_ops = {
    1202         .equals = char_exact_equals,
    1203         .producer = search_spt_reverse_producer,
    1204         .mark = search_spt_mark,
    1205         .mark_free = search_spt_mark_free,
    1206 };
    1207 
    1208 /** Ask for line and go to it. */
    1209 static void search_prompt(bool reverse)
    1210 {
    1211         char *pattern;
    1212        
    1213         const char *prompt_text = "Find next";
    1214         if (reverse)
    1215                 prompt_text = "Find previous";
    1216        
    1217         const char *default_value = "";
    1218         if (pane.previous_search)
    1219                 default_value = pane.previous_search;
    1220        
    1221         pattern = prompt(prompt_text, default_value);
    1222         if (pattern == NULL) {
    1223                 status_display("Search cancelled.");
    1224                 return;
    1225         }
    1226        
    1227         if (pane.previous_search)
    1228                 free(pane.previous_search);
    1229         pane.previous_search = pattern;
    1230         pane.previous_search_reverse = reverse;
    1231        
    1232         search(pattern, reverse);
    1233 }
    1234 
    1235 static void search_repeat(void)
    1236 {
    1237         if (pane.previous_search == NULL) {
    1238                 status_display("No previous search to repeat.");
    1239                 return;
    1240         }
    1241        
    1242         search(pane.previous_search, pane.previous_search_reverse);
    1243 }
    1244 
    1245 static void search(char *pattern, bool reverse)
    1246 {
    1247         status_display("Searching...");
    1248        
    1249         spt_t sp, producer_pos;
    1250         tag_get_pt(&pane.caret_pos, &sp);
    1251        
    1252         /* Start searching on the position before/after caret */
    1253         if (!reverse) {
    1254                 spt_next_char(sp, &sp);
    1255         }
    1256         else {
    1257                 spt_prev_char(sp, &sp);
    1258         }
    1259         producer_pos = sp;
    1260        
    1261         search_ops_t ops = search_spt_ops;
    1262         if (reverse)
    1263                 ops = search_spt_reverse_ops;
    1264        
    1265         search_t *search = search_init(pattern, &producer_pos, ops, reverse);
    1266         if (search == NULL) {
    1267                 status_display("Failed initializing search.");
    1268                 return;
    1269         }
    1270        
    1271         match_t match;
    1272         int rc = search_next_match(search, &match);
    1273         if (rc != EOK) {
    1274                 status_display("Failed searching.");
    1275                 search_fini(search);
    1276         }
    1277        
    1278         if (match.end) {
    1279                 status_display("Match found.");
    1280                 assert(match.end != NULL);
    1281                 spt_t *end = match.end;
    1282                 caret_move(*end, false, true);
    1283                 while (match.length > 0) {
    1284                         match.length--;
    1285                         if (reverse) {
    1286                                 spt_next_char(*end, end);
    1287                         }
    1288                         else {
    1289                                 spt_prev_char(*end, end);
    1290                         }
    1291                 }
    1292                 caret_move(*end, true, true);
    1293                 free(end);
    1294         }
    1295         else {
    1296                 status_display("Not found.");
    1297         }
    1298        
    1299         search_fini(search);
    1300 }
     1132        caret_move_to_line(line);
     1133}
     1134
    13011135
    13021136/** Check for non-empty selection. */
     
    13681202        pane.rflags |= REDRAW_TEXT;
    13691203        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);
    13701238}
    13711239
Note: See TracChangeset for help on using the changeset viewer.