@@ -4041,16 +4041,12 @@ static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(ImGuiInputTextState* obj, int idx)
4041
4041
4042
4042
static void STB_TEXTEDIT_DELETECHARS(ImGuiInputTextState* obj, int pos, int n)
4043
4043
{
4044
+ // Offset remaining text (+ copy zero terminator)
4044
4045
char* dst = obj->TextA.Data + pos;
4045
-
4046
+ char* src = obj->TextA.Data + pos + n;
4047
+ memmove(dst, src, obj->TextLen - n - pos + 1);
4046
4048
obj->Edited = true;
4047
4049
obj->TextLen -= n;
4048
-
4049
- // Offset remaining text (FIXME-OPT: Use memmove)
4050
- const char * src = obj->TextA .Data + pos + n;
4051
- while (char c = *src++)
4052
- *dst++ = c;
4053
- *dst = ' \0 ' ;
4054
4050
}
4055
4051
4056
4052
static bool STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const char* new_text, int new_text_len)
@@ -4174,17 +4170,16 @@ ImGuiInputTextCallbackData::ImGuiInputTextCallbackData()
4174
4170
memset(this, 0, sizeof(*this));
4175
4171
}
4176
4172
4177
- // Public API to manipulate UTF-8 text
4178
- // We expose UTF-8 to the user (unlike the STB_TEXTEDIT_* functions which are manipulating wchar)
4173
+ // Public API to manipulate UTF-8 text from within a callback.
4179
4174
// FIXME: The existence of this rarely exercised code path is a bit of a nuisance.
4175
+ // Historically they existed because STB_TEXTEDIT_INSERTCHARS() etc. worked on our ImWchar
4176
+ // buffer, but nowadays they both work on UTF-8 data. Should aim to merge both.
4180
4177
void ImGuiInputTextCallbackData::DeleteChars(int pos, int bytes_count)
4181
4178
{
4182
4179
IM_ASSERT(pos + bytes_count <= BufTextLen);
4183
4180
char* dst = Buf + pos;
4184
4181
const char* src = Buf + pos + bytes_count;
4185
- while (char c = *src++)
4186
- *dst++ = c;
4187
- *dst = ' \0 ' ;
4182
+ memmove(dst, src, BufTextLen - bytes_count - pos + 1);
4188
4183
4189
4184
if (CursorPos >= pos + bytes_count)
4190
4185
CursorPos -= bytes_count;
@@ -4209,7 +4204,6 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons
4209
4204
if (!is_resizable)
4210
4205
return;
4211
4206
4212
- // Contrary to STB_TEXTEDIT_INSERTCHARS() this is working in the UTF8 buffer, hence the mildly similar code (until we remove the U16 buffer altogether!)
4213
4207
ImGuiContext& g = *Ctx;
4214
4208
ImGuiInputTextState* edit_state = &g.InputTextState;
4215
4209
IM_ASSERT(edit_state->ID != 0 && g.ActiveId == edit_state->ID);
@@ -4333,26 +4327,23 @@ static bool InputTextFilterCharacter(ImGuiContext* ctx, unsigned int* p_char, Im
4333
4327
return true;
4334
4328
}
4335
4329
4336
- // Find the shortest single replacement we can make to get the new text from the old text.
4337
- // Important: needs to be run before TextW is rewritten with the new characters because calling STB_TEXTEDIT_GETCHAR() at the end .
4330
+ // Find the shortest single replacement we can make to get from old_buf to new_buf
4331
+ // Note that this doesn't directly alter state->TextA, state->TextLen. They are expected to be made valid separately .
4338
4332
// FIXME: Ideally we should transition toward (1) making InsertChars()/DeleteChars() update undo-stack (2) discourage (and keep reconcile) or obsolete (and remove reconcile) accessing buffer directly.
4339
- static void InputTextReconcileUndoStateAfterUserCallback (ImGuiInputTextState* state, const char * new_buf_a , int new_length_a )
4333
+ static void InputTextReconcileUndoState (ImGuiInputTextState* state, const char* old_buf , int old_length, const char* new_buf, int new_length )
4340
4334
{
4341
- const char * old_buf = state->CallbackTextBackup .Data ;
4342
- const int old_length = state->CallbackTextBackup .Size - 1 ;
4343
-
4344
- const int shorter_length = ImMin (old_length, new_length_a);
4335
+ const int shorter_length = ImMin(old_length, new_length);
4345
4336
int first_diff;
4346
4337
for (first_diff = 0; first_diff < shorter_length; first_diff++)
4347
- if (old_buf[first_diff] != new_buf_a [first_diff])
4338
+ if (old_buf[first_diff] != new_buf [first_diff])
4348
4339
break;
4349
- if (first_diff == old_length && first_diff == new_length_a )
4340
+ if (first_diff == old_length && first_diff == new_length )
4350
4341
return;
4351
4342
4352
4343
int old_last_diff = old_length - 1;
4353
- int new_last_diff = new_length_a - 1 ;
4344
+ int new_last_diff = new_length - 1;
4354
4345
for (; old_last_diff >= first_diff && new_last_diff >= first_diff; old_last_diff--, new_last_diff--)
4355
- if (old_buf[old_last_diff] != new_buf_a [new_last_diff])
4346
+ if (old_buf[old_last_diff] != new_buf [new_last_diff])
4356
4347
break;
4357
4348
4358
4349
const int insert_len = new_last_diff - first_diff + 1;
@@ -4544,16 +4535,12 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
4544
4535
if (flags & ImGuiInputTextFlags_ElideLeft)
4545
4536
state->Scroll.x += ImMax(0.0f, CalcTextSize(buf).x - frame_size.x + style.FramePadding.x * 2.0f);
4546
4537
4538
+ // Recycle existing cursor/selection/undo stack but clamp position
4539
+ // Note a single mouse click will override the cursor/position immediately by calling stb_textedit_click handler.
4547
4540
if (recycle_state)
4548
- {
4549
- // Recycle existing cursor/selection/undo stack but clamp position
4550
- // Note a single mouse click will override the cursor/position immediately by calling stb_textedit_click handler.
4551
4541
state->CursorClamp();
4552
- }
4553
4542
else
4554
- {
4555
4543
stb_textedit_initialize_state(state->Stb, !is_multiline);
4556
- }
4557
4544
4558
4545
if (init_reload_from_user_buf)
4559
4546
{
@@ -5039,7 +5026,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
5039
5026
{
5040
5027
// Callback may update buffer and thus set buf_dirty even in read-only mode.
5041
5028
IM_ASSERT(callback_data.BufTextLen == (int)strlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text!
5042
- InputTextReconcileUndoStateAfterUserCallback (state, callback_data.Buf , callback_data.BufTextLen ); // FIXME: Move the rest of this block inside function and rename to InputTextReconcileStateAfterUserCallback() ?
5029
+ InputTextReconcileUndoState (state, state->CallbackTextBackup.Data, state->CallbackTextBackup.Size - 1, callback_data.Buf, callback_data.BufTextLen);
5043
5030
state->TextLen = callback_data.BufTextLen; // Assume correct length and valid UTF-8 from user, saves us an extra strlen()
5044
5031
state->CursorAnimReset();
5045
5032
}
0 commit comments