Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/clui/tinput.c

    r9f1362d4 r5db9084  
    4040#include <assert.h>
    4141#include <bool.h>
    42 #include <tinput.h>
     42
     43#include "tinput.h"
    4344
    4445/** Seek direction */
     
    4849} seek_dir_t;
    4950
    50 static void tinput_init(tinput_t *);
    51 static void tinput_insert_string(tinput_t *, const char *);
    52 static void tinput_sel_get_bounds(tinput_t *, size_t *, size_t *);
    53 static bool tinput_sel_active(tinput_t *);
    54 static void tinput_sel_all(tinput_t *);
    55 static void tinput_sel_delete(tinput_t *);
    56 static void tinput_key_ctrl(tinput_t *, console_event_t *);
    57 static void tinput_key_shift(tinput_t *, console_event_t *);
    58 static void tinput_key_ctrl_shift(tinput_t *, console_event_t *);
    59 static void tinput_key_unmod(tinput_t *, console_event_t *);
    60 static void tinput_pre_seek(tinput_t *, bool);
    61 static void tinput_post_seek(tinput_t *, bool);
     51static void tinput_init(tinput_t *ti);
     52static void tinput_insert_string(tinput_t *ti, const char *str);
     53static void tinput_sel_get_bounds(tinput_t *ti, int *sa, int *sb);
     54static bool tinput_sel_active(tinput_t *ti);
     55static void tinput_sel_all(tinput_t *ti);
     56static void tinput_sel_delete(tinput_t *ti);
     57static void tinput_key_ctrl(tinput_t *ti, console_event_t *ev);
     58static void tinput_key_shift(tinput_t *ti, console_event_t *ev);
     59static void tinput_key_ctrl_shift(tinput_t *ti, console_event_t *ev);
     60static void tinput_key_unmod(tinput_t *ti, console_event_t *ev);
     61static void tinput_pre_seek(tinput_t *ti, bool shift_held);
     62static void tinput_post_seek(tinput_t *ti, bool shift_held);
    6263
    6364/** Create a new text input field. */
     
    6566{
    6667        tinput_t *ti;
    67        
     68
    6869        ti = malloc(sizeof(tinput_t));
    6970        if (ti == NULL)
    7071                return NULL;
    71        
     72
    7273        tinput_init(ti);
    7374        return ti;
     
    8081}
    8182
    82 static void tinput_display_tail(tinput_t *ti, size_t start, size_t pad)
    83 {
    84         wchar_t dbuf[INPUT_MAX_SIZE + 1];
    85        
    86         size_t sa;
    87         size_t sb;
     83static void tinput_display_tail(tinput_t *ti, int start, int pad)
     84{
     85        static wchar_t dbuf[INPUT_MAX_SIZE + 1];
     86        int sa, sb;
     87        int i, p;
     88
    8889        tinput_sel_get_bounds(ti, &sa, &sb);
    89        
    90         console_set_pos(fphone(stdout), (ti->col0 + start) % ti->con_cols,
     90
     91        console_goto(fphone(stdout), (ti->col0 + start) % ti->con_cols,
    9192            ti->row0 + (ti->col0 + start) / ti->con_cols);
    92         console_set_style(fphone(stdout), STYLE_NORMAL);
    93        
    94         size_t p = start;
     93        console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0);
     94
     95        p = start;
    9596        if (p < sa) {
    9697                memcpy(dbuf, ti->buffer + p, (sa - p) * sizeof(wchar_t));
     
    99100                p = sa;
    100101        }
    101        
     102
    102103        if (p < sb) {
    103104                fflush(stdout);
    104                 console_set_style(fphone(stdout), STYLE_SELECTED);
     105                console_set_color(fphone(stdout), COLOR_BLACK, COLOR_RED, 0);
    105106                memcpy(dbuf, ti->buffer + p,
    106107                    (sb - p) * sizeof(wchar_t));
     
    109110                p = sb;
    110111        }
    111        
     112
    112113        fflush(stdout);
    113         console_set_style(fphone(stdout), STYLE_NORMAL);
    114        
     114        console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0);
     115
    115116        if (p < ti->nc) {
    116117                memcpy(dbuf, ti->buffer + p,
     
    119120                printf("%ls", dbuf);
    120121        }
    121        
    122         for (p = 0; p < pad; p++)
     122
     123        for (i = 0; i < pad; ++i)
    123124                putchar(' ');
    124        
    125125        fflush(stdout);
    126126}
     
    133133static void tinput_position_caret(tinput_t *ti)
    134134{
    135         console_set_pos(fphone(stdout), (ti->col0 + ti->pos) % ti->con_cols,
     135        console_goto(fphone(stdout), (ti->col0 + ti->pos) % ti->con_cols,
    136136            ti->row0 + (ti->col0 + ti->pos) / ti->con_cols);
    137137}
     
    140140static void tinput_update_origin(tinput_t *ti)
    141141{
    142         ipcarg_t width = ti->col0 + ti->nc;
    143         ipcarg_t rows = (width / ti->con_cols) + 1;
    144        
     142        int width, rows;
     143
     144        width = ti->col0 + ti->nc;
     145        rows = (width / ti->con_cols) + 1;
     146
    145147        /* Update row0 if the screen scrolled. */
    146148        if (ti->row0 + rows > ti->con_rows)
    147                 ti->row0 = ti->con_rows - rows;
     149                ti->row0 = ti->con_rows - rows; 
    148150}
    149151
    150152static void tinput_insert_char(tinput_t *ti, wchar_t c)
    151153{
     154        int i;
     155        int new_width, new_height;
     156
    152157        if (ti->nc == INPUT_MAX_SIZE)
    153158                return;
    154        
    155         ipcarg_t new_width = ti->col0 + ti->nc + 1;
     159
     160        new_width = ti->col0 + ti->nc + 1;
    156161        if (new_width % ti->con_cols == 0) {
    157162                /* Advancing to new line. */
    158                 ipcarg_t new_height = (new_width / ti->con_cols) + 1;
    159                 if (new_height >= ti->con_rows) {
    160                         /* Disallow text longer than 1 page for now. */
    161                         return;
    162                 }
    163         }
    164        
    165         size_t i;
    166         for (i = ti->nc; i > ti->pos; i--)
     163                new_height = (new_width / ti->con_cols) + 1;
     164                if (new_height >= ti->con_rows)
     165                        return; /* Disallow text longer than 1 page for now. */
     166        }
     167
     168        for (i = ti->nc; i > ti->pos; --i)
    167169                ti->buffer[i] = ti->buffer[i - 1];
    168        
     170
    169171        ti->buffer[ti->pos] = c;
    170172        ti->pos += 1;
     
    172174        ti->buffer[ti->nc] = '\0';
    173175        ti->sel_start = ti->pos;
    174        
     176
    175177        tinput_display_tail(ti, ti->pos - 1, 0);
    176178        tinput_update_origin(ti);
     
    180182static void tinput_insert_string(tinput_t *ti, const char *str)
    181183{
    182         size_t ilen = min(str_length(str), INPUT_MAX_SIZE - ti->nc);
     184        int i;
     185        int new_width, new_height;
     186        int ilen;
     187        wchar_t c;
     188        size_t off;
     189
     190        ilen = min((ssize_t) str_length(str), INPUT_MAX_SIZE - ti->nc);
    183191        if (ilen == 0)
    184192                return;
    185        
    186         ipcarg_t new_width = ti->col0 + ti->nc + ilen;
    187         ipcarg_t new_height = (new_width / ti->con_cols) + 1;
    188         if (new_height >= ti->con_rows) {
    189                 /* Disallow text longer than 1 page for now. */
    190                 return;
    191         }
    192        
    193         if (ti->nc > 0) {
    194                 size_t i;
    195                 for (i = ti->nc; i > ti->pos; i--)
    196                         ti->buffer[i + ilen - 1] = ti->buffer[i - 1];
    197         }
    198        
    199         size_t off = 0;
    200         size_t i = 0;
     193
     194        new_width = ti->col0 + ti->nc + ilen;
     195        new_height = (new_width / ti->con_cols) + 1;
     196        if (new_height >= ti->con_rows)
     197                return; /* Disallow text longer than 1 page for now. */
     198
     199        for (i = ti->nc - 1; i >= ti->pos; --i)
     200                ti->buffer[i + ilen] = ti->buffer[i];
     201
     202        off = 0; i = 0;
    201203        while (i < ilen) {
    202                 wchar_t c = str_decode(str, &off, STR_NO_LIMIT);
     204                c = str_decode(str, &off, STR_NO_LIMIT);
    203205                if (c == '\0')
    204206                        break;
    205                
     207
    206208                /* Filter out non-printable chars. */
    207209                if (c < 32)
    208210                        c = 32;
    209                
     211
    210212                ti->buffer[ti->pos + i] = c;
    211                 i++;
    212         }
    213        
     213                ++i;
     214        }
     215
    214216        ti->pos += ilen;
    215217        ti->nc += ilen;
    216218        ti->buffer[ti->nc] = '\0';
    217219        ti->sel_start = ti->pos;
    218        
     220
    219221        tinput_display_tail(ti, ti->pos - ilen, 0);
    220222        tinput_update_origin(ti);
     
    224226static void tinput_backspace(tinput_t *ti)
    225227{
     228        int i;
     229
    226230        if (tinput_sel_active(ti)) {
    227231                tinput_sel_delete(ti);
    228232                return;
    229233        }
    230        
     234
    231235        if (ti->pos == 0)
    232236                return;
    233        
    234         size_t i;
    235         for (i = ti->pos; i < ti->nc; i++)
     237
     238        for (i = ti->pos; i < ti->nc; ++i)
    236239                ti->buffer[i - 1] = ti->buffer[i];
    237        
    238240        ti->pos -= 1;
    239241        ti->nc -= 1;
    240242        ti->buffer[ti->nc] = '\0';
    241243        ti->sel_start = ti->pos;
    242        
     244
    243245        tinput_display_tail(ti, ti->pos, 1);
    244246        tinput_position_caret(ti);
     
    251253                return;
    252254        }
    253        
     255
    254256        if (ti->pos == ti->nc)
    255257                return;
    256        
     258
    257259        ti->pos += 1;
    258260        ti->sel_start = ti->pos;
    259        
     261
    260262        tinput_backspace(ti);
    261263}
     
    264266{
    265267        tinput_pre_seek(ti, shift_held);
    266        
     268
    267269        if (dir == seek_forward) {
    268270                if (ti->pos < ti->nc)
     
    272274                        ti->pos -= 1;
    273275        }
    274        
     276
    275277        tinput_post_seek(ti, shift_held);
    276278}
     
    279281{
    280282        tinput_pre_seek(ti, shift_held);
    281        
     283
    282284        if (dir == seek_forward) {
    283285                if (ti->pos == ti->nc)
    284286                        return;
    285                
    286                 while (true) {
     287
     288                while (1) {
    287289                        ti->pos += 1;
    288                        
     290
    289291                        if (ti->pos == ti->nc)
    290292                                break;
    291                        
    292                         if ((ti->buffer[ti->pos - 1] == ' ') &&
    293                             (ti->buffer[ti->pos] != ' '))
     293
     294                        if (ti->buffer[ti->pos - 1] == ' ' &&
     295                            ti->buffer[ti->pos] != ' ')
    294296                                break;
    295297                }
     
    297299                if (ti->pos == 0)
    298300                        return;
    299                
    300                 while (true) {
     301
     302                while (1) {
    301303                        ti->pos -= 1;
    302                        
     304
    303305                        if (ti->pos == 0)
    304306                                break;
    305                        
     307
    306308                        if (ti->buffer[ti->pos - 1] == ' ' &&
    307309                            ti->buffer[ti->pos] != ' ')
    308310                                break;
    309311                }
    310        
    311         }
    312        
     312
     313        }
     314
    313315        tinput_post_seek(ti, shift_held);
    314316}
     
    317319{
    318320        tinput_pre_seek(ti, shift_held);
    319        
     321
    320322        if (dir == seek_forward) {
    321323                if (ti->pos + ti->con_cols <= ti->nc)
    322324                        ti->pos = ti->pos + ti->con_cols;
    323325        } else {
    324                 if (ti->pos >= ti->con_cols)
     326                if (ti->pos - ti->con_cols >= 0)
    325327                        ti->pos = ti->pos - ti->con_cols;
    326328        }
    327        
     329
    328330        tinput_post_seek(ti, shift_held);
    329331}
     
    332334{
    333335        tinput_pre_seek(ti, shift_held);
    334        
     336
    335337        if (dir == seek_backward)
    336338                ti->pos = 0;
    337339        else
    338340                ti->pos = ti->nc;
    339        
     341
    340342        tinput_post_seek(ti, shift_held);
    341343}
     
    343345static void tinput_pre_seek(tinput_t *ti, bool shift_held)
    344346{
    345         if ((tinput_sel_active(ti)) && (!shift_held)) {
     347        if (tinput_sel_active(ti) && !shift_held) {
    346348                /* Unselect and redraw. */
    347349                ti->sel_start = ti->pos;
     
    360362                ti->sel_start = ti->pos;
    361363        }
    362        
    363364        tinput_position_caret(ti);
    364365}
     
    366367static void tinput_history_insert(tinput_t *ti, char *str)
    367368{
     369        int i;
     370
    368371        if (ti->hnum < HISTORY_LEN) {
    369372                ti->hnum += 1;
     
    372375                        free(ti->history[HISTORY_LEN]);
    373376        }
    374        
    375         size_t i;
    376         for (i = ti->hnum; i > 1; i--)
     377
     378        for (i = ti->hnum; i > 1; --i)
    377379                ti->history[i] = ti->history[i - 1];
    378        
     380
    379381        ti->history[1] = str_dup(str);
    380        
     382
    381383        if (ti->history[0] != NULL) {
    382384                free(ti->history[0]);
     
    393395}
    394396
    395 static void tinput_sel_get_bounds(tinput_t *ti, size_t *sa, size_t *sb)
     397static void tinput_sel_get_bounds(tinput_t *ti, int *sa, int *sb)
    396398{
    397399        if (ti->sel_start < ti->pos) {
     
    406408static bool tinput_sel_active(tinput_t *ti)
    407409{
    408         return (ti->sel_start != ti->pos);
     410        return ti->sel_start != ti->pos;
    409411}
    410412
     
    419421static void tinput_sel_delete(tinput_t *ti)
    420422{
    421         size_t sa;
    422         size_t sb;
    423        
     423        int sa, sb;
     424
    424425        tinput_sel_get_bounds(ti, &sa, &sb);
    425426        if (sa == sb)
    426427                return;
    427        
     428
    428429        memmove(ti->buffer + sa, ti->buffer + sb,
    429430            (ti->nc - sb) * sizeof(wchar_t));
    430        
    431431        ti->pos = ti->sel_start = sa;
    432432        ti->nc -= (sb - sa);
    433433        ti->buffer[ti->nc] = '\0';
    434        
     434
    435435        tinput_display_tail(ti, sa, sb - sa);
    436436        tinput_position_caret(ti);
     
    439439static void tinput_sel_copy_to_cb(tinput_t *ti)
    440440{
    441         size_t sa;
    442         size_t sb;
    443        
     441        int sa, sb;
     442        char *str;
     443
    444444        tinput_sel_get_bounds(ti, &sa, &sb);
    445        
    446         char *str;
    447        
     445
    448446        if (sb < ti->nc) {
    449447                wchar_t tmp_c = ti->buffer[sb];
     
    456454        if (str == NULL)
    457455                goto error;
    458        
     456
    459457        if (clipboard_put_str(str) != EOK)
    460458                goto error;
    461        
     459
    462460        free(str);
    463461        return;
    464        
    465462error:
    466         /* TODO: Give the user some kind of warning. */
    467463        return;
     464        /* TODO: Give the user some warning. */
    468465}
    469466
     
    471468{
    472469        char *str;
    473         int rc = clipboard_get_str(&str);
    474        
    475         if ((rc != EOK) || (str == NULL)) {
    476                 /* TODO: Give the user some kind of warning. */
    477                 return;
    478         }
    479        
     470        int rc;
     471
     472        rc = clipboard_get_str(&str);
     473        if (rc != EOK || str == NULL)
     474                return; /* TODO: Give the user some warning. */
     475
    480476        tinput_insert_string(ti, str);
    481477        free(str);
     
    484480static void tinput_history_seek(tinput_t *ti, int offs)
    485481{
    486         if (offs >= 0) {
    487                 if (ti->hpos + offs > ti->hnum)
    488                         return;
    489         } else {
    490                 if (ti->hpos < (size_t) -offs)
    491                         return;
    492         }
    493        
     482        int pad;
     483
     484        if (ti->hpos + offs < 0 || ti->hpos + offs > ti->hnum)
     485                return;
     486
    494487        if (ti->history[ti->hpos] != NULL) {
    495488                free(ti->history[ti->hpos]);
    496489                ti->history[ti->hpos] = NULL;
    497490        }
    498        
     491
    499492        ti->history[ti->hpos] = tinput_get_str(ti);
    500493        ti->hpos += offs;
    501        
    502         int pad = (int) ti->nc - str_length(ti->history[ti->hpos]);
    503         if (pad < 0)
    504                 pad = 0;
    505        
     494
     495        pad = ti->nc - str_length(ti->history[ti->hpos]);
     496        if (pad < 0) pad = 0;
     497
    506498        tinput_set_str(ti, ti->history[ti->hpos]);
    507499        tinput_display_tail(ti, 0, pad);
     
    523515/** Read in one line of input.
    524516 *
    525  * @param ti   Text input.
    526  * @param dstr Place to save pointer to new string.
    527  *
    528  * @return EOK on success
    529  * @return ENOENT if user requested abort
    530  * @return EIO if communication with console failed
    531  *
     517 * @param ti    Text input.
     518 * @param dstr  Place to save pointer to new string.
     519 * @return      EOK on success, ENOENT if user requested abort, EIO
     520 *              if communication with console failed.
    532521 */
    533522int tinput_read(tinput_t *ti, char **dstr)
    534523{
     524        console_event_t ev;
     525        char *str;
     526
    535527        fflush(stdout);
     528
    536529        if (console_get_size(fphone(stdin), &ti->con_cols, &ti->con_rows) != EOK)
    537530                return EIO;
    538        
    539531        if (console_get_pos(fphone(stdin), &ti->col0, &ti->row0) != EOK)
    540532                return EIO;
    541        
    542         ti->pos = 0;
    543         ti->sel_start = 0;
     533
     534        ti->pos = ti->sel_start = 0;
    544535        ti->nc = 0;
    545536        ti->buffer[0] = '\0';
    546537        ti->done = false;
    547538        ti->exit_clui = false;
    548        
     539
    549540        while (!ti->done) {
    550541                fflush(stdout);
    551                
    552                 console_event_t ev;
    553542                if (!console_get_event(fphone(stdin), &ev))
    554543                        return EIO;
    555                
     544
    556545                if (ev.type != KEY_PRESS)
    557546                        continue;
    558                
    559                 if (((ev.mods & KM_CTRL) != 0) &&
    560                     ((ev.mods & (KM_ALT | KM_SHIFT)) == 0))
     547
     548                if ((ev.mods & KM_CTRL) != 0 &&
     549                    (ev.mods & (KM_ALT | KM_SHIFT)) == 0) {
    561550                        tinput_key_ctrl(ti, &ev);
    562                
    563                 if (((ev.mods & KM_SHIFT) != 0) &&
    564                     ((ev.mods & (KM_CTRL | KM_ALT)) == 0))
     551                }
     552
     553                if ((ev.mods & KM_SHIFT) != 0 &&
     554                    (ev.mods & (KM_CTRL | KM_ALT)) == 0) {
    565555                        tinput_key_shift(ti, &ev);
    566                
    567                 if (((ev.mods & KM_CTRL) != 0) &&
    568                     ((ev.mods & KM_SHIFT) != 0) &&
    569                     ((ev.mods & KM_ALT) == 0))
     556                }
     557
     558                if ((ev.mods & KM_CTRL) != 0 &&
     559                    (ev.mods & KM_SHIFT) != 0 &&
     560                    (ev.mods & KM_ALT) == 0) {
    570561                        tinput_key_ctrl_shift(ti, &ev);
    571                
    572                 if ((ev.mods & (KM_CTRL | KM_ALT | KM_SHIFT)) == 0)
     562                }
     563
     564                if ((ev.mods & (KM_CTRL | KM_ALT | KM_SHIFT)) == 0) {
    573565                        tinput_key_unmod(ti, &ev);
    574                
     566                }
     567
    575568                if (ev.c >= ' ') {
    576569                        tinput_sel_delete(ti);
     
    578571                }
    579572        }
    580        
     573
    581574        if (ti->exit_clui)
    582575                return ENOENT;
    583        
     576
    584577        ti->pos = ti->nc;
    585578        tinput_position_caret(ti);
    586579        putchar('\n');
    587        
    588         char *str = tinput_get_str(ti);
     580
     581        str = tinput_get_str(ti);
    589582        if (str_cmp(str, "") != 0)
    590583                tinput_history_insert(ti, str);
    591        
     584
    592585        ti->hpos = 0;
    593        
     586
    594587        *dstr = str;
    595588        return EOK;
     
    707700                break;
    708701        case KC_UP:
    709                 tinput_history_seek(ti, 1);
     702                tinput_history_seek(ti, +1);
    710703                break;
    711704        case KC_DOWN:
Note: See TracChangeset for help on using the changeset viewer.