Changeset 3b3e776 in mainline for uspace/app/edit/edit.c
- Timestamp:
- 2010-02-05T10:57:50Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 0358da0
- Parents:
- 3f085132 (diff), b4cbef1 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/edit/edit.c
r3f085132 r3b3e776 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 … … 93 98 static bool done; 94 99 static pane_t pane; 100 static bool cursor_visible; 95 101 96 102 static int scr_rows, scr_columns; … … 101 107 #define ED_INFTY 65536 102 108 109 /** Maximum filename length that can be entered. */ 110 #define INFNAME_MAX_LEN 128 111 112 static void cursor_show(void); 113 static void cursor_hide(void); 114 static void cursor_setvis(bool visible); 115 103 116 static void key_handle_unmod(console_event_t const *ev); 104 117 static void key_handle_ctrl(console_event_t const *ev); 118 static void key_handle_shift(console_event_t const *ev); 119 static void key_handle_movement(unsigned int key, bool shift); 120 105 121 static int file_save(char const *fname); 122 static void file_save_as(void); 106 123 static int file_insert(char *fname); 107 124 static int file_save_range(char const *fname, spt_t const *spos, 108 125 spt_t const *epos); 126 static char *filename_prompt(char const *prompt, char const *init_value); 127 static char *range_get_str(spt_t const *spos, spt_t const *epos); 128 109 129 static void pane_text_display(void); 110 130 static void pane_row_display(void); … … 112 132 static void pane_status_display(void); 113 133 static void pane_caret_display(void); 134 114 135 static void insert_char(wchar_t c); 115 136 static void delete_char_before(void); … … 117 138 static void caret_update(void); 118 139 static void caret_move(int drow, int dcolumn, enum dir_spec align_dir); 140 141 static bool selection_active(void); 142 static void selection_sel_all(void); 143 static void selection_get_points(spt_t *pa, spt_t *pb); 144 static void selection_delete(void); 145 static void selection_copy(void); 146 static void insert_clipboard_data(void); 147 119 148 static void pt_get_sof(spt_t *pt); 120 149 static void pt_get_eof(spt_t *pt); 150 static int tag_cmp(tag_t const *a, tag_t const *b); 151 static int spt_cmp(spt_t const *a, spt_t const *b); 152 static int coord_cmp(coord_t const *a, coord_t const *b); 153 121 154 static void status_display(char const *str); 122 155 … … 150 183 151 184 if (argc == 2) { 152 doc.file_name = argv[1];185 doc.file_name = str_dup(argv[1]); 153 186 } else if (argc > 1) { 154 187 printf("Invalid arguments.\n"); 155 188 return -2; 156 189 } else { 157 doc.file_name = "/edit.txt";190 doc.file_name = NULL; 158 191 } 159 192 160 193 new_file = false; 161 194 162 if ( file_insert(doc.file_name) != EOK)195 if (doc.file_name == NULL || file_insert(doc.file_name) != EOK) 163 196 new_file = true; 164 197 … … 166 199 caret_move(-ED_INFTY, -ED_INFTY, dir_before); 167 200 201 /* Place selection start tag. */ 202 tag_get_pt(&pane.caret_pos, &pt); 203 sheet_place_tag(&doc.sh, &pt, &pane.sel_start); 204 168 205 /* Initial display */ 206 cursor_visible = true; 207 208 cursor_hide(); 169 209 console_clear(con); 170 210 pane_text_display(); 171 211 pane_status_display(); 172 if (new_file )173 status_display("File not found. Createdempty file.");212 if (new_file && doc.file_name != NULL) 213 status_display("File not found. Starting empty file."); 174 214 pane_caret_display(); 175 215 cursor_show(); 176 216 177 217 done = false; … … 184 224 /* Handle key press. */ 185 225 if (((ev.mods & KM_ALT) == 0) && 226 ((ev.mods & KM_SHIFT) == 0) && 186 227 (ev.mods & KM_CTRL) != 0) { 187 228 key_handle_ctrl(&ev); 188 } else if ((ev.mods & (KM_CTRL | KM_ALT)) == 0) { 229 } else if (((ev.mods & KM_ALT) == 0) && 230 ((ev.mods & KM_CTRL) == 0) && 231 (ev.mods & KM_SHIFT) != 0) { 232 key_handle_shift(&ev); 233 } else if ((ev.mods & (KM_CTRL | KM_ALT | KM_SHIFT)) == 0) { 189 234 key_handle_unmod(&ev); 190 235 } … … 192 237 193 238 /* Redraw as necessary. */ 239 240 cursor_hide(); 194 241 195 242 if (pane.rflags & REDRAW_TEXT) … … 201 248 if (pane.rflags & REDRAW_CARET) 202 249 pane_caret_display(); 203 250 251 cursor_show(); 204 252 } 205 253 … … 207 255 208 256 return 0; 257 } 258 259 static void cursor_show(void) 260 { 261 cursor_setvis(true); 262 } 263 264 static void cursor_hide(void) 265 { 266 cursor_setvis(false); 267 } 268 269 static void cursor_setvis(bool visible) 270 { 271 if (cursor_visible != visible) { 272 console_cursor_visibility(con, visible); 273 cursor_visible = visible; 274 } 209 275 } 210 276 … … 214 280 switch (ev->key) { 215 281 case KC_ENTER: 282 selection_delete(); 216 283 insert_char('\n'); 217 284 caret_update(); 218 285 break; 219 286 case KC_LEFT: 220 caret_move(0, -1, dir_before);221 break;222 287 case KC_RIGHT: 223 caret_move(0, 0, dir_after);224 break;225 288 case KC_UP: 226 caret_move(-1, 0, dir_before);227 break;228 289 case KC_DOWN: 229 caret_move(+1, 0, dir_before);230 break;231 290 case KC_HOME: 232 caret_move(0, -ED_INFTY, dir_before);233 break;234 291 case KC_END: 235 caret_move(0, +ED_INFTY, dir_before);236 break;237 292 case KC_PAGE_UP: 238 caret_move(-pane.rows, 0, dir_before);239 break;240 293 case KC_PAGE_DOWN: 241 caret_move(+pane.rows, 0, dir_before);294 key_handle_movement(ev->key, false); 242 295 break; 243 296 case KC_BACKSPACE: 244 delete_char_before(); 297 if (selection_active()) 298 selection_delete(); 299 else 300 delete_char_before(); 245 301 caret_update(); 246 302 break; 247 303 case KC_DELETE: 248 delete_char_after(); 304 if (selection_active()) 305 selection_delete(); 306 else 307 delete_char_after(); 249 308 caret_update(); 250 309 break; 251 310 default: 252 311 if (ev->c >= 32 || ev->c == '\t') { 312 selection_delete(); 253 313 insert_char(ev->c); 254 314 caret_update(); … … 258 318 } 259 319 320 /** Handle Shift-key combination. */ 321 static void key_handle_shift(console_event_t const *ev) 322 { 323 switch (ev->key) { 324 case KC_LEFT: 325 case KC_RIGHT: 326 case KC_UP: 327 case KC_DOWN: 328 case KC_HOME: 329 case KC_END: 330 case KC_PAGE_UP: 331 case KC_PAGE_DOWN: 332 key_handle_movement(ev->key, true); 333 break; 334 default: 335 if (ev->c >= 32 || ev->c == '\t') { 336 selection_delete(); 337 insert_char(ev->c); 338 caret_update(); 339 } 340 break; 341 } 342 } 343 260 344 /** Handle Ctrl-key combination. */ 261 345 static void key_handle_ctrl(console_event_t const *ev) … … 266 350 break; 267 351 case KC_S: 268 (void) file_save(doc.file_name); 352 if (doc.file_name != NULL) 353 file_save(doc.file_name); 354 else 355 file_save_as(); 356 break; 357 case KC_E: 358 file_save_as(); 359 break; 360 case KC_C: 361 selection_copy(); 362 break; 363 case KC_V: 364 selection_delete(); 365 insert_clipboard_data(); 366 pane.rflags |= REDRAW_TEXT; 367 caret_update(); 368 break; 369 case KC_X: 370 selection_copy(); 371 selection_delete(); 372 pane.rflags |= REDRAW_TEXT; 373 caret_update(); 374 break; 375 case KC_A: 376 selection_sel_all(); 269 377 break; 270 378 default: … … 273 381 } 274 382 383 static void key_handle_movement(unsigned int key, bool select) 384 { 385 spt_t pt; 386 spt_t caret_pt; 387 coord_t c_old, c_new; 388 bool had_sel; 389 390 /* Check if we had selection before. */ 391 tag_get_pt(&pane.caret_pos, &caret_pt); 392 tag_get_pt(&pane.sel_start, &pt); 393 had_sel = !spt_equal(&caret_pt, &pt); 394 395 switch (key) { 396 case KC_LEFT: 397 caret_move(0, -1, dir_before); 398 break; 399 case KC_RIGHT: 400 caret_move(0, 0, dir_after); 401 break; 402 case KC_UP: 403 caret_move(-1, 0, dir_before); 404 break; 405 case KC_DOWN: 406 caret_move(+1, 0, dir_before); 407 break; 408 case KC_HOME: 409 caret_move(0, -ED_INFTY, dir_before); 410 break; 411 case KC_END: 412 caret_move(0, +ED_INFTY, dir_before); 413 break; 414 case KC_PAGE_UP: 415 caret_move(-pane.rows, 0, dir_before); 416 break; 417 case KC_PAGE_DOWN: 418 caret_move(+pane.rows, 0, dir_before); 419 break; 420 default: 421 break; 422 } 423 424 if (select == false) { 425 /* Move sel_start to the same point as caret. */ 426 sheet_remove_tag(&doc.sh, &pane.sel_start); 427 tag_get_pt(&pane.caret_pos, &pt); 428 sheet_place_tag(&doc.sh, &pt, &pane.sel_start); 429 } 430 431 if (select) { 432 tag_get_pt(&pane.caret_pos, &pt); 433 spt_get_coord(&caret_pt, &c_old); 434 spt_get_coord(&pt, &c_new); 435 436 if (c_old.row == c_new.row) 437 pane.rflags |= REDRAW_ROW; 438 else 439 pane.rflags |= REDRAW_TEXT; 440 441 } else if (had_sel == true) { 442 /* Redraw because text was unselected. */ 443 pane.rflags |= REDRAW_TEXT; 444 } 445 } 275 446 276 447 /** Save the document. */ … … 285 456 286 457 rc = file_save_range(fname, &sp, &ep); 287 status_display("File saved."); 458 459 switch (rc) { 460 case EINVAL: 461 status_display("Error opening file!"); 462 break; 463 case EIO: 464 status_display("Error writing data!"); 465 break; 466 default: 467 status_display("File saved."); 468 break; 469 } 288 470 289 471 return rc; 472 } 473 474 /** Change document name and save. */ 475 static void file_save_as(void) 476 { 477 char *old_fname, *fname; 478 int rc; 479 480 old_fname = (doc.file_name != NULL) ? doc.file_name : ""; 481 fname = filename_prompt("Save As", old_fname); 482 if (fname == NULL) { 483 status_display("Save cancelled."); 484 return; 485 } 486 487 rc = file_save(fname); 488 if (rc != EOK) 489 return; 490 491 if (doc.file_name != NULL) 492 free(doc.file_name); 493 doc.file_name = fname; 494 } 495 496 /** Ask for a file name. */ 497 static char *filename_prompt(char const *prompt, char const *init_value) 498 { 499 console_event_t ev; 500 char *str; 501 wchar_t buffer[INFNAME_MAX_LEN + 1]; 502 int max_len; 503 int nc; 504 bool done; 505 506 asprintf(&str, "%s: %s", prompt, init_value); 507 status_display(str); 508 console_goto(con, 1 + str_length(str), scr_rows - 1); 509 free(str); 510 511 console_set_color(con, COLOR_WHITE, COLOR_BLACK, 0); 512 513 max_len = min(INFNAME_MAX_LEN, scr_columns - 4 - str_length(prompt)); 514 str_to_wstr(buffer, max_len + 1, init_value); 515 nc = wstr_length(buffer); 516 done = false; 517 518 while (!done) { 519 console_get_event(con, &ev); 520 521 if (ev.type == KEY_PRESS) { 522 /* Handle key press. */ 523 if (((ev.mods & KM_ALT) == 0) && 524 (ev.mods & KM_CTRL) != 0) { 525 ; 526 } else if ((ev.mods & (KM_CTRL | KM_ALT)) == 0) { 527 switch (ev.key) { 528 case KC_ESCAPE: 529 return NULL; 530 case KC_BACKSPACE: 531 if (nc > 0) { 532 putchar('\b'); 533 fflush(stdout); 534 --nc; 535 } 536 break; 537 case KC_ENTER: 538 done = true; 539 break; 540 default: 541 if (ev.c >= 32 && nc < max_len) { 542 putchar(ev.c); 543 fflush(stdout); 544 buffer[nc++] = ev.c; 545 } 546 break; 547 } 548 } 549 } 550 } 551 552 buffer[nc] = '\0'; 553 str = wstr_to_astr(buffer); 554 555 console_set_color(con, COLOR_BLACK, COLOR_WHITE, 0); 556 557 return str; 290 558 } 291 559 … … 359 627 } while (!spt_equal(&bep, epos)); 360 628 361 fclose(f); 629 if (fclose(f) != EOK) 630 return EIO; 362 631 363 632 return EOK; 633 } 634 635 /** Return contents of range as a new string. */ 636 static char *range_get_str(spt_t const *spos, spt_t const *epos) 637 { 638 char *buf; 639 spt_t sp, bep; 640 size_t bytes; 641 size_t buf_size, bpos; 642 643 buf_size = 1; 644 645 buf = malloc(buf_size); 646 if (buf == NULL) 647 return NULL; 648 649 bpos = 0; 650 sp = *spos; 651 652 while (true) { 653 sheet_copy_out(&doc.sh, &sp, epos, &buf[bpos], buf_size - bpos, 654 &bep); 655 bytes = str_size(&buf[bpos]); 656 bpos += bytes; 657 sp = bep; 658 659 if (spt_equal(&bep, epos)) 660 break; 661 662 buf_size *= 2; 663 buf = realloc(buf, buf_size); 664 if (buf == NULL) 665 return NULL; 666 } 667 668 return buf; 364 669 } 365 670 … … 408 713 { 409 714 int i, j, fill; 410 spt_t rb, re, dep ;715 spt_t rb, re, dep, pt; 411 716 coord_t rbc, rec; 412 717 char row_buf[ROW_BUF_SIZE]; … … 414 719 size_t pos, size; 415 720 unsigned s_column; 721 coord_t csel_start, csel_end, ctmp; 722 723 /* Determine selection start and end. */ 724 725 tag_get_pt(&pane.sel_start, &pt); 726 spt_get_coord(&pt, &csel_start); 727 728 tag_get_pt(&pane.caret_pos, &pt); 729 spt_get_coord(&pt, &csel_end); 730 731 if (coord_cmp(&csel_start, &csel_end) > 0) { 732 ctmp = csel_start; 733 csel_start = csel_end; 734 csel_end = ctmp; 735 } 416 736 417 737 /* Draw rows from the sheet. */ … … 434 754 /* Display text from the buffer. */ 435 755 756 if (coord_cmp(&csel_start, &rbc) <= 0 && 757 coord_cmp(&rbc, &csel_end) < 0) { 758 fflush(stdout); 759 console_set_color(con, COLOR_BLACK, COLOR_RED, 0); 760 fflush(stdout); 761 } 762 436 763 console_goto(con, 0, i); 437 764 size = str_size(row_buf); 438 765 pos = 0; 439 s_column = 1;766 s_column = pane.sh_column; 440 767 while (pos < size) { 768 if (csel_start.row == rbc.row && csel_start.column == s_column) { 769 fflush(stdout); 770 console_set_color(con, COLOR_BLACK, COLOR_RED, 0); 771 fflush(stdout); 772 } 773 774 if (csel_end.row == rbc.row && csel_end.column == s_column) { 775 fflush(stdout); 776 console_set_color(con, COLOR_BLACK, COLOR_WHITE, 0); 777 fflush(stdout); 778 } 779 441 780 c = str_decode(row_buf, &pos, size); 442 781 if (c != '\t') { … … 453 792 } 454 793 794 if (csel_end.row == rbc.row && csel_end.column == s_column) { 795 fflush(stdout); 796 console_set_color(con, COLOR_BLACK, COLOR_WHITE, 0); 797 fflush(stdout); 798 } 799 455 800 /* Fill until the end of display area. */ 456 801 … … 463 808 putchar(' '); 464 809 fflush(stdout); 810 console_set_color(con, COLOR_BLACK, COLOR_WHITE, 0); 465 811 } 466 812 … … 473 819 spt_t caret_pt; 474 820 coord_t coord; 821 char *fname; 475 822 int n; 476 823 … … 478 825 spt_get_coord(&caret_pt, &coord); 479 826 827 fname = (doc.file_name != NULL) ? doc.file_name : "<unnamed>"; 828 480 829 console_goto(con, 0, scr_rows - 1); 481 830 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);831 n = printf(" %d, %d: File '%s'. Ctrl-Q Quit Ctrl-S Save " 832 "Ctrl-E Save As", coord.row, coord.column, fname); 484 833 printf("%*s", scr_columns - 1 - n, ""); 485 834 fflush(stdout); … … 648 997 } 649 998 999 /** Check for non-empty selection. */ 1000 static bool selection_active(void) 1001 { 1002 return (tag_cmp(&pane.caret_pos, &pane.sel_start) != 0); 1003 } 1004 1005 static void selection_get_points(spt_t *pa, spt_t *pb) 1006 { 1007 spt_t pt; 1008 1009 tag_get_pt(&pane.sel_start, pa); 1010 tag_get_pt(&pane.caret_pos, pb); 1011 1012 if (spt_cmp(pa, pb) > 0) { 1013 pt = *pa; 1014 *pa = *pb; 1015 *pb = pt; 1016 } 1017 } 1018 1019 /** Delete selected text. */ 1020 static void selection_delete(void) 1021 { 1022 spt_t pa, pb; 1023 coord_t ca, cb; 1024 int rel; 1025 1026 tag_get_pt(&pane.sel_start, &pa); 1027 tag_get_pt(&pane.caret_pos, &pb); 1028 spt_get_coord(&pa, &ca); 1029 spt_get_coord(&pb, &cb); 1030 rel = coord_cmp(&ca, &cb); 1031 1032 if (rel == 0) 1033 return; 1034 1035 if (rel < 0) 1036 sheet_delete(&doc.sh, &pa, &pb); 1037 else 1038 sheet_delete(&doc.sh, &pb, &pa); 1039 1040 if (ca.row == cb.row) 1041 pane.rflags |= REDRAW_ROW; 1042 else 1043 pane.rflags |= REDRAW_TEXT; 1044 } 1045 1046 static void selection_sel_all(void) 1047 { 1048 spt_t spt, ept; 1049 1050 pt_get_sof(&spt); 1051 pt_get_eof(&ept); 1052 sheet_remove_tag(&doc.sh, &pane.sel_start); 1053 sheet_place_tag(&doc.sh, &spt, &pane.sel_start); 1054 sheet_remove_tag(&doc.sh, &pane.caret_pos); 1055 sheet_place_tag(&doc.sh, &ept, &pane.caret_pos); 1056 1057 pane.rflags |= REDRAW_TEXT; 1058 caret_update(); 1059 } 1060 1061 static void selection_copy(void) 1062 { 1063 spt_t pa, pb; 1064 char *str; 1065 1066 selection_get_points(&pa, &pb); 1067 str = range_get_str(&pa, &pb); 1068 if (str == NULL || clipboard_put_str(str) != EOK) { 1069 status_display("Copying to clipboard failed!"); 1070 } 1071 free(str); 1072 } 1073 1074 static void insert_clipboard_data(void) 1075 { 1076 char *str; 1077 size_t off; 1078 wchar_t c; 1079 int rc; 1080 1081 rc = clipboard_get_str(&str); 1082 if (rc != EOK || str == NULL) 1083 return; 1084 1085 off = 0; 1086 1087 while (true) { 1088 c = str_decode(str, &off, STR_NO_LIMIT); 1089 if (c == '\0') 1090 break; 1091 1092 insert_char(c); 1093 } 1094 1095 free(str); 1096 } 650 1097 651 1098 /** Get start-of-file s-point. */ … … 669 1116 670 1117 sheet_get_cell_pt(&doc.sh, &coord, dir_after, pt); 1118 } 1119 1120 /** Compare tags. */ 1121 static int tag_cmp(tag_t const *a, tag_t const *b) 1122 { 1123 spt_t pa, pb; 1124 1125 tag_get_pt(a, &pa); 1126 tag_get_pt(b, &pb); 1127 1128 return spt_cmp(&pa, &pb); 1129 } 1130 1131 /** Compare s-points. */ 1132 static int spt_cmp(spt_t const *a, spt_t const *b) 1133 { 1134 coord_t ca, cb; 1135 1136 spt_get_coord(a, &ca); 1137 spt_get_coord(b, &cb); 1138 1139 return coord_cmp(&ca, &cb); 1140 } 1141 1142 /** Compare coordinats. */ 1143 static int coord_cmp(coord_t const *a, coord_t const *b) 1144 { 1145 if (a->row - b->row != 0) 1146 return a->row - b->row; 1147 1148 return a->column - b->column; 671 1149 } 672 1150
Note:
See TracChangeset
for help on using the changeset viewer.