Internal: InputText: Made clipboard copy/cut use its own temporary buffer (like paste) so we can guarantee that TempBuffer if not altered and can be preserved. Renamed TempBufferA to TextA to celebrate this.
diff --git a/imgui_internal.h b/imgui_internal.h
index 2f39967..5a80fc6 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -561,10 +561,10 @@
struct IMGUI_API ImGuiInputTextState
{
ImGuiID ID; // widget id owning the text state
+ int CurLenW, CurLenA; // we need to maintain our buffer length in both UTF-8 and wchar format.
ImVector<ImWchar> TextW; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer.
+ ImVector<char> TextA; // temporary UTF8 buffer for callbacks and other operations. this is not updated in every code-path! size=capacity.
ImVector<char> InitialTextA; // backup of end-user buffer at the time of focus (in UTF-8, unaltered)
- ImVector<char> TempBufferA; // temporary buffer for callbacks and other operations. size=capacity.
- int CurLenA, CurLenW; // we need to maintain our buffer length in both UTF-8 and wchar format.
int BufCapacityA; // end-user buffer capacity
float ScrollX; // horizontal scrolling/offset
ImStb::STB_TexteditState Stb; // state for stb_textedit.h
@@ -578,7 +578,7 @@
void* UserCallbackData;
ImGuiInputTextState() { memset(this, 0, sizeof(*this)); }
- void ClearFreeMemory() { TextW.clear(); InitialTextA.clear(); TempBufferA.clear(); }
+ void ClearFreeMemory() { TextW.clear(); TextA.clear(); InitialTextA.clear(); }
void CursorAnimReset() { CursorAnim = -0.30f; } // After a user-input the cursor stays on for a while without blinking
void CursorClamp() { Stb.cursor = ImMin(Stb.cursor, CurLenW); Stb.select_start = ImMin(Stb.select_start, CurLenW); Stb.select_end = ImMin(Stb.select_end, CurLenW); }
bool HasSelection() const { return Stb.select_start != Stb.select_end; }
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 7673491..87ce703 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -3045,10 +3045,10 @@
ImGuiContext& g = *GImGui;
ImGuiInputTextState* edit_state = &g.InputTextState;
IM_ASSERT(edit_state->ID != 0 && g.ActiveId == edit_state->ID);
- IM_ASSERT(Buf == edit_state->TempBufferA.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;
- edit_state->TempBufferA.reserve(new_buf_size + 1);
- Buf = edit_state->TempBufferA.Data;
+ edit_state->TextA.reserve(new_buf_size + 1);
+ Buf = edit_state->TextA.Data;
BufSize = edit_state->BufCapacityA = new_buf_size;
}
@@ -3444,9 +3444,11 @@
{
const int ib = state->HasSelection() ? ImMin(state->Stb.select_start, state->Stb.select_end) : 0;
const int ie = state->HasSelection() ? ImMax(state->Stb.select_start, state->Stb.select_end) : state->CurLenW;
- state->TempBufferA.resize((ie-ib) * 4 + 1);
- ImTextStrToUtf8(state->TempBufferA.Data, state->TempBufferA.Size, state->TextW.Data+ib, state->TextW.Data+ie);
- SetClipboardText(state->TempBufferA.Data);
+ const int clipboard_data_len = ImTextCountUtf8BytesFromStr(state->TextW.Data + ib, state->TextW.Data + ie) + 1;
+ char* clipboard_data = (char*)MemAlloc(clipboard_data_len * sizeof(char));
+ ImTextStrToUtf8(clipboard_data, clipboard_data_len, state->TextW.Data + ib, state->TextW.Data + ie);
+ SetClipboardText(clipboard_data);
+ MemFree(clipboard_data);
}
if (is_cut)
{
@@ -3512,8 +3514,8 @@
// FIXME-OPT: CPU waste to do this every time the widget is active, should mark dirty state from the stb_textedit callbacks.
if (!is_readonly)
{
- state->TempBufferA.resize(state->TextW.Size * 4 + 1);
- ImTextStrToUtf8(state->TempBufferA.Data, state->TempBufferA.Size, state->TextW.Data, NULL);
+ state->TextA.resize(state->TextW.Size * 4 + 1);
+ ImTextStrToUtf8(state->TextA.Data, state->TextA.Size, state->TextW.Data, NULL);
}
// User callback
@@ -3551,7 +3553,7 @@
callback_data.UserData = callback_user_data;
callback_data.EventKey = event_key;
- callback_data.Buf = state->TempBufferA.Data;
+ callback_data.Buf = state->TextA.Data;
callback_data.BufTextLen = state->CurLenA;
callback_data.BufSize = state->BufCapacityA;
callback_data.BufDirty = false;
@@ -3566,7 +3568,7 @@
callback(&callback_data);
// Read back what user may have modified
- IM_ASSERT(callback_data.Buf == state->TempBufferA.Data); // Invalid to modify those fields
+ IM_ASSERT(callback_data.Buf == state->TextA.Data); // Invalid to modify those fields
IM_ASSERT(callback_data.BufSize == state->BufCapacityA);
IM_ASSERT(callback_data.Flags == flags);
if (callback_data.CursorPos != utf8_cursor_pos) { state->Stb.cursor = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.CursorPos); state->CursorFollow = true; }
@@ -3585,9 +3587,9 @@
}
// Will copy result string if modified
- if (!is_readonly && strcmp(state->TempBufferA.Data, buf) != 0)
+ if (!is_readonly && strcmp(state->TextA.Data, buf) != 0)
{
- apply_new_text = state->TempBufferA.Data;
+ apply_new_text = state->TextA.Data;
apply_new_text_length = state->CurLenA;
}
}
@@ -3633,7 +3635,7 @@
const int buf_display_max_length = 2 * 1024 * 1024;
// Select which buffer we are going to display. We set buf to NULL to prevent accidental usage from now on.
- const char* buf_display = (state != NULL && !is_readonly) ? state->TempBufferA.Data : buf;
+ const char* buf_display = (state != NULL && !is_readonly) ? state->TextA.Data : buf;
IM_ASSERT(buf_display);
buf = NULL;