From 93feeb25d36aa4d965bf74f07163608e08f17202 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 24 Jun 2024 18:07:49 -0700 Subject: [PATCH] checkkeys: draw the IME composition text --- test/checkkeys.c | 105 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 92 insertions(+), 13 deletions(-) diff --git a/test/checkkeys.c b/test/checkkeys.c index 2270ab6595348..adaa1cb0ff61d 100644 --- a/test/checkkeys.c +++ b/test/checkkeys.c @@ -28,35 +28,53 @@ #define CURSOR_BLINK_INTERVAL_MS 500 +typedef struct +{ + SDLTest_TextWindow *textwindow; + char *edit_text; + int edit_cursor; + int edit_length; +} TextWindowState; + static SDLTest_CommonState *state; -static SDLTest_TextWindow **textwindows; +static TextWindowState *windowstates; static SDL_bool escape_pressed; static SDL_bool cursor_visible; static Uint64 last_cursor_change; static int done; -static SDLTest_TextWindow *GetTextWindowForWindowID(SDL_WindowID id) +static TextWindowState *GetTextWindowStateForWindowID(SDL_WindowID id) { int i; for (i = 0; i < state->num_windows; ++i) { if (id == SDL_GetWindowID(state->windows[i])) { - return textwindows[i]; + return &windowstates[i]; } } return NULL; } +static SDLTest_TextWindow *GetTextWindowForWindowID(SDL_WindowID id) +{ + TextWindowState *windowstate = GetTextWindowStateForWindowID(id); + if (windowstate) { + return windowstate->textwindow; + } + return NULL; +} + static void UpdateTextWindowInputRect(SDL_WindowID id) { int i; for (i = 0; i < state->num_windows; ++i) { if (id == SDL_GetWindowID(state->windows[i])) { + SDLTest_TextWindow *textwindow = windowstates[i].textwindow; int w, h; SDL_Rect rect; - int current = textwindows[i]->current; - const char *current_line = textwindows[i]->lines[current]; + int current = textwindow->current; + const char *current_line = textwindow->lines[current]; SDL_GetWindowSize(state->windows[i], &w, &h); @@ -271,13 +289,18 @@ static void CountKeysDown(void) static void DrawCursor(int i) { SDL_FRect rect; - int current = textwindows[i]->current; - const char *current_line = textwindows[i]->lines[current]; + TextWindowState *windowstate = &windowstates[i]; + SDLTest_TextWindow *textwindow = windowstate->textwindow; + int current = textwindow->current; + const char *current_line = textwindow->lines[current]; rect.x = TEXT_WINDOW_OFFSET_X; if (current_line) { rect.x += SDL_utf8strlen(current_line) * FONT_CHARACTER_SIZE; } + if (windowstate->edit_cursor > 0) { + rect.x += (float)windowstate->edit_cursor * FONT_CHARACTER_SIZE; + } rect.y = TEXT_WINDOW_OFFSET_Y + current * FONT_LINE_HEIGHT; rect.w = FONT_CHARACTER_SIZE * 0.75f; rect.h = (float)FONT_CHARACTER_SIZE; @@ -286,6 +309,45 @@ static void DrawCursor(int i) SDL_RenderFillRect(state->renderers[i], &rect); } +static void DrawEditText(int i) +{ + SDL_FRect rect; + TextWindowState *windowstate = &windowstates[i]; + SDLTest_TextWindow *textwindow = windowstate->textwindow; + int current = textwindow->current; + const char *current_line = textwindow->lines[current]; + + if (windowstate->edit_text == NULL) { + return; + } + + /* Draw the highlight under the selected text */ + if (windowstate->edit_length > 0) { + rect.x = TEXT_WINDOW_OFFSET_X; + if (current_line) { + rect.x += SDL_utf8strlen(current_line) * FONT_CHARACTER_SIZE; + } + if (windowstate->edit_cursor > 0) { + rect.x += (float)windowstate->edit_cursor * FONT_CHARACTER_SIZE; + } + rect.y = TEXT_WINDOW_OFFSET_Y + current * FONT_LINE_HEIGHT; + rect.w = (float)windowstate->edit_length * FONT_CHARACTER_SIZE; + rect.h = (float)FONT_CHARACTER_SIZE; + + SDL_SetRenderDrawColor(state->renderers[i], 0xAA, 0xAA, 0xAA, 255); + SDL_RenderFillRect(state->renderers[i], &rect); + } + + /* Draw the edit text */ + rect.x = TEXT_WINDOW_OFFSET_X; + if (current_line) { + rect.x += SDL_utf8strlen(current_line) * FONT_CHARACTER_SIZE; + } + rect.y = TEXT_WINDOW_OFFSET_Y + current * FONT_LINE_HEIGHT; + SDL_SetRenderDrawColor(state->renderers[i], 255, 255, 0, 255); + SDLTest_DrawString(state->renderers[i], rect.x, rect.y, windowstate->edit_text); +} + static void loop(void) { SDL_Event event; @@ -325,9 +387,22 @@ static void loop(void) CountKeysDown(); break; case SDL_EVENT_TEXT_EDITING: + { + TextWindowState *windowstate = GetTextWindowStateForWindowID(event.edit.windowID); + if (windowstate->edit_text) { + SDL_free(windowstate->edit_text); + windowstate->edit_text = NULL; + } + if (event.edit.text && *event.edit.text) { + windowstate->edit_text = SDL_strdup(event.edit.text); + } + windowstate->edit_cursor = event.edit.start; + windowstate->edit_length = event.edit.length; + SDL_snprintf(line, sizeof(line), "EDIT %" SDL_PRIs32 ":%" SDL_PRIs32, event.edit.start, event.edit.length); PrintText(line, event.edit.text); break; + } case SDL_EVENT_TEXT_INPUT: PrintText("INPUT", event.text.text); SDLTest_TextWindowAddText(GetTextWindowForWindowID(event.text.windowID), "%s", event.text.text); @@ -381,7 +456,7 @@ static void loop(void) SDL_SetRenderDrawColor(state->renderers[i], 255, 255, 255, 255); SDL_snprintf(caption, sizeof(caption), "Text input %s (click right mouse button to toggle)\n", SDL_TextInputActive(state->windows[i]) ? "enabled" : "disabled"); SDLTest_DrawString(state->renderers[i], TEXT_WINDOW_OFFSET_X, TEXT_WINDOW_OFFSET_X, caption); - SDLTest_TextWindowDisplay(textwindows[i], state->renderers[i]); + SDLTest_TextWindowDisplay(windowstates[i].textwindow, state->renderers[i]); /* Draw the cursor */ if ((now - last_cursor_change) >= CURSOR_BLINK_INTERVAL_MS) { @@ -391,6 +466,10 @@ static void loop(void) if (cursor_visible) { DrawCursor(i); } + + /* Draw the composition text */ + DrawEditText(i); + SDL_RenderPresent(state->renderers[i]); } @@ -434,8 +513,8 @@ int main(int argc, char *argv[]) return 1; } - textwindows = (SDLTest_TextWindow **)SDL_malloc(state->num_windows * sizeof(*textwindows)); - if (!textwindows) { + windowstates = (TextWindowState *)SDL_calloc(state->num_windows, sizeof(*windowstates)); + if (!windowstates) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't allocate text windows: %s\n", SDL_GetError()); goto done; } @@ -449,7 +528,7 @@ int main(int argc, char *argv[]) rect.y = TEXT_WINDOW_OFFSET_Y; rect.w = w - (2 * TEXT_WINDOW_OFFSET_X); rect.h = h - TEXT_WINDOW_OFFSET_Y; - textwindows[i] = SDLTest_TextWindowCreate(rect.x, rect.y, rect.w, rect.h); + windowstates[i].textwindow = SDLTest_TextWindowCreate(rect.x, rect.y, rect.w, rect.h); } #ifdef SDL_PLATFORM_IOS @@ -488,9 +567,9 @@ int main(int argc, char *argv[]) done: for (i = 0; i < state->num_windows; ++i) { - SDLTest_TextWindowDestroy(textwindows[i]); + SDLTest_TextWindowDestroy(windowstates[i].textwindow); } - SDL_free(textwindows); + SDL_free(windowstates); SDLTest_CleanupTextDrawing(); SDLTest_CommonQuit(state); return 0;