From 75f83de52abe2b419eacbcbbee5d62c99f65b85b Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 4 Nov 2024 19:48:40 +0100 Subject: [PATCH] InputText: fixed a bug (regression in 1.91.2) where modifying text buffer within a callback would sometimes prevents further appending to the buffer. (#7925) There's a confusion between TextA.Size and CurLenA we should be merging them. Amend 19accb14a --- docs/CHANGELOG.txt | 2 ++ imgui.h | 2 +- imgui_internal.h | 2 +- imgui_widgets.cpp | 6 ++++-- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 02297a64b..7bb626478 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -48,6 +48,8 @@ Other changes: - Buttons: using ImGuiItemFlags_ButtonRepeat makes default button behavior use PressedOnClick instead of PressedOnClickRelease when unspecified. - Fonts: removed const qualifiers from most font functions. +- InputText: fixed a bug (regression in 1.91.2) where modifying text buffer within + a callback would sometimes prevents further appending to the buffer. - Log/Capture: better decorating of BeginMenu() and TabItem() output. - Log/Capture: a non terminated log ends automatically in the window which called it. - Log/Capture: added experimental io.ConfigWindowsCopyContentsWithCtrlC option to diff --git a/imgui.h b/imgui.h index 726c97f73..9fd077379 100644 --- a/imgui.h +++ b/imgui.h @@ -29,7 +29,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.91.5 WIP" -#define IMGUI_VERSION_NUM 19142 +#define IMGUI_VERSION_NUM 19143 #define IMGUI_HAS_TABLE /* diff --git a/imgui_internal.h b/imgui_internal.h index 932a0484c..18b146777 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1111,7 +1111,7 @@ struct IMGUI_API ImGuiInputTextState ImStbTexteditState* Stb; // State for stb_textedit.h ImGuiID ID; // widget id owning the text state int CurLenA; // UTF-8 length of the string in TextA (in bytes) - ImVector TextA; // main UTF8 buffer. + ImVector TextA; // main UTF8 buffer. TextA.Size is a buffer size! Should always be >= buf_size passed by user (and of course >= CurLenA + 1). ImVector InitialTextA; // value to revert to when pressing Escape = backup of end-user buffer at the time of focus (in UTF-8, unaltered) ImVector CallbackTextBackup; // temporary storage for callback to support automatic reconcile of undo-stack int BufCapacityA; // end-user buffer capacity diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index def3f5870..40e482d45 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4200,6 +4200,7 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons if (new_text == new_text_end) 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)strlen(new_text); if (new_text_len + BufTextLen >= BufSize) @@ -4213,7 +4214,7 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons IM_ASSERT(edit_state->ID != 0 && g.ActiveId == edit_state->ID); IM_ASSERT(Buf == edit_state->TextA.Data); int new_buf_size = BufTextLen + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1; - edit_state->TextA.reserve(new_buf_size + 1); + edit_state->TextA.resize(new_buf_size + 1); Buf = edit_state->TextA.Data; BufSize = edit_state->BufCapacityA = new_buf_size; } @@ -5034,7 +5035,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ IM_ASSERT(callback_data.BufTextLen == (int)strlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text! InputTextReconcileUndoStateAfterUserCallback(state, callback_data.Buf, callback_data.BufTextLen); // FIXME: Move the rest of this block inside function and rename to InputTextReconcileStateAfterUserCallback() ? state->CurLenA = callback_data.BufTextLen; // Assume correct length and valid UTF-8 from user, saves us an extra strlen() - state->TextA.Size = state->CurLenA + 1; state->CursorAnimReset(); } } @@ -5342,6 +5342,8 @@ void ImGui::DebugNodeInputTextState(ImGuiInputTextState* state) Text("ID: 0x%08X, ActiveID: 0x%08X", state->ID, g.ActiveId); DebugLocateItemOnHover(state->ID); Text("CurLenA: %d, Cursor: %d, Selection: %d..%d", state->CurLenA, stb_state->cursor, stb_state->select_start, stb_state->select_end); + Text("TextA.Size: %d, Capacity: %d", state->TextA.Size, state->TextA.Capacity); + Text("BufCapacityA: %d", state->BufCapacityA); Text("has_preferred_x: %d (%.2f)", stb_state->has_preferred_x, stb_state->preferred_x); Text("undo_point: %d, redo_point: %d, undo_char_point: %d, redo_char_point: %d", undo_state->undo_point, undo_state->redo_point, undo_state->undo_char_point, undo_state->redo_char_point); if (BeginChild("undopoints", ImVec2(0.0f, GetTextLineHeight() * 10), ImGuiChildFlags_Borders | ImGuiChildFlags_ResizeY)) // Visualize undo state