add proper text editing functionality

This commit is contained in:
hippoz 2023-05-20 18:30:40 +03:00
parent 7901afc47c
commit 1d7c2c6f92
Signed by: hippoz
GPG key ID: 56C4E02A85F2FBED
5 changed files with 98 additions and 15 deletions

View file

@ -13,6 +13,7 @@
#include "dispatcher-node.h" #include "dispatcher-node.h"
#include "box-layout-node.h" #include "box-layout-node.h"
#include "colors.h" #include "colors.h"
#include <string.h>
#include <xcb/randr.h> #include <xcb/randr.h>
typedef struct AppState { typedef struct AppState {
@ -114,6 +115,8 @@ int app_handle(struct UINode *node, void *data, int event_type, size_t d, void *
text_input->node.rect.w = 120; text_input->node.rect.w = 120;
text_input->node.rect.h = 32; text_input->node.rect.h = 32;
text_input->text_node = text_node_new(&text_input->node, state->font, UINeutral50, NULL); text_input->text_node = text_node_new(&text_input->node, state->font, UINeutral50, NULL);
text_input->text_node->node.width_policy = UI_SIZE_POLICY_GROW;
text_input->text_node->node.height_policy = UI_SIZE_POLICY_GROW;
} }
/* a bunch of buttons */ /* a bunch of buttons */
@ -130,7 +133,7 @@ int app_handle(struct UINode *node, void *data, int event_type, size_t d, void *
box_layout_new(buttons, UI_DIRECTION_VERTICAL); box_layout_new(buttons, UI_DIRECTION_VERTICAL);
for (int i = 0; i < 10000; i++) { for (int i = 0; i < 20; i++) {
UINode *button = node_new(buttons, "button"); UINode *button = node_new(buttons, "button");
state_background_node_new(button, UIPurple600, UIPurple700, UIPurple800, 6.0); state_background_node_new(button, UIPurple600, UIPurple700, UIPurple800, 6.0);
text_node_new(button, state->font, UINeutral50, "button"); text_node_new(button, state->font, UINeutral50, "button");

31
src/str.c Normal file
View file

@ -0,0 +1,31 @@
#include "str.h"
#include <string.h>
int ui_string_insert(UIString *str, const size_t where, const char *d, const size_t dsize)
{
size_t required_capacity = str->size + dsize;
if (required_capacity > str->capacity) {
str->data = realloc(str->data, required_capacity + 1);
str->data[required_capacity] = '\0';
str->capacity = required_capacity;
}
memmove(str->data + where + dsize, str->data + where, str->capacity - where - dsize);
memcpy(str->data + where, d, dsize);
str->size += dsize;
return 0;
}
int ui_string_delete(UIString *str, const size_t where, const size_t amount)
{
if (str->data + where + amount > str->data + str->capacity) {
return -1;
}
memmove(str->data + where, str->data + where + amount, str->capacity - where - amount);
str->size -= amount;
str->data[str->size] = '\0';
return 0;
}

15
src/str.h Normal file
View file

@ -0,0 +1,15 @@
#ifndef _UI__STR_H
#define _UI__STR_H
#include <stdlib.h>
typedef struct UIString {
size_t size;
size_t capacity;
char *data;
} UIString;
int ui_string_insert(UIString *str, const size_t where, const char *d, const size_t dsize);
int ui_string_delete(UIString *str, const size_t where, const size_t amount);
#endif

View file

@ -1,9 +1,11 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <xkbcommon/xkbcommon.h> #include <xkbcommon/xkbcommon.h>
#include <xkbcommon/xkbcommon-keysyms.h> #include <xkbcommon/xkbcommon-keysyms.h>
#include "node.h" #include "node.h"
#include "text-node.h" #include "text-node.h"
#include "text-input-node.h" #include "text-input-node.h"
#include "str.h"
UITextInputNode *text_input_new(UINode *parent) UITextInputNode *text_input_new(UINode *parent)
{ {
@ -13,8 +15,7 @@ UITextInputNode *text_input_new(UINode *parent)
n->node.flags = UI_NODE_RETAINS_PRESS; n->node.flags = UI_NODE_RETAINS_PRESS;
n->node.text = "text_input"; n->node.text = "text_input";
n->node.handle_proto = text_input_handle; n->node.handle_proto = text_input_handle;
n->text = calloc(1, 1); n->text = (UIString){0};
n->text_size = 1;
n->text_cursor_index = 0; n->text_cursor_index = 0;
node_attach(parent, (UINode*)n); node_attach(parent, (UINode*)n);
return n; return n;
@ -36,26 +37,59 @@ int text_input_handle(UINode *node, enum UIEvent ev, size_t d, void *p)
switch (keysym) { switch (keysym) {
case XKB_KEY_BackSpace: { case XKB_KEY_BackSpace: {
if (n->text_cursor_index > 0 && n->text_size > 1) { if (n->text_cursor_index > 0) {
n->text[--n->text_cursor_index] = '\0'; ui_string_delete(&n->text, --n->text_cursor_index, 1);
n->text = realloc(n->text, n->text_size--); }
break;
}
case XKB_KEY_Delete: {
if (n->text_cursor_index > 0 && n->text_cursor_index + 1 <= n->text.size) {
ui_string_delete(&n->text, n->text_cursor_index + 1, 1);
}
if (n->text_cursor_index > n->text.size) {
n->text_cursor_index = n->text.size - 1;
}
break;
}
case XKB_KEY_Home: {
n->text_cursor_index = 0;
break;
}
case XKB_KEY_End: {
n->text_cursor_index = n->text.size;
break;
}
case XKB_KEY_Left: {
if (n->text_cursor_index > 0) {
n->text_cursor_index--;
}
break;
}
case XKB_KEY_Right: {
if (n->text_cursor_index < n->text.size) {
n->text_cursor_index++;
} }
break; break;
} }
default: { default: {
size_t key_size = xkb_state_key_get_utf8(xkb_state, keycode, NULL, 0); size_t input_size = xkb_state_key_get_utf8(xkb_state, keycode, NULL, 0) + 1;
size_t new_text_size = n->text_size + key_size; if (input_size <= 1) {
n->text = realloc(n->text, new_text_size); break;
xkb_state_key_get_utf8(xkb_state, keycode, n->text + n->text_cursor_index, key_size + 1); }
n->text_cursor_index += key_size;
n->text_size = new_text_size; char *input_buf = calloc(1, input_size);
xkb_state_key_get_utf8(xkb_state, keycode, input_buf, input_size);
ui_string_insert(&n->text, n->text_cursor_index, input_buf, input_size - 1);
n->text_cursor_index++;
free(input_buf);
break; break;
} }
} }
if (n->text_node) { if (n->text_node) {
n->text_node->pending_text = n->text; n->text_node->pending_text = n->text.data;
n->text_node->caret_index = n->text_cursor_index; n->text_node->caret_index = n->text_cursor_index;
n->text_node->wrap = true;
node_request_relayout(&n->text_node->node); node_request_relayout(&n->text_node->node);
} }

View file

@ -3,12 +3,12 @@
#include "node.h" #include "node.h"
#include "text-node.h" #include "text-node.h"
#include "str.h"
typedef struct UITextInputNode { typedef struct UITextInputNode {
UINode node; UINode node;
UITextNode *text_node; UITextNode *text_node;
char *text; UIString text;
size_t text_size;
size_t text_cursor_index; size_t text_cursor_index;
} UITextInputNode; } UITextInputNode;