Changeset 19528516 in mainline for uspace/app/bdsh/input.c


Ignore:
Timestamp:
2009-11-29T00:42:51Z (14 years ago)
Author:
jirka <jirka@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
025759c, a1622091
Parents:
2e07d27e
Message:

Rewrite command-line input routine. Adds capability to seek, insert and delete (left/right arrow keys, home, end, delete).

File:
1 edited

Legend:

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

    r2e07d27e r19528516  
    4747#include "exec.h"
    4848
    49 static void read_line(char *, int);
     49typedef struct {
     50        wchar_t buffer[INPUT_MAX];
     51        int col0, row0;
     52        int con_cols, con_rows;
     53        int nc;
     54        int pos;
     55} tinput_t;
     56
     57typedef enum {
     58        seek_cell,
     59        seek_max
     60} seek_dist_t;
     61
     62typedef enum {
     63        seek_backward = -1,
     64        seek_forward = 1
     65} seek_dir_t;
     66
     67static tinput_t tinput;
     68
     69static char *tinput_read(tinput_t *ti);
    5070
    5171/* Tokenizes input from console, sees if the first word is a built-in, if so
     
    99119}
    100120
    101 static void read_line(char *buffer, int n)
     121static void tinput_display_tail(tinput_t *ti, int start, int pad)
     122{
     123        int i;
     124
     125        console_goto(fphone(stdout), ti->col0 + start, ti->row0);
     126        printf("%ls", ti->buffer + start);
     127        for (i = 0; i < pad; ++i)
     128                putchar(' ');
     129        fflush(stdout);
     130}
     131
     132static void tinput_position_caret(tinput_t *ti)
     133{
     134        console_goto(fphone(stdout), ti->col0 + ti->pos, ti->row0);
     135}
     136
     137static void tinput_insert_char(tinput_t *ti, wchar_t c)
     138{
     139        int i;
     140
     141        if (ti->nc == INPUT_MAX)
     142                return;
     143
     144        if (ti->col0 + ti->nc >= ti->con_cols - 1)
     145                return;
     146
     147        for (i = ti->nc; i > ti->pos; --i)
     148                ti->buffer[i] = ti->buffer[i - 1];
     149
     150        ti->buffer[ti->pos] = c;
     151        ti->pos += 1;
     152        ti->nc += 1;
     153        ti->buffer[ti->nc] = '\0';
     154
     155        tinput_display_tail(ti, ti->pos - 1, 0);
     156        tinput_position_caret(ti);
     157}
     158
     159static void tinput_backspace(tinput_t *ti)
     160{
     161        int i;
     162
     163        if (ti->pos == 0)
     164                return;
     165
     166        for (i = ti->pos; i < ti->nc; ++i)
     167                ti->buffer[i - 1] = ti->buffer[i];
     168        ti->pos -= 1;
     169        ti->nc -= 1;
     170        ti->buffer[ti->nc] = '\0';
     171
     172        tinput_display_tail(ti, ti->pos, 1);
     173        tinput_position_caret(ti);
     174}
     175
     176static void tinput_delete(tinput_t *ti)
     177{
     178        if (ti->pos == ti->nc)
     179                return;
     180
     181        ti->pos += 1;
     182        tinput_backspace(ti);
     183}
     184
     185static void tinput_seek(tinput_t *ti, seek_dir_t dir, seek_dist_t dist)
     186{
     187        switch (dist) {
     188        case seek_cell:
     189                ti->pos += dir;
     190                break;
     191        case seek_max:
     192                if (dir == seek_backward)
     193                        ti->pos = 0;
     194                else
     195                        ti->pos = ti->nc;
     196                break;
     197        }
     198               
     199        if (ti->pos < 0) ti->pos = 0;
     200        if (ti->pos > ti->nc) ti->pos = ti->nc;
     201
     202        tinput_position_caret(ti);
     203}
     204
     205static char *tinput_read(tinput_t *ti)
    102206{
    103207        console_event_t ev;
    104         size_t offs, otmp;
    105         wchar_t dec;
    106 
    107         offs = 0;
     208        char *str;
     209
     210        fflush(stdout);
     211
     212        if (console_get_size(fphone(stdin), &ti->con_cols, &ti->con_rows) != EOK)
     213                return NULL;
     214        if (console_get_pos(fphone(stdin), &ti->col0, &ti->row0) != EOK)
     215                return NULL;
     216
     217        ti->pos = 0;
     218        ti->nc = 0;
     219
    108220        while (true) {
    109221                fflush(stdout);
    110222                if (!console_get_event(fphone(stdin), &ev))
    111                         return;
     223                        return NULL;
    112224               
    113225                if (ev.type != KEY_PRESS)
    114226                        continue;
    115                
    116                 if (ev.key == KC_ENTER || ev.key == KC_NENTER)
    117                         break;
    118                 if (ev.key == KC_BACKSPACE) {
    119                         if (offs > 0) {
    120                                 /*
    121                                  * Back up until we reach valid start of
    122                                  * character.
    123                                  */
    124                                 while (offs > 0) {
    125                                         --offs; otmp = offs;
    126                                         dec = str_decode(buffer, &otmp, n);
    127                                         if (dec != U_SPECIAL)
    128                                                 break;
    129                                 }
    130                                 putchar('\b');
    131                         }
     227
     228                if ((ev.mods & (KM_CTRL | KM_ALT | KM_SHIFT)) != 0)
    132229                        continue;
     230
     231                switch(ev.key) {
     232                case KC_ENTER:
     233                case KC_NENTER:
     234                        goto done;
     235                case KC_BACKSPACE:
     236                        tinput_backspace(ti);
     237                        break;
     238                case KC_DELETE:
     239                        tinput_delete(ti);
     240                        break;
     241                case KC_LEFT:
     242                        tinput_seek(ti, seek_backward, seek_cell);
     243                        break;
     244                case KC_RIGHT:
     245                        tinput_seek(ti, seek_forward, seek_cell);
     246
     247                        break;
     248                case KC_HOME:
     249                        tinput_seek(ti, seek_backward, seek_max);
     250                        break;
     251                case KC_END:
     252                        tinput_seek(ti, seek_forward, seek_max);
     253                        break;
    133254                }
    134255                if (ev.c >= ' ') {
    135                         if (chr_encode(ev.c, buffer, &offs, n - 1) == EOK)
    136                                 putchar(ev.c);
     256                        tinput_insert_char(ti, ev.c);
    137257                }
    138258        }
     259
     260done:
    139261        putchar('\n');
    140         buffer[offs] = '\0';
    141 }
    142 
    143 /* TODO:
    144  * Implement something like editline() / readline(), if even
    145  * just for command history and making arrows work. */
     262
     263        ti->buffer[ti->nc] = '\0';
     264        str = malloc(STR_BOUNDS(ti->nc) + 1);
     265        if (str == NULL)
     266                return NULL;
     267
     268        wstr_nstr(str, ti->buffer, STR_BOUNDS(ti->nc) + 1);
     269
     270        return str;
     271}
     272
    146273void get_input(cliuser_t *usr)
    147274{
    148         char line[INPUT_MAX];
     275        char *str;
    149276
    150277        fflush(stdout);
     
    154281        console_set_style(fphone(stdout), STYLE_NORMAL);
    155282
    156         read_line(line, INPUT_MAX);
    157         /* Make sure we don't have rubbish or a C/R happy user */
    158         if (str_cmp(line, "") == 0 || str_cmp(line, "\n") == 0)
    159                 return;
    160         usr->line = str_dup(line);
    161 
     283        str = tinput_read(&tinput);
     284
     285        /* Check for empty input. */
     286        if (str_cmp(str, "") == 0) {
     287                free(str);
     288                return;
     289        }
     290
     291        usr->line = str;
    162292        return;
    163293}
    164 
Note: See TracChangeset for help on using the changeset viewer.