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

Changeset 034bf0e in mainline


Ignore:
Timestamp:
2009-12-05T18:30:27Z (11 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
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).

Location:
uspace
Files:
2 added
4 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/bdsh/input.c

    r65c1778 r034bf0e  
    3636#include <io/keycode.h>
    3737#include <io/style.h>
     38#include <io/color.h>
    3839#include <vfs/vfs.h>
     40#include <clipboard.h>
     41#include <macros.h>
    3942#include <errno.h>
    4043#include <assert.h>
     
    5053#define HISTORY_LEN 10
    5154
     55/** Text input field. */
    5256typedef struct {
    53         wchar_t buffer[INPUT_MAX];
     57        /** Buffer holding text currently being edited */
     58        wchar_t buffer[INPUT_MAX + 1];
     59        /** Screen coordinates of the top-left corner of the text field */
    5460        int col0, row0;
     61        /** Screen dimensions */
    5562        int con_cols, con_rows;
     63        /** Number of characters in @c buffer */
    5664        int nc;
     65        /** Caret position within buffer */
    5766        int pos;
    58 
     67        /** Selection mark position within buffer */
     68        int sel_start;
     69
     70        /** History (dynamically allocated strings) */
    5971        char *history[1 + HISTORY_LEN];
     72        /** Number of entries in @c history, not counting [0] */
    6073        int hnum;
     74        /** Current position in history */
    6175        int hpos;
     76        /** Exit flag */
     77        bool done;
    6278} tinput_t;
    6379
     80/** Seek direction */
    6481typedef enum {
    6582        seek_backward = -1,
     
    7087
    7188static char *tinput_read(tinput_t *ti);
     89static void tinput_insert_string(tinput_t *ti, const char *str);
     90static void tinput_sel_get_bounds(tinput_t *ti, int *sa, int *sb);
     91static bool tinput_sel_active(tinput_t *ti);
     92static void tinput_sel_all(tinput_t *ti);
     93static void tinput_sel_delete(tinput_t *ti);
     94static void tinput_key_ctrl(tinput_t *ti, console_event_t *ev);
     95static void tinput_key_shift(tinput_t *ti, console_event_t *ev);
     96static void tinput_key_ctrl_shift(tinput_t *ti, console_event_t *ev);
     97static void tinput_key_unmod(tinput_t *ti, console_event_t *ev);
     98static void tinput_pre_seek(tinput_t *ti, bool shift_held);
     99static void tinput_post_seek(tinput_t *ti, bool shift_held);
    72100
    73101/* Tokenizes input from console, sees if the first word is a built-in, if so
     
    123151static void tinput_display_tail(tinput_t *ti, int start, int pad)
    124152{
    125         int i;
     153        static wchar_t dbuf[INPUT_MAX + 1];
     154        int sa, sb;
     155        int i, p;
     156
     157        tinput_sel_get_bounds(ti, &sa, &sb);
    126158
    127159        console_goto(fphone(stdout), (ti->col0 + start) % ti->con_cols,
    128160            ti->row0 + (ti->col0 + start) / ti->con_cols);
    129         printf("%ls", ti->buffer + start);
     161        console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0);
     162
     163        p = start;
     164        if (p < sa) {
     165                memcpy(dbuf, ti->buffer + p, (sa - p) * sizeof(wchar_t));
     166                dbuf[sa - p] = '\0';
     167                printf("%ls", dbuf);
     168                p = sa;
     169        }
     170
     171        if (p < sb) {
     172                fflush(stdout);
     173                console_set_color(fphone(stdout), COLOR_BLACK, COLOR_RED, 0);
     174                memcpy(dbuf, ti->buffer + p,
     175                    (sb - p) * sizeof(wchar_t));
     176                dbuf[sb - p] = '\0';
     177                printf("%ls", dbuf);
     178                p = sb;
     179        }
     180
     181        fflush(stdout);
     182        console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0);
     183
     184        if (p < ti->nc) {
     185                memcpy(dbuf, ti->buffer + p,
     186                    (ti->nc - p) * sizeof(wchar_t));
     187                dbuf[ti->nc - p] = '\0';
     188                printf("%ls", dbuf);
     189        }
     190
    130191        for (i = 0; i < pad; ++i)
    131192                putchar(' ');
     
    151212        width = ti->col0 + ti->nc;
    152213        rows = (width / ti->con_cols) + 1;
    153  
     214
    154215        /* Update row0 if the screen scrolled. */
    155216        if (ti->row0 + rows > ti->con_rows)
     
    180241        ti->nc += 1;
    181242        ti->buffer[ti->nc] = '\0';
     243        ti->sel_start = ti->pos;
    182244
    183245        tinput_display_tail(ti, ti->pos - 1, 0);
     
    186248}
    187249
     250static void tinput_insert_string(tinput_t *ti, const char *str)
     251{
     252        int i;
     253        int new_width, new_height;
     254        int ilen;
     255        wchar_t c;
     256        size_t off;
     257
     258        ilen = min((ssize_t) str_length(str), INPUT_MAX - ti->nc);
     259        if (ilen == 0)
     260                return;
     261
     262        new_width = ti->col0 + ti->nc + ilen;
     263        new_height = (new_width / ti->con_cols) + 1;
     264        if (new_height >= ti->con_rows)
     265                return; /* Disallow text longer than 1 page for now. */
     266
     267        for (i = ti->nc - 1; i >= ti->pos; --i)
     268                ti->buffer[i + ilen] = ti->buffer[i];
     269
     270        off = 0; i = 0;
     271        while (i < ilen) {
     272                c = str_decode(str, &off, STR_NO_LIMIT);
     273                if (c == '\0')
     274                        break;
     275
     276                /* Filter out non-printable chars. */
     277                if (c < 32)
     278                        c = 32;
     279
     280                ti->buffer[ti->pos + i] = c;
     281                ++i;
     282        }
     283
     284        ti->pos += ilen;
     285        ti->nc += ilen;
     286        ti->buffer[ti->nc] = '\0';
     287        ti->sel_start = ti->pos;
     288
     289        tinput_display_tail(ti, ti->pos - ilen, 0);
     290        tinput_update_origin(ti);
     291        tinput_position_caret(ti);
     292}
     293
    188294static void tinput_backspace(tinput_t *ti)
    189295{
    190296        int i;
     297
     298        if (tinput_sel_active(ti)) {
     299                tinput_sel_delete(ti);
     300                return;
     301        }
    191302
    192303        if (ti->pos == 0)
     
    198309        ti->nc -= 1;
    199310        ti->buffer[ti->nc] = '\0';
     311        ti->sel_start = ti->pos;
    200312
    201313        tinput_display_tail(ti, ti->pos, 1);
     
    205317static void tinput_delete(tinput_t *ti)
    206318{
     319        if (tinput_sel_active(ti)) {
     320                tinput_sel_delete(ti);
     321                return;
     322        }
     323
    207324        if (ti->pos == ti->nc)
    208325                return;
    209326
    210327        ti->pos += 1;
     328        ti->sel_start = ti->pos;
     329
    211330        tinput_backspace(ti);
    212331}
    213332
    214 static void tinput_seek_cell(tinput_t *ti, seek_dir_t dir)
    215 {
     333static void tinput_seek_cell(tinput_t *ti, seek_dir_t dir, bool shift_held)
     334{
     335        tinput_pre_seek(ti, shift_held);
     336
    216337        if (dir == seek_forward) {
    217338                if (ti->pos < ti->nc)
     
    222343        }
    223344
    224         tinput_position_caret(ti);
    225 }
    226 
    227 static void tinput_seek_word(tinput_t *ti, seek_dir_t dir)
    228 {
     345        tinput_post_seek(ti, shift_held);
     346}
     347
     348static void tinput_seek_word(tinput_t *ti, seek_dir_t dir, bool shift_held)
     349{
     350        tinput_pre_seek(ti, shift_held);
     351
    229352        if (dir == seek_forward) {
    230353                if (ti->pos == ti->nc)
     
    258381        }
    259382
    260         tinput_position_caret(ti);
    261 }
    262 
    263 static void tinput_seek_vertical(tinput_t *ti, seek_dir_t dir)
    264 {
     383        tinput_post_seek(ti, shift_held);
     384}
     385
     386static void tinput_seek_vertical(tinput_t *ti, seek_dir_t dir, bool shift_held)
     387{
     388        tinput_pre_seek(ti, shift_held);
     389
    265390        if (dir == seek_forward) {
    266391                if (ti->pos + ti->con_cols <= ti->nc)
     
    271396        }
    272397
    273         tinput_position_caret(ti);
    274 }
    275 
    276 static void tinput_seek_max(tinput_t *ti, seek_dir_t dir)
    277 {
     398        tinput_post_seek(ti, shift_held);
     399}
     400
     401static void tinput_seek_max(tinput_t *ti, seek_dir_t dir, bool shift_held)
     402{
     403        tinput_pre_seek(ti, shift_held);
     404
    278405        if (dir == seek_backward)
    279406                ti->pos = 0;
     
    281408                ti->pos = ti->nc;
    282409
     410        tinput_post_seek(ti, shift_held);
     411}
     412
     413static void tinput_pre_seek(tinput_t *ti, bool shift_held)
     414{
     415        if (tinput_sel_active(ti) && !shift_held) {
     416                /* Unselect and redraw. */
     417                ti->sel_start = ti->pos;
     418                tinput_display_tail(ti, 0, 0);
     419                tinput_position_caret(ti);
     420        }
     421}
     422
     423static void tinput_post_seek(tinput_t *ti, bool shift_held)
     424{
     425        if (shift_held) {
     426                /* Selecting text. Need redraw. */
     427                tinput_display_tail(ti, 0, 0);
     428        } else {
     429                /* Shift not held. Keep selection empty. */
     430                ti->sel_start = ti->pos;
     431        }
    283432        tinput_position_caret(ti);
    284433}
     
    311460        ti->nc = wstr_length(ti->buffer);
    312461        ti->pos = ti->nc;
     462        ti->sel_start = ti->pos;
     463}
     464
     465static void tinput_sel_get_bounds(tinput_t *ti, int *sa, int *sb)
     466{
     467        if (ti->sel_start < ti->pos) {
     468                *sa = ti->sel_start;
     469                *sb = ti->pos;
     470        } else {
     471                *sa = ti->pos;
     472                *sb = ti->sel_start;
     473        }
     474}
     475
     476static bool tinput_sel_active(tinput_t *ti)
     477{
     478        return ti->sel_start != ti->pos;
     479}
     480
     481static void tinput_sel_all(tinput_t *ti)
     482{
     483        ti->sel_start = 0;
     484        ti->pos = ti->nc;
     485        tinput_display_tail(ti, 0, 0);
     486        tinput_position_caret(ti);
     487}
     488
     489static void tinput_sel_delete(tinput_t *ti)
     490{
     491        int sa, sb;
     492
     493        tinput_sel_get_bounds(ti, &sa, &sb);
     494        if (sa == sb)
     495                return;
     496
     497        memmove(ti->buffer + sa, ti->buffer + sb,
     498            (ti->nc - sb) * sizeof(wchar_t));
     499        ti->pos = ti->sel_start = sa;
     500        ti->nc -= (sb - sa);
     501        ti->buffer[ti->nc] = '\0';
     502
     503        tinput_display_tail(ti, sa, sb - sa);
     504        tinput_position_caret(ti);
     505}
     506
     507static void tinput_sel_copy_to_cb(tinput_t *ti)
     508{
     509        int sa, sb;
     510        wchar_t tmp_c;
     511        char *str;
     512
     513        tinput_sel_get_bounds(ti, &sa, &sb);
     514
     515        if (sb < ti->nc) {
     516                tmp_c = ti->buffer[sb];
     517                ti->buffer[sb] = '\0';
     518        }
     519
     520        str = wstr_to_astr(ti->buffer + sa);
     521
     522        if (sb < ti->nc)
     523                ti->buffer[sb] = tmp_c;
     524
     525        if (str == NULL)
     526                goto error;
     527
     528        if (clipboard_put_str(str) != EOK)
     529                goto error;
     530
     531        free(str);
     532        return;
     533error:
     534        return;
     535        /* TODO: Give the user some warning. */
     536}
     537
     538static void tinput_paste_from_cb(tinput_t *ti)
     539{
     540        char *str;
     541        int rc;
     542
     543        rc = clipboard_get_str(&str);
     544        if (rc != EOK || str == NULL)
     545                return; /* TODO: Give the user some warning. */
     546
     547        tinput_insert_string(ti, str);
     548        free(str);
    313549}
    314550
     
    337573}
    338574
     575/** Initialize text input field.
     576 *
     577 * Must be called before using the field. It clears the history.
     578 */
    339579static void tinput_init(tinput_t *ti)
    340580{
     
    344584}
    345585
     586/** Read in one line of input. */
    346587static char *tinput_read(tinput_t *ti)
    347588{
     
    356597                return NULL;
    357598
    358         ti->pos = 0;
     599        ti->pos = ti->sel_start = 0;
    359600        ti->nc = 0;
    360601        ti->buffer[0] = '\0';
    361 
    362         while (true) {
     602        ti->done = false;
     603
     604        while (!ti->done) {
    363605                fflush(stdout);
    364606                if (!console_get_event(fphone(stdin), &ev))
    365607                        return NULL;
    366                
     608
    367609                if (ev.type != KEY_PRESS)
    368610                        continue;
     
    370612                if ((ev.mods & KM_CTRL) != 0 &&
    371613                    (ev.mods & (KM_ALT | KM_SHIFT)) == 0) {
    372                         switch (ev.key) {
    373                         case KC_LEFT:
    374                                 tinput_seek_word(ti, seek_backward);
    375                                 break;
    376                         case KC_RIGHT:
    377                                 tinput_seek_word(ti, seek_forward);
    378                                 break;
    379                         case KC_UP:
    380                                 tinput_seek_vertical(ti, seek_backward);
    381                                 break;
    382                         case KC_DOWN:
    383                                 tinput_seek_vertical(ti, seek_forward);
    384                                 break;
    385                         }
     614                        tinput_key_ctrl(ti, &ev);
    386615                }
    387616
     617                if ((ev.mods & KM_SHIFT) != 0 &&
     618                    (ev.mods & (KM_CTRL | KM_ALT)) == 0) {
     619                        tinput_key_shift(ti, &ev);
     620                }
     621
     622                if ((ev.mods & KM_CTRL) != 0 &&
     623                    (ev.mods & KM_SHIFT) != 0 &&
     624                    (ev.mods & KM_ALT) == 0) {
     625                        tinput_key_ctrl_shift(ti, &ev);
     626                }
     627
    388628                if ((ev.mods & (KM_CTRL | KM_ALT | KM_SHIFT)) == 0) {
    389                         switch (ev.key) {
    390                         case KC_ENTER:
    391                         case KC_NENTER:
    392                                 goto done;
    393                         case KC_BACKSPACE:
    394                                 tinput_backspace(ti);
    395                                 break;
    396                         case KC_DELETE:
    397                                 tinput_delete(ti);
    398                                 break;
    399                         case KC_LEFT:
    400                                 tinput_seek_cell(ti, seek_backward);
    401                                 break;
    402                         case KC_RIGHT:
    403                                 tinput_seek_cell(ti, seek_forward);
    404                                 break;
    405                         case KC_HOME:
    406                                 tinput_seek_max(ti, seek_backward);
    407                                 break;
    408                         case KC_END:
    409                                 tinput_seek_max(ti, seek_forward);
    410                                 break;
    411                         case KC_UP:
    412                                 tinput_history_seek(ti, +1);
    413                                 break;
    414                         case KC_DOWN:
    415                                 tinput_history_seek(ti, -1);
    416                                 break;
    417                         }
     629                        tinput_key_unmod(ti, &ev);
    418630                }
    419631
    420632                if (ev.c >= ' ') {
     633                        tinput_sel_delete(ti);
    421634                        tinput_insert_char(ti, ev.c);
    422635                }
    423636        }
    424637
    425 done:
    426638        ti->pos = ti->nc;
    427639        tinput_position_caret(ti);
     
    435647
    436648        return str;
     649}
     650
     651static void tinput_key_ctrl(tinput_t *ti, console_event_t *ev)
     652{
     653        switch (ev->key) {
     654        case KC_LEFT:
     655                tinput_seek_word(ti, seek_backward, false);
     656                break;
     657        case KC_RIGHT:
     658                tinput_seek_word(ti, seek_forward, false);
     659                break;
     660        case KC_UP:
     661                tinput_seek_vertical(ti, seek_backward, false);
     662                break;
     663        case KC_DOWN:
     664                tinput_seek_vertical(ti, seek_forward, false);
     665                break;
     666        case KC_X:
     667                tinput_sel_copy_to_cb(ti);
     668                tinput_sel_delete(ti);
     669                break;
     670        case KC_C:
     671                tinput_sel_copy_to_cb(ti);
     672                break;
     673        case KC_V:
     674                tinput_sel_delete(ti);
     675                tinput_paste_from_cb(ti);
     676                break;
     677        case KC_A:
     678                tinput_sel_all(ti);
     679                break;
     680        default:
     681                break;
     682        }
     683}
     684
     685static void tinput_key_ctrl_shift(tinput_t *ti, console_event_t *ev)
     686{
     687        switch (ev->key) {
     688        case KC_LEFT:
     689                tinput_seek_word(ti, seek_backward, true);
     690                break;
     691        case KC_RIGHT:
     692                tinput_seek_word(ti, seek_forward, true);
     693                break;
     694        case KC_UP:
     695                tinput_seek_vertical(ti, seek_backward, true);
     696                break;
     697        case KC_DOWN:
     698                tinput_seek_vertical(ti, seek_forward, true);
     699                break;
     700        default:
     701                break;
     702        }
     703}
     704
     705static void tinput_key_shift(tinput_t *ti, console_event_t *ev)
     706{
     707        switch (ev->key) {
     708        case KC_LEFT:
     709                tinput_seek_cell(ti, seek_backward, true);
     710                break;
     711        case KC_RIGHT:
     712                tinput_seek_cell(ti, seek_forward, true);
     713                break;
     714        case KC_UP:
     715                tinput_seek_vertical(ti, seek_backward, true);
     716                break;
     717        case KC_DOWN:
     718                tinput_seek_vertical(ti, seek_forward, true);
     719                break;
     720        case KC_HOME:
     721                tinput_seek_max(ti, seek_backward, true);
     722                break;
     723        case KC_END:
     724                tinput_seek_max(ti, seek_forward, true);
     725                break;
     726        default:
     727                break;
     728        }
     729}
     730
     731static void tinput_key_unmod(tinput_t *ti, console_event_t *ev)
     732{
     733        switch (ev->key) {
     734        case KC_ENTER:
     735        case KC_NENTER:
     736                ti->done = true;
     737                break;
     738        case KC_BACKSPACE:
     739                tinput_backspace(ti);
     740                break;
     741        case KC_DELETE:
     742                tinput_delete(ti);
     743                break;
     744        case KC_LEFT:
     745                tinput_seek_cell(ti, seek_backward, false);
     746                break;
     747        case KC_RIGHT:
     748                tinput_seek_cell(ti, seek_forward, false);
     749                break;
     750        case KC_HOME:
     751                tinput_seek_max(ti, seek_backward, false);
     752                break;
     753        case KC_END:
     754                tinput_seek_max(ti, seek_forward, false);
     755                break;
     756        case KC_UP:
     757                tinput_history_seek(ti, +1);
     758                break;
     759        case KC_DOWN:
     760                tinput_history_seek(ti, -1);
     761                break;
     762        default:
     763                break;
     764        }
    437765}
    438766
  • 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
  • uspace/lib/libc/Makefile.build

    r65c1778 r034bf0e  
    5050        generic/as.c \
    5151        generic/cap.c \
     52        generic/clipboard.c \
    5253        generic/devmap.c \
    5354        generic/event.c \
  • uspace/lib/libc/generic/io/io.c

    r65c1778 r034bf0e  
    494494       
    495495        if (chr_encode(c, buf, &sz, STR_BOUNDS(1)) == EOK) {
    496                 size_t wr = fwrite(buf, sz, 1, stream);
     496                size_t wr = fwrite(buf, 1, sz, stream);
    497497               
    498498                if (wr < sz)
Note: See TracChangeset for help on using the changeset viewer.