ui: move cursor through the text in input

This commit is contained in:
2026-01-02 12:45:41 +02:00
parent 6a9dad9557
commit 34e58daa42
5 changed files with 56 additions and 22 deletions
+2 -2
View File
@@ -12,6 +12,6 @@ TODO:
- [ ] "Server message" to notification - [ ] "Server message" to notification
INPUT: INPUT:
- [ ] hidden text for passwords - [x] hidden text for passwords
- [ ] move cursor through the text in input - [x] move cursor through the text in input
+28 -10
View File
@@ -53,8 +53,8 @@ void dialogue_default_callback(callback_args_t *args) {
new_args.active_id = d->active.id; new_args.active_id = d->active.id;
int32_t diff; int32_t diff;
d->needs_update = true; d->needs_update = true;
input_t *input;
switch (key) { switch (key) {
case KEY_RIGHT:
case '\t': case '\t':
if (d->active.type == g_content) { if (d->active.type == g_content) {
INCR_ACTIVE_ID(d, g_content, g_action); 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); INCR_ACTIVE_ID(d, g_action, g_content);
} }
*resp_value = -1; *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; break;
case KEY_LEFT: case KEY_LEFT:
if (d->active.type == g_content) { 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->value_len > input->cur_pos) {
input->cur_pos += 1;
}
} else {
DECR_ACTIVE_ID(d, g_content, g_action); DECR_ACTIVE_ID(d, g_content, g_action);
}
} else if (d->active.type == g_action) { } else if (d->active.type == g_action) {
DECR_ACTIVE_ID(d, g_action, g_content); DECR_ACTIVE_ID(d, g_action, g_content);
} }
*resp_value = -1; *resp_value = -1;
break; break;
case '\n': case '\n':
if (d->active.type == g_action) { 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; *resp_value = d->active.id - d->g_content->first_id;
return; return;
} }
break; break;
case KEY_UP: case KEY_UP:
CH_GROUP(d, g_action, g_content); CH_GROUP(d, g_action, g_content);
break; break;
case KEY_DOWN: case KEY_DOWN:
CH_GROUP(d, g_content, g_action); CH_GROUP(d, g_content, g_action);
break; break;
default: default:
/* run callback function */ /* run callback function */
@@ -239,11 +260,8 @@ int32_t draw_dialogue(dialogue_t *d) {
if (ae_ptr->type == w_input) { if (ae_ptr->type == w_input) {
input_t *input = ae_ptr->element; input_t *input = ae_ptr->element;
d->w.cur.y = input->w.cur.y; 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) { if (d->w.cur.y || d->w.cur.x) {
wmove(d->win, d->w.cur.y, d->w.cur.x); wmove(d->win, d->w.cur.y, d->w.cur.x);
curs_set(1); curs_set(1);
+17 -3
View File
@@ -5,10 +5,9 @@
#include <ncurses.h> #include <ncurses.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <sys/types.h> #include <sys/types.h>
// TODO: refactor
#define MAKE_RESPONSE_M1(args, resp_data, response) \ #define MAKE_RESPONSE_M1(args, resp_data, response) \
if (args->resp_data != NULL) { \ if (args->resp_data != NULL) { \
*response = -1; \ *response = -1; \
@@ -21,6 +20,7 @@ void group_default_callback(callback_args_t *args) {
input_t *input; input_t *input;
group_el_t *element_ptr; group_el_t *element_ptr;
int32_t element_idx = -1; int32_t element_idx = -1;
u_int32_t start_pos = 0;
switch (key) { switch (key) {
case '\n': /* Enter */ case '\n': /* Enter */
FIND_ACTIVE_ELEMENT(g, args->active_id, element_ptr, element_idx); FIND_ACTIVE_ELEMENT(g, args->active_id, element_ptr, element_idx);
@@ -32,9 +32,15 @@ void group_default_callback(callback_args_t *args) {
if (element_ptr->type == w_input) { if (element_ptr->type == w_input) {
input = (input_t *)element_ptr->element; input = (input_t *)element_ptr->element;
if (input->value_len) { if (input->value_len) {
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'; input->value[--input->value_len] = '\0';
} }
} }
}
MAKE_RESPONSE_M1(args, resp_data, response); MAKE_RESPONSE_M1(args, resp_data, response);
break; break;
default: default:
@@ -42,10 +48,17 @@ void group_default_callback(callback_args_t *args) {
if (element_ptr->type == w_input) { if (element_ptr->type == w_input) {
input = (input_t *)element_ptr->element; input = (input_t *)element_ptr->element;
if (input->max_len > input->value_len) { if (input->max_len > input->value_len) {
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++] = key;
input->value[input->value_len] = '\0'; input->value[input->value_len] = '\0';
} }
} }
}
MAKE_RESPONSE_M1(args, resp_data, response); MAKE_RESPONSE_M1(args, resp_data, response);
break; break;
} }
@@ -85,7 +98,8 @@ group_t *init_group(WINDOW **win, widget_t *w_parent, group_el_init_t *children,
break; break;
case w_input: case w_input:
elements[i].element = 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); w = &(((input_t *)elements[i].element)->w);
break; break;
case w_progress: case w_progress:
+2 -1
View File
@@ -13,7 +13,7 @@ input_t *init_input(WINDOW **win, widget_t *w_parent, char *label,
init_widget(&(input->w), w_parent, win, label); init_widget(&(input->w), w_parent, win, label);
input->is_disabled = 0; input->is_disabled = 0;
input->w.y = 3; // with borders 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 uint32_t t_len = strlen(input->w.title) + 4; // with borders and space
if (input->w.x < t_len) if (input->w.x < t_len)
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->value_len = 0;
input->max_len = length; input->max_len = length;
input->is_hidden = is_hidden_value; input->is_hidden = is_hidden_value;
input->cur_pos = 0;
return input; return input;
} }
+1
View File
@@ -8,6 +8,7 @@
typedef struct { typedef struct {
widget_t w; widget_t w;
char value[INPUT_TEXT]; char value[INPUT_TEXT];
uint32_t cur_pos; /* is relative to the end of a string */
uint32_t value_len; uint32_t value_len;
uint32_t max_len; uint32_t max_len;
uint32_t is_disabled : 1; uint32_t is_disabled : 1;