From 34e58daa426ce002ed81bab5c150ec91992574de Mon Sep 17 00:00:00 2001 From: Alexander Zhylin Date: Fri, 2 Jan 2026 12:45:41 +0200 Subject: [PATCH] ui: move cursor through the text in input --- TODO.md | 4 ++-- src/ui/widget/dialogue.c | 44 ++++++++++++++++++++++++++++------------ src/ui/widget/group.c | 26 ++++++++++++++++++------ src/ui/widget/input.c | 3 ++- src/ui/widget/input.h | 1 + 5 files changed, 56 insertions(+), 22 deletions(-) diff --git a/TODO.md b/TODO.md index 6a32339..bf10a36 100644 --- a/TODO.md +++ b/TODO.md @@ -12,6 +12,6 @@ TODO: - [ ] "Server message" to notification INPUT: -- [ ] hidden text for passwords -- [ ] move cursor through the text in input +- [x] hidden text for passwords +- [x] move cursor through the text in input diff --git a/src/ui/widget/dialogue.c b/src/ui/widget/dialogue.c index f0321c5..5cb051c 100644 --- a/src/ui/widget/dialogue.c +++ b/src/ui/widget/dialogue.c @@ -53,8 +53,8 @@ void dialogue_default_callback(callback_args_t *args) { new_args.active_id = d->active.id; int32_t diff; d->needs_update = true; - switch (key) { - case KEY_RIGHT: + input_t *input; + switch (key) { case '\t': if (d->active.type == g_content) { INCR_ACTIVE_ID(d, g_content, g_action); @@ -62,16 +62,40 @@ void dialogue_default_callback(callback_args_t *args) { INCR_ACTIVE_ID(d, g_action, g_content); } *resp_value = -1; - + break; + case KEY_RIGHT: + if (d->active.type == g_content) { + if (d->g_content->elements[d->active.id - d->g_content->first_id].type == + w_input) { + input = d->g_content->elements[d->active.id - d->g_content->first_id] + .element; + if (input->cur_pos > 0) { + input->cur_pos -= 1; + } + } else { + INCR_ACTIVE_ID(d, g_content, g_action); + } + } else if (d->active.type == g_action) { + INCR_ACTIVE_ID(d, g_action, g_content); + } + *resp_value = -1; break; case KEY_LEFT: if (d->active.type == g_content) { - DECR_ACTIVE_ID(d, g_content, g_action); + if (d->g_content->elements[d->active.id - d->g_content->first_id].type == + w_input) { + input = d->g_content->elements[d->active.id - d->g_content->first_id] + .element; + if (input->value_len > input->cur_pos) { + input->cur_pos += 1; + } + } else { + DECR_ACTIVE_ID(d, g_content, g_action); + } } else if (d->active.type == g_action) { DECR_ACTIVE_ID(d, g_action, g_content); } *resp_value = -1; - break; case '\n': if (d->active.type == g_action) { @@ -89,15 +113,12 @@ void dialogue_default_callback(callback_args_t *args) { *resp_value = d->active.id - d->g_content->first_id; return; } - break; case KEY_UP: CH_GROUP(d, g_action, g_content); - break; case KEY_DOWN: CH_GROUP(d, g_content, g_action); - break; default: /* run callback function */ @@ -239,11 +260,8 @@ int32_t draw_dialogue(dialogue_t *d) { if (ae_ptr->type == w_input) { input_t *input = ae_ptr->element; d->w.cur.y = input->w.cur.y; - if (input->max_len == input->value_len) { - d->w.cur.x = input->w.cur.x + input->value_len - 1; - } else { - d->w.cur.x = input->w.cur.x + input->value_len; - } + d->w.cur.x = input->w.cur.x + input->value_len; + d->w.cur.x -= input->cur_pos; if (d->w.cur.y || d->w.cur.x) { wmove(d->win, d->w.cur.y, d->w.cur.x); curs_set(1); diff --git a/src/ui/widget/group.c b/src/ui/widget/group.c index d5f1f62..2b8828c 100644 --- a/src/ui/widget/group.c +++ b/src/ui/widget/group.c @@ -5,10 +5,9 @@ #include #include #include +#include #include -// TODO: refactor - #define MAKE_RESPONSE_M1(args, resp_data, response) \ if (args->resp_data != NULL) { \ *response = -1; \ @@ -21,6 +20,7 @@ void group_default_callback(callback_args_t *args) { input_t *input; group_el_t *element_ptr; int32_t element_idx = -1; + u_int32_t start_pos = 0; switch (key) { case '\n': /* Enter */ FIND_ACTIVE_ELEMENT(g, args->active_id, element_ptr, element_idx); @@ -32,7 +32,13 @@ void group_default_callback(callback_args_t *args) { if (element_ptr->type == w_input) { input = (input_t *)element_ptr->element; if (input->value_len) { - input->value[--input->value_len] = '\0'; + if (input->cur_pos > 0) { + start_pos = input->value_len-- - input->cur_pos; + memmove(input->value + start_pos - 1, input->value + start_pos, + input->value_len - start_pos + 2); + } else { + input->value[--input->value_len] = '\0'; + } } } MAKE_RESPONSE_M1(args, resp_data, response); @@ -42,8 +48,15 @@ void group_default_callback(callback_args_t *args) { if (element_ptr->type == w_input) { input = (input_t *)element_ptr->element; if (input->max_len > input->value_len) { - input->value[input->value_len++] = key; - input->value[input->value_len] = '\0'; + if (input->cur_pos > 0) { + start_pos = input->value_len++ - input->cur_pos; + memmove(input->value + start_pos + 1, input->value + start_pos, + input->value_len - start_pos); + input->value[start_pos] = key; + } else { + input->value[input->value_len++] = key; + input->value[input->value_len] = '\0'; + } } } MAKE_RESPONSE_M1(args, resp_data, response); @@ -85,7 +98,8 @@ group_t *init_group(WINDOW **win, widget_t *w_parent, group_el_init_t *children, break; case w_input: elements[i].element = - init_input(win, &(group->w), children[i].label, children[i].length, children[i].is_hidden_value); + init_input(win, &(group->w), children[i].label, children[i].length, + children[i].is_hidden_value); w = &(((input_t *)elements[i].element)->w); break; case w_progress: diff --git a/src/ui/widget/input.c b/src/ui/widget/input.c index 26a066f..a9e36a9 100644 --- a/src/ui/widget/input.c +++ b/src/ui/widget/input.c @@ -13,7 +13,7 @@ input_t *init_input(WINDOW **win, widget_t *w_parent, char *label, init_widget(&(input->w), w_parent, win, label); input->is_disabled = 0; input->w.y = 3; // with borders - input->w.x = length + 2; // with borders + input->w.x = length + 3; // with borders and extra space for the last element uint32_t t_len = strlen(input->w.title) + 4; // with borders and space if (input->w.x < t_len) input->w.x = t_len; @@ -22,6 +22,7 @@ input_t *init_input(WINDOW **win, widget_t *w_parent, char *label, input->value_len = 0; input->max_len = length; input->is_hidden = is_hidden_value; + input->cur_pos = 0; return input; } diff --git a/src/ui/widget/input.h b/src/ui/widget/input.h index 9bc33e5..10731a9 100644 --- a/src/ui/widget/input.h +++ b/src/ui/widget/input.h @@ -8,6 +8,7 @@ typedef struct { widget_t w; char value[INPUT_TEXT]; + uint32_t cur_pos; /* is relative to the end of a string */ uint32_t value_len; uint32_t max_len; uint32_t is_disabled : 1;