From e2130ed111db67e77f2b28c807188feb5f041c4b Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 19 Jul 2024 12:07:19 -0700 Subject: [PATCH] The candidates in SDL_EVENT_TEXT_EDITING_CANDIDATES should be a single allocation --- src/events/SDL_keyboard.c | 37 ++++++++++++++++++++++++++++++++----- test/testime.c | 29 ++++++++--------------------- 2 files changed, 40 insertions(+), 26 deletions(-) diff --git a/src/events/SDL_keyboard.c b/src/events/SDL_keyboard.c index e7fbd070c9ad2e..8c4c7c45bcc426 100644 --- a/src/events/SDL_keyboard.c +++ b/src/events/SDL_keyboard.c @@ -760,6 +760,37 @@ int SDL_SendEditingText(const char *text, int start, int length) return posted; } +static const char * const *CreateCandidatesForEvent(char **candidates, int num_candidates) +{ + const char **event_candidates; + int i; + char *ptr; + size_t total_length = (num_candidates + 1) * sizeof(*event_candidates); + + for (i = 0; i < num_candidates; ++i) { + size_t length = SDL_strlen(candidates[i]) + 1; + + total_length += length; + } + + event_candidates = (const char **)SDL_malloc(total_length); + if (!event_candidates) { + return NULL; + } + ptr = (char *)(event_candidates + (num_candidates + 1)); + + for (i = 0; i < num_candidates; ++i) { + size_t length = SDL_strlen(candidates[i]) + 1; + + event_candidates[i] = ptr; + SDL_memcpy(ptr, candidates[i], length); + ptr += length; + } + event_candidates[i] = NULL; + + return SDL_FreeLater(event_candidates); +} + int SDL_SendEditingTextCandidates(char **candidates, int num_candidates, int selected_candidate, SDL_bool horizontal) { SDL_Keyboard *keyboard = &SDL_keyboard; @@ -778,14 +809,10 @@ int SDL_SendEditingTextCandidates(char **candidates, int num_candidates, int sel event.common.timestamp = 0; event.edit.windowID = keyboard->focus ? keyboard->focus->id : 0; if (num_candidates > 0) { - const char **event_candidates = (const char **)SDL_AllocateTemporaryMemory((num_candidates + 1) * sizeof(*event_candidates)); + const char * const *event_candidates = CreateCandidatesForEvent(candidates, num_candidates); if (!event_candidates) { return 0; } - for (int i = 0; i < num_candidates; ++i) { - event_candidates[i] = SDL_CreateTemporaryString(candidates[i]); - } - event_candidates[num_candidates] = NULL; event.edit_candidates.candidates = event_candidates; event.edit_candidates.num_candidates = num_candidates; event.edit_candidates.selected_candidate = selected_candidate; diff --git a/test/testime.c b/test/testime.c index 1427ba5e57633c..a49b6ebff14101 100644 --- a/test/testime.c +++ b/test/testime.c @@ -53,7 +53,7 @@ static int cursor_length = 0; static SDL_bool cursor_visible; static Uint64 last_cursor_change; static SDL_BlendMode highlight_mode; -static char **candidates; +static const char **candidates; static int num_candidates; static int selected_candidate; static SDL_bool horizontal_candidates; @@ -431,7 +431,7 @@ static char *utf8_advance(char *p, size_t distance) } #endif -static Uint32 utf8_decode(char *p, size_t len) +static Uint32 utf8_decode(const char *p, size_t len) { Uint32 codepoint = 0; size_t i = 0; @@ -476,11 +476,6 @@ static void InitInput(void) static void ClearCandidates(void) { - int i; - - for (i = 0; i < num_candidates; ++i) { - SDL_free(candidates[i]); - } SDL_free(candidates); candidates = NULL; num_candidates = 0; @@ -488,20 +483,12 @@ static void ClearCandidates(void) static void SaveCandidates(SDL_Event *event) { - int i; - ClearCandidates(); num_candidates = event->edit_candidates.num_candidates; if (num_candidates > 0) { - candidates = (char **)SDL_malloc(num_candidates * sizeof(*candidates)); - if (!candidates) { - num_candidates = 0; - return; - } - for (i = 0; i < num_candidates; ++i) { - candidates[i] = SDL_strdup(event->edit_candidates.candidates[i]); - } + candidates = (const char **)SDL_ClaimTemporaryMemory(event->edit_candidates.candidates); + SDL_assert(candidates); selected_candidate = event->edit_candidates.selected_candidate; horizontal_candidates = event->edit_candidates.horizontal; } @@ -529,7 +516,7 @@ static void DrawCandidates(int rendererID, SDL_FRect *cursorRect) /* FIXME */ #else if (horizontal_candidates) { - char *utext = candidates[i]; + const char *utext = candidates[i]; Uint32 codepoint; size_t len; float advance = 0.0f; @@ -544,7 +531,7 @@ static void DrawCandidates(int rendererID, SDL_FRect *cursorRect) w += advance; h = UNIFONT_GLYPH_SIZE * UNIFONT_DRAW_SCALE; } else { - char *utext = candidates[i]; + const char *utext = candidates[i]; Uint32 codepoint; size_t len; float advance = 0.0f; @@ -596,7 +583,7 @@ static void DrawCandidates(int rendererID, SDL_FRect *cursorRect) dstRect.h = UNIFONT_GLYPH_SIZE * UNIFONT_DRAW_SCALE; if (horizontal_candidates) { - char *utext = candidates[i]; + const char *utext = candidates[i]; Uint32 codepoint; size_t len; float start; @@ -621,7 +608,7 @@ static void DrawCandidates(int rendererID, SDL_FRect *cursorRect) SDL_RenderFillRect(renderer, &underlineRect); } } else { - char *utext = candidates[i]; + const char *utext = candidates[i]; Uint32 codepoint; size_t len; float start;