ui: text handling fixes
This commit is contained in:
+39
-17
@@ -17,8 +17,8 @@ static ui_theme_t *theme;
|
||||
static bool ui_key_repeat = true; // Emulate key repeat for non-character keys
|
||||
static bool ui_dynamic_glyph_load = true; // Allow text input fields to push new glyphs into the font atlas
|
||||
static float ui_key_repeat_time = 0.0;
|
||||
char ui_text_to_paste[8192];
|
||||
char ui_text_to_copy[8192];
|
||||
char ui_text_to_paste[UI_TEXT_MAX];
|
||||
char ui_text_to_copy[UI_TEXT_MAX];
|
||||
static bool ui_combo_first = true;
|
||||
static ui_handle_t *ui_combo_search_handle = NULL;
|
||||
static int touch_hold_x = -1;
|
||||
@@ -323,9 +323,13 @@ void ui_draw_string(char *text, float x_offset, float y_offset, int align, bool
|
||||
return;
|
||||
}
|
||||
if (truncation) {
|
||||
assert(strlen(text) < 1024 - 2);
|
||||
char *full_text = text;
|
||||
strcpy(truncated, text);
|
||||
size_t len = strlen(text);
|
||||
if (len > sizeof(truncated) - 3) {
|
||||
len = sizeof(truncated) - 3;
|
||||
}
|
||||
memcpy(truncated, text, len);
|
||||
truncated[len] = '\0';
|
||||
text = &truncated[0];
|
||||
while (strlen(text) > 0 && draw_string_width(current->ops->font, current->font_size, text) > current->_w - 6.0 * UI_SCALE()) {
|
||||
text[strlen(text) - 1] = 0;
|
||||
@@ -1128,6 +1132,20 @@ void ui_insert_chars_at(char *str, int at, char *cs) {
|
||||
}
|
||||
}
|
||||
|
||||
int ui_insert_chars_at_capped(char *str, int at, char *cs, int cap) {
|
||||
int len = strlen(str);
|
||||
int count = strlen(cs);
|
||||
if (len + count > cap - 1) {
|
||||
count = cap - 1 - len;
|
||||
}
|
||||
if (count <= 0) {
|
||||
return 0;
|
||||
}
|
||||
memmove(str + at + count, str + at, len - at + 1);
|
||||
memcpy(str + at, cs, count);
|
||||
return count;
|
||||
}
|
||||
|
||||
// Number of leading spaces to step over when moving/removing a tab backwards
|
||||
static int ui_tab_dedent_count(char *str, int cursor_x) {
|
||||
int n = cursor_x % 4;
|
||||
@@ -1160,7 +1178,7 @@ static int ui_tab_indent_count(char *str, int cursor_x, int len) {
|
||||
}
|
||||
|
||||
void ui_update_text_edit(int align, bool editable, bool live_update) {
|
||||
char text[1024];
|
||||
char text[UI_TEXT_MAX];
|
||||
strcpy(text, current->text_selected);
|
||||
if (current->is_key_pressed) { // Process input
|
||||
if (current->key_code == KEY_CODE_LEFT) { // Move cursor
|
||||
@@ -1318,8 +1336,8 @@ void ui_update_text_edit(int align, bool editable, bool live_update) {
|
||||
|
||||
if (editable && ui_is_paste) { // Process cut copy paste
|
||||
ui_remove_chars_at(text, current->highlight_anchor, current->cursor_x - current->highlight_anchor);
|
||||
ui_insert_chars_at(text, current->highlight_anchor, ui_text_to_paste);
|
||||
current->cursor_x += strlen(ui_text_to_paste);
|
||||
current->cursor_x = current->highlight_anchor;
|
||||
current->cursor_x += ui_insert_chars_at_capped(text, current->highlight_anchor, ui_text_to_paste, UI_TEXT_MAX);
|
||||
current->highlight_anchor = current->cursor_x;
|
||||
ui_text_to_paste[0] = 0;
|
||||
ui_is_paste = false;
|
||||
@@ -1327,20 +1345,20 @@ void ui_update_text_edit(int align, bool editable, bool live_update) {
|
||||
|
||||
if (ui_is_copy) {
|
||||
if (current->highlight_anchor == current->cursor_x) {
|
||||
strncpy(ui_text_to_copy, text, 8191); // Copy
|
||||
ui_text_to_copy[8191] = '\0';
|
||||
strncpy(ui_text_to_copy, text, UI_TEXT_MAX - 1); // Copy
|
||||
ui_text_to_copy[UI_TEXT_MAX - 1] = '\0';
|
||||
}
|
||||
else if (current->highlight_anchor < current->cursor_x) {
|
||||
int len = current->cursor_x - current->highlight_anchor;
|
||||
if (len > 8191)
|
||||
len = 8191;
|
||||
if (len > UI_TEXT_MAX - 1)
|
||||
len = UI_TEXT_MAX - 1;
|
||||
strncpy(ui_text_to_copy, text + current->highlight_anchor, len);
|
||||
ui_text_to_copy[len] = '\0';
|
||||
}
|
||||
else {
|
||||
int len = current->highlight_anchor - current->cursor_x;
|
||||
if (len > 8191)
|
||||
len = 8191;
|
||||
if (len > UI_TEXT_MAX - 1)
|
||||
len = UI_TEXT_MAX - 1;
|
||||
strncpy(ui_text_to_copy, text + current->cursor_x, len);
|
||||
ui_text_to_copy[len] = '\0';
|
||||
}
|
||||
@@ -2426,8 +2444,12 @@ void ui_separator(int h, bool fill) {
|
||||
}
|
||||
|
||||
void ui_tooltip(char *text) {
|
||||
assert(strlen(text) < 512);
|
||||
strcpy(current->tooltip_text, text);
|
||||
size_t len = strlen(text);
|
||||
if (len > sizeof(current->tooltip_text) - 1) {
|
||||
len = sizeof(current->tooltip_text) - 1;
|
||||
}
|
||||
memcpy(current->tooltip_text, text, len);
|
||||
current->tooltip_text[len] = '\0';
|
||||
current->tooltip_y = current->_y + current->_window_y;
|
||||
}
|
||||
|
||||
@@ -2739,8 +2761,8 @@ void ui_cut() {
|
||||
|
||||
void ui_paste(char *s) {
|
||||
ui_is_paste = true;
|
||||
strncpy(ui_text_to_paste, s, 8192);
|
||||
ui_text_to_paste[8191] = 0;
|
||||
strncpy(ui_text_to_paste, s, UI_TEXT_MAX - 1);
|
||||
ui_text_to_paste[UI_TEXT_MAX - 1] = 0;
|
||||
}
|
||||
|
||||
void ui_theme_default(ui_theme_t *t) {
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define UI_TEXT_MAX 8192
|
||||
|
||||
// #define UI_HANDLE(name) \
|
||||
// ui_handle_t _##name##_h = {.redraws = 2, .color = 0xffffffff, .text = "", .init = true}; \
|
||||
// ui_handle_t *name = &_##name##_h
|
||||
@@ -242,9 +244,9 @@ typedef struct ui {
|
||||
float restore_y;
|
||||
|
||||
ui_handle_t *text_selected_handle;
|
||||
char text_selected[1024];
|
||||
char text_selected[UI_TEXT_MAX];
|
||||
ui_handle_t *submit_text_handle;
|
||||
char text_to_submit[1024];
|
||||
char text_to_submit[UI_TEXT_MAX];
|
||||
bool tab_pressed;
|
||||
ui_handle_t *tab_pressed_handle;
|
||||
ui_handle_t *combo_selected_handle;
|
||||
@@ -368,6 +370,7 @@ void ui_remove_char_at(char *str, int at);
|
||||
void ui_remove_chars_at(char *str, int at, int count);
|
||||
void ui_insert_char_at(char *str, int at, char c);
|
||||
void ui_insert_chars_at(char *str, int at, char *cs);
|
||||
int ui_insert_chars_at_capped(char *str, int at, char *cs, int cap);
|
||||
|
||||
float UI_SCALE();
|
||||
float UI_ELEMENT_W();
|
||||
@@ -389,8 +392,8 @@ extern float ui_touch_speed;
|
||||
extern bool ui_is_cut;
|
||||
extern bool ui_is_copy;
|
||||
extern bool ui_is_paste;
|
||||
extern char ui_text_to_paste[8192];
|
||||
extern char ui_text_to_copy[8192];
|
||||
extern char ui_text_to_paste[UI_TEXT_MAX];
|
||||
extern char ui_text_to_copy[UI_TEXT_MAX];
|
||||
extern void (*ui_on_border_hover)(ui_handle_t *, int);
|
||||
extern void (*ui_on_tab_drop)(ui_handle_t *, int, ui_handle_t *, int);
|
||||
extern bool (*ui_picker_button)(void);
|
||||
|
||||
+31
-18
@@ -466,6 +466,19 @@ static int ui_line_pos(char *str, int line) {
|
||||
static char *lines_buffer = NULL;
|
||||
static int lines_size = 0;
|
||||
|
||||
static void ui_append_capped(char *dst, char *src, int cap) {
|
||||
int len = strlen(dst);
|
||||
int count = strlen(src);
|
||||
if (len + count > cap - 1) {
|
||||
count = cap - 1 - len;
|
||||
}
|
||||
if (count <= 0) {
|
||||
return;
|
||||
}
|
||||
memcpy(dst + len, src, count);
|
||||
dst[len + count] = '\0';
|
||||
}
|
||||
|
||||
void ui_text_area_word_wrap(char *lines, ui_handle_t *handle, bool selected) {
|
||||
ui_t *current = ui_get_current();
|
||||
bool cursor_set = false;
|
||||
@@ -479,9 +492,9 @@ void ui_text_area_word_wrap(char *lines, ui_handle_t *handle, bool selected) {
|
||||
anchor_pos += strlen(ui_extract_line(lines, i)) + 1;
|
||||
}
|
||||
int word_count = ui_word_count(lines);
|
||||
char line[1024];
|
||||
char line[UI_TEXT_MAX];
|
||||
line[0] = '\0';
|
||||
char new_lines[4096];
|
||||
char new_lines[UI_TEXT_MAX];
|
||||
new_lines[0] = '\0';
|
||||
|
||||
for (int i = 0; i < word_count; ++i) {
|
||||
@@ -491,18 +504,18 @@ void ui_text_area_word_wrap(char *lines, ui_handle_t *handle, bool selected) {
|
||||
float linew = wordw + draw_string_width(current->ops->font, current->font_size, line);
|
||||
if (linew > current->_w - 10 && linew > wordw) {
|
||||
if (new_lines[0] != '\0') {
|
||||
strcat(new_lines, "\n");
|
||||
ui_append_capped(new_lines, "\n", UI_TEXT_MAX);
|
||||
}
|
||||
strcat(new_lines, line);
|
||||
ui_append_capped(new_lines, line, UI_TEXT_MAX);
|
||||
line[0] = '\0';
|
||||
}
|
||||
|
||||
if (line[0] == '\0') {
|
||||
strcpy(line, w);
|
||||
ui_append_capped(line, w, UI_TEXT_MAX);
|
||||
}
|
||||
else {
|
||||
strcat(line, " ");
|
||||
strcat(line, w);
|
||||
ui_append_capped(line, " ", UI_TEXT_MAX);
|
||||
ui_append_capped(line, w, UI_TEXT_MAX);
|
||||
}
|
||||
|
||||
int new_line_count = new_lines[0] == '\0' ? 0 : ui_line_count(new_lines);
|
||||
@@ -522,11 +535,11 @@ void ui_text_area_word_wrap(char *lines, ui_handle_t *handle, bool selected) {
|
||||
}
|
||||
}
|
||||
if (new_lines[0] != '\0') {
|
||||
strcat(new_lines, "\n");
|
||||
ui_append_capped(new_lines, "\n", UI_TEXT_MAX);
|
||||
}
|
||||
strcat(new_lines, line);
|
||||
ui_append_capped(new_lines, line, UI_TEXT_MAX);
|
||||
if (selected) {
|
||||
strcpy(handle->text, ui_extract_line(new_lines, handle->i));
|
||||
handle->text = string_copy(ui_extract_line(new_lines, handle->i));
|
||||
strcpy(current->text_selected, handle->text);
|
||||
}
|
||||
strcpy(lines, new_lines);
|
||||
@@ -558,7 +571,7 @@ char *ui_text_area(ui_handle_t *handle, int align, bool editable, char *label, b
|
||||
handle->text = string_replace_all(handle->text, "\t", " ");
|
||||
bool selected = current->text_selected_handle == handle; // Text being edited
|
||||
|
||||
int text_size = strlen(handle->text) + 1 + 1024;
|
||||
int text_size = strlen(handle->text) + 1 + UI_TEXT_MAX;
|
||||
if (lines_size < text_size) {
|
||||
if (lines_buffer != NULL) {
|
||||
free(lines_buffer);
|
||||
@@ -598,7 +611,7 @@ char *ui_text_area(ui_handle_t *handle, int align, bool editable, char *label, b
|
||||
int lines_off = 0;
|
||||
int edit_line_pos = -1;
|
||||
int edit_line_old_len = 0;
|
||||
char edit_new_text[1024];
|
||||
char edit_new_text[UI_TEXT_MAX];
|
||||
edit_new_text[0] = '\0';
|
||||
for (int i = 0; i < line_count; ++i) { // Draw lines
|
||||
char *line = ui_extract_line_off(lines, 0, &lines_off);
|
||||
@@ -720,7 +733,7 @@ char *ui_text_area(ui_handle_t *handle, int align, bool editable, char *label, b
|
||||
ui_text_to_paste[0] = '\0';
|
||||
ui_is_paste = false;
|
||||
strcpy(current->text_selected, ui_extract_line(lines, handle->i));
|
||||
strcpy(handle->text, current->text_selected);
|
||||
handle->text = string_copy(current->text_selected);
|
||||
}
|
||||
|
||||
// Multi-line copy/cut/paste
|
||||
@@ -767,7 +780,7 @@ char *ui_text_area(ui_handle_t *handle, int align, bool editable, char *label, b
|
||||
current->cursor_x = current->highlight_anchor = sel_top_col;
|
||||
text_area_selection_start = -1;
|
||||
strcpy(current->text_selected, ui_extract_line(lines, handle->i));
|
||||
strcpy(handle->text, current->text_selected);
|
||||
handle->text = string_copy(current->text_selected);
|
||||
}
|
||||
if (editable && ui_is_paste) {
|
||||
// Delete selected range then insert clipboard
|
||||
@@ -784,7 +797,7 @@ char *ui_text_area(ui_handle_t *handle, int align, bool editable, char *label, b
|
||||
ui_text_to_paste[0] = '\0';
|
||||
ui_is_paste = false;
|
||||
strcpy(current->text_selected, ui_extract_line(lines, handle->i));
|
||||
strcpy(handle->text, current->text_selected);
|
||||
handle->text = string_copy(current->text_selected);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -823,7 +836,7 @@ char *ui_text_area(ui_handle_t *handle, int align, bool editable, char *label, b
|
||||
current->highlight_anchor = 0;
|
||||
current->cursor_sticky_x = 0;
|
||||
strcpy(current->text_selected, ui_extract_line(lines, handle->i));
|
||||
strcpy(handle->text, current->text_selected);
|
||||
handle->text = string_copy(current->text_selected);
|
||||
scroll_align(current, handle);
|
||||
}
|
||||
else if (current->key_code == KEY_CODE_LEFT && cursor_start_x == 0 && handle->i > 0 && !current->is_ctrl_down) {
|
||||
@@ -834,7 +847,7 @@ char *ui_text_area(ui_handle_t *handle, int align, bool editable, char *label, b
|
||||
current->highlight_anchor = prev_len;
|
||||
current->cursor_sticky_x = prev_len;
|
||||
strcpy(current->text_selected, ui_extract_line(lines, handle->i));
|
||||
strcpy(handle->text, current->text_selected);
|
||||
handle->text = string_copy(current->text_selected);
|
||||
scroll_align(current, handle);
|
||||
}
|
||||
else if (current->key_code == KEY_CODE_HOME || current->key_code == KEY_CODE_END) {
|
||||
@@ -848,7 +861,7 @@ char *ui_text_area(ui_handle_t *handle, int align, bool editable, char *label, b
|
||||
current->cursor_x = (int)strlen(ui_extract_line(lines, handle->i));
|
||||
current->cursor_sticky_x = current->cursor_x;
|
||||
strcpy(current->text_selected, ui_extract_line(lines, handle->i));
|
||||
strcpy(handle->text, current->text_selected);
|
||||
handle->text = string_copy(current->text_selected);
|
||||
scroll_align(current, handle);
|
||||
}
|
||||
else {
|
||||
|
||||
Reference in New Issue
Block a user