mirror of
https://github.com/Drezil/imgui.git
synced 2024-11-26 05:27:01 +00:00
InputText: Added BufTextLen in ImGuiTextEditCallbackData. Requesting user to maintain it. Zero-ing structure properly before use. (#541)
This commit is contained in:
parent
17d3c202ac
commit
cf12bc7dea
32
imgui.cpp
32
imgui.cpp
@ -149,6 +149,7 @@
|
|||||||
Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code.
|
Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code.
|
||||||
Also read releases logs https://github.com/ocornut/imgui/releases for more details.
|
Also read releases logs https://github.com/ocornut/imgui/releases for more details.
|
||||||
|
|
||||||
|
- 2016/03/02 (1.48) - InputText() completion/history/always callbacks: if you modify the text buffer manually (without using DeleteChars()/InsertChars() helper) you need to maintain the BufTextLen field. added an assert.
|
||||||
- 2016/01/23 (1.48) - fixed not honoring exact width passed to PushItemWidth(), previously it would add extra FramePadding.x*2 over that width. if you had manual pixel-perfect alignment in place it might affect you.
|
- 2016/01/23 (1.48) - fixed not honoring exact width passed to PushItemWidth(), previously it would add extra FramePadding.x*2 over that width. if you had manual pixel-perfect alignment in place it might affect you.
|
||||||
- 2015/12/27 (1.48) - fixed ImDrawList::AddRect() which used to render a rectangle 1 px too large on each axis.
|
- 2015/12/27 (1.48) - fixed ImDrawList::AddRect() which used to render a rectangle 1 px too large on each axis.
|
||||||
- 2015/12/04 (1.47) - renamed Color() helpers to ValueColor() - dangerously named, rarely used and probably to be made obsolete.
|
- 2015/12/04 (1.47) - renamed Color() helpers to ValueColor() - dangerously named, rarely used and probably to be made obsolete.
|
||||||
@ -7117,41 +7118,41 @@ void ImGuiTextEditState::OnKeyPressed(int key)
|
|||||||
|
|
||||||
// Public API to manipulate UTF-8 text
|
// Public API to manipulate UTF-8 text
|
||||||
// We expose UTF-8 to the user (unlike the STB_TEXTEDIT_* functions which are manipulating wchar)
|
// We expose UTF-8 to the user (unlike the STB_TEXTEDIT_* functions which are manipulating wchar)
|
||||||
|
// FIXME: The existence of this rarely exercised code path is a bit of a nuisance.
|
||||||
void ImGuiTextEditCallbackData::DeleteChars(int pos, int bytes_count)
|
void ImGuiTextEditCallbackData::DeleteChars(int pos, int bytes_count)
|
||||||
{
|
{
|
||||||
|
IM_ASSERT(pos + bytes_count <= BufTextLen);
|
||||||
char* dst = Buf + pos;
|
char* dst = Buf + pos;
|
||||||
const char* src = Buf + pos + bytes_count;
|
const char* src = Buf + pos + bytes_count;
|
||||||
while (char c = *src++)
|
while (char c = *src++)
|
||||||
*dst++ = c;
|
*dst++ = c;
|
||||||
*dst = '\0';
|
*dst = '\0';
|
||||||
|
|
||||||
BufDirty = true;
|
|
||||||
if (CursorPos + bytes_count >= pos)
|
if (CursorPos + bytes_count >= pos)
|
||||||
CursorPos -= bytes_count;
|
CursorPos -= bytes_count;
|
||||||
else if (CursorPos >= pos)
|
else if (CursorPos >= pos)
|
||||||
CursorPos = pos;
|
CursorPos = pos;
|
||||||
SelectionStart = SelectionEnd = CursorPos;
|
SelectionStart = SelectionEnd = CursorPos;
|
||||||
|
BufDirty = true;
|
||||||
|
BufTextLen -= bytes_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGuiTextEditCallbackData::InsertChars(int pos, const char* new_text, const char* new_text_end)
|
void ImGuiTextEditCallbackData::InsertChars(int pos, const char* new_text, const char* new_text_end)
|
||||||
{
|
{
|
||||||
const int text_len = (int)strlen(Buf);
|
const int new_text_len = new_text_end ? (int)(new_text_end - new_text) : (int)strlen(new_text);
|
||||||
if (!new_text_end)
|
if (new_text_len + BufTextLen + 1 >= BufSize)
|
||||||
new_text_end = new_text + strlen(new_text);
|
|
||||||
const int new_text_len = (int)(new_text_end - new_text);
|
|
||||||
|
|
||||||
if (new_text_len + text_len + 1 >= BufSize)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (text_len != pos)
|
if (BufTextLen != pos)
|
||||||
memmove(Buf + pos + new_text_len, Buf + pos, (size_t)(text_len - pos));
|
memmove(Buf + pos + new_text_len, Buf + pos, (size_t)(BufTextLen - pos));
|
||||||
memcpy(Buf + pos, new_text, (size_t)new_text_len * sizeof(char));
|
memcpy(Buf + pos, new_text, (size_t)new_text_len * sizeof(char));
|
||||||
Buf[text_len + new_text_len] = '\0';
|
Buf[BufTextLen + new_text_len] = '\0';
|
||||||
|
|
||||||
BufDirty = true;
|
|
||||||
if (CursorPos >= pos)
|
if (CursorPos >= pos)
|
||||||
CursorPos += new_text_len;
|
CursorPos += new_text_len;
|
||||||
SelectionStart = SelectionEnd = CursorPos;
|
SelectionStart = SelectionEnd = CursorPos;
|
||||||
|
BufDirty = true;
|
||||||
|
BufTextLen += new_text_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return false to discard a character.
|
// Return false to discard a character.
|
||||||
@ -7543,6 +7544,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
|
|||||||
if (event_key != ImGuiKey_COUNT || (flags & ImGuiInputTextFlags_CallbackAlways) != 0)
|
if (event_key != ImGuiKey_COUNT || (flags & ImGuiInputTextFlags_CallbackAlways) != 0)
|
||||||
{
|
{
|
||||||
ImGuiTextEditCallbackData callback_data;
|
ImGuiTextEditCallbackData callback_data;
|
||||||
|
memset(&callback_data, 0, sizeof(ImGuiTextEditCallbackData));
|
||||||
callback_data.EventFlag = event_flag;
|
callback_data.EventFlag = event_flag;
|
||||||
callback_data.Flags = flags;
|
callback_data.Flags = flags;
|
||||||
callback_data.UserData = user_data;
|
callback_data.UserData = user_data;
|
||||||
@ -7550,10 +7552,11 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
|
|||||||
|
|
||||||
callback_data.EventKey = event_key;
|
callback_data.EventKey = event_key;
|
||||||
callback_data.Buf = edit_state.TempTextBuffer.Data;
|
callback_data.Buf = edit_state.TempTextBuffer.Data;
|
||||||
|
callback_data.BufTextLen = edit_state.CurLenA;
|
||||||
callback_data.BufSize = edit_state.BufSizeA;
|
callback_data.BufSize = edit_state.BufSizeA;
|
||||||
callback_data.BufDirty = false;
|
callback_data.BufDirty = false;
|
||||||
|
|
||||||
// We have to convert from position from wchar to UTF-8 positions
|
// We have to convert from wchar-positions to UTF-8-positions, which can be pretty slow (an incentive to ditch the ImWchar buffer, see https://github.com/nothings/stb/issues/188)
|
||||||
ImWchar* text = edit_state.Text.Data;
|
ImWchar* text = edit_state.Text.Data;
|
||||||
const int utf8_cursor_pos = callback_data.CursorPos = ImTextCountUtf8BytesFromStr(text, text + edit_state.StbState.cursor);
|
const int utf8_cursor_pos = callback_data.CursorPos = ImTextCountUtf8BytesFromStr(text, text + edit_state.StbState.cursor);
|
||||||
const int utf8_selection_start = callback_data.SelectionStart = ImTextCountUtf8BytesFromStr(text, text + edit_state.StbState.select_start);
|
const int utf8_selection_start = callback_data.SelectionStart = ImTextCountUtf8BytesFromStr(text, text + edit_state.StbState.select_start);
|
||||||
@ -7571,8 +7574,9 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
|
|||||||
if (callback_data.SelectionEnd != utf8_selection_end) edit_state.StbState.select_end = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd);
|
if (callback_data.SelectionEnd != utf8_selection_end) edit_state.StbState.select_end = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd);
|
||||||
if (callback_data.BufDirty)
|
if (callback_data.BufDirty)
|
||||||
{
|
{
|
||||||
edit_state.CurLenW = ImTextStrFromUtf8(text, edit_state.Text.Size, edit_state.TempTextBuffer.Data, NULL);
|
IM_ASSERT(callback_data.BufTextLen == (int)strlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text!
|
||||||
edit_state.CurLenA = (int)strlen(edit_state.TempTextBuffer.Data);
|
edit_state.CurLenW = ImTextStrFromUtf8(edit_state.Text.Data, edit_state.Text.Size, callback_data.Buf, NULL);
|
||||||
|
edit_state.CurLenA = callback_data.BufTextLen; // Assume correct length and valid UTF-8 from user, saves us an extra strlen()
|
||||||
edit_state.CursorAnimReset();
|
edit_state.CursorAnimReset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
12
imgui.h
12
imgui.h
@ -944,7 +944,7 @@ struct ImGuiStorage
|
|||||||
IMGUI_API void SetAllInt(int val);
|
IMGUI_API void SetAllInt(int val);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Shared state of InputText(), passed to callback when a ImGuiInputTextFlags_Callback* flag is used.
|
// Shared state of InputText(), passed to callback when a ImGuiInputTextFlags_Callback* flag is used and the corresponding callback is triggered.
|
||||||
struct ImGuiTextEditCallbackData
|
struct ImGuiTextEditCallbackData
|
||||||
{
|
{
|
||||||
ImGuiInputTextFlags EventFlag; // One of ImGuiInputTextFlags_Callback* // Read-only
|
ImGuiInputTextFlags EventFlag; // One of ImGuiInputTextFlags_Callback* // Read-only
|
||||||
@ -956,15 +956,17 @@ struct ImGuiTextEditCallbackData
|
|||||||
ImWchar EventChar; // Character input // Read-write (replace character or set to zero)
|
ImWchar EventChar; // Character input // Read-write (replace character or set to zero)
|
||||||
|
|
||||||
// Completion,History,Always events:
|
// Completion,History,Always events:
|
||||||
|
// If you modify the buffer contents make sure you update 'BufTextLen' and set 'BufDirty' to true.
|
||||||
ImGuiKey EventKey; // Key pressed (Up/Down/TAB) // Read-only
|
ImGuiKey EventKey; // Key pressed (Up/Down/TAB) // Read-only
|
||||||
char* Buf; // Current text // Read-write (pointed data only)
|
char* Buf; // Current text buffer // Read-write (pointed data only, can't replace the actual pointer)
|
||||||
int BufSize; // // Read-only
|
int BufTextLen; // Current text length in bytes // Read-write
|
||||||
bool BufDirty; // Must set if you modify Buf directly // Write
|
int BufSize; // Maximum text length in bytes // Read-only
|
||||||
|
bool BufDirty; // Set if you modify Buf/BufTextLen!! // Write
|
||||||
int CursorPos; // // Read-write
|
int CursorPos; // // Read-write
|
||||||
int SelectionStart; // // Read-write (== to SelectionEnd when no selection)
|
int SelectionStart; // // Read-write (== to SelectionEnd when no selection)
|
||||||
int SelectionEnd; // // Read-write
|
int SelectionEnd; // // Read-write
|
||||||
|
|
||||||
// NB: calling those function loses selection.
|
// NB: Helper functions for text manipulation. Calling those function loses selection.
|
||||||
void DeleteChars(int pos, int bytes_count);
|
void DeleteChars(int pos, int bytes_count);
|
||||||
void InsertChars(int pos, const char* text, const char* text_end = NULL);
|
void InsertChars(int pos, const char* text, const char* text_end = NULL);
|
||||||
bool HasSelection() const { return SelectionStart != SelectionEnd; }
|
bool HasSelection() const { return SelectionStart != SelectionEnd; }
|
||||||
|
@ -1888,6 +1888,7 @@ struct ExampleAppConsole
|
|||||||
Commands.push_back("HISTORY");
|
Commands.push_back("HISTORY");
|
||||||
Commands.push_back("CLEAR");
|
Commands.push_back("CLEAR");
|
||||||
Commands.push_back("CLASSIFY"); // "classify" is here to provide an example of "C"+[tab] completing to "CL" and displaying matches.
|
Commands.push_back("CLASSIFY"); // "classify" is here to provide an example of "C"+[tab] completing to "CL" and displaying matches.
|
||||||
|
AddLog("Welcome to ImGui!");
|
||||||
}
|
}
|
||||||
~ExampleAppConsole()
|
~ExampleAppConsole()
|
||||||
{
|
{
|
||||||
@ -2128,9 +2129,8 @@ struct ExampleAppConsole
|
|||||||
// A better implementation would preserve the data on the current input line along with cursor position.
|
// A better implementation would preserve the data on the current input line along with cursor position.
|
||||||
if (prev_history_pos != HistoryPos)
|
if (prev_history_pos != HistoryPos)
|
||||||
{
|
{
|
||||||
snprintf(data->Buf, data->BufSize, "%s", (HistoryPos >= 0) ? History[HistoryPos] : "");
|
data->CursorPos = data->SelectionStart = data->SelectionEnd = data->BufTextLen = (int)snprintf(data->Buf, data->BufSize, "%s", (HistoryPos >= 0) ? History[HistoryPos] : "");
|
||||||
data->BufDirty = true;
|
data->BufDirty = true;
|
||||||
data->CursorPos = data->SelectionStart = data->SelectionEnd = (int)strlen(data->Buf);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user