From 9ec8d8b637e504addb75fbbe74e7ea2070a45b96 Mon Sep 17 00:00:00 2001 From: Dav999 Date: Fri, 2 Aug 2024 01:11:45 +0200 Subject: [PATCH] Add selection background to IME rendering Decided to implement it anyway since the broken behavior (selection length always being 0, at least on Windows) may get fixed later in SDL, so let's do it right in one go. --- desktop_version/src/IMERender.cpp | 48 +++++++++++++++++++++++++++++++ desktop_version/src/KeyPoll.cpp | 10 +++++++ desktop_version/src/KeyPoll.h | 2 ++ 3 files changed, 60 insertions(+) diff --git a/desktop_version/src/IMERender.cpp b/desktop_version/src/IMERender.cpp index dde7e37d..559123d3 100644 --- a/desktop_version/src/IMERender.cpp +++ b/desktop_version/src/IMERender.cpp @@ -4,6 +4,7 @@ #include "Font.h" #include "Graphics.h" #include "KeyPoll.h" +#include "UTF8.h" static bool render_done = false; static SDL_Rect imebox; @@ -31,6 +32,53 @@ void ime_render(void) graphics.fill_rect(&imebox_border, 128, 128, 128); graphics.fill_rect(&imebox, 0, 0, 0); + + if (key.imebuffer_length > 0) + { + /* Also show a selection, so we need to know where and how long it is... + * Because SDL gives us the number of "characters" (so, codepoints)... */ + const char* imebuffer_ptr = key.imebuffer.c_str(); + const char* sel_start_ptr = imebuffer_ptr; + for (int i = 0; i < key.imebuffer_start; i++) + { + if (UTF8_next(&sel_start_ptr) == 0) + { + // Already past the '\0'... + sel_start_ptr--; + break; + } + } + const char* sel_end_ptr = sel_start_ptr; + for (int i = 0; i < key.imebuffer_length; i++) + { + if (UTF8_next(&sel_end_ptr) == 0) + { + break; + } + } + size_t before_sel_nbytes = sel_start_ptr - imebuffer_ptr; + size_t in_sel_nbytes = sel_end_ptr - sel_start_ptr; + char* before_sel = (char*) SDL_malloc(before_sel_nbytes + 1); + char* in_sel = (char*) SDL_malloc(in_sel_nbytes + 1); + if (before_sel != NULL && in_sel != NULL) + { + SDL_memcpy(before_sel, imebuffer_ptr, before_sel_nbytes); + before_sel[before_sel_nbytes] = '\0'; + SDL_memcpy(in_sel, sel_start_ptr, in_sel_nbytes); + in_sel[in_sel_nbytes] = '\0'; + + int before_sel_pixels = font::len(PR_FONT_LEVEL, before_sel); + int in_sel_pixels = font::len(PR_FONT_LEVEL, in_sel); + + SDL_Rect selrect = imebox; + selrect.x += before_sel_pixels + 1; + selrect.w = in_sel_pixels; + graphics.fill_rect(&selrect, 128, 64, 0); + } + SDL_free(before_sel); + SDL_free(in_sel); + } + font::print(PR_FONT_LEVEL | PR_CJK_LOW, imebox.x + 1, imebox.y + 1, key.imebuffer, 255, 255, 255); render_done = true; diff --git a/desktop_version/src/KeyPoll.cpp b/desktop_version/src/KeyPoll.cpp index 55779915..44ef3aec 100644 --- a/desktop_version/src/KeyPoll.cpp +++ b/desktop_version/src/KeyPoll.cpp @@ -52,6 +52,8 @@ KeyPoll::KeyPoll(void) keybuffer = ""; imebuffer = ""; + imebuffer_start = 0; + imebuffer_length = 0; leftbutton=0; rightbutton=0; middlebutton=0; mousex = 0; mousey = 0; @@ -67,6 +69,8 @@ void KeyPoll::enabletextentry(void) { keybuffer = ""; imebuffer = ""; + imebuffer_start = 0; + imebuffer_length = 0; SDL_StartTextInput(); } @@ -74,6 +78,8 @@ void KeyPoll::disabletextentry(void) { SDL_StopTextInput(); imebuffer = ""; + imebuffer_start = 0; + imebuffer_length = 0; } bool KeyPoll::textentry(void) @@ -326,9 +332,13 @@ void KeyPoll::Poll(void) break; case SDL_TEXTEDITING: imebuffer = evt.edit.text; + imebuffer_start = evt.edit.start; + imebuffer_length = evt.edit.length; break; case SDL_TEXTEDITING_EXT: imebuffer = evt.editExt.text; + imebuffer_start = evt.editExt.start; + imebuffer_length = evt.editExt.length; SDL_free(evt.editExt.text); break; diff --git a/desktop_version/src/KeyPoll.h b/desktop_version/src/KeyPoll.h index 2d7c5f9b..d51a6b26 100644 --- a/desktop_version/src/KeyPoll.h +++ b/desktop_version/src/KeyPoll.h @@ -70,6 +70,8 @@ public: bool pressedbackspace; std::string keybuffer; std::string imebuffer; + int imebuffer_start; + int imebuffer_length; bool linealreadyemptykludge;