Changes in uspace/app/edit/edit.c [8312577:69cf3a4] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/edit/edit.c
r8312577 r69cf3a4 1 1 /* 2 2 * Copyright (c) 2009 Jiri Svoboda 3 * Copyright (c) 2012 Martin Sucha4 3 * All rights reserved. 5 4 * … … 50 49 51 50 #include "sheet.h" 52 #include "search.h"53 51 54 52 enum redraw_flags { … … 85 83 */ 86 84 int ideal_column; 87 88 char *previous_search;89 bool previous_search_reverse;90 85 } pane_t; 91 86 … … 145 140 static void delete_char_after(void); 146 141 static 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); 142 static void caret_move(int drow, int dcolumn, enum dir_spec align_dir); 143 static void caret_move_word_left(void); 144 static void caret_move_word_right(void); 145 static void caret_move_to_line(int row); 152 146 static void caret_go_to_line_ask(void); 153 147 … … 155 149 static void selection_sel_all(void); 156 150 static void selection_sel_range(spt_t pa, spt_t pb); 151 static void selection_sel_prev_word(void); 152 static void selection_sel_next_word(void); 157 153 static void selection_get_points(spt_t *pa, spt_t *pb); 158 154 static void selection_delete(void); 159 155 static void selection_copy(void); 160 156 static 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);165 157 166 158 static void pt_get_sof(spt_t *pt); … … 171 163 static bool pt_is_delimiter(spt_t *pt); 172 164 static 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 176 165 static int tag_cmp(tag_t const *a, tag_t const *b); 177 166 static int spt_cmp(spt_t const *a, spt_t const *b); … … 184 173 { 185 174 kbd_event_t ev; 175 coord_t coord; 186 176 bool new_file; 187 177 int rc; 178 179 spt_t pt; 188 180 189 181 con = console_init(stdin, stdout); … … 205 197 206 198 /* 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; 211 203 212 204 if (argc == 2) { … … 224 216 new_file = true; 225 217 218 /* Move to beginning of file. */ 219 caret_move(-ED_INFTY, -ED_INFTY, dir_before); 220 226 221 /* 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); 232 224 233 225 /* Initial display */ … … 408 400 selection_sel_all(); 409 401 break; 402 case KC_W: 403 if (selection_active()) 404 break; 405 selection_sel_prev_word(); 406 selection_delete(); 407 break; 410 408 case KC_RIGHT: 411 caret_move_word_right( false);409 caret_move_word_right(); 412 410 break; 413 411 case KC_LEFT: 414 caret_move_word_left( false);412 caret_move_word_left(); 415 413 break; 416 414 case KC_L: 417 415 caret_go_to_line_ask(); 418 416 break; 419 case KC_F:420 search_prompt(false);421 break;422 case KC_N:423 search_repeat();424 break;425 417 default: 426 418 break; … … 432 424 switch(ev->key) { 433 425 case KC_LEFT: 434 caret_move_word_left(true);426 selection_sel_prev_word(); 435 427 break; 436 428 case KC_RIGHT: 437 caret_move_word_right(true); 438 break; 439 case KC_F: 440 search_prompt(true); 429 selection_sel_next_word(); 441 430 break; 442 431 default: … … 446 435 447 436 /** 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; 437 static 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; 451 442 coord_t c_old, c_new; 452 443 bool had_sel; 453 444 454 445 /* 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); 462 451 463 452 if (select == false) { 464 453 /* Move sel_start to the same point as caret. */ 465 454 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 470 459 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); 472 463 473 464 if (c_old.row == c_new.row) … … 480 471 pane.rflags |= REDRAW_TEXT; 481 472 } 482 483 if (update_ideal_column)484 pane.ideal_column = c_new.column;485 486 caret_update();487 473 } 488 474 … … 491 477 switch (key) { 492 478 case KC_LEFT: 493 caret_move _relative(0, -1, dir_before, select);479 caret_movement(0, -1, dir_before, select); 494 480 break; 495 481 case KC_RIGHT: 496 caret_move _relative(0, 0, dir_after, select);482 caret_movement(0, 0, dir_after, select); 497 483 break; 498 484 case KC_UP: 499 caret_move _relative(-1, 0, dir_before, select);485 caret_movement(-1, 0, dir_before, select); 500 486 break; 501 487 case KC_DOWN: 502 caret_move _relative(+1, 0, dir_before, select);488 caret_movement(+1, 0, dir_before, select); 503 489 break; 504 490 case KC_HOME: 505 caret_move _relative(0, -ED_INFTY, dir_after, select);491 caret_movement(0, -ED_INFTY, dir_before, select); 506 492 break; 507 493 case KC_END: 508 caret_move _relative(0, +ED_INFTY, dir_before, select);494 caret_movement(0, +ED_INFTY, dir_before, select); 509 495 break; 510 496 case KC_PAGE_UP: 511 caret_move _relative(-pane.rows, 0, dir_before, select);497 caret_movement(-pane.rows, 0, dir_before, select); 512 498 break; 513 499 case KC_PAGE_DOWN: 514 caret_move _relative(+pane.rows, 0, dir_before, select);500 caret_movement(+pane.rows, 0, dir_before, select); 515 501 break; 516 502 default: … … 1026 1012 } 1027 1013 1028 /** Relatively move caret position.1014 /** Change the caret position. 1029 1015 * 1030 1016 * Moves caret relatively to the current position. Looking at the first … … 1032 1018 * to a new character cell, and thus a new character. Then we either go to the 1033 1019 * 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 is1036 1020 */ 1037 static void caret_move_relative(int drow, int dcolumn, enum dir_spec align_dir, 1038 bool select) 1021 static void caret_move(int drow, int dcolumn, enum dir_spec align_dir) 1039 1022 { 1040 1023 spt_t pt; … … 1072 1055 */ 1073 1056 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); 1074 1059 1075 1060 /* 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 1069 static 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 1085 static 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 1086 1102 */ 1087 static void caret_move_ absolute(int row, int column, enum dir_spec align_dir,1088 bool select) 1089 { 1103 static void caret_move_to_line(int row) 1104 { 1105 spt_t pt; 1090 1106 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 1121 1108 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); 1132 1112 } 1133 1113 … … 1146 1126 int line = strtol(sline, &endptr, 10); 1147 1127 if (*endptr != '\0') { 1148 free(sline);1149 1128 status_display("Invalid number entered."); 1150 1129 return; 1151 1130 } 1152 free(sline);1153 1131 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 1301 1135 1302 1136 /** Check for non-empty selection. */ … … 1368 1202 pane.rflags |= REDRAW_TEXT; 1369 1203 caret_update(); 1204 } 1205 1206 /** Add the previous word to the selection */ 1207 static 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 */ 1224 static 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); 1370 1238 } 1371 1239
Note:
See TracChangeset
for help on using the changeset viewer.