Changeset 61bf9dd9 in mainline


Ignore:
Timestamp:
2021-06-30T16:48:54Z (3 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
d63623f
Parents:
5d1ff11
Message:

Seeking in entry text (using keyboard)

Seek using Home, End, Left Arrow and Right Arrow keys, delete character
after cursor using Delete key.

Location:
uspace/lib/ui
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/ui/include/ui/entry.h

    r5d1ff11 r61bf9dd9  
    5353extern errno_t ui_entry_set_text(ui_entry_t *, const char *);
    5454extern errno_t ui_entry_paint(ui_entry_t *);
     55extern void ui_entry_backspace(ui_entry_t *);
     56extern void ui_entry_delete(ui_entry_t *);
     57extern void ui_entry_seek_start(ui_entry_t *);
     58extern void ui_entry_seek_end(ui_entry_t *);
     59extern void ui_entry_seek_prev_char(ui_entry_t *);
     60extern void ui_entry_seek_next_char(ui_entry_t *);
    5561extern ui_evclaim_t ui_entry_kbd_event(ui_entry_t *, kbd_event_t *);
    5662extern ui_evclaim_t ui_entry_pos_event(ui_entry_t *, pos_event_t *);
  • uspace/lib/ui/private/entry.h

    r5d1ff11 r61bf9dd9  
    5858        /** Text */
    5959        char *text;
     60        /** Cursor position in the text (offset in bytes) */
     61        unsigned pos;
    6062        /** Pointer is currently inside */
    6163        bool pointer_inside;
     
    6567
    6668extern errno_t ui_entry_insert_str(ui_entry_t *, const char *);
    67 extern void ui_entry_backspace(ui_entry_t *);
    6869extern ui_evclaim_t ui_entry_key_press_unmod(ui_entry_t *, kbd_event_t *);
    6970extern void ui_entry_activate(ui_entry_t *);
  • uspace/lib/ui/src/entry.c

    r5d1ff11 r61bf9dd9  
    180180        free(entry->text);
    181181        entry->text = tcopy;
     182        entry->pos = str_size(text);
    182183
    183184        return EOK;
     
    223224error:
    224225        return rc;
     226}
     227
     228/** Return width of text before cursor.
     229 *
     230 * @param entry Text entry
     231 * @return Widht of text before cursor
     232 */
     233static gfx_coord_t ui_entry_lwidth(ui_entry_t *entry)
     234{
     235        ui_resource_t *res;
     236        uint8_t tmp;
     237        gfx_coord_t width;
     238
     239        res = ui_window_get_res(entry->window);
     240
     241        tmp = entry->text[entry->pos];
     242
     243        entry->text[entry->pos] = '\0';
     244        width = gfx_text_width(res->font, entry->text);
     245        entry->text[entry->pos] = tmp;
     246
     247        return width;
    225248}
    226249
     
    304327        if (entry->active) {
    305328                /* Cursor */
    306                 pos.x += width;
     329                pos.x += ui_entry_lwidth(entry);
    307330
    308331                rc = ui_entry_paint_cursor(entry, &pos);
     
    357380errno_t ui_entry_insert_str(ui_entry_t *entry, const char *str)
    358381{
     382        uint8_t tmp;
     383        char *ltext = NULL;
    359384        char *newtext;
    360385        char *oldtext;
    361386        int rc;
    362387
    363         rc = asprintf(&newtext, "%s%s", entry->text, str);
    364         if (rc < 0)
     388        tmp = entry->text[entry->pos];
     389        entry->text[entry->pos] = '\0';
     390        ltext = str_dup(entry->text);
     391        if (ltext == NULL)
    365392                return ENOMEM;
     393
     394        entry->text[entry->pos] = tmp;
     395
     396        rc = asprintf(&newtext, "%s%s%s", ltext, str, entry->text + entry->pos);
     397        if (rc < 0) {
     398                free(ltext);
     399                return ENOMEM;
     400        }
    366401
    367402        oldtext = entry->text;
    368403        entry->text = newtext;
     404        entry->pos += str_size(str);
    369405        free(oldtext);
     406        free(ltext);
     407
    370408        ui_entry_paint(entry);
    371409
     
    381419        size_t off;
    382420
    383         off = str_size(entry->text);
     421        if (entry->pos == 0)
     422                return;
     423
     424        /* Find offset where character before cursor starts */
     425        off = entry->pos;
    384426        (void) str_decode_reverse(entry->text, &off,
    385427            str_size(entry->text));
    386         entry->text[off] = '\0';
     428
     429        memmove(entry->text + off, entry->text + entry->pos,
     430            str_size(entry->text + entry->pos) + 1);
     431        entry->pos = off;
     432
     433        ui_entry_paint(entry);
     434}
     435
     436/** Delete character after cursor.
     437 *
     438 * @param entry Text entry
     439 */
     440void ui_entry_delete(ui_entry_t *entry)
     441{
     442        size_t off;
     443
     444        /* Find offset where character after cursor end */
     445        off = entry->pos;
     446        (void) str_decode(entry->text, &off,
     447            str_size(entry->text));
     448
     449        memmove(entry->text + entry->pos, entry->text + off,
     450            str_size(entry->text + off) + 1);
     451
    387452        ui_entry_paint(entry);
    388453}
     
    398463        assert(event->type == KEY_PRESS);
    399464
    400         if (event->key == KC_BACKSPACE)
     465        switch (event->key) {
     466        case KC_BACKSPACE:
    401467                ui_entry_backspace(entry);
    402 
    403         if (event->key == KC_ESCAPE)
     468                break;
     469
     470        case KC_DELETE:
     471                ui_entry_delete(entry);
     472                break;
     473
     474        case KC_ESCAPE:
    404475                ui_entry_deactivate(entry);
     476                break;
     477
     478        case KC_HOME:
     479                ui_entry_seek_start(entry);
     480                break;
     481
     482        case KC_END:
     483                ui_entry_seek_end(entry);
     484                break;
     485
     486        case KC_LEFT:
     487                ui_entry_seek_prev_char(entry);
     488                break;
     489
     490        case KC_RIGHT:
     491                ui_entry_seek_next_char(entry);
     492                break;
     493
     494        default:
     495                break;
     496        }
    405497
    406498        return ui_claimed;
     
    526618
    527619        entry->active = true;
     620        entry->pos = str_size(entry->text);
    528621        (void) ui_entry_paint(entry);
    529622
     
    532625}
    533626
     627/** Move text cursor to the beginning of text.
     628 *
     629 * @param entry Text entry
     630 */
     631void ui_entry_seek_start(ui_entry_t *entry)
     632{
     633        entry->pos = 0;
     634        (void) ui_entry_paint(entry);
     635}
     636
     637/** Move text cursor to the end of text.
     638 *
     639 * @param entry Text entry
     640 */
     641void ui_entry_seek_end(ui_entry_t *entry)
     642{
     643        entry->pos = str_size(entry->text);
     644        (void) ui_entry_paint(entry);
     645}
     646
     647/** Move text cursor one character backward.
     648 *
     649 * @param entry Text entry
     650 */
     651void ui_entry_seek_prev_char(ui_entry_t *entry)
     652{
     653        size_t off;
     654
     655        off = entry->pos;
     656        (void) str_decode_reverse(entry->text, &off,
     657            str_size(entry->text));
     658        entry->pos = off;
     659        (void) ui_entry_paint(entry);
     660}
     661
     662/** Move text cursor one character forward.
     663 *
     664 * @param entry Text entry
     665 */
     666void ui_entry_seek_next_char(ui_entry_t *entry)
     667{
     668        size_t off;
     669
     670        off = entry->pos;
     671        (void) str_decode(entry->text, &off,
     672            str_size(entry->text));
     673        entry->pos = off;
     674        (void) ui_entry_paint(entry);
     675}
     676
    534677/** Deactivate text entry.
    535678 *
  • uspace/lib/ui/test/entry.c

    r5d1ff11 r61bf9dd9  
    214214        PCUT_ASSERT_STR_EQUALS("A", entry->text);
    215215
     216        /* This moves the cursor to the end of the text */
     217        ui_entry_activate(entry);
     218
    216219        rc = ui_entry_insert_str(entry, "B");
    217220        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     
    219222        PCUT_ASSERT_STR_EQUALS("AB", entry->text);
    220223
     224        rc = ui_entry_insert_str(entry, "EF");
     225        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     226
     227        PCUT_ASSERT_STR_EQUALS("ABEF", entry->text);
     228
     229        entry->pos = 2;
    221230        rc = ui_entry_insert_str(entry, "CD");
    222231        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
    223232
    224         PCUT_ASSERT_STR_EQUALS("ABCD", entry->text);
     233        PCUT_ASSERT_STR_EQUALS("ABCDEF", entry->text);
    225234
    226235        ui_entry_destroy(entry);
     
    248257        PCUT_ASSERT_NOT_NULL(window);
    249258
    250         rc = ui_entry_create(window, "ABC", &entry);
    251         PCUT_ASSERT_ERRNO_VAL(EOK, rc);
    252 
    253         PCUT_ASSERT_STR_EQUALS("ABC", entry->text);
     259        rc = ui_entry_create(window, "ABCD", &entry);
     260        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     261
     262        PCUT_ASSERT_STR_EQUALS("ABCD", entry->text);
     263        entry->pos = 3;
    254264
    255265        ui_entry_backspace(entry);
    256         PCUT_ASSERT_STR_EQUALS("AB", entry->text);
     266        PCUT_ASSERT_STR_EQUALS("ABD", entry->text);
    257267
    258268        ui_entry_backspace(entry);
     269        PCUT_ASSERT_STR_EQUALS("AD", entry->text);
     270
     271        ui_entry_backspace(entry);
     272        PCUT_ASSERT_STR_EQUALS("D", entry->text);
     273
     274        ui_entry_backspace(entry);
     275        PCUT_ASSERT_STR_EQUALS("D", entry->text);
     276
     277        ui_entry_destroy(entry);
     278        ui_window_destroy(window);
     279        ui_destroy(ui);
     280}
     281
     282/** ui_entry_delete() deletes character after cursor. */
     283PCUT_TEST(delete)
     284{
     285        errno_t rc;
     286        ui_t *ui = NULL;
     287        ui_window_t *window = NULL;
     288        ui_wnd_params_t params;
     289        ui_entry_t *entry;
     290
     291        rc = ui_create_disp(NULL, &ui);
     292        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     293
     294        ui_wnd_params_init(&params);
     295        params.caption = "Hello";
     296
     297        rc = ui_window_create(ui, &params, &window);
     298        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     299        PCUT_ASSERT_NOT_NULL(window);
     300
     301        rc = ui_entry_create(window, "ABCD", &entry);
     302        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     303
     304        PCUT_ASSERT_STR_EQUALS("ABCD", entry->text);
     305        entry->pos = 1;
     306
     307        ui_entry_delete(entry);
     308        PCUT_ASSERT_STR_EQUALS("ACD", entry->text);
     309
     310        ui_entry_delete(entry);
     311        PCUT_ASSERT_STR_EQUALS("AD", entry->text);
     312
     313        ui_entry_delete(entry);
    259314        PCUT_ASSERT_STR_EQUALS("A", entry->text);
    260315
    261         ui_entry_backspace(entry);
    262         PCUT_ASSERT_STR_EQUALS("", entry->text);
    263 
    264         ui_entry_backspace(entry);
    265         PCUT_ASSERT_STR_EQUALS("", entry->text);
     316        ui_entry_delete(entry);
     317        PCUT_ASSERT_STR_EQUALS("A", entry->text);
     318
     319        ui_entry_destroy(entry);
     320        ui_window_destroy(window);
     321        ui_destroy(ui);
     322}
     323
     324/** ui_entry_seek_start() moves cursor to beginning of text */
     325PCUT_TEST(seek_start)
     326{
     327        errno_t rc;
     328        ui_t *ui = NULL;
     329        ui_window_t *window = NULL;
     330        ui_wnd_params_t params;
     331        ui_entry_t *entry;
     332
     333        rc = ui_create_disp(NULL, &ui);
     334        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     335
     336        ui_wnd_params_init(&params);
     337        params.caption = "Hello";
     338
     339        rc = ui_window_create(ui, &params, &window);
     340        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     341        PCUT_ASSERT_NOT_NULL(window);
     342
     343        rc = ui_entry_create(window, "ABCD", &entry);
     344        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     345
     346        PCUT_ASSERT_STR_EQUALS("ABCD", entry->text);
     347        entry->pos = 2;
     348
     349        ui_entry_seek_start(entry);
     350        PCUT_ASSERT_INT_EQUALS(0, entry->pos);
     351
     352        ui_entry_destroy(entry);
     353        ui_window_destroy(window);
     354        ui_destroy(ui);
     355}
     356
     357/** ui_entry_seek_end() moves cursor to the end of text */
     358PCUT_TEST(seek_end)
     359{
     360        errno_t rc;
     361        ui_t *ui = NULL;
     362        ui_window_t *window = NULL;
     363        ui_wnd_params_t params;
     364        ui_entry_t *entry;
     365
     366        rc = ui_create_disp(NULL, &ui);
     367        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     368
     369        ui_wnd_params_init(&params);
     370        params.caption = "Hello";
     371
     372        rc = ui_window_create(ui, &params, &window);
     373        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     374        PCUT_ASSERT_NOT_NULL(window);
     375
     376        rc = ui_entry_create(window, "ABCD", &entry);
     377        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     378
     379        PCUT_ASSERT_STR_EQUALS("ABCD", entry->text);
     380        entry->pos = 2;
     381
     382        ui_entry_seek_end(entry);
     383        PCUT_ASSERT_INT_EQUALS(4, entry->pos);
     384
     385        ui_entry_destroy(entry);
     386        ui_window_destroy(window);
     387        ui_destroy(ui);
     388}
     389
     390/** ui_entry_seek_prev_char() moves cursor to the previous character */
     391PCUT_TEST(seek_prev_char)
     392{
     393        errno_t rc;
     394        ui_t *ui = NULL;
     395        ui_window_t *window = NULL;
     396        ui_wnd_params_t params;
     397        ui_entry_t *entry;
     398
     399        rc = ui_create_disp(NULL, &ui);
     400        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     401
     402        ui_wnd_params_init(&params);
     403        params.caption = "Hello";
     404
     405        rc = ui_window_create(ui, &params, &window);
     406        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     407        PCUT_ASSERT_NOT_NULL(window);
     408
     409        rc = ui_entry_create(window, "ABCD", &entry);
     410        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     411
     412        PCUT_ASSERT_STR_EQUALS("ABCD", entry->text);
     413        entry->pos = 2;
     414
     415        ui_entry_seek_prev_char(entry);
     416        PCUT_ASSERT_INT_EQUALS(1, entry->pos);
     417
     418        ui_entry_destroy(entry);
     419        ui_window_destroy(window);
     420        ui_destroy(ui);
     421}
     422
     423/** ui_entry_seek_prev_char() moves cursor to the next character */
     424PCUT_TEST(seek_next_char)
     425{
     426        errno_t rc;
     427        ui_t *ui = NULL;
     428        ui_window_t *window = NULL;
     429        ui_wnd_params_t params;
     430        ui_entry_t *entry;
     431
     432        rc = ui_create_disp(NULL, &ui);
     433        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     434
     435        ui_wnd_params_init(&params);
     436        params.caption = "Hello";
     437
     438        rc = ui_window_create(ui, &params, &window);
     439        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     440        PCUT_ASSERT_NOT_NULL(window);
     441
     442        rc = ui_entry_create(window, "ABCD", &entry);
     443        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     444
     445        PCUT_ASSERT_STR_EQUALS("ABCD", entry->text);
     446        entry->pos = 2;
     447
     448        ui_entry_seek_next_char(entry);
     449        PCUT_ASSERT_INT_EQUALS(3, entry->pos);
    266450
    267451        ui_entry_destroy(entry);
Note: See TracChangeset for help on using the changeset viewer.