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
This commit is contained in:
ocornut 2024-11-04 19:48:40 +01:00
parent f77d22837c
commit 75f83de52a
4 changed files with 8 additions and 4 deletions

View File

@ -48,6 +48,8 @@ Other changes:
- Buttons: using ImGuiItemFlags_ButtonRepeat makes default button behavior use - Buttons: using ImGuiItemFlags_ButtonRepeat makes default button behavior use
PressedOnClick instead of PressedOnClickRelease when unspecified. PressedOnClick instead of PressedOnClickRelease when unspecified.
- Fonts: removed const qualifiers from most font functions. - 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: better decorating of BeginMenu() and TabItem() output.
- Log/Capture: a non terminated log ends automatically in the window which called it. - Log/Capture: a non terminated log ends automatically in the window which called it.
- Log/Capture: added experimental io.ConfigWindowsCopyContentsWithCtrlC option to - Log/Capture: added experimental io.ConfigWindowsCopyContentsWithCtrlC option to

View File

@ -29,7 +29,7 @@
// Library Version // Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') // (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 "1.91.5 WIP"
#define IMGUI_VERSION_NUM 19142 #define IMGUI_VERSION_NUM 19143
#define IMGUI_HAS_TABLE #define IMGUI_HAS_TABLE
/* /*

View File

@ -1111,7 +1111,7 @@ struct IMGUI_API ImGuiInputTextState
ImStbTexteditState* Stb; // State for stb_textedit.h ImStbTexteditState* Stb; // State for stb_textedit.h
ImGuiID ID; // widget id owning the text state ImGuiID ID; // widget id owning the text state
int CurLenA; // UTF-8 length of the string in TextA (in bytes) int CurLenA; // UTF-8 length of the string in TextA (in bytes)
ImVector<char> TextA; // main UTF8 buffer. ImVector<char> TextA; // main UTF8 buffer. TextA.Size is a buffer size! Should always be >= buf_size passed by user (and of course >= CurLenA + 1).
ImVector<char> InitialTextA; // value to revert to when pressing Escape = backup of end-user buffer at the time of focus (in UTF-8, unaltered) ImVector<char> InitialTextA; // value to revert to when pressing Escape = backup of end-user buffer at the time of focus (in UTF-8, unaltered)
ImVector<char> CallbackTextBackup; // temporary storage for callback to support automatic reconcile of undo-stack ImVector<char> CallbackTextBackup; // temporary storage for callback to support automatic reconcile of undo-stack
int BufCapacityA; // end-user buffer capacity int BufCapacityA; // end-user buffer capacity

View File

@ -4200,6 +4200,7 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons
if (new_text == new_text_end) if (new_text == new_text_end)
return; return;
// Grow internal buffer if needed
const bool is_resizable = (Flags & ImGuiInputTextFlags_CallbackResize) != 0; 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); const int new_text_len = new_text_end ? (int)(new_text_end - new_text) : (int)strlen(new_text);
if (new_text_len + BufTextLen >= BufSize) 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(edit_state->ID != 0 && g.ActiveId == edit_state->ID);
IM_ASSERT(Buf == edit_state->TextA.Data); IM_ASSERT(Buf == edit_state->TextA.Data);
int new_buf_size = BufTextLen + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1; 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; Buf = edit_state->TextA.Data;
BufSize = edit_state->BufCapacityA = new_buf_size; 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! 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() ? 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->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(); state->CursorAnimReset();
} }
} }
@ -5342,6 +5342,8 @@ void ImGui::DebugNodeInputTextState(ImGuiInputTextState* state)
Text("ID: 0x%08X, ActiveID: 0x%08X", state->ID, g.ActiveId); Text("ID: 0x%08X, ActiveID: 0x%08X", state->ID, g.ActiveId);
DebugLocateItemOnHover(state->ID); 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("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("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); 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 if (BeginChild("undopoints", ImVec2(0.0f, GetTextLineHeight() * 10), ImGuiChildFlags_Borders | ImGuiChildFlags_ResizeY)) // Visualize undo state