Changes in uspace/app/edit/edit.c [c80be58:79ae36dd] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/edit/edit.c
rc80be58 r79ae36dd 1 1 /* 2 2 * Copyright (c) 2009 Jiri Svoboda 3 * Copyright (c) 2012 Martin Sucha4 3 * All rights reserved. 5 4 * … … 47 46 #include <macros.h> 48 47 #include <clipboard.h> 49 #include < stdbool.h>48 #include <bool.h> 50 49 51 50 #include "sheet.h" 52 #include "search.h"53 51 54 52 enum redraw_flags { … … 80 78 tag_t sel_start; 81 79 82 /** Active keyboard modifiers */83 keymod_t keymod;84 85 80 /** 86 81 * Ideal column where the caret should try to get. This is used … … 88 83 */ 89 84 int ideal_column; 90 91 char *previous_search;92 bool previous_search_reverse;93 85 } pane_t; 94 86 … … 99 91 typedef struct { 100 92 char *file_name; 101 sheet_t *sh;93 sheet_t sh; 102 94 } doc_t; 103 95 … … 114 106 #define BUF_SIZE 64 115 107 #define TAB_WIDTH 8 108 #define ED_INFTY 65536 116 109 117 110 /** Maximum filename length that can be entered. */ … … 122 115 static void cursor_setvis(bool visible); 123 116 124 static void key_handle_press(kbd_event_t *ev);125 117 static void key_handle_unmod(kbd_event_t const *ev); 126 118 static void key_handle_ctrl(kbd_event_t const *ev); 127 119 static void key_handle_shift(kbd_event_t const *ev); 128 static void key_handle_shift_ctrl(kbd_event_t const *ev);129 120 static void key_handle_movement(unsigned int key, bool shift); 130 131 static void pos_handle(pos_event_t *ev);132 121 133 122 static int file_save(char const *fname); … … 136 125 static int file_save_range(char const *fname, spt_t const *spos, 137 126 spt_t const *epos); 127 static char *filename_prompt(char const *prompt, char const *init_value); 138 128 static char *range_get_str(spt_t const *spos, spt_t const *epos); 139 140 static char *prompt(char const *prompt, char const *init_value);141 129 142 130 static void pane_text_display(void); … … 150 138 static void delete_char_after(void); 151 139 static void caret_update(void); 152 static void caret_move_relative(int drow, int dcolumn, enum dir_spec align_dir, bool select); 153 static void caret_move_absolute(int row, int column, enum dir_spec align_dir, bool select); 154 static void caret_move(spt_t spt, bool select, bool update_ideal_column); 155 static void caret_move_word_left(bool select); 156 static void caret_move_word_right(bool select); 157 static void caret_go_to_line_ask(void); 140 static void caret_move(int drow, int dcolumn, enum dir_spec align_dir); 158 141 159 142 static bool selection_active(void); 160 143 static void selection_sel_all(void); 161 static void selection_sel_range(spt_t pa, spt_t pb);162 144 static void selection_get_points(spt_t *pa, spt_t *pb); 163 145 static void selection_delete(void); … … 165 147 static void insert_clipboard_data(void); 166 148 167 static void search(char *pattern, bool reverse);168 static void search_prompt(bool reverse);169 static void search_repeat(void);170 171 149 static void pt_get_sof(spt_t *pt); 172 150 static void pt_get_eof(spt_t *pt); 173 static void pt_get_sol(spt_t *cpt, spt_t *spt);174 static void pt_get_eol(spt_t *cpt, spt_t *ept);175 static bool pt_is_word_beginning(spt_t *pt);176 static bool pt_is_delimiter(spt_t *pt);177 static bool pt_is_punctuation(spt_t *pt);178 static spt_t pt_find_word_left(spt_t spt);179 static spt_t pt_find_word_left(spt_t spt);180 181 151 static int tag_cmp(tag_t const *a, tag_t const *b); 182 152 static int spt_cmp(spt_t const *a, spt_t const *b); … … 188 158 int main(int argc, char *argv[]) 189 159 { 190 cons_event_t ev; 160 kbd_event_t ev; 161 coord_t coord; 191 162 bool new_file; 192 int rc; 163 164 spt_t pt; 193 165 194 166 con = console_init(stdin, stdout); … … 203 175 204 176 /* Start with an empty sheet. */ 205 rc = sheet_create(&doc.sh); 206 if (rc != EOK) { 207 printf("Out of memory.\n"); 208 return -1; 209 } 177 sheet_init(&doc.sh); 210 178 211 179 /* Place caret at the beginning of file. */ 212 spt_t sof;213 pt_get_sof(&sof);214 sheet_place_tag( doc.sh, &sof, &pane.caret_pos);215 pane.ideal_column = 1;180 coord.row = coord.column = 1; 181 sheet_get_cell_pt(&doc.sh, &coord, dir_before, &pt); 182 sheet_place_tag(&doc.sh, &pt, &pane.caret_pos); 183 pane.ideal_column = coord.column; 216 184 217 185 if (argc == 2) { … … 229 197 new_file = true; 230 198 199 /* Move to beginning of file. */ 200 caret_move(-ED_INFTY, -ED_INFTY, dir_before); 201 231 202 /* Place selection start tag. */ 232 sheet_place_tag(doc.sh, &sof, &pane.sel_start); 233 234 /* Move to beginning of file. */ 235 pt_get_sof(&sof); 236 caret_move(sof, true, true); 203 tag_get_pt(&pane.caret_pos, &pt); 204 sheet_place_tag(&doc.sh, &pt, &pane.sel_start); 237 205 238 206 /* Initial display */ … … 251 219 252 220 while (!done) { 253 console_get_ event(con, &ev);221 console_get_kbd_event(con, &ev); 254 222 pane.rflags = 0; 255 223 256 switch (ev.type) { 257 case CEV_KEY: 258 pane.keymod = ev.ev.key.mods; 259 if (ev.ev.key.type == KEY_PRESS) 260 key_handle_press(&ev.ev.key); 261 break; 262 case CEV_POS: 263 pos_handle(&ev.ev.pos); 264 break; 224 if (ev.type == KEY_PRESS) { 225 /* Handle key press. */ 226 if (((ev.mods & KM_ALT) == 0) && 227 ((ev.mods & KM_SHIFT) == 0) && 228 (ev.mods & KM_CTRL) != 0) { 229 key_handle_ctrl(&ev); 230 } else if (((ev.mods & KM_ALT) == 0) && 231 ((ev.mods & KM_CTRL) == 0) && 232 (ev.mods & KM_SHIFT) != 0) { 233 key_handle_shift(&ev); 234 } else if ((ev.mods & (KM_CTRL | KM_ALT | KM_SHIFT)) == 0) { 235 key_handle_unmod(&ev); 236 } 265 237 } 266 238 … … 284 256 285 257 return 0; 286 }287 288 /* Handle key press. */289 static void key_handle_press(kbd_event_t *ev)290 {291 if (((ev->mods & KM_ALT) == 0) &&292 ((ev->mods & KM_SHIFT) == 0) &&293 (ev->mods & KM_CTRL) != 0) {294 key_handle_ctrl(ev);295 } else if (((ev->mods & KM_ALT) == 0) &&296 ((ev->mods & KM_CTRL) == 0) &&297 (ev->mods & KM_SHIFT) != 0) {298 key_handle_shift(ev);299 } else if (((ev->mods & KM_ALT) == 0) &&300 ((ev->mods & KM_CTRL) != 0) &&301 (ev->mods & KM_SHIFT) != 0) {302 key_handle_shift_ctrl(ev);303 } else if ((ev->mods & (KM_CTRL | KM_ALT | KM_SHIFT)) == 0) {304 key_handle_unmod(ev);305 }306 258 } 307 259 … … 394 346 static void key_handle_ctrl(kbd_event_t const *ev) 395 347 { 396 spt_t pt;397 348 switch (ev->key) { 398 349 case KC_Q: … … 426 377 selection_sel_all(); 427 378 break; 428 case KC_RIGHT:429 caret_move_word_right(false);430 break;431 case KC_LEFT:432 caret_move_word_left(false);433 break;434 case KC_L:435 caret_go_to_line_ask();436 break;437 case KC_F:438 search_prompt(false);439 break;440 case KC_N:441 search_repeat();442 break;443 case KC_HOME:444 pt_get_sof(&pt);445 caret_move(pt, false, true);446 break;447 case KC_END:448 pt_get_eof(&pt);449 caret_move(pt, false, true);450 break;451 379 default: 452 380 break; … … 454 382 } 455 383 456 static void key_handle_ shift_ctrl(kbd_event_t const *ev)384 static void key_handle_movement(unsigned int key, bool select) 457 385 { 458 386 spt_t pt; 459 switch(ev->key) { 460 case KC_LEFT: 461 caret_move_word_left(true); 462 break; 463 case KC_RIGHT: 464 caret_move_word_right(true); 465 break; 466 case KC_F: 467 search_prompt(true); 468 break; 469 case KC_HOME: 470 pt_get_sof(&pt); 471 caret_move(pt, true, true); 472 break; 473 case KC_END: 474 pt_get_eof(&pt); 475 caret_move(pt, true, true); 476 break; 477 default: 478 break; 479 } 480 } 481 482 static void pos_handle(pos_event_t *ev) 483 { 484 coord_t bc; 485 spt_t pt; 486 bool select; 487 488 if (ev->type == POS_PRESS && ev->vpos < (unsigned)pane.rows) { 489 bc.row = pane.sh_row + ev->vpos; 490 bc.column = pane.sh_column + ev->hpos; 491 sheet_get_cell_pt(doc.sh, &bc, dir_before, &pt); 492 493 select = (pane.keymod & KM_SHIFT) != 0; 494 495 caret_move(pt, select, true); 496 } 497 } 498 499 /** Move caret while preserving or resetting selection. */ 500 static void caret_move(spt_t new_caret_pt, bool select, bool update_ideal_column) 501 { 502 spt_t old_caret_pt, old_sel_pt; 387 spt_t caret_pt; 503 388 coord_t c_old, c_new; 504 389 bool had_sel; 505 390 506 391 /* Check if we had selection before. */ 507 tag_get_pt(&pane.caret_pos, &old_caret_pt); 508 tag_get_pt(&pane.sel_start, &old_sel_pt); 509 had_sel = !spt_equal(&old_caret_pt, &old_sel_pt); 510 511 /* Place tag of the caret */ 512 sheet_remove_tag(doc.sh, &pane.caret_pos); 513 sheet_place_tag(doc.sh, &new_caret_pt, &pane.caret_pos); 392 tag_get_pt(&pane.caret_pos, &caret_pt); 393 tag_get_pt(&pane.sel_start, &pt); 394 had_sel = !spt_equal(&caret_pt, &pt); 395 396 switch (key) { 397 case KC_LEFT: 398 caret_move(0, -1, dir_before); 399 break; 400 case KC_RIGHT: 401 caret_move(0, 0, dir_after); 402 break; 403 case KC_UP: 404 caret_move(-1, 0, dir_before); 405 break; 406 case KC_DOWN: 407 caret_move(+1, 0, dir_before); 408 break; 409 case KC_HOME: 410 caret_move(0, -ED_INFTY, dir_before); 411 break; 412 case KC_END: 413 caret_move(0, +ED_INFTY, dir_before); 414 break; 415 case KC_PAGE_UP: 416 caret_move(-pane.rows, 0, dir_before); 417 break; 418 case KC_PAGE_DOWN: 419 caret_move(+pane.rows, 0, dir_before); 420 break; 421 default: 422 break; 423 } 514 424 515 425 if (select == false) { 516 426 /* Move sel_start to the same point as caret. */ 517 sheet_remove_tag( doc.sh, &pane.sel_start);518 sheet_place_tag(doc.sh, &new_caret_pt, &pane.sel_start);519 }520 521 spt_get_coord(&new_caret_pt, &c_new); 427 sheet_remove_tag(&doc.sh, &pane.sel_start); 428 tag_get_pt(&pane.caret_pos, &pt); 429 sheet_place_tag(&doc.sh, &pt, &pane.sel_start); 430 } 431 522 432 if (select) { 523 spt_get_coord(&old_caret_pt, &c_old); 433 tag_get_pt(&pane.caret_pos, &pt); 434 spt_get_coord(&caret_pt, &c_old); 435 spt_get_coord(&pt, &c_new); 524 436 525 437 if (c_old.row == c_new.row) … … 532 444 pane.rflags |= REDRAW_TEXT; 533 445 } 534 535 if (update_ideal_column)536 pane.ideal_column = c_new.column;537 538 caret_update();539 }540 541 static void key_handle_movement(unsigned int key, bool select)542 {543 spt_t pt;544 switch (key) {545 case KC_LEFT:546 caret_move_relative(0, -1, dir_before, select);547 break;548 case KC_RIGHT:549 caret_move_relative(0, 0, dir_after, select);550 break;551 case KC_UP:552 caret_move_relative(-1, 0, dir_before, select);553 break;554 case KC_DOWN:555 caret_move_relative(+1, 0, dir_before, select);556 break;557 case KC_HOME:558 tag_get_pt(&pane.caret_pos, &pt);559 pt_get_sol(&pt, &pt);560 caret_move(pt, select, true);561 break;562 case KC_END:563 tag_get_pt(&pane.caret_pos, &pt);564 pt_get_eol(&pt, &pt);565 caret_move(pt, select, true);566 break;567 case KC_PAGE_UP:568 caret_move_relative(-pane.rows, 0, dir_before, select);569 break;570 case KC_PAGE_DOWN:571 caret_move_relative(+pane.rows, 0, dir_before, select);572 break;573 default:574 break;575 }576 446 } 577 447 … … 609 479 char *fname; 610 480 611 fname = prompt("Save As", old_fname);481 fname = filename_prompt("Save As", old_fname); 612 482 if (fname == NULL) { 613 483 status_display("Save cancelled."); … … 624 494 } 625 495 626 /** Ask for a string. */ 627 static char *prompt(char const *prompt, char const *init_value) 628 { 629 cons_event_t ev; 630 kbd_event_t *kev; 496 /** Ask for a file name. */ 497 static char *filename_prompt(char const *prompt, char const *init_value) 498 { 499 kbd_event_t ev; 631 500 char *str; 632 501 wchar_t buffer[INFNAME_MAX_LEN + 1]; … … 648 517 649 518 while (!done) { 650 console_get_event(con, &ev); 651 652 if (ev.type == CEV_KEY && ev.ev.key.type == KEY_PRESS) { 653 kev = &ev.ev.key; 654 519 console_get_kbd_event(con, &ev); 520 521 if (ev.type == KEY_PRESS) { 655 522 /* Handle key press. */ 656 if ((( kev->mods & KM_ALT) == 0) &&657 ( kev->mods & KM_CTRL) != 0) {523 if (((ev.mods & KM_ALT) == 0) && 524 (ev.mods & KM_CTRL) != 0) { 658 525 ; 659 } else if (( kev->mods & (KM_CTRL | KM_ALT)) == 0) {660 switch ( kev->key) {526 } else if ((ev.mods & (KM_CTRL | KM_ALT)) == 0) { 527 switch (ev.key) { 661 528 case KC_ESCAPE: 662 529 return NULL; … … 672 539 break; 673 540 default: 674 if ( kev->c >= 32 && nc < max_len) {675 putchar( kev->c);541 if (ev.c >= 32 && nc < max_len) { 542 putchar(ev.c); 676 543 console_flush(con); 677 buffer[nc++] = kev->c;544 buffer[nc++] = ev.c; 678 545 } 679 546 break; … … 749 616 750 617 do { 751 sheet_copy_out( doc.sh, &sp, epos, buf, BUF_SIZE, &bep);618 sheet_copy_out(&doc.sh, &sp, epos, buf, BUF_SIZE, &bep); 752 619 bytes = str_size(buf); 753 620 … … 784 651 785 652 while (true) { 786 sheet_copy_out( doc.sh, &sp, epos, &buf[bpos], buf_size - bpos,653 sheet_copy_out(&doc.sh, &sp, epos, &buf[bpos], buf_size - bpos, 787 654 &bep); 788 655 bytes = str_size(&buf[bpos]); … … 806 673 int sh_rows, rows; 807 674 808 sheet_get_num_rows( doc.sh, &sh_rows);675 sheet_get_num_rows(&doc.sh, &sh_rows); 809 676 rows = min(sh_rows - pane.sh_row + 1, pane.rows); 810 677 … … 876 743 rbc.row = pane.sh_row + i; 877 744 rbc.column = pane.sh_column; 878 sheet_get_cell_pt( doc.sh, &rbc, dir_before, &rb);745 sheet_get_cell_pt(&doc.sh, &rbc, dir_before, &rb); 879 746 880 747 /* Ending point for row display */ 881 748 rec.row = pane.sh_row + i; 882 749 rec.column = pane.sh_column + pane.columns; 883 sheet_get_cell_pt( doc.sh, &rec, dir_before, &re);750 sheet_get_cell_pt(&doc.sh, &rec, dir_before, &re); 884 751 885 752 /* Copy the text of the row to the buffer. */ 886 sheet_copy_out( doc.sh, &rb, &re, row_buf, ROW_BUF_SIZE, &dep);753 sheet_copy_out(&doc.sh, &rb, &re, row_buf, ROW_BUF_SIZE, &dep); 887 754 888 755 /* Display text from the buffer. */ … … 934 801 /* Fill until the end of display area. */ 935 802 936 if ( (unsigned)s_column - 1 <scr_columns)937 fill = scr_columns - (s_column - 1);803 if (str_length(row_buf) < (unsigned) scr_columns) 804 fill = scr_columns - str_length(row_buf); 938 805 else 939 806 fill = 0; … … 953 820 spt_t caret_pt; 954 821 coord_t coord; 955 int last_row;956 822 957 823 tag_get_pt(&pane.caret_pos, &caret_pt); 958 824 spt_get_coord(&caret_pt, &coord); 959 825 960 sheet_get_num_rows(doc.sh, &last_row);961 962 826 const char *fname = (doc.file_name != NULL) ? doc.file_name : "<unnamed>"; 963 827 964 828 console_set_pos(con, 0, scr_rows - 1); 965 829 console_set_style(con, STYLE_INVERTED); 966 int n = printf(" %d, %d (%d): File '%s'. Ctrl-Q Quit Ctrl-S Save "967 "Ctrl-E Save As", coord.row, coord.column, last_row,fname);830 int n = printf(" %d, %d: File '%s'. Ctrl-Q Quit Ctrl-S Save " 831 "Ctrl-E Save As", coord.row, coord.column, fname); 968 832 969 833 int pos = scr_columns - 1 - n; … … 1001 865 cbuf[offs] = '\0'; 1002 866 1003 (void) sheet_insert( doc.sh, &pt, dir_before, cbuf);867 (void) sheet_insert(&doc.sh, &pt, dir_before, cbuf); 1004 868 1005 869 pane.rflags |= REDRAW_ROW; … … 1018 882 1019 883 coord.column -= 1; 1020 sheet_get_cell_pt( doc.sh, &coord, dir_before, &sp);1021 1022 (void) sheet_delete( doc.sh, &sp, &ep);884 sheet_get_cell_pt(&doc.sh, &coord, dir_before, &sp); 885 886 (void) sheet_delete(&doc.sh, &sp, &ep); 1023 887 1024 888 pane.rflags |= REDRAW_ROW; … … 1036 900 spt_get_coord(&sp, &sc); 1037 901 1038 sheet_get_cell_pt( doc.sh, &sc, dir_after, &ep);902 sheet_get_cell_pt(&doc.sh, &sc, dir_after, &ep); 1039 903 spt_get_coord(&ep, &ec); 1040 904 1041 (void) sheet_delete( doc.sh, &sp, &ep);905 (void) sheet_delete(&doc.sh, &sp, &ep); 1042 906 1043 907 pane.rflags |= REDRAW_ROW; … … 1086 950 } 1087 951 1088 /** Relatively move caret position.952 /** Change the caret position. 1089 953 * 1090 954 * Moves caret relatively to the current position. Looking at the first … … 1092 956 * to a new character cell, and thus a new character. Then we either go to the 1093 957 * point before the the character or after it, depending on @a align_dir. 1094 *1095 * @param select true if the selection tag should stay where it is1096 958 */ 1097 static void caret_move_relative(int drow, int dcolumn, enum dir_spec align_dir, 1098 bool select) 959 static void caret_move(int drow, int dcolumn, enum dir_spec align_dir) 1099 960 { 1100 961 spt_t pt; … … 1109 970 /* Clamp coordinates. */ 1110 971 if (drow < 0 && coord.row < 1) coord.row = 1; 1111 if (dcolumn < 0 && coord.column < 1) { 1112 if (coord.row < 2) 1113 coord.column = 1; 1114 else { 1115 coord.row--; 1116 sheet_get_row_width(doc.sh, coord.row, &coord.column); 1117 } 1118 } 972 if (dcolumn < 0 && coord.column < 1) coord.column = 1; 1119 973 if (drow > 0) { 1120 sheet_get_num_rows( doc.sh, &num_rows);974 sheet_get_num_rows(&doc.sh, &num_rows); 1121 975 if (coord.row > num_rows) coord.row = num_rows; 1122 976 } … … 1131 985 * coordinates. The character can be wider than one cell (e.g. tab). 1132 986 */ 1133 sheet_get_cell_pt(doc.sh, &coord, align_dir, &pt); 987 sheet_get_cell_pt(&doc.sh, &coord, align_dir, &pt); 988 sheet_remove_tag(&doc.sh, &pane.caret_pos); 989 sheet_place_tag(&doc.sh, &pt, &pane.caret_pos); 1134 990 1135 991 /* For non-vertical movement set the new value for @c ideal_column. */ 1136 caret_move(pt, select, !pure_vertical); 1137 } 1138 1139 /** Absolutely move caret position. 1140 * 1141 * Moves caret to a specified position. We get to a new character cell, and 1142 * thus a new character. Then we either go to the point before the the character 1143 * or after it, depending on @a align_dir. 1144 * 1145 * @param select true if the selection tag should stay where it is 1146 */ 1147 static void caret_move_absolute(int row, int column, enum dir_spec align_dir, 1148 bool select) 1149 { 1150 coord_t coord; 1151 coord.row = row; 1152 coord.column = column; 1153 1154 spt_t pt; 1155 sheet_get_cell_pt(doc.sh, &coord, align_dir, &pt); 1156 1157 caret_move(pt, select, true); 1158 } 1159 1160 /** Find beginning of a word to the left of spt */ 1161 static spt_t pt_find_word_left(spt_t spt) 1162 { 1163 do { 1164 spt_prev_char(spt, &spt); 1165 } while (!pt_is_word_beginning(&spt)); 1166 return spt; 1167 } 1168 1169 /** Find beginning of a word to the right of spt */ 1170 static spt_t pt_find_word_right(spt_t spt) 1171 { 1172 do { 1173 spt_next_char(spt, &spt); 1174 } while (!pt_is_word_beginning(&spt)); 1175 return spt; 1176 } 1177 1178 static void caret_move_word_left(bool select) 1179 { 1180 spt_t pt; 1181 tag_get_pt(&pane.caret_pos, &pt); 1182 spt_t word_left = pt_find_word_left(pt); 1183 caret_move(word_left, select, true); 1184 } 1185 1186 static void caret_move_word_right(bool select) 1187 { 1188 spt_t pt; 1189 tag_get_pt(&pane.caret_pos, &pt); 1190 spt_t word_right = pt_find_word_right(pt); 1191 caret_move(word_right, select, true); 1192 } 1193 1194 /** Ask for line and go to it. */ 1195 static void caret_go_to_line_ask(void) 1196 { 1197 char *sline; 1198 1199 sline = prompt("Go to line", ""); 1200 if (sline == NULL) { 1201 status_display("Go to line cancelled."); 1202 return; 1203 } 1204 1205 char *endptr; 1206 int line = strtol(sline, &endptr, 10); 1207 if (*endptr != '\0') { 1208 free(sline); 1209 status_display("Invalid number entered."); 1210 return; 1211 } 1212 free(sline); 1213 1214 caret_move_absolute(line, pane.ideal_column, dir_before, false); 1215 } 1216 1217 /* Search operations */ 1218 static int search_spt_producer(void *data, wchar_t *ret) 1219 { 1220 assert(data != NULL); 1221 assert(ret != NULL); 1222 spt_t *spt = data; 1223 *ret = spt_next_char(*spt, spt); 1224 return EOK; 1225 } 1226 1227 static int search_spt_reverse_producer(void *data, wchar_t *ret) 1228 { 1229 assert(data != NULL); 1230 assert(ret != NULL); 1231 spt_t *spt = data; 1232 *ret = spt_prev_char(*spt, spt); 1233 return EOK; 1234 } 1235 1236 static int search_spt_mark(void *data, void **mark) 1237 { 1238 assert(data != NULL); 1239 assert(mark != NULL); 1240 spt_t *spt = data; 1241 spt_t *new = calloc(1, sizeof(spt_t)); 1242 *mark = new; 1243 if (new == NULL) 1244 return ENOMEM; 1245 *new = *spt; 1246 return EOK; 1247 } 1248 1249 static void search_spt_mark_free(void *data) 1250 { 1251 free(data); 1252 } 1253 1254 static search_ops_t search_spt_ops = { 1255 .equals = char_exact_equals, 1256 .producer = search_spt_producer, 1257 .mark = search_spt_mark, 1258 .mark_free = search_spt_mark_free, 1259 }; 1260 1261 static search_ops_t search_spt_reverse_ops = { 1262 .equals = char_exact_equals, 1263 .producer = search_spt_reverse_producer, 1264 .mark = search_spt_mark, 1265 .mark_free = search_spt_mark_free, 1266 }; 1267 1268 /** Ask for line and go to it. */ 1269 static void search_prompt(bool reverse) 1270 { 1271 char *pattern; 1272 1273 const char *prompt_text = "Find next"; 1274 if (reverse) 1275 prompt_text = "Find previous"; 1276 1277 const char *default_value = ""; 1278 if (pane.previous_search) 1279 default_value = pane.previous_search; 1280 1281 pattern = prompt(prompt_text, default_value); 1282 if (pattern == NULL) { 1283 status_display("Search cancelled."); 1284 return; 1285 } 1286 1287 if (pane.previous_search) 1288 free(pane.previous_search); 1289 pane.previous_search = pattern; 1290 pane.previous_search_reverse = reverse; 1291 1292 search(pattern, reverse); 1293 } 1294 1295 static void search_repeat(void) 1296 { 1297 if (pane.previous_search == NULL) { 1298 status_display("No previous search to repeat."); 1299 return; 1300 } 1301 1302 search(pane.previous_search, pane.previous_search_reverse); 1303 } 1304 1305 static void search(char *pattern, bool reverse) 1306 { 1307 status_display("Searching..."); 1308 1309 spt_t sp, producer_pos; 1310 tag_get_pt(&pane.caret_pos, &sp); 1311 1312 /* Start searching on the position before/after caret */ 1313 if (!reverse) { 1314 spt_next_char(sp, &sp); 1315 } 1316 else { 1317 spt_prev_char(sp, &sp); 1318 } 1319 producer_pos = sp; 1320 1321 search_ops_t ops = search_spt_ops; 1322 if (reverse) 1323 ops = search_spt_reverse_ops; 1324 1325 search_t *search = search_init(pattern, &producer_pos, ops, reverse); 1326 if (search == NULL) { 1327 status_display("Failed initializing search."); 1328 return; 1329 } 1330 1331 match_t match; 1332 int rc = search_next_match(search, &match); 1333 if (rc != EOK) { 1334 status_display("Failed searching."); 1335 search_fini(search); 1336 } 1337 1338 if (match.end) { 1339 status_display("Match found."); 1340 assert(match.end != NULL); 1341 spt_t *end = match.end; 1342 caret_move(*end, false, true); 1343 while (match.length > 0) { 1344 match.length--; 1345 if (reverse) { 1346 spt_next_char(*end, end); 1347 } 1348 else { 1349 spt_prev_char(*end, end); 1350 } 1351 } 1352 caret_move(*end, true, true); 1353 free(end); 1354 } 1355 else { 1356 status_display("Not found."); 1357 } 1358 1359 search_fini(search); 992 if (!pure_vertical) { 993 spt_get_coord(&pt, &coord); 994 pane.ideal_column = coord.column; 995 } 996 997 caret_update(); 1360 998 } 1361 999 … … 1397 1035 1398 1036 if (rel < 0) 1399 sheet_delete( doc.sh, &pa, &pb);1037 sheet_delete(&doc.sh, &pa, &pb); 1400 1038 else 1401 sheet_delete( doc.sh, &pb, &pa);1039 sheet_delete(&doc.sh, &pb, &pa); 1402 1040 1403 1041 if (ca.row == cb.row) … … 1407 1045 } 1408 1046 1409 /** Select all text in the editor */1410 1047 static void selection_sel_all(void) 1411 1048 { … … 1414 1051 pt_get_sof(&spt); 1415 1052 pt_get_eof(&ept); 1416 1417 selection_sel_range(spt, ept); 1418 } 1419 1420 /** Select select all text in a given range with the given direction */ 1421 static void selection_sel_range(spt_t pa, spt_t pb) 1422 { 1423 sheet_remove_tag(doc.sh, &pane.sel_start); 1424 sheet_place_tag(doc.sh, &pa, &pane.sel_start); 1425 sheet_remove_tag(doc.sh, &pane.caret_pos); 1426 sheet_place_tag(doc.sh, &pb, &pane.caret_pos); 1053 sheet_remove_tag(&doc.sh, &pane.sel_start); 1054 sheet_place_tag(&doc.sh, &spt, &pane.sel_start); 1055 sheet_remove_tag(&doc.sh, &pane.caret_pos); 1056 sheet_place_tag(&doc.sh, &ept, &pane.caret_pos); 1427 1057 1428 1058 pane.rflags |= REDRAW_TEXT; … … 1473 1103 1474 1104 coord.row = coord.column = 1; 1475 sheet_get_cell_pt( doc.sh, &coord, dir_before, pt);1105 sheet_get_cell_pt(&doc.sh, &coord, dir_before, pt); 1476 1106 } 1477 1107 … … 1482 1112 int num_rows; 1483 1113 1484 sheet_get_num_rows( doc.sh, &num_rows);1114 sheet_get_num_rows(&doc.sh, &num_rows); 1485 1115 coord.row = num_rows + 1; 1486 1116 coord.column = 1; 1487 1117 1488 sheet_get_cell_pt(doc.sh, &coord, dir_after, pt); 1489 } 1490 1491 /** Get start-of-line s-point for given s-point cpt */ 1492 static void pt_get_sol(spt_t *cpt, spt_t *spt) 1493 { 1494 coord_t coord; 1495 1496 spt_get_coord(cpt, &coord); 1497 coord.column = 1; 1498 1499 sheet_get_cell_pt(doc.sh, &coord, dir_before, spt); 1500 } 1501 1502 /** Get end-of-line s-point for given s-point cpt */ 1503 static void pt_get_eol(spt_t *cpt, spt_t *ept) 1504 { 1505 coord_t coord; 1506 int row_width; 1507 1508 spt_get_coord(cpt, &coord); 1509 sheet_get_row_width(doc.sh, coord.row, &row_width); 1510 coord.column = row_width - 1; 1511 1512 sheet_get_cell_pt(doc.sh, &coord, dir_after, ept); 1513 } 1514 1515 /** Check whether the spt is at a beginning of a word */ 1516 static bool pt_is_word_beginning(spt_t *pt) 1517 { 1518 spt_t lp, sfp, efp, slp, elp; 1519 coord_t coord; 1520 1521 pt_get_sof(&sfp); 1522 pt_get_eof(&efp); 1523 pt_get_sol(pt, &slp); 1524 pt_get_eol(pt, &elp); 1525 1526 /* the spt is at the beginning or end of the file or line */ 1527 if ((spt_cmp(&sfp, pt) == 0) || (spt_cmp(&efp, pt) == 0) 1528 || (spt_cmp(&slp, pt) == 0) || (spt_cmp(&elp, pt) == 0)) 1529 return true; 1530 1531 /* the spt is a delimiter */ 1532 if (pt_is_delimiter(pt)) 1533 return false; 1534 1535 spt_get_coord(pt, &coord); 1536 1537 coord.column -= 1; 1538 sheet_get_cell_pt(doc.sh, &coord, dir_before, &lp); 1539 1540 return pt_is_delimiter(&lp) 1541 || (pt_is_punctuation(pt) && !pt_is_punctuation(&lp)) 1542 || (pt_is_punctuation(&lp) && !pt_is_punctuation(pt)); 1543 } 1544 1545 static wchar_t get_first_wchar(const char *str) 1546 { 1547 size_t offset = 0; 1548 return str_decode(str, &offset, str_size(str)); 1549 } 1550 1551 static bool pt_is_delimiter(spt_t *pt) 1552 { 1553 spt_t rp; 1554 coord_t coord; 1555 char *ch = NULL; 1556 1557 spt_get_coord(pt, &coord); 1558 1559 coord.column += 1; 1560 sheet_get_cell_pt(doc.sh, &coord, dir_after, &rp); 1561 1562 ch = range_get_str(pt, &rp); 1563 if (ch == NULL) 1564 return false; 1565 1566 wchar_t first_char = get_first_wchar(ch); 1567 switch(first_char) { 1568 case ' ': 1569 case '\t': 1570 case '\n': 1571 return true; 1572 default: 1573 return false; 1574 } 1575 } 1576 1577 static bool pt_is_punctuation(spt_t *pt) 1578 { 1579 spt_t rp; 1580 coord_t coord; 1581 char *ch = NULL; 1582 1583 spt_get_coord(pt, &coord); 1584 1585 coord.column += 1; 1586 sheet_get_cell_pt(doc.sh, &coord, dir_after, &rp); 1587 1588 ch = range_get_str(pt, &rp); 1589 if (ch == NULL) 1590 return false; 1591 1592 wchar_t first_char = get_first_wchar(ch); 1593 switch(first_char) { 1594 case ',': 1595 case '.': 1596 case ';': 1597 case ':': 1598 case '/': 1599 case '?': 1600 case '\\': 1601 case '|': 1602 case '_': 1603 case '+': 1604 case '-': 1605 case '*': 1606 case '=': 1607 case '<': 1608 case '>': 1609 return true; 1610 default: 1611 return false; 1612 } 1118 sheet_get_cell_pt(&doc.sh, &coord, dir_after, pt); 1613 1119 } 1614 1120
Note:
See TracChangeset
for help on using the changeset viewer.