diff --git a/base/sources/iron_ui.c b/base/sources/iron_ui.c index 2e9561c8..b3ddd395 100644 --- a/base/sources/iron_ui.c +++ b/base/sources/iron_ui.c @@ -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) { diff --git a/base/sources/iron_ui.h b/base/sources/iron_ui.h index d85e26f1..97629482 100644 --- a/base/sources/iron_ui.h +++ b/base/sources/iron_ui.h @@ -8,6 +8,8 @@ #include #include +#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); diff --git a/base/sources/iron_ui_ext.c b/base/sources/iron_ui_ext.c index a9f1ca7f..ce43111d 100644 --- a/base/sources/iron_ui_ext.c +++ b/base/sources/iron_ui_ext.c @@ -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 {