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

Changeset 9f1362d4 in mainline for uspace/lib/clui/tinput.c


Ignore:
Timestamp:
2010-04-19T19:58:18Z (12 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master
Children:
369a5f8
Parents:
caad59a
Message:

console output improvements

  • define new generic styles (STYLE_INVERTED for inverted print and STYLE_SELECTION for selections), use them primarily instead of specifying colors or RGBs
  • use console_set_style(fphone(stdout), STYLE_NORMAL) as the correct mean for reseting console settings (instead of specifying conrete hardcoded colors)
  • rename console_goto() to console_set_pos() (consistency with console_get_pos())
  • use semantically correct unsigned types for console sizes and cursor positions (instead of signed types)
  • use unsigned types for sizes and positions in libclui
  • top: nicer screen redrawing (do not use console_clear() which causes flickering, but repaint the screen properly — not entirely finished yet)
  • initialize mouse pointer coordinates (so the mouse cursor does not behave erratic after boot, unfortunatelly this does not solve ticket #223)
File:
1 edited

Legend:

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

    rcaad59a r9f1362d4  
    4040#include <assert.h>
    4141#include <bool.h>
    42 
    43 #include "tinput.h"
     42#include <tinput.h>
    4443
    4544/** Seek direction */
     
    4948} seek_dir_t;
    5049
    51 static void tinput_init(tinput_t *ti);
    52 static void tinput_insert_string(tinput_t *ti, const char *str);
    53 static void tinput_sel_get_bounds(tinput_t *ti, int *sa, int *sb);
    54 static bool tinput_sel_active(tinput_t *ti);
    55 static void tinput_sel_all(tinput_t *ti);
    56 static void tinput_sel_delete(tinput_t *ti);
    57 static void tinput_key_ctrl(tinput_t *ti, console_event_t *ev);
    58 static void tinput_key_shift(tinput_t *ti, console_event_t *ev);
    59 static void tinput_key_ctrl_shift(tinput_t *ti, console_event_t *ev);
    60 static void tinput_key_unmod(tinput_t *ti, console_event_t *ev);
    61 static void tinput_pre_seek(tinput_t *ti, bool shift_held);
    62 static void tinput_post_seek(tinput_t *ti, bool shift_held);
     50static void tinput_init(tinput_t *);
     51static void tinput_insert_string(tinput_t *, const char *);
     52static void tinput_sel_get_bounds(tinput_t *, size_t *, size_t *);
     53static bool tinput_sel_active(tinput_t *);
     54static void tinput_sel_all(tinput_t *);
     55static void tinput_sel_delete(tinput_t *);
     56static void tinput_key_ctrl(tinput_t *, console_event_t *);
     57static void tinput_key_shift(tinput_t *, console_event_t *);
     58static void tinput_key_ctrl_shift(tinput_t *, console_event_t *);
     59static void tinput_key_unmod(tinput_t *, console_event_t *);
     60static void tinput_pre_seek(tinput_t *, bool);
     61static void tinput_post_seek(tinput_t *, bool);
    6362
    6463/** Create a new text input field. */
     
    6665{
    6766        tinput_t *ti;
    68 
     67       
    6968        ti = malloc(sizeof(tinput_t));
    7069        if (ti == NULL)
    7170                return NULL;
    72 
     71       
    7372        tinput_init(ti);
    7473        return ti;
     
    8180}
    8281
    83 static 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 
     82static 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;
    8988        tinput_sel_get_bounds(ti, &sa, &sb);
    90 
    91         console_goto(fphone(stdout), (ti->col0 + start) % ti->con_cols,
     89       
     90        console_set_pos(fphone(stdout), (ti->col0 + start) % ti->con_cols,
    9291            ti->row0 + (ti->col0 + start) / ti->con_cols);
    93         console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0);
    94 
    95         p = start;
     92        console_set_style(fphone(stdout), STYLE_NORMAL);
     93       
     94        size_t p = start;
    9695        if (p < sa) {
    9796                memcpy(dbuf, ti->buffer + p, (sa - p) * sizeof(wchar_t));
     
    10099                p = sa;
    101100        }
    102 
     101       
    103102        if (p < sb) {
    104103                fflush(stdout);
    105                 console_set_color(fphone(stdout), COLOR_BLACK, COLOR_RED, 0);
     104                console_set_style(fphone(stdout), STYLE_SELECTED);
    106105                memcpy(dbuf, ti->buffer + p,
    107106                    (sb - p) * sizeof(wchar_t));
     
    110109                p = sb;
    111110        }
    112 
     111       
    113112        fflush(stdout);
    114         console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0);
    115 
     113        console_set_style(fphone(stdout), STYLE_NORMAL);
     114       
    116115        if (p < ti->nc) {
    117116                memcpy(dbuf, ti->buffer + p,
     
    120119                printf("%ls", dbuf);
    121120        }
    122 
    123         for (i = 0; i < pad; ++i)
     121       
     122        for (p = 0; p < pad; p++)
    124123                putchar(' ');
     124       
    125125        fflush(stdout);
    126126}
     
    133133static void tinput_position_caret(tinput_t *ti)
    134134{
    135         console_goto(fphone(stdout), (ti->col0 + ti->pos) % ti->con_cols,
     135        console_set_pos(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         int width, rows;
    143 
    144         width = ti->col0 + ti->nc;
    145         rows = (width / ti->con_cols) + 1;
    146 
     142        ipcarg_t width = ti->col0 + ti->nc;
     143        ipcarg_t rows = (width / ti->con_cols) + 1;
     144       
    147145        /* Update row0 if the screen scrolled. */
    148146        if (ti->row0 + rows > ti->con_rows)
    149                 ti->row0 = ti->con_rows - rows; 
     147                ti->row0 = ti->con_rows - rows;
    150148}
    151149
    152150static void tinput_insert_char(tinput_t *ti, wchar_t c)
    153151{
    154         int i;
    155         int new_width, new_height;
    156 
    157152        if (ti->nc == INPUT_MAX_SIZE)
    158153                return;
    159 
    160         new_width = ti->col0 + ti->nc + 1;
     154       
     155        ipcarg_t new_width = ti->col0 + ti->nc + 1;
    161156        if (new_width % ti->con_cols == 0) {
    162157                /* Advancing to new line. */
    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)
     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--)
    169167                ti->buffer[i] = ti->buffer[i - 1];
    170 
     168       
    171169        ti->buffer[ti->pos] = c;
    172170        ti->pos += 1;
     
    174172        ti->buffer[ti->nc] = '\0';
    175173        ti->sel_start = ti->pos;
    176 
     174       
    177175        tinput_display_tail(ti, ti->pos - 1, 0);
    178176        tinput_update_origin(ti);
     
    182180static void tinput_insert_string(tinput_t *ti, const char *str)
    183181{
    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);
     182        size_t ilen = min(str_length(str), INPUT_MAX_SIZE - ti->nc);
    191183        if (ilen == 0)
    192184                return;
    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;
     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;
    203201        while (i < ilen) {
    204                 c = str_decode(str, &off, STR_NO_LIMIT);
     202                wchar_t c = str_decode(str, &off, STR_NO_LIMIT);
    205203                if (c == '\0')
    206204                        break;
    207 
     205               
    208206                /* Filter out non-printable chars. */
    209207                if (c < 32)
    210208                        c = 32;
    211 
     209               
    212210                ti->buffer[ti->pos + i] = c;
    213                 ++i;
    214         }
    215 
     211                i++;
     212        }
     213       
    216214        ti->pos += ilen;
    217215        ti->nc += ilen;
    218216        ti->buffer[ti->nc] = '\0';
    219217        ti->sel_start = ti->pos;
    220 
     218       
    221219        tinput_display_tail(ti, ti->pos - ilen, 0);
    222220        tinput_update_origin(ti);
     
    226224static void tinput_backspace(tinput_t *ti)
    227225{
    228         int i;
    229 
    230226        if (tinput_sel_active(ti)) {
    231227                tinput_sel_delete(ti);
    232228                return;
    233229        }
    234 
     230       
    235231        if (ti->pos == 0)
    236232                return;
    237 
    238         for (i = ti->pos; i < ti->nc; ++i)
     233       
     234        size_t i;
     235        for (i = ti->pos; i < ti->nc; i++)
    239236                ti->buffer[i - 1] = ti->buffer[i];
     237       
    240238        ti->pos -= 1;
    241239        ti->nc -= 1;
    242240        ti->buffer[ti->nc] = '\0';
    243241        ti->sel_start = ti->pos;
    244 
     242       
    245243        tinput_display_tail(ti, ti->pos, 1);
    246244        tinput_position_caret(ti);
     
    253251                return;
    254252        }
    255 
     253       
    256254        if (ti->pos == ti->nc)
    257255                return;
    258 
     256       
    259257        ti->pos += 1;
    260258        ti->sel_start = ti->pos;
    261 
     259       
    262260        tinput_backspace(ti);
    263261}
     
    266264{
    267265        tinput_pre_seek(ti, shift_held);
    268 
     266       
    269267        if (dir == seek_forward) {
    270268                if (ti->pos < ti->nc)
     
    274272                        ti->pos -= 1;
    275273        }
    276 
     274       
    277275        tinput_post_seek(ti, shift_held);
    278276}
     
    281279{
    282280        tinput_pre_seek(ti, shift_held);
    283 
     281       
    284282        if (dir == seek_forward) {
    285283                if (ti->pos == ti->nc)
    286284                        return;
    287 
    288                 while (1) {
     285               
     286                while (true) {
    289287                        ti->pos += 1;
    290 
     288                       
    291289                        if (ti->pos == ti->nc)
    292290                                break;
    293 
    294                         if (ti->buffer[ti->pos - 1] == ' ' &&
    295                             ti->buffer[ti->pos] != ' ')
     291                       
     292                        if ((ti->buffer[ti->pos - 1] == ' ') &&
     293                            (ti->buffer[ti->pos] != ' '))
    296294                                break;
    297295                }
     
    299297                if (ti->pos == 0)
    300298                        return;
    301 
    302                 while (1) {
     299               
     300                while (true) {
    303301                        ti->pos -= 1;
    304 
     302                       
    305303                        if (ti->pos == 0)
    306304                                break;
    307 
     305                       
    308306                        if (ti->buffer[ti->pos - 1] == ' ' &&
    309307                            ti->buffer[ti->pos] != ' ')
    310308                                break;
    311309                }
    312 
    313         }
    314 
     310       
     311        }
     312       
    315313        tinput_post_seek(ti, shift_held);
    316314}
     
    319317{
    320318        tinput_pre_seek(ti, shift_held);
    321 
     319       
    322320        if (dir == seek_forward) {
    323321                if (ti->pos + ti->con_cols <= ti->nc)
    324322                        ti->pos = ti->pos + ti->con_cols;
    325323        } else {
    326                 if (ti->pos - ti->con_cols >= 0)
     324                if (ti->pos >= ti->con_cols)
    327325                        ti->pos = ti->pos - ti->con_cols;
    328326        }
    329 
     327       
    330328        tinput_post_seek(ti, shift_held);
    331329}
     
    334332{
    335333        tinput_pre_seek(ti, shift_held);
    336 
     334       
    337335        if (dir == seek_backward)
    338336                ti->pos = 0;
    339337        else
    340338                ti->pos = ti->nc;
    341 
     339       
    342340        tinput_post_seek(ti, shift_held);
    343341}
     
    345343static void tinput_pre_seek(tinput_t *ti, bool shift_held)
    346344{
    347         if (tinput_sel_active(ti) && !shift_held) {
     345        if ((tinput_sel_active(ti)) && (!shift_held)) {
    348346                /* Unselect and redraw. */
    349347                ti->sel_start = ti->pos;
     
    362360                ti->sel_start = ti->pos;
    363361        }
     362       
    364363        tinput_position_caret(ti);
    365364}
     
    367366static void tinput_history_insert(tinput_t *ti, char *str)
    368367{
    369         int i;
    370 
    371368        if (ti->hnum < HISTORY_LEN) {
    372369                ti->hnum += 1;
     
    375372                        free(ti->history[HISTORY_LEN]);
    376373        }
    377 
    378         for (i = ti->hnum; i > 1; --i)
     374       
     375        size_t i;
     376        for (i = ti->hnum; i > 1; i--)
    379377                ti->history[i] = ti->history[i - 1];
    380 
     378       
    381379        ti->history[1] = str_dup(str);
    382 
     380       
    383381        if (ti->history[0] != NULL) {
    384382                free(ti->history[0]);
     
    395393}
    396394
    397 static void tinput_sel_get_bounds(tinput_t *ti, int *sa, int *sb)
     395static void tinput_sel_get_bounds(tinput_t *ti, size_t *sa, size_t *sb)
    398396{
    399397        if (ti->sel_start < ti->pos) {
     
    408406static bool tinput_sel_active(tinput_t *ti)
    409407{
    410         return ti->sel_start != ti->pos;
     408        return (ti->sel_start != ti->pos);
    411409}
    412410
     
    421419static void tinput_sel_delete(tinput_t *ti)
    422420{
    423         int sa, sb;
    424 
     421        size_t sa;
     422        size_t sb;
     423       
    425424        tinput_sel_get_bounds(ti, &sa, &sb);
    426425        if (sa == sb)
    427426                return;
    428 
     427       
    429428        memmove(ti->buffer + sa, ti->buffer + sb,
    430429            (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         int sa, sb;
     441        size_t sa;
     442        size_t sb;
     443       
     444        tinput_sel_get_bounds(ti, &sa, &sb);
     445       
    442446        char *str;
    443 
    444         tinput_sel_get_bounds(ti, &sa, &sb);
    445 
     447       
    446448        if (sb < ti->nc) {
    447449                wchar_t tmp_c = ti->buffer[sb];
     
    454456        if (str == NULL)
    455457                goto error;
    456 
     458       
    457459        if (clipboard_put_str(str) != EOK)
    458460                goto error;
    459 
     461       
    460462        free(str);
    461463        return;
     464       
    462465error:
     466        /* TODO: Give the user some kind of warning. */
    463467        return;
    464         /* TODO: Give the user some warning. */
    465468}
    466469
     
    468471{
    469472        char *str;
    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 
     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       
    476480        tinput_insert_string(ti, str);
    477481        free(str);
     
    480484static void tinput_history_seek(tinput_t *ti, int offs)
    481485{
    482         int pad;
    483 
    484         if (ti->hpos + offs < 0 || ti->hpos + offs > ti->hnum)
    485                 return;
    486 
     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       
    487494        if (ti->history[ti->hpos] != NULL) {
    488495                free(ti->history[ti->hpos]);
    489496                ti->history[ti->hpos] = NULL;
    490497        }
    491 
     498       
    492499        ti->history[ti->hpos] = tinput_get_str(ti);
    493500        ti->hpos += offs;
    494 
    495         pad = ti->nc - str_length(ti->history[ti->hpos]);
    496         if (pad < 0) pad = 0;
    497 
     501       
     502        int pad = (int) ti->nc - str_length(ti->history[ti->hpos]);
     503        if (pad < 0)
     504                pad = 0;
     505       
    498506        tinput_set_str(ti, ti->history[ti->hpos]);
    499507        tinput_display_tail(ti, 0, pad);
     
    515523/** Read in one line of input.
    516524 *
    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.
     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 *
    521532 */
    522533int tinput_read(tinput_t *ti, char **dstr)
    523534{
    524         console_event_t ev;
    525         char *str;
    526 
    527535        fflush(stdout);
    528 
    529536        if (console_get_size(fphone(stdin), &ti->con_cols, &ti->con_rows) != EOK)
    530537                return EIO;
     538       
    531539        if (console_get_pos(fphone(stdin), &ti->col0, &ti->row0) != EOK)
    532540                return EIO;
    533 
    534         ti->pos = ti->sel_start = 0;
     541       
     542        ti->pos = 0;
     543        ti->sel_start = 0;
    535544        ti->nc = 0;
    536545        ti->buffer[0] = '\0';
    537546        ti->done = false;
    538547        ti->exit_clui = false;
    539 
     548       
    540549        while (!ti->done) {
    541550                fflush(stdout);
     551               
     552                console_event_t ev;
    542553                if (!console_get_event(fphone(stdin), &ev))
    543554                        return EIO;
    544 
     555               
    545556                if (ev.type != KEY_PRESS)
    546557                        continue;
    547 
    548                 if ((ev.mods & KM_CTRL) != 0 &&
    549                     (ev.mods & (KM_ALT | KM_SHIFT)) == 0) {
     558               
     559                if (((ev.mods & KM_CTRL) != 0) &&
     560                    ((ev.mods & (KM_ALT | KM_SHIFT)) == 0))
    550561                        tinput_key_ctrl(ti, &ev);
    551                 }
    552 
    553                 if ((ev.mods & KM_SHIFT) != 0 &&
    554                     (ev.mods & (KM_CTRL | KM_ALT)) == 0) {
     562               
     563                if (((ev.mods & KM_SHIFT) != 0) &&
     564                    ((ev.mods & (KM_CTRL | KM_ALT)) == 0))
    555565                        tinput_key_shift(ti, &ev);
    556                 }
    557 
    558                 if ((ev.mods & KM_CTRL) != 0 &&
    559                     (ev.mods & KM_SHIFT) != 0 &&
    560                     (ev.mods & KM_ALT) == 0) {
     566               
     567                if (((ev.mods & KM_CTRL) != 0) &&
     568                    ((ev.mods & KM_SHIFT) != 0) &&
     569                    ((ev.mods & KM_ALT) == 0))
    561570                        tinput_key_ctrl_shift(ti, &ev);
    562                 }
    563 
    564                 if ((ev.mods & (KM_CTRL | KM_ALT | KM_SHIFT)) == 0) {
     571               
     572                if ((ev.mods & (KM_CTRL | KM_ALT | KM_SHIFT)) == 0)
    565573                        tinput_key_unmod(ti, &ev);
    566                 }
    567 
     574               
    568575                if (ev.c >= ' ') {
    569576                        tinput_sel_delete(ti);
     
    571578                }
    572579        }
    573 
     580       
    574581        if (ti->exit_clui)
    575582                return ENOENT;
    576 
     583       
    577584        ti->pos = ti->nc;
    578585        tinput_position_caret(ti);
    579586        putchar('\n');
    580 
    581         str = tinput_get_str(ti);
     587       
     588        char *str = tinput_get_str(ti);
    582589        if (str_cmp(str, "") != 0)
    583590                tinput_history_insert(ti, str);
    584 
     591       
    585592        ti->hpos = 0;
    586 
     593       
    587594        *dstr = str;
    588595        return EOK;
     
    700707                break;
    701708        case KC_UP:
    702                 tinput_history_seek(ti, +1);
     709                tinput_history_seek(ti, 1);
    703710                break;
    704711        case KC_DOWN:
Note: See TracChangeset for help on using the changeset viewer.