Changeset 899bdfd in mainline for uspace/lib/clui/src/tinput.c


Ignore:
Timestamp:
2024-09-12T13:14:20Z (3 months ago)
Author:
Jiří Zárevúcky <zarevucky.jiri@…>
Branches:
master
Children:
4c2339b
Parents:
dd50aa19
git-author:
Jiří Zárevúcky <zarevucky.jiri@…> (2024-09-12 11:47:56)
git-committer:
Jiří Zárevúcky <zarevucky.jiri@…> (2024-09-12 13:14:20)
Message:

Terminal scrolling and resizing support

File:
1 edited

Legend:

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

    rdd50aa19 r899bdfd  
    113113static void tinput_display_tail(tinput_t *ti, size_t start, size_t pad)
    114114{
    115         char32_t *dbuf = malloc((INPUT_MAX_SIZE + 1) * sizeof(char32_t));
    116         if (!dbuf)
    117                 return;
    118 
     115        char32_t stash;
    119116        size_t sa;
    120117        size_t sb;
    121118        tinput_sel_get_bounds(ti, &sa, &sb);
     119        assert(sa <= sb);
    122120
    123121        tinput_console_set_lpos(ti, ti->text_coord + start);
    124122        console_set_style(ti->console, STYLE_NORMAL);
    125123
    126         size_t p = start;
    127         if (p < sa) {
    128                 memcpy(dbuf, ti->buffer + p, (sa - p) * sizeof(char32_t));
    129                 dbuf[sa - p] = '\0';
    130                 printf("%ls", dbuf);
    131                 p = sa;
    132         }
    133 
    134         if (p < sb) {
     124        sa = max(start, sa);
     125        sb = max(start, sb);
     126
     127        if (start < sa) {
     128                stash = ti->buffer[sa];
     129                ti->buffer[sa] = L'\0';
     130                printf("%ls", &ti->buffer[start]);
     131                ti->buffer[sa] = stash;
     132        }
     133
     134        if (sa < sb) {
    135135                console_flush(ti->console);
    136136                console_set_style(ti->console, STYLE_SELECTED);
    137137
    138                 memcpy(dbuf, ti->buffer + p,
    139                     (sb - p) * sizeof(char32_t));
    140                 dbuf[sb - p] = '\0';
    141                 printf("%ls", dbuf);
    142                 p = sb;
    143         }
     138                stash = ti->buffer[sb];
     139                ti->buffer[sb] = L'\0';
     140                printf("%ls", &ti->buffer[sa]);
     141                ti->buffer[sb] = stash;
     142
     143                console_flush(ti->console);
     144                console_set_style(ti->console, STYLE_NORMAL);
     145        }
     146
     147        if (sb < ti->nc) {
     148                ti->buffer[ti->nc] = L'\0';
     149                printf("%ls", &ti->buffer[sb]);
     150        }
     151
     152        for (; pad > 0; pad--)
     153                putuchar(' ');
    144154
    145155        console_flush(ti->console);
    146         console_set_style(ti->console, STYLE_NORMAL);
    147 
    148         if (p < ti->nc) {
    149                 memcpy(dbuf, ti->buffer + p,
    150                     (ti->nc - p) * sizeof(char32_t));
    151                 dbuf[ti->nc - p] = '\0';
    152                 printf("%ls", dbuf);
    153         }
    154 
    155         for (p = 0; p < pad; p++)
    156                 putuchar(' ');
    157 
    158         console_flush(ti->console);
    159 
    160         free(dbuf);
    161156}
    162157
     
    218213        tinput_display_prompt(ti);
    219214
    220         /* The screen might have scrolled after priting the prompt */
     215        /* The screen might have scrolled after printing the prompt */
    221216        tinput_update_origin_coord(ti, ti->prompt_coord + str_width(ti->prompt));
    222217
     
    237232                return;
    238233
    239         unsigned new_width = LIN_TO_COL(ti, ti->text_coord) + ti->nc + 1;
    240         if (new_width % ti->con_cols == 0) {
    241                 /* Advancing to new line. */
    242                 sysarg_t new_height = (new_width / ti->con_cols) + 1;
    243                 if (new_height >= ti->con_rows) {
    244                         /* Disallow text longer than 1 page for now. */
    245                         return;
    246                 }
    247         }
     234        /* Disallow text longer than 1 page for now. */
     235        unsigned prompt_len = ti->text_coord - ti->prompt_coord;
     236        if (prompt_len + ti->nc + 1 >= ti->con_cols * ti->con_rows)
     237                return;
    248238
    249239        size_t i;
     
    881871}
    882872
     873static errno_t tinput_resize(tinput_t *ti)
     874{
     875        assert(ti->prompt_coord % ti->con_cols == 0);
     876
     877        errno_t rc = console_get_size(ti->console, &ti->con_cols, &ti->con_rows);
     878        if (rc != EOK)
     879                return rc;
     880
     881        sysarg_t col, row;
     882        rc = console_get_pos(ti->console, &col, &row);
     883        if (rc != EOK)
     884                return rc;
     885
     886        assert(ti->prompt_coord <= ti->text_coord);
     887        unsigned prompt_len = ti->text_coord - ti->prompt_coord;
     888
     889        size_t new_caret_coord = row * ti->con_cols + col;
     890
     891        if (prompt_len <= new_caret_coord && ti->pos <= new_caret_coord - prompt_len) {
     892                ti->text_coord = new_caret_coord - ti->pos;
     893                ti->prompt_coord = ti->text_coord - prompt_len;
     894
     895                unsigned prompt_col = ti->prompt_coord % ti->con_cols;
     896                if (prompt_col != 0) {
     897                        /*
     898                         * Prompt doesn't seem to start at column 0, which means
     899                         * the console didn't reflow the line like we expected it to.
     900                         * Change offsets a bit to recover.
     901                         */
     902                        fprintf(stderr, "Unexpected prompt position after resize.\n");
     903                        ti->prompt_coord -= prompt_col;
     904                        ti->text_coord -= prompt_col;
     905
     906                        console_cursor_visibility(ti->console, false);
     907                        tinput_display_prompt(ti);
     908                        tinput_display_tail(ti, 0, prompt_col);
     909                        tinput_position_caret(ti);
     910                        console_cursor_visibility(ti->console, true);
     911                }
     912
     913                assert(ti->prompt_coord % ti->con_cols == 0);
     914        } else {
     915                /*
     916                 * Overflown screen.
     917                 * We will just trim the buffer and rewrite everything.
     918                 */
     919                console_clear(ti->console);
     920
     921                ti->nc = min(ti->nc, ti->con_cols * ti->con_rows - prompt_len - 1);
     922                ti->pos = min(ti->pos, ti->nc);
     923                ti->sel_start = min(ti->sel_start, ti->nc);
     924
     925                ti->prompt_coord = 0;
     926                ti->text_coord = prompt_len;
     927
     928                console_cursor_visibility(ti->console, false);
     929                tinput_display_prompt(ti);
     930                tinput_display_tail(ti, 0, 0);
     931                tinput_position_caret(ti);
     932                console_cursor_visibility(ti->console, true);
     933        }
     934
     935        assert(ti->nc + ti->text_coord < ti->con_cols * ti->con_rows);
     936
     937        return EOK;
     938}
     939
    883940/** Read in one line of input with initial text provided.
    884941 *
     
    927984                        tinput_pos(ti, &ev.ev.pos);
    928985                        break;
     986                case CEV_RESIZE:
     987                        tinput_resize(ti);
     988                        break;
    929989                }
    930990        }
Note: See TracChangeset for help on using the changeset viewer.