Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add native UTF8 support for InputText and remove ImWchar buffer #7925

Merged
merged 7 commits into from
Sep 11, 2024
4 changes: 4 additions & 0 deletions docs/CHANGELOG.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ Other changes:
#6223, #6364, #6387, #6567, #6692, #6724, #6939, #6984, #7246, #7270, #7375, #7421, #7434,
#7472, #7581, #7724, #7926, #7937 and probably more..)
- Nav: pressing any keyboard key while holding Alt disable toggling nav layer on Alt release. (#4439)
- InputText: internal refactoring to simplify and optimize the code. The ImWchar buffer has been
removed. Simplifications allowed to implement new optimizations for handling very large text buffers
(e.g. in our testing, handling of a 1 MB text buffer is now 3 times faster in VS2022 Debug build).
This is the first step toward more refactorig. (#7925) [@alektron, @ocornut]
- InputText: added CJK double-width punctuation to list of separators considered for CTRL+Arrow.
- TextLinkOpenURL(): modified tooltip to display a verb "Open 'xxxx'". (#7885, #7660)
- Backends: SDL2: use SDL_Vulkan_GetDrawableSize() when available. (#7967, #3190) [@scribam]
Expand Down
1 change: 0 additions & 1 deletion docs/TODO.txt
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- selectable: generic BeginSelectable()/EndSelectable() mechanism. (work out alongside range-select branch)
- selectable: a way to visualize partial/mixed selection (e.g. parent tree node has children with mixed selection)

- input text: clean up the mess caused by converting UTF-8 <> wchar. the code is rather inefficient right now and super fragile. (WIP branch)
- input text: preserve scrolling when unfocused?
- input text: reorganize event handling, allow CharFilter to modify buffers, allow multiple events? (#541)
- input text: expose CursorPos in char filter event (#816)
Expand Down
2 changes: 1 addition & 1 deletion imgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1975,7 +1975,7 @@ const char* ImStreolRange(const char* str, const char* str_end)
return p ? p : str_end;
}

const ImWchar* ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin) // find beginning-of-line
const char* ImStrbol(const char* buf_mid_line, const char* buf_begin) // find beginning-of-line
{
while (buf_mid_line > buf_begin && buf_mid_line[-1] != '\n')
buf_mid_line--;
Expand Down
2 changes: 1 addition & 1 deletion imgui.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.2 WIP"
#define IMGUI_VERSION_NUM 19113
#define IMGUI_VERSION_NUM 19114
#define IMGUI_HAS_TABLE

/*
Expand Down
16 changes: 8 additions & 8 deletions imgui_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ IMGUI_API const char* ImStristr(const char* haystack, const char* haystack_end
IMGUI_API void ImStrTrimBlanks(char* str); // Remove leading and trailing blanks from a buffer.
IMGUI_API const char* ImStrSkipBlank(const char* str); // Find first non-blank character.
IMGUI_API int ImStrlenW(const ImWchar* str); // Computer string length (ImWchar string)
IMGUI_API const ImWchar*ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin); // Find beginning-of-line (ImWchar string)
IMGUI_API const char* ImStrbol(const char* buf_mid_line, const char* buf_begin); // Find beginning-of-line
IM_MSVC_RUNTIME_CHECKS_OFF
static inline char ImToUpper(char c) { return (c >= 'a' && c <= 'z') ? c &= ~32 : c; }
static inline bool ImCharIsBlankA(char c) { return c == ' ' || c == '\t'; }
Expand Down Expand Up @@ -1097,7 +1097,7 @@ struct IMGUI_API ImGuiInputTextDeactivatedState
#undef IMSTB_TEXTEDIT_STRING
#undef IMSTB_TEXTEDIT_CHARTYPE
#define IMSTB_TEXTEDIT_STRING ImGuiInputTextState
#define IMSTB_TEXTEDIT_CHARTYPE ImWchar
#define IMSTB_TEXTEDIT_CHARTYPE char
#define IMSTB_TEXTEDIT_GETWIDTH_NEWLINE (-1.0f)
#define IMSTB_TEXTEDIT_UNDOSTATECOUNT 99
#define IMSTB_TEXTEDIT_UNDOCHARCOUNT 999
Expand All @@ -1111,11 +1111,10 @@ struct IMGUI_API ImGuiInputTextState
ImGuiContext* Ctx; // parent UI context (needs to be set explicitly by parent).
ImStbTexteditState* Stb; // State for stb_textedit.h
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. UTF-8 length is valid even if TextA is not.
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.
int CurLenA; // UTF-8 length of the string in TextA (in bytes)
ImVector<char> TextA; // main UTF8 buffer.
ImVector<char> InitialTextA; // value to revert to when pressing Escape = backup of end-user buffer at the time of focus (in UTF-8, unaltered)
bool TextAIsValid; // temporary UTF8 buffer is not initially valid before we make the widget active (until then we pull the data from user argument)
ImVector<char> CallbackTextBackup; // temporary storage for callback to support automatic reconcile of undo-stack
int BufCapacityA; // end-user buffer capacity
ImVec2 Scroll; // horizontal offset (managed manually) + vertical scrolling (pulled from child window's own Scroll.y)
float CursorAnim; // timer for cursor blink, reset on every user action so the cursor reappears immediately
Expand All @@ -1129,9 +1128,10 @@ struct IMGUI_API ImGuiInputTextState

ImGuiInputTextState();
~ImGuiInputTextState();
void ClearText() { CurLenW = CurLenA = 0; TextW[0] = 0; TextA[0] = 0; CursorClamp(); }
void ClearFreeMemory() { TextW.clear(); TextA.clear(); InitialTextA.clear(); }
void ClearText() { CurLenA = 0; TextA[0] = 0; CursorClamp(); }
void ClearFreeMemory() { TextA.clear(); InitialTextA.clear(); }
void OnKeyPressed(int key); // Cannot be inline because we call in code in stb_textedit.h implementation
void OnCharPressed(unsigned int c);

// Cursor & Selection
void CursorAnimReset();
Expand Down
Loading
Loading