From e6125361f988d6ed94a2e1593ab929e2b8ce1d83 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 23 Oct 2025 20:53:29 +0200 Subject: [PATCH] InputText: paste does a truncate when not fitting instead of ignoring it. (#9029) --- docs/CHANGELOG.txt | 2 ++ imgui_widgets.cpp | 30 +++++++++++++++++++----------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 3b2587547..4b7cd65c6 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -47,6 +47,8 @@ Other Changes: result in temporarily incorrect state, which would lead to bugs to side effects in various locations, e.g. GetContentRegionAvail() calls or using clipper. (#9005) EndTable() was mistakenly restoring a wrong current table. +- InputText: when buffer is not resizable, trying to paste contents that + cannot fit will now truncate text instead of 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_widgets.cpp b/imgui_widgets.cpp index c83158360..e2a8e9580 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4148,15 +4148,17 @@ static int STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const cha const int text_len = obj->TextLen; IM_ASSERT(pos <= text_len); - if (!is_resizable && (new_text_len + obj->TextLen + 1 > obj->BufCapacity)) + // 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 = avail; // 0 + if (new_text_len == 0) return 0; // Grow internal buffer if needed IM_ASSERT(obj->TextSrc == obj->TextA.Data); - if (new_text_len + text_len + 1 > obj->TextA.Size) + if (text_len + new_text_len + 1 > obj->TextA.Size && is_resizable) { - if (!is_resizable) - return 0; obj->TextA.resize(text_len + ImClamp(new_text_len, 32, ImMax(256, new_text_len)) + 1); obj->TextSrc = obj->TextA.Data; } @@ -4205,7 +4207,8 @@ static void stb_textedit_replace(ImGuiInputTextState* str, STB_TexteditState* st state->cursor = state->select_start = state->select_end = 0; if (text_len <= 0) return; - if (ImStb::STB_TEXTEDIT_INSERTCHARS(str, 0, text, text_len)) + int text_len_inserted = ImStb::STB_TEXTEDIT_INSERTCHARS(str, 0, text, text_len); + if (text_len_inserted > 0) { state->cursor = state->select_start = state->select_end = text_len; state->has_preferred_x = 0; @@ -4300,15 +4303,20 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons ImGuiContext& g = *Ctx; ImGuiInputTextState* obj = &g.InputTextState; IM_ASSERT(obj->ID != 0 && g.ActiveId == obj->ID); + const bool is_resizable = (Flags & ImGuiInputTextFlags_CallbackResize) != 0; + const bool is_readonly = (Flags & ImGuiInputTextFlags_ReadOnly) != 0; + int new_text_len = new_text_end ? (int)(new_text_end - new_text) : (int)ImStrlen(new_text); + + // 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 = avail; // 0 + if (new_text_len == 0) + return; // Grow internal buffer if needed - const bool is_resizable = (Flags & ImGuiInputTextFlags_CallbackResize) != 0; - const int new_text_len = new_text_end ? (int)(new_text_end - new_text) : (int)ImStrlen(new_text); - if (new_text_len + BufTextLen + 1 > obj->TextA.Size && (Flags & ImGuiInputTextFlags_ReadOnly) == 0) + if (new_text_len + BufTextLen + 1 > obj->TextA.Size && is_resizable && !is_readonly) { - if (!is_resizable) - return; - IM_ASSERT(Buf == obj->TextA.Data); int new_buf_size = BufTextLen + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1; obj->TextA.resize(new_buf_size + 1);