diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index fe22fa6ef..25f02f298 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -49,6 +49,9 @@ Other Changes: EndTable() was mistakenly restoring a wrong current table. - Disabled: fixed a bug when a previously enabled item that got nav focus and then turns disabled could still be activated using keyboard. (#9036) +- InputText: when buffer is not resizable, trying to paste contents that + cannot fit will now truncate text to nearest UTF-8 codepoint boundaries, + instead of completely ignoring the paste. (#9029) - InputText: avoid continuously overwriting ownership of ImGuiKey_Enter/_KeypadEnter keys in order to allow e.g. external Shortcut override behavior. (#9004) - InputText: when using a callback to reduce/manipulate the value of BufTextLen, diff --git a/imgui.cpp b/imgui.cpp index 8a446fc4c..87b261046 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2663,17 +2663,29 @@ int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_e return bytes_count; } -const char* ImTextFindPreviousUtf8Codepoint(const char* in_text_start, const char* in_text_curr) +const char* ImTextFindPreviousUtf8Codepoint(const char* in_text_start, const char* in_p) { - while (in_text_curr > in_text_start) + while (in_p > in_text_start) { - in_text_curr--; - if ((*in_text_curr & 0xC0) != 0x80) - return in_text_curr; + in_p--; + if ((*in_p & 0xC0) != 0x80) + return in_p; } return in_text_start; } +const char* ImTextFindValidUtf8CodepointEnd(const char* in_text_start, const char* in_text_end, const char* in_p) +{ + if (in_text_start == in_p) + return in_text_start; + const char* prev = ImTextFindPreviousUtf8Codepoint(in_text_start, in_p); + unsigned int prev_c; + int prev_c_len = ImTextCharFromUtf8(&prev_c, prev, in_text_end); + if (prev_c != IM_UNICODE_CODEPOINT_INVALID && prev_c_len <= (int)(in_p - prev)) + return in_p; + return prev; +} + int ImTextCountLines(const char* in_text, const char* in_text_end) { if (in_text_end == NULL) diff --git a/imgui_internal.h b/imgui_internal.h index c3c783efa..149f89fea 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -428,7 +428,8 @@ IMGUI_API int ImTextStrFromUtf8(ImWchar* out_buf, int out_buf_size, co IMGUI_API int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end); // return number of UTF-8 code-points (NOT bytes count) IMGUI_API int ImTextCountUtf8BytesFromChar(const char* in_text, const char* in_text_end); // return number of bytes to express one char in UTF-8 IMGUI_API int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end); // return number of bytes to express string in UTF-8 -IMGUI_API const char* ImTextFindPreviousUtf8Codepoint(const char* in_text_start, const char* in_text_curr); // return previous UTF-8 code-point. +IMGUI_API const char* ImTextFindPreviousUtf8Codepoint(const char* in_text_start, const char* in_p); // return previous UTF-8 code-point. +IMGUI_API const char* ImTextFindValidUtf8CodepointEnd(const char* in_text_start, const char* in_text_end, const char* in_p); // return previous UTF-8 code-point if 'in_p' is not the end of a valid one. IMGUI_API int ImTextCountLines(const char* in_text, const char* in_text_end); // return number of lines taken by text. trailing carriage return doesn't count as an extra line. // Helpers: High-level text functions (DO NOT USE!!! THIS IS A MINIMAL SUBSET OF LARGER UPCOMING CHANGES) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index d7c0df486..6d17213a2 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4155,7 +4155,7 @@ static int STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const cha // We support partial insertion (with a mod in stb_textedit.h) const int avail = obj->BufCapacity - 1 - obj->TextLen; if (!is_resizable && new_text_len > avail) - new_text_len = 0; // avail + new_text_len = (int)(ImTextFindValidUtf8CodepointEnd(new_text, new_text + new_text_len, new_text + avail) - new_text); // Truncate to closest UTF-8 codepoint. Alternative: return 0 to cancel insertion. if (new_text_len == 0) return 0; @@ -4314,7 +4314,7 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons // We support partial insertion (with a mod in stb_textedit.h) const int avail = BufSize - 1 - BufTextLen; if (!is_resizable && new_text_len > avail) - new_text_len = 0; // avail + new_text_len = (int)(ImTextFindValidUtf8CodepointEnd(new_text, new_text + new_text_len, new_text + avail) - new_text); // Truncate to closest UTF-8 codepoint. Alternative: return 0 to cancel insertion. if (new_text_len == 0) return;