Ignore:
File:
1 edited

Legend:

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

    r8190e63 r00413c5c  
    3636
    3737#include <stdio.h>
    38 #include <stdlib.h>
    3938#include <sys/types.h>
    4039#include <vfs/vfs.h>
     
    4544#include <align.h>
    4645#include <macros.h>
    47 #include <clipboard.h>
    4846#include <bool.h>
    4947
     
    7573        tag_t caret_pos;
    7674
    77         /** Start of selection */
    78         tag_t sel_start;
    79 
    8075        /**
    8176         * Ideal column where the caret should try to get. This is used
     
    9893static bool done;
    9994static pane_t pane;
    100 static bool cursor_visible;
    10195
    10296static int scr_rows, scr_columns;
     
    107101#define ED_INFTY 65536
    108102
    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 
    116103static void key_handle_unmod(console_event_t const *ev);
    117104static 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 
    121105static int file_save(char const *fname);
    122 static void file_save_as(void);
    123106static int file_insert(char *fname);
    124107static int file_save_range(char const *fname, spt_t const *spos,
    125108    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 
    129109static void pane_text_display(void);
    130110static void pane_row_display(void);
     
    132112static void pane_status_display(void);
    133113static void pane_caret_display(void);
    134 
    135114static void insert_char(wchar_t c);
    136115static void delete_char_before(void);
     
    138117static void caret_update(void);
    139118static 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 
    148119static void pt_get_sof(spt_t *pt);
    149120static 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 
    154121static void status_display(char const *str);
    155122
     
    183150
    184151        if (argc == 2) {
    185                 doc.file_name = str_dup(argv[1]);
     152                doc.file_name = argv[1];
    186153        } else if (argc > 1) {
    187154                printf("Invalid arguments.\n");
    188155                return -2;
    189156        } else {
    190                 doc.file_name = NULL;
     157                doc.file_name = "/edit.txt";
    191158        }
    192159
    193160        new_file = false;
    194161
    195         if (doc.file_name == NULL || file_insert(doc.file_name) != EOK)
     162        if (file_insert(doc.file_name) != EOK)
    196163                new_file = true;
    197164
     
    199166        caret_move(-ED_INFTY, -ED_INFTY, dir_before);
    200167
    201         /* Place selection start tag. */
    202         tag_get_pt(&pane.caret_pos, &pt);
    203         sheet_place_tag(&doc.sh, &pt, &pane.sel_start);
    204 
    205168        /* Initial display */
    206         cursor_visible = true;
    207 
    208         cursor_hide();
    209169        console_clear(con);
    210170        pane_text_display();
    211171        pane_status_display();
    212         if (new_file && doc.file_name != NULL)
    213                 status_display("File not found. Starting empty file.");
     172        if (new_file)
     173                status_display("File not found. Created empty file.");
    214174        pane_caret_display();
    215         cursor_show();
     175
    216176
    217177        done = false;
     
    224184                        /* Handle key press. */
    225185                        if (((ev.mods & KM_ALT) == 0) &&
    226                             ((ev.mods & KM_SHIFT) == 0) &&
    227186                             (ev.mods & KM_CTRL) != 0) {
    228187                                key_handle_ctrl(&ev);
    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) {
     188                        } else if ((ev.mods & (KM_CTRL | KM_ALT)) == 0) {
    234189                                key_handle_unmod(&ev);
    235190                        }
     
    237192
    238193                /* Redraw as necessary. */
    239 
    240                 cursor_hide();
    241194
    242195                if (pane.rflags & REDRAW_TEXT)
     
    248201                if (pane.rflags & REDRAW_CARET)
    249202                        pane_caret_display();
    250 
    251                 cursor_show();
     203                       
    252204        }
    253205
     
    255207
    256208        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         }
    275209}
    276210
     
    280214        switch (ev->key) {
    281215        case KC_ENTER:
    282                 selection_delete();
    283216                insert_char('\n');
    284217                caret_update();
    285218                break;
    286219        case KC_LEFT:
     220                caret_move(0, -1, dir_before);
     221                break;
    287222        case KC_RIGHT:
     223                caret_move(0, 0, dir_after);
     224                break;
    288225        case KC_UP:
     226                caret_move(-1, 0, dir_before);
     227                break;
    289228        case KC_DOWN:
     229                caret_move(+1, 0, dir_before);
     230                break;
    290231        case KC_HOME:
     232                caret_move(0, -ED_INFTY, dir_before);
     233                break;
    291234        case KC_END:
     235                caret_move(0, +ED_INFTY, dir_before);
     236                break;
    292237        case KC_PAGE_UP:
     238                caret_move(-pane.rows, 0, dir_before);
     239                break;
    293240        case KC_PAGE_DOWN:
    294                 key_handle_movement(ev->key, false);
     241                caret_move(+pane.rows, 0, dir_before);
    295242                break;
    296243        case KC_BACKSPACE:
    297                 if (selection_active())
    298                         selection_delete();
    299                 else
    300                         delete_char_before();
     244                delete_char_before();
    301245                caret_update();
    302246                break;
    303247        case KC_DELETE:
    304                 if (selection_active())
    305                         selection_delete();
    306                 else
    307                         delete_char_after();
     248                delete_char_after();
    308249                caret_update();
    309250                break;
    310251        default:
    311252                if (ev->c >= 32 || ev->c == '\t') {
    312                         selection_delete();
    313253                        insert_char(ev->c);
    314254                        caret_update();
     
    318258}
    319259
    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 
    344260/** Handle Ctrl-key combination. */
    345261static void key_handle_ctrl(console_event_t const *ev)
     
    350266                break;
    351267        case KC_S:
    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();
     268                (void) file_save(doc.file_name);
    377269                break;
    378270        default:
     
    381273}
    382274
    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 }
    446275
    447276/** Save the document. */
     
    456285
    457286        rc = file_save_range(fname, &sp, &ep);
    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         }
     287        status_display("File saved.");
    470288
    471289        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;
    558290}
    559291
     
    627359        } while (!spt_equal(&bep, epos));
    628360
    629         if (fclose(f) != EOK)
    630                 return EIO;
     361        fclose(f);
    631362
    632363        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;
    669364}
    670365
     
    713408{
    714409        int i, j, fill;
    715         spt_t rb, re, dep, pt;
     410        spt_t rb, re, dep;
    716411        coord_t rbc, rec;
    717412        char row_buf[ROW_BUF_SIZE];
     
    719414        size_t pos, size;
    720415        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         }
    736416
    737417        /* Draw rows from the sheet. */
     
    754434                /* Display text from the buffer. */
    755435
    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 
    763436                console_goto(con, 0, i);
    764437                size = str_size(row_buf);
    765438                pos = 0;
    766                 s_column = pane.sh_column;
     439                s_column = 1;
    767440                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        
    780441                        c = str_decode(row_buf, &pos, size);
    781442                        if (c != '\t') {
     
    792453                }
    793454
    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 
    800455                /* Fill until the end of display area. */
    801456
     
    808463                        putchar(' ');
    809464                fflush(stdout);
    810                 console_set_color(con, COLOR_BLACK, COLOR_WHITE, 0);
    811465        }
    812466
     
    819473        spt_t caret_pt;
    820474        coord_t coord;
    821         char *fname;
    822475        int n;
    823476
     
    825478        spt_get_coord(&caret_pt, &coord);
    826479
    827         fname = (doc.file_name != NULL) ? doc.file_name : "<unnamed>";
    828 
    829480        console_goto(con, 0, scr_rows - 1);
    830481        console_set_color(con, COLOR_WHITE, COLOR_BLACK, 0);
    831         n = printf(" %d, %d: File '%s'. Ctrl-Q Quit  Ctrl-S Save  "
    832             "Ctrl-E Save As", coord.row, coord.column, fname);
     482        n = printf(" %d, %d: File '%s'. Ctrl-S Save  Ctrl-Q Quit",
     483            coord.row, coord.column, doc.file_name);
    833484        printf("%*s", scr_columns - 1 - n, "");
    834485        fflush(stdout);
     
    997648}
    998649
    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 }
    1097650
    1098651/** Get start-of-file s-point. */
     
    1116669
    1117670        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;
    1149671}
    1150672
Note: See TracChangeset for help on using the changeset viewer.