Changes in uspace/app/edit/edit.c [743e17b:cd82bb1] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/edit/edit.c
r743e17b rcd82bb1 36 36 37 37 #include <stdio.h> 38 #include <stdlib.h> 38 39 #include <sys/types.h> 39 40 #include <vfs/vfs.h> … … 44 45 #include <align.h> 45 46 #include <macros.h> 47 #include <clipboard.h> 46 48 #include <bool.h> 47 49 … … 73 75 tag_t caret_pos; 74 76 77 /** Start of selection */ 78 tag_t sel_start; 79 75 80 /** 76 81 * Ideal column where the caret should try to get. This is used … … 101 106 #define ED_INFTY 65536 102 107 108 /** Maximum filename length that can be entered. */ 109 #define INFNAME_MAX_LEN 128 110 103 111 static void key_handle_unmod(console_event_t const *ev); 104 112 static void key_handle_ctrl(console_event_t const *ev); 113 static void key_handle_shift(console_event_t const *ev); 114 static void key_handle_movement(unsigned int key, bool shift); 115 105 116 static int file_save(char const *fname); 117 static void file_save_as(void); 106 118 static int file_insert(char *fname); 107 119 static int file_save_range(char const *fname, spt_t const *spos, 108 120 spt_t const *epos); 121 static char *filename_prompt(char const *prompt, char const *init_value); 122 static char *range_get_str(spt_t const *spos, spt_t const *epos); 123 109 124 static void pane_text_display(void); 110 125 static void pane_row_display(void); … … 112 127 static void pane_status_display(void); 113 128 static void pane_caret_display(void); 129 114 130 static void insert_char(wchar_t c); 115 131 static void delete_char_before(void); … … 117 133 static void caret_update(void); 118 134 static void caret_move(int drow, int dcolumn, enum dir_spec align_dir); 135 136 static bool selection_active(void); 137 static void selection_sel_all(void); 138 static void selection_get_points(spt_t *pa, spt_t *pb); 139 static void selection_delete(void); 140 static void selection_copy(void); 141 static void insert_clipboard_data(void); 142 119 143 static void pt_get_sof(spt_t *pt); 120 144 static void pt_get_eof(spt_t *pt); 145 static int tag_cmp(tag_t const *a, tag_t const *b); 146 static int spt_cmp(spt_t const *a, spt_t const *b); 147 static int coord_cmp(coord_t const *a, coord_t const *b); 148 121 149 static void status_display(char const *str); 122 150 … … 150 178 151 179 if (argc == 2) { 152 doc.file_name = argv[1];180 doc.file_name = str_dup(argv[1]); 153 181 } else if (argc > 1) { 154 182 printf("Invalid arguments.\n"); 155 183 return -2; 156 184 } else { 157 doc.file_name = "/edit.txt";185 doc.file_name = NULL; 158 186 } 159 187 160 188 new_file = false; 161 189 162 if ( file_insert(doc.file_name) != EOK)190 if (doc.file_name == NULL || file_insert(doc.file_name) != EOK) 163 191 new_file = true; 164 192 165 193 /* Move to beginning of file. */ 166 194 caret_move(-ED_INFTY, -ED_INFTY, dir_before); 195 196 /* Place selection start tag. */ 197 tag_get_pt(&pane.caret_pos, &pt); 198 sheet_place_tag(&doc.sh, &pt, &pane.sel_start); 167 199 168 200 /* Initial display */ … … 170 202 pane_text_display(); 171 203 pane_status_display(); 172 if (new_file )173 status_display("File not found. Createdempty file.");204 if (new_file && doc.file_name != NULL) 205 status_display("File not found. Starting empty file."); 174 206 pane_caret_display(); 175 207 … … 184 216 /* Handle key press. */ 185 217 if (((ev.mods & KM_ALT) == 0) && 218 ((ev.mods & KM_SHIFT) == 0) && 186 219 (ev.mods & KM_CTRL) != 0) { 187 220 key_handle_ctrl(&ev); 188 } else if ((ev.mods & (KM_CTRL | KM_ALT)) == 0) { 221 } else if (((ev.mods & KM_ALT) == 0) && 222 ((ev.mods & KM_CTRL) == 0) && 223 (ev.mods & KM_SHIFT) != 0) { 224 key_handle_shift(&ev); 225 } else if ((ev.mods & (KM_CTRL | KM_ALT | KM_SHIFT)) == 0) { 189 226 key_handle_unmod(&ev); 190 227 } … … 201 238 if (pane.rflags & REDRAW_CARET) 202 239 pane_caret_display(); 203 204 240 } 205 241 … … 214 250 switch (ev->key) { 215 251 case KC_ENTER: 252 selection_delete(); 216 253 insert_char('\n'); 217 254 caret_update(); 218 255 break; 219 256 case KC_LEFT: 220 caret_move(0, -1, dir_before);221 break;222 257 case KC_RIGHT: 223 caret_move(0, 0, dir_after);224 break;225 258 case KC_UP: 226 caret_move(-1, 0, dir_before);227 break;228 259 case KC_DOWN: 229 caret_move(+1, 0, dir_before);230 break;231 260 case KC_HOME: 232 caret_move(0, -ED_INFTY, dir_before);233 break;234 261 case KC_END: 235 caret_move(0, +ED_INFTY, dir_before);236 break;237 262 case KC_PAGE_UP: 238 caret_move(-pane.rows, 0, dir_before);239 break;240 263 case KC_PAGE_DOWN: 241 caret_move(+pane.rows, 0, dir_before);264 key_handle_movement(ev->key, false); 242 265 break; 243 266 case KC_BACKSPACE: 244 delete_char_before(); 267 if (selection_active()) 268 selection_delete(); 269 else 270 delete_char_before(); 245 271 caret_update(); 246 272 break; 247 273 case KC_DELETE: 248 delete_char_after(); 274 if (selection_active()) 275 selection_delete(); 276 else 277 delete_char_after(); 249 278 caret_update(); 250 279 break; 251 280 default: 252 281 if (ev->c >= 32 || ev->c == '\t') { 282 selection_delete(); 253 283 insert_char(ev->c); 254 284 caret_update(); … … 258 288 } 259 289 290 /** Handle Shift-key combination. */ 291 static void key_handle_shift(console_event_t const *ev) 292 { 293 switch (ev->key) { 294 case KC_LEFT: 295 case KC_RIGHT: 296 case KC_UP: 297 case KC_DOWN: 298 case KC_HOME: 299 case KC_END: 300 case KC_PAGE_UP: 301 case KC_PAGE_DOWN: 302 key_handle_movement(ev->key, true); 303 break; 304 default: 305 if (ev->c >= 32 || ev->c == '\t') { 306 selection_delete(); 307 insert_char(ev->c); 308 caret_update(); 309 } 310 break; 311 } 312 } 313 260 314 /** Handle Ctrl-key combination. */ 261 315 static void key_handle_ctrl(console_event_t const *ev) … … 266 320 break; 267 321 case KC_S: 268 (void) file_save(doc.file_name); 322 if (doc.file_name != NULL) 323 file_save(doc.file_name); 324 else 325 file_save_as(); 326 break; 327 case KC_E: 328 file_save_as(); 329 break; 330 case KC_C: 331 selection_copy(); 332 break; 333 case KC_V: 334 selection_delete(); 335 insert_clipboard_data(); 336 pane.rflags |= REDRAW_TEXT; 337 caret_update(); 338 break; 339 case KC_X: 340 selection_copy(); 341 selection_delete(); 342 pane.rflags |= REDRAW_TEXT; 343 caret_update(); 344 break; 345 case KC_A: 346 selection_sel_all(); 269 347 break; 270 348 default: … … 273 351 } 274 352 353 static void key_handle_movement(unsigned int key, bool select) 354 { 355 spt_t pt; 356 spt_t caret_pt; 357 coord_t c_old, c_new; 358 bool had_sel; 359 360 /* Check if we had selection before. */ 361 tag_get_pt(&pane.caret_pos, &caret_pt); 362 tag_get_pt(&pane.sel_start, &pt); 363 had_sel = !spt_equal(&caret_pt, &pt); 364 365 switch (key) { 366 case KC_LEFT: 367 caret_move(0, -1, dir_before); 368 break; 369 case KC_RIGHT: 370 caret_move(0, 0, dir_after); 371 break; 372 case KC_UP: 373 caret_move(-1, 0, dir_before); 374 break; 375 case KC_DOWN: 376 caret_move(+1, 0, dir_before); 377 break; 378 case KC_HOME: 379 caret_move(0, -ED_INFTY, dir_before); 380 break; 381 case KC_END: 382 caret_move(0, +ED_INFTY, dir_before); 383 break; 384 case KC_PAGE_UP: 385 caret_move(-pane.rows, 0, dir_before); 386 break; 387 case KC_PAGE_DOWN: 388 caret_move(+pane.rows, 0, dir_before); 389 break; 390 default: 391 break; 392 } 393 394 if (select == false) { 395 /* Move sel_start to the same point as caret. */ 396 sheet_remove_tag(&doc.sh, &pane.sel_start); 397 tag_get_pt(&pane.caret_pos, &pt); 398 sheet_place_tag(&doc.sh, &pt, &pane.sel_start); 399 } 400 401 if (select) { 402 tag_get_pt(&pane.caret_pos, &pt); 403 spt_get_coord(&caret_pt, &c_old); 404 spt_get_coord(&pt, &c_new); 405 406 if (c_old.row == c_new.row) 407 pane.rflags |= REDRAW_ROW; 408 else 409 pane.rflags |= REDRAW_TEXT; 410 411 } else if (had_sel == true) { 412 /* Redraw because text was unselected. */ 413 pane.rflags |= REDRAW_TEXT; 414 } 415 } 275 416 276 417 /** Save the document. */ … … 285 426 286 427 rc = file_save_range(fname, &sp, &ep); 287 status_display("File saved."); 428 429 switch (rc) { 430 case EINVAL: 431 status_display("Error opening file!"); 432 break; 433 case EIO: 434 status_display("Error writing data!"); 435 break; 436 default: 437 status_display("File saved."); 438 break; 439 } 288 440 289 441 return rc; 442 } 443 444 /** Change document name and save. */ 445 static void file_save_as(void) 446 { 447 char *old_fname, *fname; 448 int rc; 449 450 old_fname = (doc.file_name != NULL) ? doc.file_name : ""; 451 fname = filename_prompt("Save As", old_fname); 452 if (fname == NULL) { 453 status_display("Save cancelled."); 454 return; 455 } 456 457 rc = file_save(fname); 458 if (rc != EOK) 459 return; 460 461 if (doc.file_name != NULL) 462 free(doc.file_name); 463 doc.file_name = fname; 464 } 465 466 /** Ask for a file name. */ 467 static char *filename_prompt(char const *prompt, char const *init_value) 468 { 469 console_event_t ev; 470 char *str; 471 wchar_t buffer[INFNAME_MAX_LEN + 1]; 472 int max_len; 473 int nc; 474 bool done; 475 476 asprintf(&str, "%s: %s", prompt, init_value); 477 status_display(str); 478 console_goto(con, 1 + str_length(str), scr_rows - 1); 479 free(str); 480 481 console_set_color(con, COLOR_WHITE, COLOR_BLACK, 0); 482 483 max_len = min(INFNAME_MAX_LEN, scr_columns - 4 - str_length(prompt)); 484 str_to_wstr(buffer, max_len + 1, init_value); 485 nc = wstr_length(buffer); 486 done = false; 487 488 while (!done) { 489 console_get_event(con, &ev); 490 491 if (ev.type == KEY_PRESS) { 492 /* Handle key press. */ 493 if (((ev.mods & KM_ALT) == 0) && 494 (ev.mods & KM_CTRL) != 0) { 495 ; 496 } else if ((ev.mods & (KM_CTRL | KM_ALT)) == 0) { 497 switch (ev.key) { 498 case KC_ESCAPE: 499 return NULL; 500 case KC_BACKSPACE: 501 if (nc > 0) { 502 putchar('\b'); 503 fflush(stdout); 504 --nc; 505 } 506 break; 507 case KC_ENTER: 508 done = true; 509 break; 510 default: 511 if (ev.c >= 32 && nc < max_len) { 512 putchar(ev.c); 513 fflush(stdout); 514 buffer[nc++] = ev.c; 515 } 516 break; 517 } 518 } 519 } 520 } 521 522 buffer[nc] = '\0'; 523 str = wstr_to_astr(buffer); 524 525 console_set_color(con, COLOR_BLACK, COLOR_WHITE, 0); 526 527 return str; 290 528 } 291 529 … … 359 597 } while (!spt_equal(&bep, epos)); 360 598 361 fclose(f); 599 if (fclose(f) != EOK) 600 return EIO; 362 601 363 602 return EOK; 603 } 604 605 /** Return contents of range as a new string. */ 606 static char *range_get_str(spt_t const *spos, spt_t const *epos) 607 { 608 char *buf; 609 spt_t sp, bep; 610 size_t bytes; 611 size_t buf_size, bpos; 612 613 buf_size = 1; 614 615 buf = malloc(buf_size); 616 if (buf == NULL) 617 return NULL; 618 619 bpos = 0; 620 sp = *spos; 621 622 while (true) { 623 sheet_copy_out(&doc.sh, &sp, epos, &buf[bpos], buf_size - bpos, 624 &bep); 625 bytes = str_size(&buf[bpos]); 626 bpos += bytes; 627 sp = bep; 628 629 if (spt_equal(&bep, epos)) 630 break; 631 632 buf_size *= 2; 633 buf = realloc(buf, buf_size); 634 if (buf == NULL) 635 return NULL; 636 } 637 638 return buf; 364 639 } 365 640 … … 408 683 { 409 684 int i, j, fill; 410 spt_t rb, re, dep ;685 spt_t rb, re, dep, pt; 411 686 coord_t rbc, rec; 412 687 char row_buf[ROW_BUF_SIZE]; … … 414 689 size_t pos, size; 415 690 unsigned s_column; 691 coord_t csel_start, csel_end, ctmp; 692 693 /* Determine selection start and end. */ 694 695 tag_get_pt(&pane.sel_start, &pt); 696 spt_get_coord(&pt, &csel_start); 697 698 tag_get_pt(&pane.caret_pos, &pt); 699 spt_get_coord(&pt, &csel_end); 700 701 if (coord_cmp(&csel_start, &csel_end) > 0) { 702 ctmp = csel_start; 703 csel_start = csel_end; 704 csel_end = ctmp; 705 } 416 706 417 707 /* Draw rows from the sheet. */ … … 434 724 /* Display text from the buffer. */ 435 725 726 if (coord_cmp(&csel_start, &rbc) <= 0 && 727 coord_cmp(&rbc, &csel_end) < 0) { 728 fflush(stdout); 729 console_set_color(con, COLOR_BLACK, COLOR_RED, 0); 730 fflush(stdout); 731 } 732 436 733 console_goto(con, 0, i); 437 734 size = str_size(row_buf); 438 735 pos = 0; 439 s_column = 1;736 s_column = pane.sh_column; 440 737 while (pos < size) { 738 if (csel_start.row == rbc.row && csel_start.column == s_column) { 739 fflush(stdout); 740 console_set_color(con, COLOR_BLACK, COLOR_RED, 0); 741 fflush(stdout); 742 } 743 744 if (csel_end.row == rbc.row && csel_end.column == s_column) { 745 fflush(stdout); 746 console_set_color(con, COLOR_BLACK, COLOR_WHITE, 0); 747 fflush(stdout); 748 } 749 441 750 c = str_decode(row_buf, &pos, size); 442 751 if (c != '\t') { … … 453 762 } 454 763 764 if (csel_end.row == rbc.row && csel_end.column == s_column) { 765 fflush(stdout); 766 console_set_color(con, COLOR_BLACK, COLOR_WHITE, 0); 767 fflush(stdout); 768 } 769 455 770 /* Fill until the end of display area. */ 456 771 … … 463 778 putchar(' '); 464 779 fflush(stdout); 780 console_set_color(con, COLOR_BLACK, COLOR_WHITE, 0); 465 781 } 466 782 … … 473 789 spt_t caret_pt; 474 790 coord_t coord; 791 char *fname; 475 792 int n; 476 793 … … 478 795 spt_get_coord(&caret_pt, &coord); 479 796 797 fname = (doc.file_name != NULL) ? doc.file_name : "<unnamed>"; 798 480 799 console_goto(con, 0, scr_rows - 1); 481 800 console_set_color(con, COLOR_WHITE, COLOR_BLACK, 0); 482 n = printf(" %d, %d: File '%s'. Ctrl- S Save Ctrl-Q Quit",483 coord.row, coord.column, doc.file_name);801 n = printf(" %d, %d: File '%s'. Ctrl-Q Quit Ctrl-S Save " 802 "Ctrl-E Save As", coord.row, coord.column, fname); 484 803 printf("%*s", scr_columns - 1 - n, ""); 485 804 fflush(stdout); … … 648 967 } 649 968 969 /** Check for non-empty selection. */ 970 static bool selection_active(void) 971 { 972 return (tag_cmp(&pane.caret_pos, &pane.sel_start) != 0); 973 } 974 975 static void selection_get_points(spt_t *pa, spt_t *pb) 976 { 977 spt_t pt; 978 979 tag_get_pt(&pane.sel_start, pa); 980 tag_get_pt(&pane.caret_pos, pb); 981 982 if (spt_cmp(pa, pb) > 0) { 983 pt = *pa; 984 *pa = *pb; 985 *pb = pt; 986 } 987 } 988 989 /** Delete selected text. */ 990 static void selection_delete(void) 991 { 992 spt_t pa, pb; 993 coord_t ca, cb; 994 int rel; 995 996 tag_get_pt(&pane.sel_start, &pa); 997 tag_get_pt(&pane.caret_pos, &pb); 998 spt_get_coord(&pa, &ca); 999 spt_get_coord(&pb, &cb); 1000 rel = coord_cmp(&ca, &cb); 1001 1002 if (rel == 0) 1003 return; 1004 1005 if (rel < 0) 1006 sheet_delete(&doc.sh, &pa, &pb); 1007 else 1008 sheet_delete(&doc.sh, &pb, &pa); 1009 1010 if (ca.row == cb.row) 1011 pane.rflags |= REDRAW_ROW; 1012 else 1013 pane.rflags |= REDRAW_TEXT; 1014 } 1015 1016 static void selection_sel_all(void) 1017 { 1018 spt_t spt, ept; 1019 1020 pt_get_sof(&spt); 1021 pt_get_eof(&ept); 1022 sheet_remove_tag(&doc.sh, &pane.sel_start); 1023 sheet_place_tag(&doc.sh, &spt, &pane.sel_start); 1024 sheet_remove_tag(&doc.sh, &pane.caret_pos); 1025 sheet_place_tag(&doc.sh, &ept, &pane.caret_pos); 1026 1027 pane.rflags |= REDRAW_TEXT; 1028 caret_update(); 1029 } 1030 1031 static void selection_copy(void) 1032 { 1033 spt_t pa, pb; 1034 char *str; 1035 1036 selection_get_points(&pa, &pb); 1037 str = range_get_str(&pa, &pb); 1038 if (str == NULL || clipboard_put_str(str) != EOK) { 1039 status_display("Copying to clipboard failed!"); 1040 } 1041 free(str); 1042 } 1043 1044 static void insert_clipboard_data(void) 1045 { 1046 char *str; 1047 size_t off; 1048 wchar_t c; 1049 int rc; 1050 1051 rc = clipboard_get_str(&str); 1052 if (rc != EOK || str == NULL) 1053 return; 1054 1055 off = 0; 1056 1057 while (true) { 1058 c = str_decode(str, &off, STR_NO_LIMIT); 1059 if (c == '\0') 1060 break; 1061 1062 insert_char(c); 1063 } 1064 1065 free(str); 1066 } 650 1067 651 1068 /** Get start-of-file s-point. */ … … 665 1082 666 1083 sheet_get_num_rows(&doc.sh, &num_rows); 667 coord.row = num_rows ;1084 coord.row = num_rows + 1; 668 1085 coord.column = 1; 669 1086 670 1087 sheet_get_cell_pt(&doc.sh, &coord, dir_after, pt); 1088 } 1089 1090 /** Compare tags. */ 1091 static int tag_cmp(tag_t const *a, tag_t const *b) 1092 { 1093 spt_t pa, pb; 1094 1095 tag_get_pt(a, &pa); 1096 tag_get_pt(b, &pb); 1097 1098 return spt_cmp(&pa, &pb); 1099 } 1100 1101 /** Compare s-points. */ 1102 static int spt_cmp(spt_t const *a, spt_t const *b) 1103 { 1104 coord_t ca, cb; 1105 1106 spt_get_coord(a, &ca); 1107 spt_get_coord(b, &cb); 1108 1109 return coord_cmp(&ca, &cb); 1110 } 1111 1112 /** Compare coordinats. */ 1113 static int coord_cmp(coord_t const *a, coord_t const *b) 1114 { 1115 if (a->row - b->row != 0) 1116 return a->row - b->row; 1117 1118 return a->column - b->column; 671 1119 } 672 1120
Note:
See TracChangeset
for help on using the changeset viewer.