Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 034bf0e in mainline for uspace/app/edit/edit.c


Ignore:
Timestamp:
2009-12-05T18:30:27Z (12 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master
Children:
45d5f86
Parents:
65c1778 (diff), bc77bfa (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.
Message:

Merge project X (Copy and paste for text editor and CLI, clipboard).

File:
1 edited

Legend:

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

    r65c1778 r034bf0e  
    4545#include <align.h>
    4646#include <macros.h>
     47#include <clipboard.h>
    4748#include <bool.h>
    4849
     
    7475        tag_t caret_pos;
    7576
     77        /** Start of selection */
     78        tag_t sel_start;
     79
    7680        /**
    7781         * Ideal column where the caret should try to get. This is used
     
    107111static void key_handle_unmod(console_event_t const *ev);
    108112static void key_handle_ctrl(console_event_t const *ev);
     113static void key_handle_shift(console_event_t const *ev);
     114static void key_handle_movement(unsigned int key, bool shift);
     115
    109116static int file_save(char const *fname);
    110117static void file_save_as(void);
     
    113120    spt_t const *epos);
    114121static char *filename_prompt(char const *prompt, char const *init_value);
     122static char *range_get_str(spt_t const *spos, spt_t const *epos);
     123
    115124static void pane_text_display(void);
    116125static void pane_row_display(void);
     
    118127static void pane_status_display(void);
    119128static void pane_caret_display(void);
     129
    120130static void insert_char(wchar_t c);
    121131static void delete_char_before(void);
     
    123133static void caret_update(void);
    124134static void caret_move(int drow, int dcolumn, enum dir_spec align_dir);
     135
     136static bool selection_active(void);
     137static void selection_sel_all(void);
     138static void selection_get_points(spt_t *pa, spt_t *pb);
     139static void selection_delete(void);
     140static void selection_copy(void);
     141static void insert_clipboard_data(void);
     142
    125143static void pt_get_sof(spt_t *pt);
    126144static void pt_get_eof(spt_t *pt);
     145static int tag_cmp(tag_t const *a, tag_t const *b);
     146static int spt_cmp(spt_t const *a, spt_t const *b);
     147static int coord_cmp(coord_t const *a, coord_t const *b);
     148
    127149static void status_display(char const *str);
    128150
     
    172194        caret_move(-ED_INFTY, -ED_INFTY, dir_before);
    173195
     196        /* Place selection start tag. */
     197        tag_get_pt(&pane.caret_pos, &pt);
     198        sheet_place_tag(&doc.sh, &pt, &pane.sel_start);
     199
    174200        /* Initial display */
    175201        console_clear(con);
     
    190216                        /* Handle key press. */
    191217                        if (((ev.mods & KM_ALT) == 0) &&
     218                            ((ev.mods & KM_SHIFT) == 0) &&
    192219                             (ev.mods & KM_CTRL) != 0) {
    193220                                key_handle_ctrl(&ev);
    194                         } 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) {
    195226                                key_handle_unmod(&ev);
    196227                        }
     
    207238                if (pane.rflags & REDRAW_CARET)
    208239                        pane_caret_display();
    209                        
    210240        }
    211241
     
    220250        switch (ev->key) {
    221251        case KC_ENTER:
     252                selection_delete();
    222253                insert_char('\n');
    223254                caret_update();
    224255                break;
    225256        case KC_LEFT:
    226                 caret_move(0, -1, dir_before);
    227                 break;
    228257        case KC_RIGHT:
    229                 caret_move(0, 0, dir_after);
    230                 break;
    231258        case KC_UP:
    232                 caret_move(-1, 0, dir_before);
    233                 break;
    234259        case KC_DOWN:
    235                 caret_move(+1, 0, dir_before);
    236                 break;
    237260        case KC_HOME:
    238                 caret_move(0, -ED_INFTY, dir_before);
    239                 break;
    240261        case KC_END:
    241                 caret_move(0, +ED_INFTY, dir_before);
    242                 break;
    243262        case KC_PAGE_UP:
    244                 caret_move(-pane.rows, 0, dir_before);
    245                 break;
    246263        case KC_PAGE_DOWN:
    247                 caret_move(+pane.rows, 0, dir_before);
     264                key_handle_movement(ev->key, false);
    248265                break;
    249266        case KC_BACKSPACE:
    250                 delete_char_before();
     267                if (selection_active())
     268                        selection_delete();
     269                else
     270                        delete_char_before();
    251271                caret_update();
    252272                break;
    253273        case KC_DELETE:
    254                 delete_char_after();
     274                if (selection_active())
     275                        selection_delete();
     276                else
     277                        delete_char_after();
    255278                caret_update();
    256279                break;
    257280        default:
    258281                if (ev->c >= 32 || ev->c == '\t') {
     282                        selection_delete();
     283                        insert_char(ev->c);
     284                        caret_update();
     285                }
     286                break;
     287        }
     288}
     289
     290/** Handle Shift-key combination. */
     291static 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();
    259307                        insert_char(ev->c);
    260308                        caret_update();
     
    280328                file_save_as();
    281329                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();
     347                break;
    282348        default:
    283349                break;
     350        }
     351}
     352
     353static 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;
    284414        }
    285415}
     
    473603}
    474604
     605/** Return contents of range as a new string. */
     606static 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;
     639}
     640
    475641static void pane_text_display(void)
    476642{
     
    517683{
    518684        int i, j, fill;
    519         spt_t rb, re, dep;
     685        spt_t rb, re, dep, pt;
    520686        coord_t rbc, rec;
    521687        char row_buf[ROW_BUF_SIZE];
     
    523689        size_t pos, size;
    524690        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        }
    525706
    526707        /* Draw rows from the sheet. */
     
    543724                /* Display text from the buffer. */
    544725
     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
    545733                console_goto(con, 0, i);
    546734                size = str_size(row_buf);
     
    548736                s_column = 1;
    549737                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       
    550750                        c = str_decode(row_buf, &pos, size);
    551751                        if (c != '\t') {
     
    562762                }
    563763
     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
    564770                /* Fill until the end of display area. */
    565771
     
    572778                        putchar(' ');
    573779                fflush(stdout);
     780                console_set_color(con, COLOR_BLACK, COLOR_WHITE, 0);
    574781        }
    575782
     
    760967}
    761968
     969/** Check for non-empty selection. */
     970static bool selection_active(void)
     971{
     972        return (tag_cmp(&pane.caret_pos, &pane.sel_start) != 0);
     973}
     974
     975static 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. */
     990static 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
     1016static 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}
     1029
     1030static void selection_copy(void)
     1031{
     1032        spt_t pa, pb;
     1033        char *str;
     1034
     1035        selection_get_points(&pa, &pb);
     1036        str = range_get_str(&pa, &pb);
     1037        if (str == NULL || clipboard_put_str(str) != EOK) {
     1038                status_display("Copying to clipboard failed!");
     1039        }
     1040        free(str);
     1041}
     1042
     1043static void insert_clipboard_data(void)
     1044{
     1045        char *str;
     1046        size_t off;
     1047        wchar_t c;
     1048        int rc;
     1049
     1050        rc = clipboard_get_str(&str);
     1051        if (rc != EOK || str == NULL)
     1052                return;
     1053
     1054        off = 0;
     1055
     1056        while (true) {
     1057                c = str_decode(str, &off, STR_NO_LIMIT);
     1058                if (c == '\0')
     1059                        break;
     1060
     1061                insert_char(c);
     1062        }
     1063
     1064        free(str);
     1065}
    7621066
    7631067/** Get start-of-file s-point. */
     
    7811085
    7821086        sheet_get_cell_pt(&doc.sh, &coord, dir_after, pt);
     1087}
     1088
     1089/** Compare tags. */
     1090static int tag_cmp(tag_t const *a, tag_t const *b)
     1091{
     1092        spt_t pa, pb;
     1093
     1094        tag_get_pt(a, &pa);
     1095        tag_get_pt(b, &pb);
     1096
     1097        return spt_cmp(&pa, &pb);
     1098}
     1099
     1100/** Compare s-points. */
     1101static int spt_cmp(spt_t const *a, spt_t const *b)
     1102{
     1103        coord_t ca, cb;
     1104
     1105        spt_get_coord(a, &ca);
     1106        spt_get_coord(b, &cb);
     1107
     1108        return coord_cmp(&ca, &cb);
     1109}
     1110
     1111/** Compare coordinats. */
     1112static int coord_cmp(coord_t const *a, coord_t const *b)
     1113{
     1114        if (a->row - b->row != 0)
     1115                return a->row - b->row;
     1116
     1117        return a->column - b->column;
    7831118}
    7841119
Note: See TracChangeset for help on using the changeset viewer.