From 652998ed0be197879727166977295ae34878b626 Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Tue, 14 Jul 2020 14:14:17 +0300 Subject: [PATCH 01/15] ImStrv: Step 1 - change string type to ImStrv in API. (REBASED) (last rebase amend 2024/12/11) --- imgui.cpp | 87 ++++++++------- imgui.h | 276 +++++++++++++++++++++++----------------------- imgui_demo.cpp | 4 +- imgui_draw.cpp | 8 +- imgui_internal.h | 60 +++++----- imgui_tables.cpp | 16 +-- imgui_widgets.cpp | 227 +++++++++++++++++++------------------- 7 files changed, 340 insertions(+), 338 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 585e8a9b2..ebc04e8ea 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1429,7 +1429,7 @@ static const ImVec2 TOOLTIP_DEFAULT_PIVOT_TOUCH = ImVec2(0.5f, 1.0f); // Multi //------------------------------------------------------------------------- static void SetCurrentWindow(ImGuiWindow* window); -static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags); +static ImGuiWindow* CreateNewWindow(ImStrv name, ImGuiWindowFlags flags); static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window); static void AddWindowToSortBuffer(ImVector* out_sorted_windows, ImGuiWindow* window); @@ -1503,7 +1503,7 @@ static void UpdateSettings(); static int UpdateWindowManualResize(ImGuiWindow* window, int* border_hovered, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4], const ImRect& visibility_rect); static void RenderWindowOuterBorders(ImGuiWindow* window); static void RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar_rect, bool title_bar_is_highlight, bool handle_borders_and_resize_grips, int resize_grip_count, const ImU32 resize_grip_col[4], float resize_grip_draw_size); -static void RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& title_bar_rect, const char* name, bool* p_open); +static void RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& title_bar_rect, ImStrv name, bool* p_open); static void RenderDimmedBackgroundBehindWindow(ImGuiWindow* window, ImU32 col); static void RenderDimmedBackgrounds(); static void SetLastItemDataForWindow(ImGuiWindow* window, const ImRect& rect); @@ -2632,7 +2632,7 @@ const char* ImHashSkipUncontributingPrefix(const char* label) // Default file functions #ifndef IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS -ImFileHandle ImFileOpen(const char* filename, const char* mode) +ImFileHandle ImFileOpen(ImStrv filename, ImStrv mode) { #if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && (defined(__MINGW32__) || (!defined(__CYGWIN__) && !defined(__GNUC__))) // We need a fopen() wrapper because MSVC/Windows fopen doesn't handle UTF-8 filenames. @@ -2666,7 +2666,7 @@ ImU64 ImFileWrite(const void* data, ImU64 sz, ImU64 count, ImFileHandle f) // Helper: Load file content into memory // Memory allocated with IM_ALLOC(), must be freed by user using IM_FREE() == ImGui::MemFree() // This can't really be used with "rt" because fseek size won't match read size. -void* ImFileLoadToMemory(const char* filename, const char* mode, size_t* out_file_size, int padding_bytes) +void* ImFileLoadToMemory(ImStrv filename, ImStrv mode, size_t* out_file_size, int padding_bytes) { IM_ASSERT(filename && mode); if (out_file_size) @@ -3153,7 +3153,7 @@ IM_MSVC_RUNTIME_CHECKS_RESTORE //----------------------------------------------------------------------------- // Helper: Parse and apply text filters e.g. 'aaa bbb -ccc'. -ImGuiTextFilter::ImGuiTextFilter(const char* default_filter) //-V1077 +ImGuiTextFilter::ImGuiTextFilter(ImStrv default_filter) //-V1077 { InputBuf[0] = 0; _CountExclude = 0; @@ -3164,7 +3164,7 @@ ImGuiTextFilter::ImGuiTextFilter(const char* default_filter) //-V1077 } } -bool ImGuiTextFilter::Draw(const char* label) +bool ImGuiTextFilter::Draw(ImStrv label) { return DrawWithHint(label, "incl -excl"); } @@ -4754,7 +4754,7 @@ void ImGui::CallContextHooks(ImGuiContext* ctx, ImGuiContextHookType hook_type) //----------------------------------------------------------------------------- // ImGuiWindow is mostly a dumb struct. It merely has a constructor and a few helper methods -ImGuiWindow::ImGuiWindow(ImGuiContext* ctx, const char* name) : DrawListInst(NULL) +ImGuiWindow::ImGuiWindow(ImGuiContext* ctx, ImStrv name) : DrawListInst(NULL) { memset((void*)this, 0, sizeof(*this)); Ctx = ctx; @@ -5323,7 +5323,7 @@ const char* ImGui::GetClipboardText() return g.PlatformIO.Platform_GetClipboardTextFn ? g.PlatformIO.Platform_GetClipboardTextFn(&g) : NULL; } -void ImGui::SetClipboardText(const char* text) +void ImGui::SetClipboardText(ImStrv text) { ImGuiContext& g = *GImGui; if (g.PlatformIO.Platform_SetClipboardTextFn != NULL) @@ -6613,9 +6613,9 @@ ImGuiItemFlags ImGui::GetItemFlags() return g.LastItemData.ItemFlags; } -// Prior to v1.90 2023/10/16, the BeginChild() function took a 'bool border = false' parameter instead of 'ImGuiChildFlags child_flags = 0'. +// Prior to v1.90 2023/10/16, the BeginChild() function took a 'bool borders = false' parameter instead of 'ImGuiChildFlags child_flags = 0'. // ImGuiChildFlags_Borders is defined as always == 1 in order to allow old code passing 'true'. Read comments in imgui.h for details! -bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags) +bool ImGui::BeginChild(ImStrv str_id, const ImVec2& size_arg, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags) { ImGuiID id = GetCurrentWindow()->GetID(str_id); return BeginChildEx(str_id, id, size_arg, child_flags, window_flags); @@ -6626,7 +6626,7 @@ bool ImGui::BeginChild(ImGuiID id, const ImVec2& size_arg, ImGuiChildFlags child return BeginChildEx(NULL, id, size_arg, child_flags, window_flags); } -bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags) +bool ImGui::BeginChildEx(ImStrv name, ImGuiID id, const ImVec2& size_arg, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags) { ImGuiContext& g = *GImGui; ImGuiWindow* parent_window = g.CurrentWindow; @@ -6822,7 +6822,7 @@ ImGuiWindow* ImGui::FindWindowByID(ImGuiID id) return (ImGuiWindow*)g.WindowsById.GetVoidPtr(id); } -ImGuiWindow* ImGui::FindWindowByName(const char* name) +ImGuiWindow* ImGui::FindWindowByName(ImStrv name) { ImGuiID id = ImHashStr(name); return FindWindowByID(id); @@ -6872,7 +6872,7 @@ static void InitOrLoadWindowSettings(ImGuiWindow* window, ImGuiWindowSettings* s settings->LastUsedDate = g.SessionDate; } -static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags) +static ImGuiWindow* CreateNewWindow(ImStrv name, ImGuiWindowFlags flags) { // Create window the first time //IMGUI_DEBUG_LOG("CreateNewWindow '%s', flags = 0x%08X\n", name, flags); @@ -7470,7 +7470,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar } // Render title text, collapse button, close button -void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& title_bar_rect, const char* name, bool* p_open) +void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& title_bar_rect, ImStrv name, bool* p_open) { ImGuiContext& g = *GImGui; ImGuiStyle& style = g.Style; @@ -7624,7 +7624,7 @@ static void SetWindowActiveForSkipRefresh(ImGuiWindow* window) // You can use the "##" or "###" markers to use the same label with different id, or same id with different label. See documentation at the top of this file. // - Return false when window is collapsed, so you can early out in your code. You always need to call ImGui::End() even if false is returned. // - Passing 'bool* p_open' displays a Close button on the upper-right corner of the window, the pointed value will be set to false when the button is pressed. -bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) +bool ImGui::Begin(ImStrv name, bool* p_open, ImGuiWindowFlags flags) { ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; @@ -8757,7 +8757,7 @@ void ImGui::SetWindowPos(const ImVec2& pos, ImGuiCond cond) SetWindowPos(window, pos, cond); } -void ImGui::SetWindowPos(const char* name, const ImVec2& pos, ImGuiCond cond) +void ImGui::SetWindowPos(ImStrv name, const ImVec2& pos, ImGuiCond cond) { if (ImGuiWindow* window = FindWindowByName(name)) SetWindowPos(window, pos, cond); @@ -8803,7 +8803,7 @@ void ImGui::SetWindowSize(const ImVec2& size, ImGuiCond cond) SetWindowSize(GImGui->CurrentWindow, size, cond); } -void ImGui::SetWindowSize(const char* name, const ImVec2& size, ImGuiCond cond) +void ImGui::SetWindowSize(ImStrv name, const ImVec2& size, ImGuiCond cond) { if (ImGuiWindow* window = FindWindowByName(name)) SetWindowSize(window, size, cond); @@ -8852,7 +8852,7 @@ bool ImGui::IsWindowAppearing() return window->Appearing; } -void ImGui::SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond) +void ImGui::SetWindowCollapsed(ImStrv name, bool collapsed, ImGuiCond cond) { if (ImGuiWindow* window = FindWindowByName(name)) SetWindowCollapsed(window, collapsed, cond); @@ -9479,7 +9479,7 @@ ImGuiID ImGuiWindow::GetIDFromRectangle(const ImRect& r_abs) return id; } -void ImGui::PushID(const char* str_id) +void ImGui::PushID(ImStrv str_id) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; @@ -9555,7 +9555,7 @@ void ImGui::PopID() window->IDStack.pop_back(); } -ImGuiID ImGui::GetID(const char* str_id) +ImGuiID ImGui::GetID(ImStrv str_id) { ImGuiWindow* window = GImGui->CurrentWindow; return window->GetID(str_id); @@ -11143,7 +11143,7 @@ bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID own // Which is why it is required you put them in your imconfig file (and NOT only before including imgui.h). // Otherwise it is possible that different compilation units would see different structure layout. // If you don't want to modify imconfig.h you can use the IMGUI_USER_CONFIG define to change filename. -bool ImGui::DebugCheckVersionAndDataLayout(const char* version, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_vert, size_t sz_idx) +bool ImGui::DebugCheckVersionAndDataLayout(ImStrv version, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_vert, size_t sz_idx) { bool error = false; if (strcmp(version, IMGUI_VERSION) != 0) { error = true; IM_ASSERT(strcmp(version, IMGUI_VERSION) == 0 && "Mismatched version string!"); } @@ -12503,7 +12503,7 @@ bool ImGui::IsPopupOpen(ImGuiID id, ImGuiPopupFlags popup_flags) } } -bool ImGui::IsPopupOpen(const char* str_id, ImGuiPopupFlags popup_flags) +bool ImGui::IsPopupOpen(ImStrv str_id, ImGuiPopupFlags popup_flags) { ImGuiContext& g = *GImGui; ImGuiID id = (popup_flags & ImGuiPopupFlags_AnyPopupId) ? 0 : g.CurrentWindow->GetID(str_id); @@ -12534,7 +12534,6 @@ ImGuiWindow* ImGui::GetTopMostAndVisiblePopupModal() return NULL; } - // When a modal popup is open, newly created windows that want focus (i.e. are not popups and do not specify ImGuiWindowFlags_NoFocusOnAppearing) // should be positioned behind that modal window, unless the window was created inside the modal begin-stack. // In case of multiple stacked modals newly created window honors begin stack order and does not go below its own modal parent. @@ -12571,7 +12570,7 @@ ImGuiWindow* ImGui::FindBlockingModal(ImGuiWindow* window) return NULL; } -bool ImGui::OpenPopup(const char* str_id, ImGuiPopupFlags popup_flags) +bool ImGui::OpenPopup(ImStrv str_id, ImGuiPopupFlags popup_flags) { ImGuiContext& g = *GImGui; ImGuiID id = g.CurrentWindow->GetID(str_id); @@ -12786,7 +12785,7 @@ bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_window_flags) return is_open; } -bool ImGui::BeginPopupMenuEx(ImGuiID id, const char* label, ImGuiWindowFlags extra_window_flags) +bool ImGui::BeginPopupMenuEx(ImGuiID id, ImStrv label, ImGuiWindowFlags extra_window_flags) { ImGuiContext& g = *GImGui; if (!IsPopupOpen(id, ImGuiPopupFlags_None)) @@ -12810,7 +12809,7 @@ bool ImGui::BeginPopupMenuEx(ImGuiID id, const char* label, ImGuiWindowFlags ext return is_open; } -bool ImGui::BeginPopup(const char* str_id, ImGuiWindowFlags flags) +bool ImGui::BeginPopup(ImStrv str_id, ImGuiWindowFlags flags) { ImGuiContext& g = *GImGui; if (g.OpenPopupStack.Size <= g.BeginPopupStack.Size) // Early out for performance @@ -12827,7 +12826,7 @@ bool ImGui::BeginPopup(const char* str_id, ImGuiWindowFlags flags) // Note that popup visibility status is owned by Dear ImGui (and manipulated with e.g. OpenPopup). // - *p_open set back to false in BeginPopupModal() when popup is not open. // - if you set *p_open to false before calling BeginPopupModal(), it will close the popup. -bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags flags) +bool ImGui::BeginPopupModal(ImStrv name, bool* p_open, ImGuiWindowFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; @@ -12921,7 +12920,7 @@ bool ImGui::IsPopupOpenRequestForWindow(ImGuiPopupFlags popup_flags) // Helper to open a popup if mouse button is released over the item // - This is essentially the same as BeginPopupContextItem() but without the trailing BeginPopup() -bool ImGui::OpenPopupOnItemClick(const char* str_id, ImGuiPopupFlags popup_flags) +bool ImGui::OpenPopupOnItemClick(ImStrv str_id, ImGuiPopupFlags popup_flags) { ImGuiContext& g = *GImGui; if (IsPopupOpenRequestForItem(popup_flags, g.LastItemData.ID)) @@ -12950,7 +12949,7 @@ bool ImGui::OpenPopupOnItemClick(const char* str_id, ImGuiPopupFlags popup_flags // OpenPopup(id); // return BeginPopup(id); // The main difference being that this is tweaked to avoid computing the ID twice. -bool ImGui::BeginPopupContextItem(const char* str_id, ImGuiPopupFlags popup_flags) +bool ImGui::BeginPopupContextItem(ImStrv str_id, ImGuiPopupFlags popup_flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; @@ -12963,7 +12962,7 @@ bool ImGui::BeginPopupContextItem(const char* str_id, ImGuiPopupFlags popup_flag return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings); } -bool ImGui::BeginPopupContextWindow(const char* str_id, ImGuiPopupFlags popup_flags) +bool ImGui::BeginPopupContextWindow(ImStrv str_id, ImGuiPopupFlags popup_flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; @@ -12975,7 +12974,7 @@ bool ImGui::BeginPopupContextWindow(const char* str_id, ImGuiPopupFlags popup_fl return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings); } -bool ImGui::BeginPopupContextVoid(const char* str_id, ImGuiPopupFlags popup_flags) +bool ImGui::BeginPopupContextVoid(ImStrv str_id, ImGuiPopupFlags popup_flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; @@ -13156,7 +13155,7 @@ void ImGui::SetWindowFocus() FocusWindow(GImGui->CurrentWindow); } -void ImGui::SetWindowFocus(const char* name) +void ImGui::SetWindowFocus(ImStrv name) { if (name) { @@ -15303,7 +15302,7 @@ void ImGui::EndDragDropSource() } // Use 'cond' to choose to submit payload on drag start or every frame -bool ImGui::SetDragDropPayload(const char* type, const void* data, size_t data_size, ImGuiCond cond) +bool ImGui::SetDragDropPayload(ImStrv type, const void* data, size_t data_size, ImGuiCond cond) { ImGuiContext& g = *GImGui; ImGuiPayload& payload = g.DragDropPayload; @@ -15437,7 +15436,7 @@ bool ImGui::IsDragDropPayloadBeingAccepted() return g.DragDropActive && g.DragDropAcceptIdPrev != 0; } -const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDropFlags flags) +const ImGuiPayload* ImGui::AcceptDragDropPayload(ImStrv type, ImGuiDragDropFlags flags) { ImGuiContext& g = *GImGui; ImGuiPayload& payload = g.DragDropPayload; @@ -15677,7 +15676,7 @@ void ImGui::LogToTTY(int auto_open_depth) } // Start logging/capturing text output to given file -void ImGui::LogToFile(int auto_open_depth, const char* filename) +void ImGui::LogToFile(int auto_open_depth, ImStrv filename) { ImGuiContext& g = *GImGui; if (g.LogEnabled) @@ -15850,14 +15849,14 @@ void ImGui::AddSettingsHandler(const ImGuiSettingsHandler* handler) g.SettingsHandlers.push_back(*handler); } -void ImGui::RemoveSettingsHandler(const char* type_name) +void ImGui::RemoveSettingsHandler(ImStrv type_name) { ImGuiContext& g = *GImGui; if (ImGuiSettingsHandler* handler = FindSettingsHandler(type_name)) g.SettingsHandlers.erase(handler); } -ImGuiSettingsHandler* ImGui::FindSettingsHandler(const char* type_name) +ImGuiSettingsHandler* ImGui::FindSettingsHandler(ImStrv type_name) { ImGuiContext& g = *GImGui; const ImGuiID type_hash = ImHashStr(type_name); @@ -15897,7 +15896,7 @@ void ImGui::CleanupIniSettings(ImGuiSettingsCleanupArgs* args) handler.CleanupFn(&g, &handler, args); } -void ImGui::LoadIniSettingsFromDisk(const char* ini_filename) +void ImGui::LoadIniSettingsFromDisk(ImStrv ini_filename) { size_t file_data_size = 0; char* file_data = (char*)ImFileLoadToMemory(ini_filename, "rb", &file_data_size); @@ -15910,7 +15909,7 @@ void ImGui::LoadIniSettingsFromDisk(const char* ini_filename) // Zero-tolerance, no error reporting, cheap .ini parsing // Set ini_size==0 to let us use strlen(ini_data). Do not call this function with a 0 if your buffer is actually empty! -void ImGui::LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size) +void ImGui::LoadIniSettingsFromMemory(ImStrv ini_data, size_t ini_size) { ImGuiContext& g = *GImGui; IM_ASSERT(g.Initialized); @@ -15986,7 +15985,7 @@ void ImGui::LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size) handler.ApplyAllFn(&g, &handler); } -void ImGui::SaveIniSettingsToDisk(const char* ini_filename) +void ImGui::SaveIniSettingsToDisk(ImStrv ini_filename) { ImGuiContext& g = *GImGui; g.SettingsDirtyTimer = 0.0f; @@ -16016,7 +16015,7 @@ const char* ImGui::SaveIniSettingsToMemory(size_t* out_size) return g.SettingsIniData.c_str(); } -ImGuiWindowSettings* ImGui::CreateNewWindowSettings(const char* name) +ImGuiWindowSettings* ImGui::CreateNewWindowSettings(ImStrv name) { ImGuiContext& g = *GImGui; @@ -16056,7 +16055,7 @@ ImGuiWindowSettings* ImGui::FindWindowSettingsByWindow(ImGuiWindow* window) } // This will revert window to its initial state, including enabling the ImGuiCond_FirstUseEver/ImGuiCond_Once conditions once more. -void ImGui::ClearWindowSettings(const char* name) +void ImGui::ClearWindowSettings(ImStrv name) { //IMGUI_DEBUG_LOG("ClearWindowSettings('%s')\n", name); ImGuiWindow* window = FindWindowByName(name); @@ -16680,7 +16679,7 @@ void ImGui::DebugRenderKeyboardPreview(ImDrawList* draw_list) } // Helper tool to diagnose between text encoding issues and font loading issues. Pass your UTF-8 string and verify that there are correct. -void ImGui::DebugTextEncoding(const char* str) +void ImGui::DebugTextEncoding(ImStrv str) { Text("Text: \"%s\"", str); if (!BeginTable("##DebugTextEncoding", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable)) @@ -18733,7 +18732,7 @@ void ImGui::DebugHookIdInfo(ImGuiID, ImGuiDataType, const void*, const void*) {} #if !defined(IMGUI_DISABLE_DEMO_WINDOWS) || !defined(IMGUI_DISABLE_DEBUG_TOOLS) // Demo helper function to select among loaded fonts. // Here we use the regular BeginCombo()/EndCombo() api which is the more flexible one. -void ImGui::ShowFontSelector(const char* label) +void ImGui::ShowFontSelector(ImStrv label) { ImGuiIO& io = GetIO(); ImFont* font_current = GetFont(); diff --git a/imgui.h b/imgui.h index fdbcf80ba..16773381a 100644 --- a/imgui.h +++ b/imgui.h @@ -327,6 +327,8 @@ struct ImVec4 }; IM_MSVC_RUNTIME_CHECKS_RESTORE +typedef const char* ImStrv; + //----------------------------------------------------------------------------- // [SECTION] Texture identifiers (ImTextureID, ImTextureRef) //----------------------------------------------------------------------------- @@ -423,8 +425,8 @@ namespace ImGui IMGUI_API void ShowIDStackToolWindow(bool* p_open = NULL); // create Stack Tool window. hover items with mouse to query information about the source of their unique ID. IMGUI_API void ShowAboutWindow(bool* p_open = NULL); // create About window. display Dear ImGui version, credits and build/system information. IMGUI_API void ShowStyleEditor(ImGuiStyle* ref = NULL); // add style editor block (not a window). you can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it uses the default style) - IMGUI_API bool ShowStyleSelector(const char* label); // add style selector block (not a window), essentially a combo listing the default styles. - IMGUI_API void ShowFontSelector(const char* label); // add font selector block (not a window), essentially a combo listing the loaded fonts. + IMGUI_API bool ShowStyleSelector(ImStrv label); // add style selector block (not a window), essentially a combo listing the default styles. + IMGUI_API void ShowFontSelector(ImStrv label); // add font selector block (not a window), essentially a combo listing the loaded fonts. IMGUI_API void ShowUserGuide(); // add basic help/info block (not a window): how to manipulate ImGui as an end-user (mouse/keyboard controls). IMGUI_API const char* GetVersion(); // get the compiled version string e.g. "1.80 WIP" (essentially the value for IMGUI_VERSION from the compiled version of imgui.cpp) @@ -445,7 +447,7 @@ namespace ImGui // such as BeginMenu/EndMenu, BeginPopup/EndPopup, etc. where the EndXXX call should only be called if the corresponding // BeginXXX function returned true. Begin and BeginChild are the only odd ones out. Will be fixed in a future update.] // - Note that the bottom of window stack always contains a window called "Debug". - IMGUI_API bool Begin(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); + IMGUI_API bool Begin(ImStrv name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); IMGUI_API void End(); // Child Windows @@ -466,7 +468,7 @@ namespace ImGui // [Important: due to legacy reason, Begin/End and BeginChild/EndChild are inconsistent with all other functions // such as BeginMenu/EndMenu, BeginPopup/EndPopup, etc. where the EndXXX call should only be called if the corresponding // BeginXXX function returned true. Begin and BeginChild are the only odd ones out. Will be fixed in a future update.] - IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0, 0), ImGuiChildFlags child_flags = 0, ImGuiWindowFlags window_flags = 0); + IMGUI_API bool BeginChild(ImStrv str_id, const ImVec2& size = ImVec2(0, 0), ImGuiChildFlags child_flags = 0, ImGuiWindowFlags window_flags = 0); IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0, 0), ImGuiChildFlags child_flags = 0, ImGuiWindowFlags window_flags = 0); IMGUI_API void EndChild(); @@ -496,10 +498,10 @@ namespace ImGui IMGUI_API void SetWindowSize(const ImVec2& size, ImGuiCond cond = 0); // (not recommended) set current window size - call within Begin()/End(). set to ImVec2(0, 0) to force an auto-fit. prefer using SetNextWindowSize(), as this may incur tearing and minor side-effects. IMGUI_API void SetWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // (not recommended) set current window collapsed state. prefer using SetNextWindowCollapsed(). IMGUI_API void SetWindowFocus(); // (not recommended) set current window to be focused / top-most. prefer using SetNextWindowFocus(). - IMGUI_API void SetWindowPos(const char* name, const ImVec2& pos, ImGuiCond cond = 0); // set named window position. - IMGUI_API void SetWindowSize(const char* name, const ImVec2& size, ImGuiCond cond = 0); // set named window size. set axis to 0.0f to force an auto-fit on this axis. - IMGUI_API void SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond = 0); // set named window collapsed state - IMGUI_API void SetWindowFocus(const char* name); // set named window to be focused / top-most. use NULL to remove focus. + IMGUI_API void SetWindowPos(ImStrv name, const ImVec2& pos, ImGuiCond cond = 0); // set named window position. + IMGUI_API void SetWindowSize(ImStrv name, const ImVec2& size, ImGuiCond cond = 0); // set named window size. set axis to 0.0f to force an auto-fit on this axis. + IMGUI_API void SetWindowCollapsed(ImStrv name, bool collapsed, ImGuiCond cond = 0); // set named window collapsed state + IMGUI_API void SetWindowFocus(ImStrv name); // set named window to be focused / top-most. use NULL to remove focus. // Windows Scrolling // - Any change of Scroll will be applied at the beginning of next frame in the first call to Begin(). @@ -613,12 +615,12 @@ namespace ImGui // - You can also use the "Label##foobar" syntax within widget label to distinguish them from each others. // - In this header file we use the "label"/"name" terminology to denote a string that will be displayed + used as an ID, // whereas "str_id" denote a string that is only used as an ID and not normally displayed. - IMGUI_API void PushID(const char* str_id); // push string into the ID stack (will hash string). + IMGUI_API void PushID(ImStrv str_id); // push string into the ID stack (will hash string). IMGUI_API void PushID(const char* str_id_begin, const char* str_id_end); // push string into the ID stack (will hash string). IMGUI_API void PushID(const void* ptr_id); // push pointer into the ID stack (will hash pointer). IMGUI_API void PushID(int int_id); // push integer into the ID stack (will hash integer). IMGUI_API void PopID(); // pop from the ID stack. - IMGUI_API ImGuiID GetID(const char* str_id); // calculate unique ID (hash of whole ID stack + given parameter). e.g. if you want to query into ImGuiStorage yourself + IMGUI_API ImGuiID GetID(ImStrv str_id); // calculate unique ID (hash of whole ID stack + given parameter). e.g. if you want to query into ImGuiStorage yourself IMGUI_API ImGuiID GetID(const char* str_id_begin, const char* str_id_end); IMGUI_API ImGuiID GetID(const void* ptr_id); IMGUI_API ImGuiID GetID(int int_id); @@ -634,28 +636,28 @@ namespace ImGui IMGUI_API void TextDisabledV(const char* fmt, va_list args) IM_FMTLIST(1); IMGUI_API void TextWrapped(const char* fmt, ...) IM_FMTARGS(1); // shortcut for PushTextWrapPos(0.0f); Text(fmt, ...); PopTextWrapPos();. Note that this won't work on an auto-resizing window if there's no other widgets to extend the window width, yoy may need to set a size using SetNextWindowSize(). IMGUI_API void TextWrappedV(const char* fmt, va_list args) IM_FMTLIST(1); - IMGUI_API void LabelText(const char* label, const char* fmt, ...) IM_FMTARGS(2); // display text+label aligned the same way as value+label widgets - IMGUI_API void LabelTextV(const char* label, const char* fmt, va_list args) IM_FMTLIST(2); + IMGUI_API void LabelText(ImStrv label, const char* fmt, ...) IM_FMTARGS(2); // display text+label aligned the same way as value+label widgets + IMGUI_API void LabelTextV(ImStrv label, const char* fmt, va_list args) IM_FMTLIST(2); IMGUI_API void BulletText(const char* fmt, ...) IM_FMTARGS(1); // shortcut for Bullet()+Text() IMGUI_API void BulletTextV(const char* fmt, va_list args) IM_FMTLIST(1); - IMGUI_API void SeparatorText(const char* label); // currently: formatted text with a horizontal line + IMGUI_API void SeparatorText(ImStrv label); // currently: formatted text with a horizontal line // Widgets: Main // - Most widgets return true when the value has been changed or when pressed/selected // - You may also use one of the many IsItemXXX functions (e.g. IsItemActive, IsItemHovered, etc.) to query widget state. - IMGUI_API bool Button(const char* label, const ImVec2& size = ImVec2(0, 0)); // button - IMGUI_API bool SmallButton(const char* label); // button with (FramePadding.y == 0) to easily embed within text - IMGUI_API bool InvisibleButton(const char* str_id, const ImVec2& size, ImGuiButtonFlags flags = 0); // flexible button behavior without the visuals, frequently useful to build custom behaviors using the public api (along with IsItemActive, IsItemHovered, etc.) - IMGUI_API bool ArrowButton(const char* str_id, ImGuiDir dir); // square button with an arrow shape - IMGUI_API bool Checkbox(const char* label, bool* v); - IMGUI_API bool CheckboxFlags(const char* label, int* flags, int flags_value); - IMGUI_API bool CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value); - IMGUI_API bool RadioButton(const char* label, bool active); // use with e.g. if (RadioButton("one", my_value==1)) { my_value = 1; } - IMGUI_API bool RadioButton(const char* label, int* v, int v_button); // shortcut to handle the above pattern when value is an integer - IMGUI_API void ProgressBar(float fraction, const ImVec2& size_arg = ImVec2(-FLT_MIN, 0), const char* overlay = NULL); + IMGUI_API bool Button(const ImStrv label, const ImVec2& size = ImVec2(0, 0)); // button + IMGUI_API bool SmallButton(ImStrv label); // button with (FramePadding.y == 0) to easily embed within text + IMGUI_API bool InvisibleButton(ImStrv str_id, const ImVec2& size, ImGuiButtonFlags flags = 0); // flexible button behavior without the visuals, frequently useful to build custom behaviors using the public api (along with IsItemActive, IsItemHovered, etc.) + IMGUI_API bool ArrowButton(ImStrv str_id, ImGuiDir dir); // square button with an arrow shape + IMGUI_API bool Checkbox(ImStrv label, bool* v); + IMGUI_API bool CheckboxFlags(ImStrv label, int* flags, int flags_value); + IMGUI_API bool CheckboxFlags(ImStrv label, unsigned int* flags, unsigned int flags_value); + IMGUI_API bool RadioButton(ImStrv label, bool active); // use with e.g. if (RadioButton("one", my_value==1)) { my_value = 1; } + IMGUI_API bool RadioButton(ImStrv label, int* v, int v_button); // shortcut to handle the above pattern when value is an integer + IMGUI_API void ProgressBar(float fraction, const ImVec2& size_arg = ImVec2(-FLT_MIN, 0), ImStrv overlay = NULL); IMGUI_API void Bullet(); // draw a small circle + keep the cursor on the same line. advance cursor x position by GetTreeNodeToLabelSpacing(), same distance that TreeNode() uses - IMGUI_API bool TextLink(const char* label); // hyperlink text button, return true when clicked - IMGUI_API bool TextLinkOpenURL(const char* label, const char* url = NULL); // hyperlink text button, automatically open file/url when clicked + IMGUI_API bool TextLink(ImStrv label); // hyperlink text button, return true when clicked + IMGUI_API bool TextLinkOpenURL(ImStrv label, ImStrv url = NULL); // hyperlink text button, automatically open file/url when clicked // Widgets: Images // - Read about ImTextureID/ImTextureRef here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples @@ -665,16 +667,16 @@ namespace ImGui // - An obsolete version of Image(), before 1.91.9 (March 2025), had a 'tint_col' parameter which is now supported by the ImageWithBg() function. IMGUI_API void Image(ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1)); IMGUI_API void ImageWithBg(ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1)); - IMGUI_API bool ImageButton(const char* str_id, ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1)); + IMGUI_API bool ImageButton(ImStrv str_id, ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1)); // Widgets: Combo Box (Dropdown) // - The BeginCombo()/EndCombo() api allows you to manage your contents and selection state however you want it, by creating e.g. Selectable() items. // - The old Combo() api are helpers over BeginCombo()/EndCombo() which are kept available for convenience purpose. This is analogous to how ListBox are created. - IMGUI_API bool BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags = 0); + IMGUI_API bool BeginCombo(ImStrv label, ImStrv preview_value, ImGuiComboFlags flags = 0); IMGUI_API void EndCombo(); // only call EndCombo() if BeginCombo() returns true! - IMGUI_API bool Combo(const char* label, int* current_item, const char* const items[], int items_count, int popup_max_height_in_items = -1); - IMGUI_API bool Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int popup_max_height_in_items = -1); // Separate items with \0 within a string, end item-list with \0\0. e.g. "One\0Two\0Three\0" - IMGUI_API bool Combo(const char* label, int* current_item, const char* (*getter)(void* user_data, int idx), void* user_data, int items_count, int popup_max_height_in_items = -1); + IMGUI_API bool Combo(ImStrv label, int* current_item, const char* const items[], int items_count, int popup_max_height_in_items = -1); + IMGUI_API bool Combo(ImStrv label, int* current_item, const char* items_separated_by_zeros, int popup_max_height_in_items = -1); // Separate items with \0 within a string, end item-list with \0\0. e.g. "One\0Two\0Three\0" + IMGUI_API bool Combo(ImStrv label, int* current_item, const char* (*getter)(void* user_data, int idx), void* user_data, int items_count, int popup_max_height_in_items = -1); // Widgets: Drag Sliders // - Ctrl+Click on any drag box to turn them into an input box. Manually input values aren't clamped by default and can go off-bounds. Use ImGuiSliderFlags_AlwaysClamp to always clamp. @@ -688,18 +690,18 @@ namespace ImGui // - We use the same sets of flags for DragXXX() and SliderXXX() functions as the features are the same and it makes it easier to swap them. // - Legacy: Pre-1.78 there are DragXXX() function signatures that take a final `float power=1.0f' argument instead of the `ImGuiSliderFlags flags=0' argument. // If you get a warning converting a float to ImGuiSliderFlags, read https://github.com/ocornut/imgui/issues/3361 - IMGUI_API bool DragFloat(const char* label, float* v, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", ImGuiSliderFlags flags = 0); // If v_min >= v_max we have no bound - IMGUI_API bool DragFloat2(const char* label, float v[2], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", ImGuiSliderFlags flags = 0); - IMGUI_API bool DragFloat3(const char* label, float v[3], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", ImGuiSliderFlags flags = 0); - IMGUI_API bool DragFloat4(const char* label, float v[4], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", ImGuiSliderFlags flags = 0); - IMGUI_API bool DragFloatRange2(const char* label, float* v_current_min, float* v_current_max, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", const char* format_max = NULL, ImGuiSliderFlags flags = 0); - IMGUI_API bool DragInt(const char* label, int* v, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", ImGuiSliderFlags flags = 0); // If v_min >= v_max we have no bound - IMGUI_API bool DragInt2(const char* label, int v[2], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", ImGuiSliderFlags flags = 0); - IMGUI_API bool DragInt3(const char* label, int v[3], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", ImGuiSliderFlags flags = 0); - IMGUI_API bool DragInt4(const char* label, int v[4], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", ImGuiSliderFlags flags = 0); - IMGUI_API bool DragIntRange2(const char* label, int* v_current_min, int* v_current_max, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", const char* format_max = NULL, ImGuiSliderFlags flags = 0); - IMGUI_API bool DragScalar(const char* label, ImGuiDataType data_type, void* p_data, float v_speed = 1.0f, const void* p_min = NULL, const void* p_max = NULL, const char* format = NULL, ImGuiSliderFlags flags = 0); - IMGUI_API bool DragScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, float v_speed = 1.0f, const void* p_min = NULL, const void* p_max = NULL, const char* format = NULL, ImGuiSliderFlags flags = 0); + IMGUI_API bool DragFloat(ImStrv label, float* v, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, ImStrv format = "%.3f", ImGuiSliderFlags flags = 0); // If v_min >= v_max we have no bound + IMGUI_API bool DragFloat2(ImStrv label, float v[2], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, ImStrv format = "%.3f", ImGuiSliderFlags flags = 0); + IMGUI_API bool DragFloat3(ImStrv label, float v[3], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, ImStrv format = "%.3f", ImGuiSliderFlags flags = 0); + IMGUI_API bool DragFloat4(ImStrv label, float v[4], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, ImStrv format = "%.3f", ImGuiSliderFlags flags = 0); + IMGUI_API bool DragFloatRange2(ImStrv label, float* v_current_min, float* v_current_max, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, ImStrv format = "%.3f", ImStrv format_max = NULL, ImGuiSliderFlags flags = 0); + IMGUI_API bool DragInt(ImStrv label, int* v, float v_speed = 1.0f, int v_min = 0, int v_max = 0, ImStrv format = "%d", ImGuiSliderFlags flags = 0); // If v_min >= v_max we have no bound + IMGUI_API bool DragInt2(ImStrv label, int v[2], float v_speed = 1.0f, int v_min = 0, int v_max = 0, ImStrv format = "%d", ImGuiSliderFlags flags = 0); + IMGUI_API bool DragInt3(ImStrv label, int v[3], float v_speed = 1.0f, int v_min = 0, int v_max = 0, ImStrv format = "%d", ImGuiSliderFlags flags = 0); + IMGUI_API bool DragInt4(ImStrv label, int v[4], float v_speed = 1.0f, int v_min = 0, int v_max = 0, ImStrv format = "%d", ImGuiSliderFlags flags = 0); + IMGUI_API bool DragIntRange2(ImStrv label, int* v_current_min, int* v_current_max, float v_speed = 1.0f, int v_min = 0, int v_max = 0, ImStrv format = "%d", ImStrv format_max = NULL, ImGuiSliderFlags flags = 0); + IMGUI_API bool DragScalar(ImStrv label, ImGuiDataType data_type, void* p_data, float v_speed = 1.0f, const void* p_min = NULL, const void* p_max = NULL, ImStrv format = NULL, ImGuiSliderFlags flags = 0); + IMGUI_API bool DragScalarN(ImStrv label, ImGuiDataType data_type, void* p_data, int components, float v_speed = 1.0f, const void* p_min = NULL, const void* p_max = NULL, ImStrv format = NULL, ImGuiSliderFlags flags = 0); // Widgets: Regular Sliders // - Ctrl+Click on any slider to turn them into an input box. Manually input values aren't clamped by default and can go off-bounds. Use ImGuiSliderFlags_AlwaysClamp to always clamp. @@ -707,66 +709,67 @@ namespace ImGui // - Format string may also be set to NULL or use the default format ("%f" or "%d"). // - Legacy: Pre-1.78 there are SliderXXX() function signatures that take a final `float power=1.0f' argument instead of the `ImGuiSliderFlags flags=0' argument. // If you get a warning converting a float to ImGuiSliderFlags, read https://github.com/ocornut/imgui/issues/3361 - IMGUI_API bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format = "%.3f", ImGuiSliderFlags flags = 0); // adjust format to decorate the value with a prefix or a suffix for in-slider labels or unit display. - IMGUI_API bool SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* format = "%.3f", ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* format = "%.3f", ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* format = "%.3f", ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderAngle(const char* label, float* v_rad, float v_degrees_min = -360.0f, float v_degrees_max = +360.0f, const char* format = "%.0f deg", ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderInt(const char* label, int* v, int v_min, int v_max, const char* format = "%d", ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* format = "%d", ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* format = "%d", ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* format = "%d", ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format = NULL, ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, const void* p_min, const void* p_max, const char* format = NULL, ImGuiSliderFlags flags = 0); - IMGUI_API bool VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* format = "%.3f", ImGuiSliderFlags flags = 0); - IMGUI_API bool VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* format = "%d", ImGuiSliderFlags flags = 0); - IMGUI_API bool VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format = NULL, ImGuiSliderFlags flags = 0); + IMGUI_API bool SliderFloat(ImStrv label, float* v, float v_min, float v_max, ImStrv format = "%.3f", ImGuiSliderFlags flags = 0); // adjust format to decorate the value with a prefix or a suffix for in-slider labels or unit display. + IMGUI_API bool SliderFloat2(ImStrv label, float v[2], float v_min, float v_max, ImStrv format = "%.3f", ImGuiSliderFlags flags = 0); + IMGUI_API bool SliderFloat3(ImStrv label, float v[3], float v_min, float v_max, ImStrv format = "%.3f", ImGuiSliderFlags flags = 0); + IMGUI_API bool SliderFloat4(ImStrv label, float v[4], float v_min, float v_max, ImStrv format = "%.3f", ImGuiSliderFlags flags = 0); + IMGUI_API bool SliderAngle(ImStrv label, float* v_rad, float v_degrees_min = -360.0f, float v_degrees_max = +360.0f, ImStrv format = "%.0f deg", ImGuiSliderFlags flags = 0); + IMGUI_API bool SliderInt(ImStrv label, int* v, int v_min, int v_max, ImStrv format = "%d", ImGuiSliderFlags flags = 0); + IMGUI_API bool SliderInt2(ImStrv label, int v[2], int v_min, int v_max, ImStrv format = "%d", ImGuiSliderFlags flags = 0); + IMGUI_API bool SliderInt3(ImStrv label, int v[3], int v_min, int v_max, ImStrv format = "%d", ImGuiSliderFlags flags = 0); + IMGUI_API bool SliderInt4(ImStrv label, int v[4], int v_min, int v_max, ImStrv format = "%d", ImGuiSliderFlags flags = 0); + IMGUI_API bool SliderScalar(ImStrv label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, ImStrv format = NULL, ImGuiSliderFlags flags = 0); + IMGUI_API bool SliderScalarN(ImStrv label, ImGuiDataType data_type, void* p_data, int components, const void* p_min, const void* p_max, ImStrv format = NULL, ImGuiSliderFlags flags = 0); + IMGUI_API bool VSliderFloat(ImStrv label, const ImVec2& size, float* v, float v_min, float v_max, ImStrv format = "%.3f", ImGuiSliderFlags flags = 0); + IMGUI_API bool VSliderInt(ImStrv label, const ImVec2& size, int* v, int v_min, int v_max, ImStrv format = "%d", ImGuiSliderFlags flags = 0); + IMGUI_API bool VSliderScalar(ImStrv label, const ImVec2& size, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, ImStrv format = NULL, ImGuiSliderFlags flags = 0); // Widgets: Input with Keyboard // - If you want to use InputText() with std::string or any custom dynamic string type, use the wrapper in misc/cpp/imgui_stdlib.h/.cpp! // - Most of the ImGuiInputTextFlags flags are only useful for InputText() and not for InputFloatX, InputIntX, InputDouble etc. - IMGUI_API bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); - IMGUI_API bool InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); - IMGUI_API bool InputTextWithHint(const char* label, const char* hint, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); - IMGUI_API bool InputFloat(const char* label, float* v, float step = 0.0f, float step_fast = 0.0f, const char* format = "%.3f", ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputFloat2(const char* label, float v[2], const char* format = "%.3f", ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputFloat3(const char* label, float v[3], const char* format = "%.3f", ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputFloat4(const char* label, float v[4], const char* format = "%.3f", ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputInt(const char* label, int* v, int step = 1, int step_fast = 100, ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputInt2(const char* label, int v[2], ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputInt3(const char* label, int v[3], ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputInt4(const char* label, int v[4], ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputDouble(const char* label, double* v, double step = 0.0, double step_fast = 0.0, const char* format = "%.6f", ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_step = NULL, const void* p_step_fast = NULL, const char* format = NULL, ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, const void* p_step = NULL, const void* p_step_fast = NULL, const char* format = NULL, ImGuiInputTextFlags flags = 0); + // - Format parameter is limited to 63 bytes. + IMGUI_API bool InputText(ImStrv label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); + IMGUI_API bool InputTextMultiline(ImStrv label, char* buf, size_t buf_size, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); + IMGUI_API bool InputTextWithHint(ImStrv label, ImStrv hint, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); + IMGUI_API bool InputFloat(ImStrv label, float* v, float step = 0.0f, float step_fast = 0.0f, ImStrv format = "%.3f", ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputFloat2(ImStrv label, float v[2], ImStrv format = "%.3f", ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputFloat3(ImStrv label, float v[3], ImStrv format = "%.3f", ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputFloat4(ImStrv label, float v[4], ImStrv format = "%.3f", ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputInt(ImStrv label, int* v, int step = 1, int step_fast = 100, ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputInt2(ImStrv label, int v[2], ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputInt3(ImStrv label, int v[3], ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputInt4(ImStrv label, int v[4], ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputDouble(ImStrv label, double* v, double step = 0.0, double step_fast = 0.0, ImStrv format = "%.6f", ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputScalar(ImStrv label, ImGuiDataType data_type, void* p_data, const void* p_step = NULL, const void* p_step_fast = NULL, ImStrv format = NULL, ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputScalarN(ImStrv label, ImGuiDataType data_type, void* p_data, int components, const void* p_step = NULL, const void* p_step_fast = NULL, ImStrv format = NULL, ImGuiInputTextFlags flags = 0); // Widgets: Color Editor/Picker (tip: the ColorEdit* functions have a little color square that can be left-clicked to open a picker, and right-clicked to open an option menu.) // - Note that in C++ a 'float v[X]' function argument is the _same_ as 'float* v', the array syntax is just a way to document the number of elements that are expected to be accessible. // - You can pass the address of a first float element out of a contiguous structure, e.g. &myvector.x - IMGUI_API bool ColorEdit3(const char* label, float col[3], ImGuiColorEditFlags flags = 0); - IMGUI_API bool ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags = 0); - IMGUI_API bool ColorPicker3(const char* label, float col[3], ImGuiColorEditFlags flags = 0); - IMGUI_API bool ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags = 0, const float* ref_col = NULL); - IMGUI_API bool ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // display a color square/button, hover for details, return true when pressed. + IMGUI_API bool ColorEdit3(ImStrv label, float col[3], ImGuiColorEditFlags flags = 0); + IMGUI_API bool ColorEdit4(ImStrv label, float col[4], ImGuiColorEditFlags flags = 0); + IMGUI_API bool ColorPicker3(ImStrv label, float col[3], ImGuiColorEditFlags flags = 0); + IMGUI_API bool ColorPicker4(ImStrv label, float col[4], ImGuiColorEditFlags flags = 0, const float* ref_col = NULL); + IMGUI_API bool ColorButton(ImStrv desc_id, const ImVec4& col, ImGuiColorEditFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // display a color square/button, hover for details, return true when pressed. // Widgets: Trees // - TreeNode functions return true when the node is open, in which case you need to also call TreePop() when you are finished displaying the tree node contents. - IMGUI_API bool TreeNode(const char* label); - IMGUI_API bool TreeNode(const char* str_id, const char* fmt, ...) IM_FMTARGS(2); // helper variation to easily decorrelate the id from the displayed string. Read the FAQ about why and how to use ID. to align arbitrary text at the same level as a TreeNode() you can use Bullet(). + IMGUI_API bool TreeNode(ImStrv label); + IMGUI_API bool TreeNode(ImStrv str_id, const char* fmt, ...) IM_FMTARGS(2); // helper variation to easily decorrelate the id from the displayed string. Read the FAQ about why and how to use ID. to align arbitrary text at the same level as a TreeNode() you can use Bullet(). IMGUI_API bool TreeNode(const void* ptr_id, const char* fmt, ...) IM_FMTARGS(2); // " - IMGUI_API bool TreeNodeV(const char* str_id, const char* fmt, va_list args) IM_FMTLIST(2); + IMGUI_API bool TreeNodeV(ImStrv str_id, const char* fmt, va_list args) IM_FMTLIST(2); IMGUI_API bool TreeNodeV(const void* ptr_id, const char* fmt, va_list args) IM_FMTLIST(2); - IMGUI_API bool TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags = 0); - IMGUI_API bool TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_FMTARGS(3); + IMGUI_API bool TreeNodeEx(ImStrv label, ImGuiTreeNodeFlags flags = 0); + IMGUI_API bool TreeNodeEx(ImStrv str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_FMTARGS(3); IMGUI_API bool TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_FMTARGS(3); - IMGUI_API bool TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) IM_FMTLIST(3); + IMGUI_API bool TreeNodeExV(ImStrv str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) IM_FMTLIST(3); IMGUI_API bool TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) IM_FMTLIST(3); - IMGUI_API void TreePush(const char* str_id); // ~ Indent()+PushID(). Already called by TreeNode() when returning true, but you can call TreePush/TreePop yourself if desired. + IMGUI_API void TreePush(ImStrv str_id); // ~ Indent()+PushID(). Already called by TreeNode() when returning true, but you can call TreePush/TreePop yourself if desired. IMGUI_API void TreePush(const void* ptr_id); // " IMGUI_API void TreePop(); // ~ Unindent()+PopID() IMGUI_API float GetTreeNodeToLabelSpacing(); // horizontal distance preceding label when using TreeNode*() or Bullet() == (g.FontSize + style.FramePadding.x*2) for a regular unframed TreeNode - IMGUI_API bool CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags = 0); // if returning 'true' the header is open. doesn't indent nor push on ID stack. user doesn't have to call TreePop(). - IMGUI_API bool CollapsingHeader(const char* label, bool* p_visible, ImGuiTreeNodeFlags flags = 0); // when 'p_visible != NULL': if '*p_visible==true' display an additional small close button on upper right of the header which will set the bool to false when clicked, if '*p_visible==false' don't display the header. + IMGUI_API bool CollapsingHeader(ImStrv label, ImGuiTreeNodeFlags flags = 0); // if returning 'true' the header is open. doesn't indent nor push on ID stack. user doesn't have to call TreePop(). + IMGUI_API bool CollapsingHeader(ImStrv label, bool* p_visible, ImGuiTreeNodeFlags flags = 0); // when 'p_visible != NULL': if '*p_visible==true' display an additional small close button on upper right of the header which will set the bool to false when clicked, if '*p_visible==false' don't display the header. IMGUI_API void SetNextItemOpen(bool is_open, ImGuiCond cond = 0); // set next TreeNode/CollapsingHeader open state. IMGUI_API void SetNextItemStorageID(ImGuiID storage_id); // set id to use for open/close storage (default to same as item id). IMGUI_API bool TreeNodeGetOpen(ImGuiID storage_id); // retrieve tree node open/close state. @@ -774,8 +777,8 @@ namespace ImGui // Widgets: Selectables // - A selectable highlights when hovered, and can display another color when selected. // - Neighbors selectable extend their highlight bounds in order to leave no gap between them. This is so a series of selected Selectable appear contiguous. - IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // "bool selected" carry the selection state (read-only). Selectable() is clicked is returns true so you can modify your selection state. size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height - IMGUI_API bool Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // "bool* p_selected" point to the selection state (read-write), as a convenient helper. + IMGUI_API bool Selectable(ImStrv label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // "bool selected" carry the selection state (read-only). Selectable() is clicked is returns true so you can modify your selection state. size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height + IMGUI_API bool Selectable(ImStrv label, bool* p_selected, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // "bool* p_selected" point to the selection state (read-write), as a convenient helper. // Multi-selection system for Selectable(), Checkbox(), TreeNode() functions [BETA] // - This enables standard multi-selection/range-selection idioms (Ctrl+Mouse/Keyboard, Shift+Mouse/Keyboard, etc.) in a way that also allow a clipper to be used. @@ -796,24 +799,24 @@ namespace ImGui // - The simplified/old ListBox() api are helpers over BeginListBox()/EndListBox() which are kept available for convenience purpose. This is analogous to how Combos are created. // - Choose frame width: size.x > 0.0f: custom / size.x < 0.0f or -FLT_MIN: right-align / size.x = 0.0f (default): use current ItemWidth // - Choose frame height: size.y > 0.0f: custom / size.y < 0.0f or -FLT_MIN: bottom-align / size.y = 0.0f (default): arbitrary default height which can fit ~7 items - IMGUI_API bool BeginListBox(const char* label, const ImVec2& size = ImVec2(0, 0)); // open a framed scrolling region + IMGUI_API bool BeginListBox(ImStrv label, const ImVec2& size = ImVec2(0, 0)); // open a framed scrolling region IMGUI_API void EndListBox(); // only call EndListBox() if BeginListBox() returned true! - IMGUI_API bool ListBox(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items = -1); - IMGUI_API bool ListBox(const char* label, int* current_item, const char* (*getter)(void* user_data, int idx), void* user_data, int items_count, int height_in_items = -1); + IMGUI_API bool ListBox(ImStrv label, int* current_item, const char* const items[], int items_count, int height_in_items = -1); + IMGUI_API bool ListBox(ImStrv label, int* current_item, const char* (*getter)(void* user_data, int idx), void* user_data, int items_count, int height_in_items = -1); // Widgets: Data Plotting // - Consider using ImPlot (https://github.com/epezent/implot) which is much better! - IMGUI_API void PlotLines(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0), int stride = sizeof(float)); - IMGUI_API void PlotLines(const char* label, float(*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0)); - IMGUI_API void PlotHistogram(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0), int stride = sizeof(float)); - IMGUI_API void PlotHistogram(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0)); + IMGUI_API void PlotLines(ImStrv label, const float* values, int values_count, int values_offset = 0, ImStrv overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0), int stride = sizeof(float)); + IMGUI_API void PlotLines(ImStrv label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, ImStrv overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0)); + IMGUI_API void PlotHistogram(ImStrv label, const float* values, int values_count, int values_offset = 0, ImStrv overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0), int stride = sizeof(float)); + IMGUI_API void PlotHistogram(ImStrv label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, ImStrv overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0)); // Widgets: Value() Helpers. // - Those are merely shortcut to calling Text() with a format string. Output single value in "name: value" format (tip: freely declare more in your code to handle your types. you can add functions to the ImGui namespace) - IMGUI_API void Value(const char* prefix, bool b); - IMGUI_API void Value(const char* prefix, int v); - IMGUI_API void Value(const char* prefix, unsigned int v); - IMGUI_API void Value(const char* prefix, float v, const char* float_format = NULL); + IMGUI_API void Value(ImStrv prefix, bool b); + IMGUI_API void Value(ImStrv prefix, int v); + IMGUI_API void Value(ImStrv prefix, unsigned int v); + IMGUI_API void Value(ImStrv prefix, float v, ImStrv float_format = NULL); // Widgets: Menus // - Use BeginMenuBar() on a window ImGuiWindowFlags_MenuBar to append to its menu bar. @@ -824,10 +827,10 @@ namespace ImGui IMGUI_API void EndMenuBar(); // only call EndMenuBar() if BeginMenuBar() returns true! IMGUI_API bool BeginMainMenuBar(); // create and append to a full screen menu-bar. IMGUI_API void EndMainMenuBar(); // only call EndMainMenuBar() if BeginMainMenuBar() returns true! - IMGUI_API bool BeginMenu(const char* label, bool enabled = true); // create a sub-menu entry. only call EndMenu() if this returns true! + IMGUI_API bool BeginMenu(ImStrv label, bool enabled = true); // create a sub-menu entry. only call EndMenu() if this returns true! IMGUI_API void EndMenu(); // only call EndMenu() if BeginMenu() returns true! - IMGUI_API bool MenuItem(const char* label, const char* shortcut = NULL, bool selected = false, bool enabled = true); // return true when activated. - IMGUI_API bool MenuItem(const char* label, const char* shortcut, bool* p_selected, bool enabled = true); // return true when activated + toggle (*p_selected) if p_selected != NULL + IMGUI_API bool MenuItem(ImStrv label, ImStrv shortcut = NULL, bool selected = false, bool enabled = true); // return true when activated. + IMGUI_API bool MenuItem(ImStrv label, ImStrv shortcut, bool* p_selected, bool enabled = true); // return true when activated + toggle (*p_selected) if p_selected != NULL // Tooltips // - Tooltips are windows following the mouse. They do not take focus away. @@ -856,8 +859,8 @@ namespace ImGui // This is sometimes leading to confusing mistakes. May rework this in the future. // - BeginPopup(): query popup state, if open start appending into the window. Call EndPopup() afterwards if returned true. ImGuiWindowFlags are forwarded to the window. // - BeginPopupModal(): block every interaction behind the window, cannot be closed by user, add a dimming background, has a title bar. - IMGUI_API bool BeginPopup(const char* str_id, ImGuiWindowFlags flags = 0); // return true if the popup is open, and you can start outputting to it. - IMGUI_API bool BeginPopupModal(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // return true if the modal is open, and you can start outputting to it. + IMGUI_API bool BeginPopup(ImStrv str_id, ImGuiWindowFlags flags = 0); // return true if the popup is open, and you can start outputting to it. + IMGUI_API bool BeginPopupModal(ImStrv name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // return true if the modal is open, and you can start outputting to it. IMGUI_API void EndPopup(); // only call EndPopup() if BeginPopupXXX() returns true! // Popups: open/close functions @@ -869,9 +872,9 @@ namespace ImGui // - CloseCurrentPopup() is called by default by Selectable()/MenuItem() when activated (FIXME: need some options). // - Use ImGuiPopupFlags_NoOpenOverExistingPopup to avoid opening a popup if there's already one at the same level. This is equivalent to e.g. testing for !IsAnyPopupOpen() prior to OpenPopup(). // - Use IsWindowAppearing() after BeginPopup() to tell if a window just opened. - IMGUI_API bool OpenPopup(const char* str_id, ImGuiPopupFlags popup_flags = 0); // call to mark popup as open (don't call every frame!). + IMGUI_API bool OpenPopup(ImStrv str_id, ImGuiPopupFlags popup_flags = 0); // call to mark popup as open (don't call every frame!). IMGUI_API bool OpenPopup(ImGuiID id, ImGuiPopupFlags popup_flags = 0); // id overload to facilitate calling from nested stacks - IMGUI_API bool OpenPopupOnItemClick(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 0); // helper to open popup when clicked on last item. Default to ImGuiPopupFlags_MouseButtonRight == 1. (note: actually triggers on the mouse _released_ event to be consistent with popup behaviors) + IMGUI_API bool OpenPopupOnItemClick(ImStrv str_id = NULL, ImGuiPopupFlags popup_flags = 0); // helper to open popup when clicked on last item. Default to ImGuiPopupFlags_MouseButtonRight == 1. (note: actually triggers on the mouse _released_ event to be consistent with popup behaviors) IMGUI_API void CloseCurrentPopup(); // manually close the popup we have begin-ed into. // Popups: Open+Begin popup combined functions helpers to create context menus. @@ -883,15 +886,15 @@ namespace ImGui // - After: The default = 0 means ImGuiPopupFlags_MouseButtonRight. Explicitly passing a literal 1 also means ImGuiPopupFlags_MouseButtonRight (if legacy behavior are enabled) or will assert (if legacy behavior are disabled). // - TL;DR: if you don't want to use right mouse button for popups, always specify it explicitly using a named ImGuiPopupFlags_MouseButtonXXXX value. // - Read "API BREAKING CHANGES" 2026/01/07 (1.92.6) entry in imgui.cpp or GitHub topic #9157 for all details. - IMGUI_API bool BeginPopupContextItem(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 0); // open+begin popup when clicked on last item. Use str_id==NULL to associate the popup to previous item. If you want to use that on a non-interactive item such as Text() you need to pass in an explicit ID here. read comments in .cpp! - IMGUI_API bool BeginPopupContextWindow(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 0);// open+begin popup when clicked on current window. - IMGUI_API bool BeginPopupContextVoid(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 0); // open+begin popup when clicked in void (where there are no windows). + IMGUI_API bool BeginPopupContextItem(ImStrv str_id = NULL, ImGuiPopupFlags popup_flags = 0); // open+begin popup when clicked on last item. Use str_id==NULL to associate the popup to previous item. If you want to use that on a non-interactive item such as Text() you need to pass in an explicit ID here. read comments in .cpp! + IMGUI_API bool BeginPopupContextWindow(ImStrv str_id = NULL, ImGuiPopupFlags popup_flags = 0); // open+begin popup when clicked on current window. + IMGUI_API bool BeginPopupContextVoid(ImStrv str_id = NULL, ImGuiPopupFlags popup_flags = 0); // open+begin popup when clicked in void (where there are no windows). // Popups: query functions // - IsPopupOpen(): return true if the popup is open at the current BeginPopup() level of the popup stack. // - IsPopupOpen() with ImGuiPopupFlags_AnyPopupId: return true if any popup is open at the current BeginPopup() level of the popup stack. // - IsPopupOpen() with ImGuiPopupFlags_AnyPopupId + ImGuiPopupFlags_AnyPopupLevel: return true if any popup is open. - IMGUI_API bool IsPopupOpen(const char* str_id, ImGuiPopupFlags flags = 0); // return true if the popup is open. + IMGUI_API bool IsPopupOpen(ImStrv str_id, ImGuiPopupFlags flags = 0); // return true if the popup is open. // Tables // - Full-featured replacement for old Columns API. @@ -914,7 +917,7 @@ namespace ImGui // - TableNextColumn() -> Text("Hello 0") -> TableNextColumn() -> Text("Hello 1") // OK: TableNextColumn() automatically gets to next row! // - TableNextRow() -> Text("Hello 0") // Not OK! Missing TableSetColumnIndex() or TableNextColumn()! Text will not appear! // - 5. Call EndTable() - IMGUI_API bool BeginTable(const char* str_id, int columns, ImGuiTableFlags flags = 0, const ImVec2& outer_size = ImVec2(0.0f, 0.0f), float inner_width = 0.0f); + IMGUI_API bool BeginTable(ImStrv str_id, int columns, ImGuiTableFlags flags = 0, const ImVec2& outer_size = ImVec2(0.0f, 0.0f), float inner_width = 0.0f); IMGUI_API void EndTable(); // only call EndTable() if BeginTable() returns true! IMGUI_API void TableNextRow(ImGuiTableRowFlags row_flags = 0, float min_row_height = 0.0f); // append into the first cell of a new row. 'min_row_height' include the minimum top and bottom padding aka CellPadding.y * 2.0f. IMGUI_API bool TableNextColumn(); // append into the next column (or first column of next row if currently in last column). Return true when column is visible. @@ -929,9 +932,9 @@ namespace ImGui // - You may manually submit headers using TableNextRow() + TableHeader() calls, but this is only useful in // some advanced use cases (e.g. adding custom widgets in header row). // - Use TableSetupScrollFreeze() to lock columns/rows so they stay visible when scrolled. When freezing columns you would usually also use ImGuiTableColumnFlags_NoHide on them. - IMGUI_API void TableSetupColumn(const char* label, ImGuiTableColumnFlags flags = 0, float init_width_or_weight = 0.0f, ImGuiID user_data = 0); + IMGUI_API void TableSetupColumn(ImStrv label, ImGuiTableColumnFlags flags = 0, float init_width_or_weight = 0.0f, ImGuiID user_data = 0); IMGUI_API void TableSetupScrollFreeze(int cols, int rows); // lock columns/rows so they stay visible when scrolled. - IMGUI_API void TableHeader(const char* label); // submit one header cell manually (rarely used) + IMGUI_API void TableHeader(ImStrv label); // submit one header cell manually (rarely used) IMGUI_API void TableHeadersRow(); // submit a row with headers cells based on data provided to TableSetupColumn() + submit context menu IMGUI_API void TableAngledHeadersRow(); // submit a row with angled headers for every column with the ImGuiTableColumnFlags_AngledHeader flag. MUST BE FIRST ROW. @@ -953,7 +956,7 @@ namespace ImGui // Legacy Columns API (prefer using Tables!) // - You can also use SameLine(pos_x) to mimic simplified columns. - IMGUI_API void Columns(int count = 1, const char* id = NULL, bool borders = true); + IMGUI_API void Columns(int count = 1, ImStrv id = NULL, bool borders = true); IMGUI_API void NextColumn(); // next column, defaults to current row or next row if the current row is finished IMGUI_API int GetColumnIndex(); // get current column index IMGUI_API float GetColumnWidth(int column_index = -1); // get column width (in pixels). pass -1 to use current column @@ -964,17 +967,17 @@ namespace ImGui // Tab Bars, Tabs // - Note: Tabs are automatically created by the docking system (when in 'docking' branch). Use this to create tab bars/tabs yourself. - IMGUI_API bool BeginTabBar(const char* str_id, ImGuiTabBarFlags flags = 0); // create and append into a TabBar + IMGUI_API bool BeginTabBar(ImStrv str_id, ImGuiTabBarFlags flags = 0); // create and append into a TabBar IMGUI_API void EndTabBar(); // only call EndTabBar() if BeginTabBar() returns true! - IMGUI_API bool BeginTabItem(const char* label, bool* p_open = NULL, ImGuiTabItemFlags flags = 0); // create a Tab. Returns true if the Tab is selected. + IMGUI_API bool BeginTabItem(ImStrv label, bool* p_open = NULL, ImGuiTabItemFlags flags = 0);// create a Tab. Returns true if the Tab is selected. IMGUI_API void EndTabItem(); // only call EndTabItem() if BeginTabItem() returns true! - IMGUI_API bool TabItemButton(const char* label, ImGuiTabItemFlags flags = 0); // create a Tab behaving like a button. return true when clicked. cannot be selected in the tab bar. - IMGUI_API void SetTabItemClosed(const char* tab_or_docked_window_label); // notify TabBar or Docking system of a closed tab/window ahead (useful to reduce visual flicker on reorderable tab bars). For tab-bar: call after BeginTabBar() and before Tab submissions. Otherwise call with a window name. + IMGUI_API bool TabItemButton(ImStrv label, ImGuiTabItemFlags flags = 0); // create a Tab behaving like a button. return true when clicked. cannot be selected in the tab bar. + IMGUI_API void SetTabItemClosed(ImStrv tab_or_docked_window_label); // notify TabBar or Docking system of a closed tab/window ahead (useful to reduce visual flicker on reorderable tab bars). For tab-bar: call after BeginTabBar() and before Tab submissions. Otherwise call with a window name. // Logging/Capture // - All text output from the interface can be captured into tty/file/clipboard. By default, tree nodes are automatically opened during logging. IMGUI_API void LogToTTY(int auto_open_depth = -1); // start logging to tty (stdout) - IMGUI_API void LogToFile(int auto_open_depth = -1, const char* filename = NULL); // start logging to file + IMGUI_API void LogToFile(int auto_open_depth = -1, ImStrv filename = NULL); // start logging to file IMGUI_API void LogToClipboard(int auto_open_depth = -1); // start logging to OS clipboard IMGUI_API void LogFinish(); // stop logging (close file, etc.) IMGUI_API void LogButtons(); // helper to display buttons for logging to tty/file/clipboard @@ -987,10 +990,10 @@ namespace ImGui // - If you stop calling BeginDragDropSource() the payload is preserved however it won't have a preview tooltip (we currently display a fallback "..." tooltip, see #1725) // - An item can be both drag source and drop target. IMGUI_API bool BeginDragDropSource(ImGuiDragDropFlags flags = 0); // call after submitting an item which may be dragged. when this return true, you can call SetDragDropPayload() + EndDragDropSource() - IMGUI_API bool SetDragDropPayload(const char* type, const void* data, size_t sz, ImGuiCond cond = 0); // type is a user defined string of maximum 32 characters. Strings starting with '_' are reserved for dear imgui internal types. Data is copied and held by imgui. Return true when payload has been accepted. + IMGUI_API bool SetDragDropPayload(ImStrv type, const void* data, size_t sz, ImGuiCond cond = 0); // type is a user defined string of maximum 32 characters. Strings starting with '_' are reserved for dear imgui internal types. Data is copied and held by imgui. Return true when payload has been accepted. IMGUI_API void EndDragDropSource(); // only call EndDragDropSource() if BeginDragDropSource() returns true! IMGUI_API bool BeginDragDropTarget(); // call after submitting an item that may receive a payload. If this returns true, you can call AcceptDragDropPayload() + EndDragDropTarget() - IMGUI_API const ImGuiPayload* AcceptDragDropPayload(const char* type, ImGuiDragDropFlags flags = 0); // accept contents of a given type. If ImGuiDragDropFlags_AcceptBeforeDelivery is set you can peek into the payload before the mouse button is released. + IMGUI_API const ImGuiPayload* AcceptDragDropPayload(ImStrv type, ImGuiDragDropFlags flags = 0); // accept contents of a given type. If ImGuiDragDropFlags_AcceptBeforeDelivery is set you can peek into the payload before the mouse button is released. IMGUI_API void EndDragDropTarget(); // only call EndDragDropTarget() if BeginDragDropTarget() returns true! IMGUI_API const ImGuiPayload* GetDragDropPayload(); // peek directly into the current payload from anywhere. returns NULL when drag and drop is finished or inactive. use ImGuiPayload::IsDataType() to test for the payload type. @@ -1138,25 +1141,25 @@ namespace ImGui // Clipboard Utilities // - Also see the LogToClipboard() function to capture GUI into clipboard, or easily output text data to the clipboard. IMGUI_API const char* GetClipboardText(); - IMGUI_API void SetClipboardText(const char* text); + IMGUI_API void SetClipboardText(ImStrv text); // Settings/.Ini Utilities // - The disk functions are automatically called if io.IniFilename != NULL (default is "imgui.ini"). // - Set io.IniFilename to NULL to load/save manually. Read io.WantSaveIniSettings description about handling .ini saving manually. // - Important: default value "imgui.ini" is relative to current working dir! Most apps will want to lock this to an absolute path (e.g. same path as executables). - IMGUI_API void LoadIniSettingsFromDisk(const char* ini_filename); // call after CreateContext() and before the first call to NewFrame(). NewFrame() automatically calls LoadIniSettingsFromDisk(io.IniFilename). - IMGUI_API void LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size=0); // call after CreateContext() and before the first call to NewFrame() to provide .ini data from your own data source. - IMGUI_API void SaveIniSettingsToDisk(const char* ini_filename); // this is automatically called (if io.IniFilename is not empty) a few seconds after any modification that should be reflected in the .ini file (and also by DestroyContext). + IMGUI_API void LoadIniSettingsFromDisk(ImStrv ini_filename); // call after CreateContext() and before the first call to NewFrame(). NewFrame() automatically calls LoadIniSettingsFromDisk(io.IniFilename). + IMGUI_API void LoadIniSettingsFromMemory(ImStrv ini_data, size_t ini_size= 0); // call after CreateContext() and before the first call to NewFrame() to provide .ini data from your own data source. + IMGUI_API void SaveIniSettingsToDisk(ImStrv ini_filename); // this is automatically called (if io.IniFilename is not empty) a few seconds after any modification that should be reflected in the .ini file (and also by DestroyContext). IMGUI_API const char* SaveIniSettingsToMemory(size_t* out_ini_size = NULL); // return a zero-terminated string with the .ini data which you can save by your own mean. call when io.WantSaveIniSettings is set, then save data by your own mean and clear io.WantSaveIniSettings. // Debug Utilities // - Your main debugging friend is the ShowMetricsWindow() function. // - Interactive tools are all accessible from the 'Dear ImGui Demo->Tools' menu. // - Read https://github.com/ocornut/imgui/wiki/Debug-Tools for a description of all available debug tools. - IMGUI_API void DebugTextEncoding(const char* text); + IMGUI_API void DebugTextEncoding(ImStrv text); IMGUI_API void DebugFlashStyleColor(ImGuiCol idx); IMGUI_API void DebugStartItemPicker(); - IMGUI_API bool DebugCheckVersionAndDataLayout(const char* version_str, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_drawvert, size_t sz_drawidx); // This is called by IMGUI_CHECKVERSION() macro. + IMGUI_API bool DebugCheckVersionAndDataLayout(ImStrv version_str, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_drawvert, size_t sz_drawidx); // This is called by IMGUI_CHECKVERSION() macro. #ifndef IMGUI_DISABLE_DEBUG_TOOLS IMGUI_API void DebugLog(const char* fmt, ...) IM_FMTARGS(1); // Call via IMGUI_DEBUG_LOG() for maximum stripping in caller code! IMGUI_API void DebugLogV(const char* fmt, va_list args) IM_FMTLIST(1); @@ -2767,7 +2770,7 @@ struct ImGuiPayload ImGuiPayload() { Clear(); } void Clear() { SourceId = SourceParentId = 0; Data = NULL; DataSize = 0; memset(DataType, 0, sizeof(DataType)); DataFrameCount = -1; Preview = Delivery = false; } - bool IsDataType(const char* type) const { return DataFrameCount != -1 && strcmp(type, DataType) == 0; } + bool IsDataType(ImStrv type) const { return DataFrameCount != -1 && strcmp(type, DataType) == 0; } bool IsPreview() const { return Preview; } bool IsDelivery() const { return Delivery; } }; @@ -2797,17 +2800,17 @@ struct ImGuiOnceUponAFrame struct ImGuiTextFilterItem; struct ImGuiTextFilter { - IMGUI_API ImGuiTextFilter(const char* default_filter = ""); + IMGUI_API ImGuiTextFilter(ImStrv default_filter = ""); IMGUI_API bool PassFilter(const char* text, const char* text_end = NULL) const; IMGUI_API void Build(); // Update internal data when filter changes inline void Clear() { InputBuf[0] = 0; Build(); } // Clear filter inline bool IsActive() const { return _Items.Size != 0; } // Useful if you need e.g. an alternative code-path when there are no filters // Helper to call InputText() + Build() when buffer is changed. - IMGUI_API bool Draw(const char* label = "Filter"); - IMGUI_API bool DrawWithHint(const char* label = "Filter", const char* hint = "incl -excl"); + IMGUI_API bool Draw(ImStrv label = "Filter"); + IMGUI_API bool DrawWithHint(ImStrv label = "Filter", ImStrv hint = "incl -excl"); #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - inline bool Draw(const char* label, float width) { if (width != 0.0f) ImGui::SetNextItemWidth(width); return Draw(label); } + inline bool Draw(ImStrv label, float width) { if (width != 0.0f) ImGui::SetNextItemWidth(width); return Draw(label); } #endif // Members @@ -3828,12 +3831,13 @@ struct ImFontAtlas IMGUI_API ImFont* AddFontDefault(const ImFontConfig* font_cfg = NULL); // Selects between AddFontDefaultVector() and AddFontDefaultBitmap(). IMGUI_API ImFont* AddFontDefaultVector(const ImFontConfig* font_cfg = NULL); // Embedded scalable font. Recommended at any higher size. IMGUI_API ImFont* AddFontDefaultBitmap(const ImFontConfig* font_cfg = NULL); // Embedded classic pixel-clean font. Recommended at Size 13px with no scaling. - IMGUI_API ImFont* AddFontFromFileTTF(const char* filename, float size_pixels = 0.0f, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); - IMGUI_API ImFont* AddFontFromMemoryTTF(void* font_data, int font_data_size, float size_pixels = 0.0f, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // Note: Transfer ownership of 'ttf_data' to ImFontAtlas! Will be deleted after destruction of the atlas. Set font_cfg->FontDataOwnedByAtlas=false to keep ownership of your data and it won't be freed. - IMGUI_API ImFont* AddFontFromMemoryCompressedTTF(const void* compressed_font_data, int compressed_font_data_size, float size_pixels = 0.0f, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data' still owned by caller. Compress with binary_to_compressed_c.cpp. - IMGUI_API ImFont* AddFontFromMemoryCompressedBase85TTF(const char* compressed_font_data_base85, float size_pixels = 0.0f, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data_base85' still owned by caller. Compress with binary_to_compressed_c.cpp with -base85 parameter. + IMGUI_API ImFont* AddFontFromFileTTF(ImStrv filename, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); + IMGUI_API ImFont* AddFontFromMemoryTTF(void* font_data, int font_data_size, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // Note: Transfer ownership of 'ttf_data' to ImFontAtlas! Will be deleted after destruction of the atlas. Set font_cfg->FontDataOwnedByAtlas=false to keep ownership of your data and it won't be freed. + IMGUI_API ImFont* AddFontFromMemoryCompressedTTF(const void* compressed_font_data, int compressed_font_data_size, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data' still owned by caller. Compress with binary_to_compressed_c.cpp. + IMGUI_API ImFont* AddFontFromMemoryCompressedBase85TTF(ImStrv compressed_font_data_base85, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data_base85' still owned by caller. Compress with binary_to_compressed_c.cpp with -base85 parameter. IMGUI_API void RemoveFont(ImFont* font); // Remove a font IMGUI_API void CompactCache(); // Compact cached glyphs and texture. + IMGUI_API void SetFontLoader(const ImFontLoader* font_loader); // Change font loader at runtime. // Clearing the atlas/fonts has little use nowadays, unless you want to batch remove all fonts. @@ -3841,7 +3845,7 @@ struct ImFontAtlas // - As we are transitioning toward our new font system the semantic for those functions gets increasingly misleading and are often a source of issues. // TL;DR; most likely, don't use any of those functions. We expect to obsolete/rework them. IMGUI_API void Clear(); // Clear everything (fonts + textures). Don't call mid-frame! - IMGUI_API void ClearFonts(); // Clear input+output font data/glyphs. New fonts and textures will be recreated afterwards. + IMGUI_API void ClearFonts(); // Clear input+output font data/glyphs. You can call this mid-frame if you load new fonts afterwards! IMGUI_API void ClearInputData(); // [OBSOLETE] Clear input data (all ImFontConfig structures including sizes, TTF data, glyph ranges, etc.) = all the data used to build the texture and fonts. IMGUI_API void ClearTexData(); // [OBSOLETE] Clear CPU-side copy of the texture data. Saves RAM once the texture has been copied to graphics memory. @@ -4273,7 +4277,7 @@ namespace ImGui //static inline bool ListBoxHeader(const char* label, int items_count, int height_in_items = -1) { float height = GetTextLineHeightWithSpacing() * ((height_in_items < 0 ? ImMin(items_count, 7) : height_in_items) + 0.25f) + GetStyle().FramePadding.y * 2.0f; return BeginListBox(label, ImVec2(0.0f, height)); } // Helper to calculate size from items_count and height_in_items //static inline void ListBoxFooter() { EndListBox(); } //-- OBSOLETED in 1.79 (from August 2020) - //static inline void OpenPopupContextItem(const char* str_id = NULL, ImGuiMouseButton mb = 1) { OpenPopupOnItemClick(str_id, mb); } // Bool return value removed. Use IsWindowAppearing() in BeginPopup() instead. Renamed in 1.77, renamed back in 1.79. Sorry! + //static inline void OpenPopupContextItem(ImStrv str_id = NULL, ImGuiMouseButton mb = 1) { OpenPopupOnItemClick(str_id, mb); } // Bool return value removed. Use IsWindowAppearing() in BeginPopup() instead. Renamed in 1.77, renamed back in 1.79. Sorry! //-- OBSOLETED in 1.78 (from June 2020): Old drag/sliders functions that took a 'float power > 1.0f' argument instead of ImGuiSliderFlags_Logarithmic. See github.com/ocornut/imgui/issues/3361 for details. //IMGUI_API bool DragScalar(const char* label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min, const void* p_max, const char* format, float power = 1.0f) // OBSOLETED in 1.78 (from June 2020) //IMGUI_API bool DragScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, float v_speed, const void* p_min, const void* p_max, const char* format, float power = 1.0f); // OBSOLETED in 1.78 (from June 2020) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index ede2eeb07..b1ac4d9e6 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -8614,7 +8614,7 @@ void ImGui::ShowAboutWindow(bool* p_open) //----------------------------------------------------------------------------- // Demo helper function to select among default colors. See ShowStyleEditor() for more advanced options. -bool ImGui::ShowStyleSelector(const char* label) +bool ImGui::ShowStyleSelector(ImStrv label) { // FIXME: This is a bit tricky to get right as style are functions, they don't register a name nor the fact that one is active. // So we keep track of last active one among our limited selection. @@ -11545,7 +11545,7 @@ void ImGui::ShowAboutWindow(bool*) {} void ImGui::ShowDemoWindow(bool*) {} void ImGui::ShowUserGuide() {} void ImGui::ShowStyleEditor(ImGuiStyle*) {} -bool ImGui::ShowStyleSelector(const char*) { return false; } +bool ImGui::ShowStyleSelector(ImStrv) { return false; } #endif // #ifndef IMGUI_DISABLE_DEMO_WINDOWS diff --git a/imgui_draw.cpp b/imgui_draw.cpp index f5ea37700..3bddfabe8 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -4371,7 +4371,7 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg_in) static unsigned int stb_decompress_length(const unsigned char* input); static unsigned int stb_decompress(unsigned char* output, const unsigned char* input, unsigned int length); static unsigned int Decode85Byte(char c) { return c >= '\\' ? c-36 : c-35; } -static void Decode85(const unsigned char* src, unsigned char* dst) +static void Decode85(ImStrv src, unsigned char* dst) { while (*src) { @@ -4465,7 +4465,7 @@ ImFont* ImFontAtlas::AddFontDefaultVector(const ImFontConfig* font_cfg_template) #endif } -ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges) +ImFont* ImFontAtlas::AddFontFromFileTTF(ImStrv filename, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges) { IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!"); size_t data_size = 0; @@ -4517,11 +4517,11 @@ ImFont* ImFontAtlas::AddFontFromMemoryCompressedTTF(const void* compressed_ttf_d return AddFontFromMemoryTTF(buf_decompressed_data, (int)buf_decompressed_size, size_pixels, &font_cfg, glyph_ranges); } -ImFont* ImFontAtlas::AddFontFromMemoryCompressedBase85TTF(const char* compressed_ttf_data_base85, float size_pixels, const ImFontConfig* font_cfg, const ImWchar* glyph_ranges) +ImFont* ImFontAtlas::AddFontFromMemoryCompressedBase85TTF(ImStrv compressed_ttf_data_base85, float size_pixels, const ImFontConfig* font_cfg, const ImWchar* glyph_ranges) { int compressed_ttf_size = (((int)ImStrlen(compressed_ttf_data_base85) + 4) / 5) * 4; void* compressed_ttf = IM_ALLOC((size_t)compressed_ttf_size); - Decode85((const unsigned char*)compressed_ttf_data_base85, (unsigned char*)compressed_ttf); + Decode85(compressed_ttf_data_base85, (unsigned char*)compressed_ttf); ImFont* font = AddFontFromMemoryCompressedTTF(compressed_ttf, compressed_ttf_size, size_pixels, font_cfg, glyph_ranges); IM_FREE(compressed_ttf); return font; diff --git a/imgui_internal.h b/imgui_internal.h index 875c51f42..7c8aca3ad 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -464,7 +464,7 @@ IMGUI_API void ImTextClassifierSetCharClassFromStr(ImU32* bits, unsigne #ifdef IMGUI_DISABLE_FILE_FUNCTIONS #define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS typedef void* ImFileHandle; -inline ImFileHandle ImFileOpen(const char*, const char*) { return NULL; } +inline ImFileHandle ImFileOpen(ImStrv, ImStrv) { return NULL; } inline bool ImFileClose(ImFileHandle) { return false; } inline ImU64 ImFileGetSize(ImFileHandle) { return (ImU64)-1; } inline ImU64 ImFileRead(void*, ImU64, ImU64, ImFileHandle) { return 0; } @@ -472,7 +472,7 @@ inline ImU64 ImFileWrite(const void*, ImU64, ImU64, ImFileHandle) #endif #ifndef IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS typedef FILE* ImFileHandle; -IMGUI_API ImFileHandle ImFileOpen(const char* filename, const char* mode); +IMGUI_API ImFileHandle ImFileOpen(ImStrv filename, ImStrv mode); IMGUI_API bool ImFileClose(ImFileHandle file); IMGUI_API ImU64 ImFileGetSize(ImFileHandle file); IMGUI_API ImU64 ImFileRead(void* data, ImU64 size, ImU64 count, ImFileHandle file); @@ -480,7 +480,7 @@ IMGUI_API ImU64 ImFileWrite(const void* data, ImU64 size, ImU64 coun #else #define IMGUI_DISABLE_TTY_FUNCTIONS // Can't use stdout, fflush if we are not using default file functions #endif -IMGUI_API void* ImFileLoadToMemory(const char* filename, const char* mode, size_t* out_file_size = NULL, int padding_bytes = 0); +IMGUI_API void* ImFileLoadToMemory(ImStrv filename, ImStrv mode, size_t* out_file_size = NULL, int padding_bytes = 0); // Helpers: Maths IM_MSVC_RUNTIME_CHECKS_OFF @@ -2890,7 +2890,7 @@ struct IMGUI_API ImGuiWindow bool MemoryCompacted; // Set when window extraneous data have been garbage collected public: - ImGuiWindow(ImGuiContext* context, const char* name); + ImGuiWindow(ImGuiContext* context, ImStrv name); ~ImGuiWindow(); ImGuiID GetID(const char* str, const char* str_end = NULL); @@ -3336,7 +3336,7 @@ namespace ImGui // Tables: Internals inline ImGuiTable* GetCurrentTable() { ImGuiContext& g = *GImGui; return g.CurrentTable; } IMGUI_API ImGuiTable* TableFindByID(ImGuiID id); - IMGUI_API bool BeginTableEx(const char* name, ImGuiID id, int columns_count, ImGuiTableFlags flags = 0, const ImVec2& outer_size = ImVec2(0, 0), float inner_width = 0.0f); + IMGUI_API bool BeginTableEx(ImStrv name, ImGuiID id, int columns_count, ImGuiTableFlags flags = 0, const ImVec2& outer_size = ImVec2(0, 0), float inner_width = 0.0f); IMGUI_API void TableBeginInitMemory(ImGuiTable* table, int columns_count); IMGUI_API void TableApplyQueuedRequests(ImGuiTable* table); IMGUI_API void TableSetupDrawChannels(ImGuiTable* table); @@ -3388,12 +3388,12 @@ namespace ImGui // Legacy Columns API (this is not exposed because we will encourage transitioning to the Tables API) IMGUI_API void SetWindowClipRectBeforeSetChannel(ImGuiWindow* window, const ImRect& clip_rect); - IMGUI_API void BeginColumns(const char* str_id, int count, ImGuiOldColumnFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns(). + IMGUI_API void BeginColumns(ImStrv str_id, int count, ImGuiOldColumnFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns(). IMGUI_API void EndColumns(); // close columns IMGUI_API void PushColumnClipRect(int column_index); IMGUI_API void PushColumnsBackground(); IMGUI_API void PopColumnsBackground(); - IMGUI_API ImGuiID GetColumnsID(const char* str_id, int count); + IMGUI_API ImGuiID GetColumnsID(ImStrv str_id, int count); IMGUI_API ImGuiOldColumns* FindOrCreateColumns(ImGuiWindow* window, ImGuiID id); IMGUI_API float GetColumnOffsetFromNorm(const ImGuiOldColumns* columns, float offset_norm); IMGUI_API float GetColumnNormFromOffset(const ImGuiOldColumns* columns, float offset); @@ -3417,7 +3417,7 @@ namespace ImGui inline ImGuiWindow* GetCurrentWindowRead() { ImGuiContext& g = *GImGui; return g.CurrentWindow; } inline ImGuiWindow* GetCurrentWindow() { ImGuiContext& g = *GImGui; g.CurrentWindow->WriteAccessed = true; return g.CurrentWindow; } IMGUI_API ImGuiWindow* FindWindowByID(ImGuiID id); - IMGUI_API ImGuiWindow* FindWindowByName(const char* name); + IMGUI_API ImGuiWindow* FindWindowByName(ImStrv name); IMGUI_API void UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window); IMGUI_API void UpdateWindowSkipRefresh(ImGuiWindow* window); IMGUI_API ImVec2 CalcWindowNextAutoFitSize(ImGuiWindow* window); @@ -3500,14 +3500,14 @@ namespace ImGui IMGUI_API void ClearIniSettings(); IMGUI_API void CleanupIniSettings(ImGuiSettingsCleanupArgs* args); // [BETA] Expected to turn into a public API. Please report if you are using this! IMGUI_API void AddSettingsHandler(const ImGuiSettingsHandler* handler); - IMGUI_API void RemoveSettingsHandler(const char* type_name); - IMGUI_API ImGuiSettingsHandler* FindSettingsHandler(const char* type_name); + IMGUI_API void RemoveSettingsHandler(ImStrv type_name); + IMGUI_API ImGuiSettingsHandler* FindSettingsHandler(ImStrv type_name); // Settings - Windows - IMGUI_API ImGuiWindowSettings* CreateNewWindowSettings(const char* name); + IMGUI_API ImGuiWindowSettings* CreateNewWindowSettings(ImStrv name); IMGUI_API ImGuiWindowSettings* FindWindowSettingsByID(ImGuiID id); IMGUI_API ImGuiWindowSettings* FindWindowSettingsByWindow(ImGuiWindow* window); - IMGUI_API void ClearWindowSettings(const char* name); + IMGUI_API void ClearWindowSettings(ImStrv name); // Localization IMGUI_API void LocalizeRegisterEntries(const ImGuiLocEntry* entries, int count); @@ -3568,12 +3568,12 @@ namespace ImGui IMGUI_API void LogSetNextTextDecoration(const char* prefix, const char* suffix); // Childs - IMGUI_API bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags); + IMGUI_API bool BeginChildEx(ImStrv name, ImGuiID id, const ImVec2& size_arg, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags); IMGUI_API ImGuiWindow* FindFrontMostVisibleChildWindow(ImGuiWindow* window); // Popups, Modals IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_window_flags); - IMGUI_API bool BeginPopupMenuEx(ImGuiID id, const char* label, ImGuiWindowFlags extra_window_flags); + IMGUI_API bool BeginPopupMenuEx(ImGuiID id, ImStrv label, ImGuiWindowFlags extra_window_flags); IMGUI_API bool OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags = ImGuiPopupFlags_None); IMGUI_API void ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_popup); IMGUI_API void ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to_window_under_popup); @@ -3594,9 +3594,9 @@ namespace ImGui IMGUI_API bool BeginTooltipHidden(); // Menus - IMGUI_API bool BeginViewportSideBar(const char* name, ImGuiViewport* viewport, ImGuiDir dir, float size, ImGuiWindowFlags window_flags); - IMGUI_API bool BeginMenuEx(const char* label, const char* icon, bool enabled = true); - IMGUI_API bool MenuItemEx(const char* label, const char* icon, const char* shortcut = NULL, bool selected = false, bool enabled = true); + IMGUI_API bool BeginViewportSideBar(ImStrv name, ImGuiViewport* viewport, ImGuiDir dir, float size, ImGuiWindowFlags window_flags); + IMGUI_API bool BeginMenuEx(ImStrv label, ImStrv icon, bool enabled = true); + IMGUI_API bool MenuItemEx(ImStrv label, ImStrv icon, ImStrv shortcut = NULL, bool selected = false, bool enabled = true); // Combos IMGUI_API bool BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags flags); @@ -3774,12 +3774,12 @@ namespace ImGui IMGUI_API void TabBarQueueReorder(ImGuiTabBar* tab_bar, ImGuiTabItem* tab, int offset); IMGUI_API void TabBarQueueReorderFromMousePos(ImGuiTabBar* tab_bar, ImGuiTabItem* tab, ImVec2 mouse_pos); IMGUI_API bool TabBarProcessReorder(ImGuiTabBar* tab_bar); - IMGUI_API bool TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImGuiTabItemFlags flags, ImGuiWindow* docked_window); - IMGUI_API void TabItemSpacing(const char* str_id, ImGuiTabItemFlags flags, float width); - IMGUI_API ImVec2 TabItemCalcSize(const char* label, bool has_close_button_or_unsaved_marker); + IMGUI_API bool TabItemEx(ImGuiTabBar* tab_bar, ImStrv label, bool* p_open, ImGuiTabItemFlags flags, ImGuiWindow* docked_window); + IMGUI_API void TabItemSpacing(ImStrv str_id, ImGuiTabItemFlags flags, float width); + IMGUI_API ImVec2 TabItemCalcSize(ImStrv label, bool has_close_button_or_unsaved_marker); IMGUI_API ImVec2 TabItemCalcSize(ImGuiWindow* window); IMGUI_API void TabItemBackground(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImU32 col); - IMGUI_API void TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImVec2 frame_padding, const char* label, ImGuiID tab_id, ImGuiID close_button_id, bool is_contents_visible, bool* out_just_closed, bool* out_text_clipped); + IMGUI_API void TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImVec2 frame_padding, ImStrv label, ImGuiID tab_id, ImGuiID close_button_id, bool is_contents_visible, bool* out_just_closed, bool* out_text_clipped); // Render helpers // AVOID USING OUTSIDE OF IMGUI.CPP! NOT FOR PUBLIC CONSUMPTION. THOSE FUNCTIONS ARE A MESS. THEIR SIGNATURE AND BEHAVIOR WILL CHANGE, THEY NEED TO BE REFACTORED INTO SOMETHING DECENT. @@ -3815,13 +3815,13 @@ namespace ImGui IMGUI_API void TextAlignedV(float align_x, float width, const char* fmt, va_list args) IM_FMTLIST(3); // Widgets - IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0); - IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags = 0); + IMGUI_API bool ButtonEx(ImStrv label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0); + IMGUI_API bool ArrowButtonEx(ImStrv str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags = 0); IMGUI_API bool ImageButtonEx(ImGuiID id, ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags = 0); IMGUI_API void SeparatorEx(ImGuiSeparatorFlags flags, float thickness = 1.0f); IMGUI_API void SeparatorTextEx(ImGuiID id, const char* label, const char* label_end, float extra_width); - IMGUI_API bool CheckboxFlags(const char* label, ImS64* flags, ImS64 flags_value); - IMGUI_API bool CheckboxFlags(const char* label, ImU64* flags, ImU64 flags_value); + IMGUI_API bool CheckboxFlags(ImStrv label, ImS64* flags, ImS64 flags_value); + IMGUI_API bool CheckboxFlags(ImStrv label, ImU64* flags, ImU64 flags_value); // Widgets: Window Decorations IMGUI_API bool CloseButton(ImGuiID id, const ImVec2& pos); @@ -3868,23 +3868,23 @@ namespace ImGui IMGUI_API bool DataTypeIsZero(ImGuiDataType data_type, const void* p_data); // InputText - IMGUI_API bool InputTextEx(const char* label, const char* hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); + IMGUI_API bool InputTextEx(ImStrv label, ImStrv hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); IMGUI_API void InputTextDeactivateHook(ImGuiID id); - IMGUI_API bool TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); - IMGUI_API bool TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min = NULL, const void* p_clamp_max = NULL); + IMGUI_API bool TempInputText(const ImRect& bb, ImGuiID id, ImStrv label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); + IMGUI_API bool TempInputScalar(const ImRect& bb, ImGuiID id, ImStrv label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min = NULL, const void* p_clamp_max = NULL); inline bool TempInputIsActive(ImGuiID id) { ImGuiContext& g = *GImGui; return (g.TempInputId == id && g.ActiveId == id) || (g.InputTextDeactivatedState.ID == id); } inline ImGuiInputTextState* GetInputTextState(ImGuiID id) { ImGuiContext& g = *GImGui; return (id != 0 && g.InputTextState.ID == id) ? &g.InputTextState : NULL; } // Get input text state if active IMGUI_API void SetNextItemRefVal(ImGuiDataType data_type, void* p_data); inline bool IsItemActiveAsInputText() { ImGuiContext& g = *GImGui; return g.ActiveId != 0 && g.ActiveId == g.LastItemData.ID && g.InputTextState.ID == g.LastItemData.ID; } // This may be useful to apply workaround that a based on distinguish whenever an item is active as a text input field. // Color - IMGUI_API void ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags); + IMGUI_API void ColorTooltip(ImStrv text, const float* col, ImGuiColorEditFlags flags); IMGUI_API void ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags); IMGUI_API void ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags flags); inline void SetNextItemColorMarker(ImU32 col) { ImGuiContext& g = *GImGui; g.NextItemData.HasFlags |= ImGuiNextItemDataFlags_HasColorMarker; g.NextItemData.ColorMarker = col; } // Plot - IMGUI_API int PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, const ImVec2& size_arg); + IMGUI_API int PlotEx(ImGuiPlotType plot_type, ImStrv label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, ImStrv overlay_text, float scale_min, float scale_max, const ImVec2& size_arg); // Shade functions (write over already created vertices) IMGUI_API void ShadeVertsLinearColorGradientKeepAlpha(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1); diff --git a/imgui_tables.cpp b/imgui_tables.cpp index ee208d160..1f2fc1ea7 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -312,13 +312,13 @@ ImGuiTable* ImGui::TableFindByID(ImGuiID id) } // Read about "TABLE SIZING" at the top of this file. -bool ImGui::BeginTable(const char* str_id, int columns_count, ImGuiTableFlags flags, const ImVec2& outer_size, float inner_width) +bool ImGui::BeginTable(ImStrv str_id, int columns_count, ImGuiTableFlags flags, const ImVec2& outer_size, float inner_width) { ImGuiID id = GetID(str_id); return BeginTableEx(str_id, id, columns_count, flags, outer_size, inner_width); } -bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImGuiTableFlags flags, const ImVec2& outer_size, float inner_width) +bool ImGui::BeginTableEx(ImStrv name, ImGuiID id, int columns_count, ImGuiTableFlags flags, const ImVec2& outer_size, float inner_width) { ImGuiContext& g = *GImGui; ImGuiWindow* outer_window = GetCurrentWindow(); @@ -1732,7 +1732,7 @@ static void TableSetupColumnApply(ImGuiTable* table, int idx, ImGuiID id, ImS16 column->InitStretchWeightOrWidth = init_width_or_weight; } -void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, float init_width_or_weight, ImGuiID user_data) +void ImGui::TableSetupColumn(ImStrv label, ImGuiTableColumnFlags flags, float init_width_or_weight, ImGuiID user_data) { ImGuiContext& g = *GImGui; ImGuiTable* table = g.CurrentTable; @@ -3320,7 +3320,7 @@ void ImGui::TableHeadersRow() // Emit a column header (text + optional sort order) // We cpu-clip text here so that all columns headers can be merged into a same draw call. // Note that because of how we cpu-clip and display sorting indicators, you _cannot_ use SameLine() after a TableHeader() -void ImGui::TableHeader(const char* label) +void ImGui::TableHeader(ImStrv label) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; @@ -3674,7 +3674,7 @@ bool ImGui::TableBeginContextMenuPopup(ImGuiTable* table) } // FIXME: Copied from MenuItem() for the purpose of being able to pass _SelectOnRelease (#9312) -static bool MenuItemForColumnReorder(const char* label, bool selected, bool enabled) +static bool MenuItemForColumnReorder(ImStrv label, bool selected, bool enabled) { using namespace ImGui; ImGuiContext& g = *GImGui; @@ -4663,7 +4663,7 @@ ImGuiOldColumns* ImGui::FindOrCreateColumns(ImGuiWindow* window, ImGuiID id) return columns; } -ImGuiID ImGui::GetColumnsID(const char* str_id, int columns_count) +ImGuiID ImGui::GetColumnsID(ImStrv str_id, int columns_count) { ImGuiWindow* window = GetCurrentWindow(); @@ -4676,7 +4676,7 @@ ImGuiID ImGui::GetColumnsID(const char* str_id, int columns_count) return id; } -void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiOldColumnFlags flags) +void ImGui::BeginColumns(ImStrv str_id, int columns_count, ImGuiOldColumnFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); @@ -4887,7 +4887,7 @@ void ImGui::EndColumns() NavUpdateCurrentWindowIsScrollPushableX(); } -void ImGui::Columns(int columns_count, const char* id, bool borders) +void ImGui::Columns(int columns_count, ImStrv id, bool borders) { ImGuiWindow* window = GetCurrentWindow(); IM_ASSERT(columns_count >= 1); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 4acdc0a6b..cd60c15cb 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -384,7 +384,7 @@ void ImGui::TextAlignedV(float align_x, float width, const char* fmt, va_list ar SetTooltip("%.*s", (int)(text_end - text), text); } -void ImGui::LabelText(const char* label, const char* fmt, ...) +void ImGui::LabelText(ImStrv label, const char* fmt, ...) { va_list args; va_start(args, fmt); @@ -393,7 +393,7 @@ void ImGui::LabelText(const char* label, const char* fmt, ...) } // Add a label+text combo aligned to other label+value widgets -void ImGui::LabelTextV(const char* label, const char* fmt, va_list args) +void ImGui::LabelTextV(ImStrv label, const char* fmt, va_list args) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -785,7 +785,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool return pressed; } -bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags flags) +bool ImGui::ButtonEx(ImStrv label, const ImVec2& size_arg, ImGuiButtonFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -827,13 +827,13 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags return pressed; } -bool ImGui::Button(const char* label, const ImVec2& size_arg) +bool ImGui::Button(ImStrv label, const ImVec2& size_arg) { return ButtonEx(label, size_arg, ImGuiButtonFlags_None); } // Small buttons fits within text without additional vertical spacing. -bool ImGui::SmallButton(const char* label) +bool ImGui::SmallButton(ImStrv label) { ImGuiContext& g = *GImGui; float backup_padding_y = g.Style.FramePadding.y; @@ -845,7 +845,7 @@ bool ImGui::SmallButton(const char* label) // Tip: use ImGui::PushID()/PopID() to push indices or pointers in the ID stack. // Then you can keep 'str_id' empty or the same for all your buttons (instead of creating a string based on a non-string id) -bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size_arg, ImGuiButtonFlags flags) +bool ImGui::InvisibleButton(ImStrv str_id, const ImVec2& size_arg, ImGuiButtonFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); @@ -869,7 +869,7 @@ bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size_arg, ImGuiBut return pressed; } -bool ImGui::ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size, ImGuiButtonFlags flags) +bool ImGui::ArrowButtonEx(ImStrv str_id, ImGuiDir dir, ImVec2 size, ImGuiButtonFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); @@ -897,7 +897,7 @@ bool ImGui::ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size, ImGuiBu return pressed; } -bool ImGui::ArrowButton(const char* str_id, ImGuiDir dir) +bool ImGui::ArrowButton(ImStrv str_id, ImGuiDir dir) { float sz = GetFrameHeight(); return ArrowButtonEx(str_id, dir, ImVec2(sz, sz), ImGuiButtonFlags_None); @@ -1209,7 +1209,7 @@ bool ImGui::ImageButtonEx(ImGuiID id, ImTextureRef tex_ref, const ImVec2& image_ // - ImageButton() adds style.FramePadding*2.0f to provided size. This is in order to facilitate fitting an image in a button. // - ImageButton() draws a background based on regular Button() color + optionally an inner background if specified. (#8165) // FIXME: Maybe that's not the best design? -bool ImGui::ImageButton(const char* str_id, ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col) +bool ImGui::ImageButton(ImStrv str_id, ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; @@ -1241,7 +1241,7 @@ bool ImGui::ImageButton(ImTextureID user_texture_id, const ImVec2& size, const I */ #endif // #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS -bool ImGui::Checkbox(const char* label, bool* v) +bool ImGui::Checkbox(ImStrv label, bool* v) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -1319,7 +1319,7 @@ bool ImGui::Checkbox(const char* label, bool* v) } template -bool ImGui::CheckboxFlagsT(const char* label, T* flags, T flags_value) +bool ImGui::CheckboxFlagsT(ImStrv label, T* flags, T flags_value) { bool all_on = (*flags & flags_value) == flags_value; bool any_on = (*flags & flags_value) != 0; @@ -1345,27 +1345,27 @@ bool ImGui::CheckboxFlagsT(const char* label, T* flags, T flags_value) return pressed; } -bool ImGui::CheckboxFlags(const char* label, int* flags, int flags_value) +bool ImGui::CheckboxFlags(ImStrv label, int* flags, int flags_value) { return CheckboxFlagsT(label, flags, flags_value); } -bool ImGui::CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value) +bool ImGui::CheckboxFlags(ImStrv label, unsigned int* flags, unsigned int flags_value) { return CheckboxFlagsT(label, flags, flags_value); } -bool ImGui::CheckboxFlags(const char* label, ImS64* flags, ImS64 flags_value) +bool ImGui::CheckboxFlags(ImStrv label, ImS64* flags, ImS64 flags_value) { return CheckboxFlagsT(label, flags, flags_value); } -bool ImGui::CheckboxFlags(const char* label, ImU64* flags, ImU64 flags_value) +bool ImGui::CheckboxFlags(ImStrv label, ImU64* flags, ImU64 flags_value) { return CheckboxFlagsT(label, flags, flags_value); } -bool ImGui::RadioButton(const char* label, bool active) +bool ImGui::RadioButton(ImStrv label, bool active) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -1421,7 +1421,7 @@ bool ImGui::RadioButton(const char* label, bool active) } // FIXME: This would work nicely if it was a public template, e.g. 'template RadioButton(const char* label, T* v, T v_button)', but I'm not sure how we would expose it.. -bool ImGui::RadioButton(const char* label, int* v, int v_button) +bool ImGui::RadioButton(ImStrv label, int* v, int v_button) { const bool pressed = RadioButton(label, *v == v_button); if (pressed) @@ -1430,7 +1430,7 @@ bool ImGui::RadioButton(const char* label, int* v, int v_button) } // size_arg (for each axis) < 0.0f: align to end, 0.0f: auto, > 0.0f: specified size -void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, const char* overlay) +void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, ImStrv overlay) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -1519,7 +1519,7 @@ void ImGui::Bullet() // FIXME-STYLE: we delayed adding as there is a larger plan to revamp the styling system. // Because of this we currently don't provide many styling options for this widget // (e.g. hovered/active colors are automatically inferred from a single color). -bool ImGui::TextLink(const char* label) +bool ImGui::TextLink(ImStrv label) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -1571,7 +1571,7 @@ bool ImGui::TextLink(const char* label) return pressed; } -bool ImGui::TextLinkOpenURL(const char* label, const char* url) +bool ImGui::TextLinkOpenURL(ImStrv label, ImStrv url) { ImGuiContext& g = *GImGui; if (url == NULL) @@ -1787,7 +1787,7 @@ void ImGui::SeparatorTextEx(ImGuiID id, const char* label, const char* label_end } } -void ImGui::SeparatorText(const char* label) +void ImGui::SeparatorText(ImStrv label) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -1937,7 +1937,7 @@ static float CalcMaxPopupHeightFromItemCount(int items_count) return (g.FontSize + g.Style.ItemSpacing.y) * items_count - g.Style.ItemSpacing.y + (g.Style.WindowPadding.y * 2); } -bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags) +bool ImGui::BeginCombo(ImStrv label, ImStrv preview_value, ImGuiComboFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); @@ -2180,7 +2180,7 @@ static const char* Items_SingleStringGetter(void* data, int idx) } // Old API, prefer using BeginCombo() nowadays if you can. -bool ImGui::Combo(const char* label, int* current_item, const char* (*getter)(void* user_data, int idx), void* user_data, int items_count, int popup_max_height_in_items) +bool ImGui::Combo(ImStrv label, int* current_item, const char* (*getter)(void* user_data, int idx), void* user_data, int items_count, int popup_max_height_in_items) { ImGuiContext& g = *GImGui; @@ -2230,14 +2230,14 @@ bool ImGui::Combo(const char* label, int* current_item, const char* (*getter)(vo } // Combo box helper allowing to pass an array of strings. -bool ImGui::Combo(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items) +bool ImGui::Combo(ImStrv label, int* current_item, const char* const items[], int items_count, int height_in_items) { const bool value_changed = Combo(label, current_item, Items_ArrayGetter, (void*)items, items_count, height_in_items); return value_changed; } // Combo box helper allowing to pass all items in a single string literal holding multiple zero-terminated items "item1\0item2\0" -bool ImGui::Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int height_in_items) +bool ImGui::Combo(ImStrv label, int* current_item, const char* items_separated_by_zeros, int height_in_items) { int items_count = 0; const char* p = items_separated_by_zeros; // FIXME-OPT: Avoid computing this, or at least only when combo is open @@ -2745,7 +2745,7 @@ static bool TempInputIsClampEnabled(ImGuiSliderFlags flags, ImGuiDataType data_t // Note: p_data, p_min and p_max are _pointers_ to a memory address holding the data. For a Drag widget, p_min and p_max are optional. // Read code of e.g. DragFloat(), DragInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly. -bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags) +bool ImGui::DragScalar(ImStrv label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min, const void* p_max, ImStrv format, ImGuiSliderFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -2845,7 +2845,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data, return value_changed; } -bool ImGui::DragScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags) +bool ImGui::DragScalarN(ImStrv label, ImGuiDataType data_type, void* p_data, int components, float v_speed, const void* p_min, const void* p_max, ImStrv format, ImGuiSliderFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -2882,28 +2882,28 @@ bool ImGui::DragScalarN(const char* label, ImGuiDataType data_type, void* p_data return value_changed; } -bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, float v_max, const char* format, ImGuiSliderFlags flags) +bool ImGui::DragFloat(ImStrv label, float* v, float v_speed, float v_min, float v_max, ImStrv format, ImGuiSliderFlags flags) { return DragScalar(label, ImGuiDataType_Float, v, v_speed, &v_min, &v_max, format, flags); } -bool ImGui::DragFloat2(const char* label, float v[2], float v_speed, float v_min, float v_max, const char* format, ImGuiSliderFlags flags) +bool ImGui::DragFloat2(ImStrv label, float v[2], float v_speed, float v_min, float v_max, ImStrv format, ImGuiSliderFlags flags) { return DragScalarN(label, ImGuiDataType_Float, v, 2, v_speed, &v_min, &v_max, format, flags); } -bool ImGui::DragFloat3(const char* label, float v[3], float v_speed, float v_min, float v_max, const char* format, ImGuiSliderFlags flags) +bool ImGui::DragFloat3(ImStrv label, float v[3], float v_speed, float v_min, float v_max, ImStrv format, ImGuiSliderFlags flags) { return DragScalarN(label, ImGuiDataType_Float, v, 3, v_speed, &v_min, &v_max, format, flags); } -bool ImGui::DragFloat4(const char* label, float v[4], float v_speed, float v_min, float v_max, const char* format, ImGuiSliderFlags flags) +bool ImGui::DragFloat4(ImStrv label, float v[4], float v_speed, float v_min, float v_max, ImStrv format, ImGuiSliderFlags flags) { return DragScalarN(label, ImGuiDataType_Float, v, 4, v_speed, &v_min, &v_max, format, flags); } // NB: You likely want to specify the ImGuiSliderFlags_AlwaysClamp when using this. -bool ImGui::DragFloatRange2(const char* label, float* v_current_min, float* v_current_max, float v_speed, float v_min, float v_max, const char* format, const char* format_max, ImGuiSliderFlags flags) +bool ImGui::DragFloatRange2(ImStrv label, float* v_current_min, float* v_current_max, float v_speed, float v_min, float v_max, ImStrv format, ImStrv format_max, ImGuiSliderFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -2936,28 +2936,28 @@ bool ImGui::DragFloatRange2(const char* label, float* v_current_min, float* v_cu } // NB: v_speed is float to allow adjusting the drag speed with more precision -bool ImGui::DragInt(const char* label, int* v, float v_speed, int v_min, int v_max, const char* format, ImGuiSliderFlags flags) +bool ImGui::DragInt(ImStrv label, int* v, float v_speed, int v_min, int v_max, ImStrv format, ImGuiSliderFlags flags) { return DragScalar(label, ImGuiDataType_S32, v, v_speed, &v_min, &v_max, format, flags); } -bool ImGui::DragInt2(const char* label, int v[2], float v_speed, int v_min, int v_max, const char* format, ImGuiSliderFlags flags) +bool ImGui::DragInt2(ImStrv label, int v[2], float v_speed, int v_min, int v_max, ImStrv format, ImGuiSliderFlags flags) { return DragScalarN(label, ImGuiDataType_S32, v, 2, v_speed, &v_min, &v_max, format, flags); } -bool ImGui::DragInt3(const char* label, int v[3], float v_speed, int v_min, int v_max, const char* format, ImGuiSliderFlags flags) +bool ImGui::DragInt3(ImStrv label, int v[3], float v_speed, int v_min, int v_max, ImStrv format, ImGuiSliderFlags flags) { return DragScalarN(label, ImGuiDataType_S32, v, 3, v_speed, &v_min, &v_max, format, flags); } -bool ImGui::DragInt4(const char* label, int v[4], float v_speed, int v_min, int v_max, const char* format, ImGuiSliderFlags flags) +bool ImGui::DragInt4(ImStrv label, int v[4], float v_speed, int v_min, int v_max, ImStrv format, ImGuiSliderFlags flags) { return DragScalarN(label, ImGuiDataType_S32, v, 4, v_speed, &v_min, &v_max, format, flags); } // NB: You likely want to specify the ImGuiSliderFlags_AlwaysClamp when using this. -bool ImGui::DragIntRange2(const char* label, int* v_current_min, int* v_current_max, float v_speed, int v_min, int v_max, const char* format, const char* format_max, ImGuiSliderFlags flags) +bool ImGui::DragIntRange2(ImStrv label, int* v_current_min, int* v_current_max, float v_speed, int v_min, int v_max, ImStrv format, ImStrv format_max, ImGuiSliderFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -3361,7 +3361,7 @@ bool ImGui::SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type // Note: p_data, p_min and p_max are _pointers_ to a memory address holding the data. For a slider, they are all required. // Read code of e.g. SliderFloat(), SliderInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly. -bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags) +bool ImGui::SliderScalar(ImStrv label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, ImStrv format, ImGuiSliderFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -3458,7 +3458,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat } // Add multiple sliders on 1 line for compact edition of multiple components -bool ImGui::SliderScalarN(const char* label, ImGuiDataType data_type, void* v, int components, const void* v_min, const void* v_max, const char* format, ImGuiSliderFlags flags) +bool ImGui::SliderScalarN(ImStrv label, ImGuiDataType data_type, void* v, int components, const void* v_min, const void* v_max, ImStrv format, ImGuiSliderFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -3495,27 +3495,27 @@ bool ImGui::SliderScalarN(const char* label, ImGuiDataType data_type, void* v, i return value_changed; } -bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format, ImGuiSliderFlags flags) +bool ImGui::SliderFloat(ImStrv label, float* v, float v_min, float v_max, ImStrv format, ImGuiSliderFlags flags) { return SliderScalar(label, ImGuiDataType_Float, v, &v_min, &v_max, format, flags); } -bool ImGui::SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* format, ImGuiSliderFlags flags) +bool ImGui::SliderFloat2(ImStrv label, float v[2], float v_min, float v_max, ImStrv format, ImGuiSliderFlags flags) { return SliderScalarN(label, ImGuiDataType_Float, v, 2, &v_min, &v_max, format, flags); } -bool ImGui::SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* format, ImGuiSliderFlags flags) +bool ImGui::SliderFloat3(ImStrv label, float v[3], float v_min, float v_max, ImStrv format, ImGuiSliderFlags flags) { return SliderScalarN(label, ImGuiDataType_Float, v, 3, &v_min, &v_max, format, flags); } -bool ImGui::SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* format, ImGuiSliderFlags flags) +bool ImGui::SliderFloat4(ImStrv label, float v[4], float v_min, float v_max, ImStrv format, ImGuiSliderFlags flags) { return SliderScalarN(label, ImGuiDataType_Float, v, 4, &v_min, &v_max, format, flags); } -bool ImGui::SliderAngle(const char* label, float* v_rad, float v_degrees_min, float v_degrees_max, const char* format, ImGuiSliderFlags flags) +bool ImGui::SliderAngle(ImStrv label, float* v_rad, float v_degrees_min, float v_degrees_max, ImStrv format, ImGuiSliderFlags flags) { if (format == NULL) format = "%.0f deg"; @@ -3526,27 +3526,27 @@ bool ImGui::SliderAngle(const char* label, float* v_rad, float v_degrees_min, fl return value_changed; } -bool ImGui::SliderInt(const char* label, int* v, int v_min, int v_max, const char* format, ImGuiSliderFlags flags) +bool ImGui::SliderInt(ImStrv label, int* v, int v_min, int v_max, ImStrv format, ImGuiSliderFlags flags) { return SliderScalar(label, ImGuiDataType_S32, v, &v_min, &v_max, format, flags); } -bool ImGui::SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* format, ImGuiSliderFlags flags) +bool ImGui::SliderInt2(ImStrv label, int v[2], int v_min, int v_max, ImStrv format, ImGuiSliderFlags flags) { return SliderScalarN(label, ImGuiDataType_S32, v, 2, &v_min, &v_max, format, flags); } -bool ImGui::SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* format, ImGuiSliderFlags flags) +bool ImGui::SliderInt3(ImStrv label, int v[3], int v_min, int v_max, ImStrv format, ImGuiSliderFlags flags) { return SliderScalarN(label, ImGuiDataType_S32, v, 3, &v_min, &v_max, format, flags); } -bool ImGui::SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* format, ImGuiSliderFlags flags) +bool ImGui::SliderInt4(ImStrv label, int v[4], int v_min, int v_max, ImStrv format, ImGuiSliderFlags flags) { return SliderScalarN(label, ImGuiDataType_S32, v, 4, &v_min, &v_max, format, flags); } -bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags) +bool ImGui::VSliderScalar(ImStrv label, const ImVec2& size, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, ImStrv format, ImGuiSliderFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -3614,12 +3614,12 @@ bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType d return value_changed; } -bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* format, ImGuiSliderFlags flags) +bool ImGui::VSliderFloat(ImStrv label, const ImVec2& size, float* v, float v_min, float v_max, ImStrv format, ImGuiSliderFlags flags) { return VSliderScalar(label, size, ImGuiDataType_Float, v, &v_min, &v_max, format, flags); } -bool ImGui::VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* format, ImGuiSliderFlags flags) +bool ImGui::VSliderInt(ImStrv label, const ImVec2& size, int* v, int v_min, int v_max, ImStrv format, ImGuiSliderFlags flags) { return VSliderScalar(label, size, ImGuiDataType_S32, v, &v_min, &v_max, format, flags); } @@ -3775,7 +3775,7 @@ int ImParseFormatPrecision(const char* fmt, int default_precision) // Create text input in place of another active widget (e.g. used when doing a Ctrl+Click on drag/slider widgets) // - This must be submitted right after the item it is overlaying. // FIXME: Facilitate using this in variety of other situations. -bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) +bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, ImStrv label, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) { // On the first frame, g.TempInputTextId == 0, then on subsequent frames it becomes == id. // We clear ActiveID on the first frame to allow the InputText() taking it back. @@ -3807,7 +3807,7 @@ bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* // Note that Drag/Slider functions are only forwarding the min/max values clamping values if the ImGuiSliderFlags_AlwaysClamp flag is set! // This is intended: this way we allow Ctrl+Click manual input to set a value out of bounds, for maximum flexibility. // However this may not be ideal for all uses, as some user code may break on out of bound values. -bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min, const void* p_clamp_max) +bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, ImStrv label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min, const void* p_clamp_max) { // FIXME: May need to clarify display behavior if format doesn't contain %. // "%d" -> "%d" / "There are %d items" -> "%d" / "items" -> "%d" (fallback). Also see #6405 @@ -3862,7 +3862,7 @@ void ImGui::SetNextItemRefVal(ImGuiDataType data_type, void* p_data) // Note: p_data, p_step, p_step_fast are _pointers_ to a memory address holding the data. For an Input widget, p_step and p_step_fast are optional. // Read code of e.g. InputFloat(), InputInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly. -bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_step, const void* p_step_fast, const char* format, ImGuiInputTextFlags flags) +bool ImGui::InputScalar(ImStrv label, ImGuiDataType data_type, void* p_data, const void* p_step, const void* p_step_fast, ImStrv format, ImGuiInputTextFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -3973,7 +3973,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data return value_changed; } -bool ImGui::InputScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, const void* p_step, const void* p_step_fast, const char* format, ImGuiInputTextFlags flags) +bool ImGui::InputScalarN(ImStrv label, ImGuiDataType data_type, void* p_data, int components, const void* p_step, const void* p_step_fast, ImStrv format, ImGuiInputTextFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -4008,49 +4008,49 @@ bool ImGui::InputScalarN(const char* label, ImGuiDataType data_type, void* p_dat return value_changed; } -bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, const char* format, ImGuiInputTextFlags flags) +bool ImGui::InputFloat(ImStrv label, float* v, float step, float step_fast, ImStrv format, ImGuiInputTextFlags flags) { return InputScalar(label, ImGuiDataType_Float, (void*)v, (void*)(step > 0.0f ? &step : NULL), (void*)(step_fast > 0.0f ? &step_fast : NULL), format, flags); } -bool ImGui::InputFloat2(const char* label, float v[2], const char* format, ImGuiInputTextFlags flags) +bool ImGui::InputFloat2(ImStrv label, float v[2], ImStrv format, ImGuiInputTextFlags flags) { return InputScalarN(label, ImGuiDataType_Float, v, 2, NULL, NULL, format, flags); } -bool ImGui::InputFloat3(const char* label, float v[3], const char* format, ImGuiInputTextFlags flags) +bool ImGui::InputFloat3(ImStrv label, float v[3], ImStrv format, ImGuiInputTextFlags flags) { return InputScalarN(label, ImGuiDataType_Float, v, 3, NULL, NULL, format, flags); } -bool ImGui::InputFloat4(const char* label, float v[4], const char* format, ImGuiInputTextFlags flags) +bool ImGui::InputFloat4(ImStrv label, float v[4], ImStrv format, ImGuiInputTextFlags flags) { return InputScalarN(label, ImGuiDataType_Float, v, 4, NULL, NULL, format, flags); } -bool ImGui::InputInt(const char* label, int* v, int step, int step_fast, ImGuiInputTextFlags flags) +bool ImGui::InputInt(ImStrv label, int* v, int step, int step_fast, ImGuiInputTextFlags flags) { // Hexadecimal input provided as a convenience but the flag name is awkward. Typically you'd use InputText() to parse your own data, if you want to handle prefixes. const char* format = (flags & ImGuiInputTextFlags_CharsHexadecimal) ? "%08X" : "%d"; return InputScalar(label, ImGuiDataType_S32, (void*)v, (void*)(step > 0 ? &step : NULL), (void*)(step_fast > 0 ? &step_fast : NULL), format, flags); } -bool ImGui::InputInt2(const char* label, int v[2], ImGuiInputTextFlags flags) +bool ImGui::InputInt2(ImStrv label, int v[2], ImGuiInputTextFlags flags) { return InputScalarN(label, ImGuiDataType_S32, v, 2, NULL, NULL, "%d", flags); } -bool ImGui::InputInt3(const char* label, int v[3], ImGuiInputTextFlags flags) +bool ImGui::InputInt3(ImStrv label, int v[3], ImGuiInputTextFlags flags) { return InputScalarN(label, ImGuiDataType_S32, v, 3, NULL, NULL, "%d", flags); } -bool ImGui::InputInt4(const char* label, int v[4], ImGuiInputTextFlags flags) +bool ImGui::InputInt4(ImStrv label, int v[4], ImGuiInputTextFlags flags) { return InputScalarN(label, ImGuiDataType_S32, v, 4, NULL, NULL, "%d", flags); } -bool ImGui::InputDouble(const char* label, double* v, double step, double step_fast, const char* format, ImGuiInputTextFlags flags) +bool ImGui::InputDouble(ImStrv label, double* v, double step, double step_fast, ImStrv format, ImGuiInputTextFlags flags) { return InputScalar(label, ImGuiDataType_Double, (void*)v, (void*)(step > 0.0 ? &step : NULL), (void*)(step_fast > 0.0 ? &step_fast : NULL), format, flags); } @@ -4072,18 +4072,18 @@ namespace ImStb } // If you want to use InputText() with std::string or any custom dynamic string type, use the wrapper in misc/cpp/imgui_stdlib.h/.cpp! -bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) +bool ImGui::InputText(ImStrv label, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) { IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline)); // call InputTextMultiline() return InputTextEx(label, NULL, buf, (int)buf_size, ImVec2(0, 0), flags, callback, user_data); } -bool ImGui::InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) +bool ImGui::InputTextMultiline(ImStrv label, char* buf, size_t buf_size, const ImVec2& size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) { return InputTextEx(label, NULL, buf, (int)buf_size, size, flags | ImGuiInputTextFlags_Multiline, callback, user_data); } -bool ImGui::InputTextWithHint(const char* label, const char* hint, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) +bool ImGui::InputTextWithHint(ImStrv label, ImStrv hint, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) { IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline)); // call InputTextMultiline() or InputTextEx() manually if you need multi-line + hint. return InputTextEx(label, hint, buf, (int)buf_size, ImVec2(0, 0), flags, callback, user_data); @@ -4786,7 +4786,7 @@ static ImVec2 InputTextLineIndexGetPosOffset(ImGuiContext& g, ImGuiInputTextStat // Note that in std::string world, capacity() would omit 1 byte used by the zero-terminator. // - When active, hold on a privately held copy of the text (and apply back to 'buf'). So changing 'buf' while the InputText is active has no effect. // - If you want to use InputText() with std::string or any custom dynamic string type, use the wrapper in misc/cpp/imgui_stdlib.h/.cpp! -bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* callback_user_data) +bool ImGui::InputTextEx(ImStrv label, ImStrv hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* callback_user_data) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -5876,7 +5876,7 @@ void ImGui::DebugNodeInputTextState(ImGuiInputTextState* state) // - ColorPickerOptionsPopup() [Internal] //------------------------------------------------------------------------- -bool ImGui::ColorEdit3(const char* label, float col[3], ImGuiColorEditFlags flags) +bool ImGui::ColorEdit3(ImStrv label, float col[3], ImGuiColorEditFlags flags) { return ColorEdit4(label, col, flags | ImGuiColorEditFlags_NoAlpha); } @@ -5912,7 +5912,7 @@ static void ColorEditRestoreHS(const float* col, float* H, float* S, float* V) // Edit colors components (each component in 0.0f..1.0f range). // See enum ImGuiColorEditFlags_ for available options. e.g. Only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set. // With typical options: Left-click on color square to open color picker. Right-click to open option menu. Ctrl+Click over input fields to edit them and TAB to go to next item. -bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags) +bool ImGui::ColorEdit4(ImStrv label, float col[4], ImGuiColorEditFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -6167,7 +6167,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag return value_changed; } -bool ImGui::ColorPicker3(const char* label, float col[3], ImGuiColorEditFlags flags) +bool ImGui::ColorPicker3(ImStrv label, float col[3], ImGuiColorEditFlags flags) { float col4[4] = { col[0], col[1], col[2], 1.0f }; if (!ColorPicker4(label, col4, flags | ImGuiColorEditFlags_NoAlpha)) @@ -6190,7 +6190,7 @@ static void RenderArrowsForVerticalBar(ImDrawList* draw_list, ImVec2 pos, ImVec2 // (In C++ the 'float col[4]' notation for a function argument is equivalent to 'float* col', we only specify a size to facilitate understanding of the code.) // FIXME: we adjust the big color square height based on item width, which may cause a flickering feedback loop (if automatic height makes a vertical scrollbar appears, affecting automatic width..) // FIXME: this is trying to be aware of style.Alpha but not fully correct. Also, the color wheel will have overlapping glitches with (style.Alpha < 1.0) -bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags, const float* ref_col) +bool ImGui::ColorPicker4(ImStrv label, float col[4], ImGuiColorEditFlags flags, const float* ref_col) { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); @@ -6578,7 +6578,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl // FIXME: May want to display/ignore the alpha component in the color display? Yet show it in the tooltip. // 'desc_id' is not called 'label' because we don't display it next to the button, but only in the tooltip. // Note that 'col' may be encoded in HSV if ImGuiColorEditFlags_InputHSV is set. -bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFlags flags, const ImVec2& size_arg) +bool ImGui::ColorButton(ImStrv desc_id, const ImVec4& col, ImGuiColorEditFlags flags, const ImVec2& size_arg) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -6685,7 +6685,7 @@ void ImGui::SetColorEditOptions(ImGuiColorEditFlags flags) #endif // Note: only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set. -void ImGui::ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags) +void ImGui::ColorTooltip(ImStrv text, const float* col, ImGuiColorEditFlags flags) { ImGuiContext& g = *GImGui; @@ -6834,7 +6834,7 @@ void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags fl // - CollapsingHeader() //------------------------------------------------------------------------- -bool ImGui::TreeNode(const char* str_id, const char* fmt, ...) +bool ImGui::TreeNode(ImStrv str_id, const char* fmt, ...) { va_list args; va_start(args, fmt); @@ -6852,7 +6852,7 @@ bool ImGui::TreeNode(const void* ptr_id, const char* fmt, ...) return is_open; } -bool ImGui::TreeNode(const char* label) +bool ImGui::TreeNode(ImStrv label) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -6861,7 +6861,7 @@ bool ImGui::TreeNode(const char* label) return TreeNodeBehavior(id, ImGuiTreeNodeFlags_None, label, NULL); } -bool ImGui::TreeNodeV(const char* str_id, const char* fmt, va_list args) +bool ImGui::TreeNodeV(ImStrv str_id, const char* fmt, va_list args) { return TreeNodeExV(str_id, 0, fmt, args); } @@ -6871,7 +6871,7 @@ bool ImGui::TreeNodeV(const void* ptr_id, const char* fmt, va_list args) return TreeNodeExV(ptr_id, 0, fmt, args); } -bool ImGui::TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags) +bool ImGui::TreeNodeEx(ImStrv label, ImGuiTreeNodeFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -6880,7 +6880,7 @@ bool ImGui::TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags) return TreeNodeBehavior(id, flags, label, NULL); } -bool ImGui::TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) +bool ImGui::TreeNodeEx(ImStrv str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) { va_list args; va_start(args, fmt); @@ -6898,7 +6898,7 @@ bool ImGui::TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* return is_open; } -bool ImGui::TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) +bool ImGui::TreeNodeExV(ImStrv str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -7364,7 +7364,7 @@ void ImGui::TreeNodeDrawLineToTreePop(const ImGuiTreeNodeStackData* data) TablePopColumnChannel(); } -void ImGui::TreePush(const char* str_id) +void ImGui::TreePush(ImStrv str_id) { ImGuiWindow* window = GetCurrentWindow(); Indent(); @@ -7450,7 +7450,7 @@ void ImGui::SetNextItemStorageID(ImGuiID storage_id) // CollapsingHeader returns true when opened but do not indent nor push into the ID stack (because of the ImGuiTreeNodeFlags_NoTreePushOnOpen flag). // This is basically the same as calling TreeNodeEx(label, ImGuiTreeNodeFlags_CollapsingHeader). You can remove the _NoTreePushOnOpen flag if you want behavior closer to normal TreeNode(). -bool ImGui::CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags) +bool ImGui::CollapsingHeader(ImStrv label, ImGuiTreeNodeFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -7463,7 +7463,7 @@ bool ImGui::CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags) // p_visible != NULL && *p_visible == true : show a small close button on the corner of the header, clicking the button will set *p_visible = false // p_visible != NULL && *p_visible == false : do not show the header at all // Do not mistake this with the Open state of the header itself, which you can adjust with SetNextItemOpen() or ImGuiTreeNodeFlags_DefaultOpen. -bool ImGui::CollapsingHeader(const char* label, bool* p_visible, ImGuiTreeNodeFlags flags) +bool ImGui::CollapsingHeader(ImStrv label, bool* p_visible, ImGuiTreeNodeFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -7506,7 +7506,7 @@ bool ImGui::CollapsingHeader(const char* label, bool* p_visible, ImGuiTreeNodeFl // But you need to make sure the ID is unique, e.g. enclose calls in PushID/PopID or use ##unique_id. // With this scheme, ImGuiSelectableFlags_SpanAllColumns and ImGuiSelectableFlags_AllowOverlap are also frequently used flags. // FIXME: Selectable() with (size.x == 0.0f) and (SelectableTextAlign.x > 0.0f) followed by SameLine() is currently not supported. -bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags flags, const ImVec2& size_arg) +bool ImGui::Selectable(ImStrv label, bool selected, ImGuiSelectableFlags flags, const ImVec2& size_arg) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -7698,7 +7698,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl return pressed; //-V1020 } -bool ImGui::Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags, const ImVec2& size_arg) +bool ImGui::Selectable(ImStrv label, bool* p_selected, ImGuiSelectableFlags flags, const ImVec2& size_arg) { if (Selectable(label, *p_selected, flags, size_arg)) { @@ -8941,7 +8941,7 @@ void ImGuiSelectionExternalStorage::ApplyRequests(ImGuiMultiSelectIO* ms_io) // If you don't need a label you can pretty much directly use ImGui::BeginChild() with ImGuiChildFlags_FrameStyle. // Tip: To have a list filling the entire window width, use size.x = -FLT_MIN and pass an non-visible label e.g. "##empty" // Tip: If your vertical size is calculated from an item count (e.g. 10 * item_height) consider adding a fractional part to facilitate seeing scrolling boundaries (e.g. 10.5f * item_height). -bool ImGui::BeginListBox(const char* label, const ImVec2& size_arg) +bool ImGui::BeginListBox(ImStrv label, const ImVec2& size_arg) { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); @@ -8994,7 +8994,7 @@ void ImGui::EndListBox() EndGroup(); // This is only required to be able to do IsItemXXX query on the whole ListBox including label } -bool ImGui::ListBox(const char* label, int* current_item, const char* const items[], int items_count, int height_items) +bool ImGui::ListBox(ImStrv label, int* current_item, const char* const items[], int items_count, int height_items) { const bool value_changed = ListBox(label, current_item, Items_ArrayGetter, (void*)items, items_count, height_items); return value_changed; @@ -9002,7 +9002,7 @@ bool ImGui::ListBox(const char* label, int* current_item, const char* const item // This is merely a helper around BeginListBox(), EndListBox(). // Considering using those directly to submit custom data or store selection differently. -bool ImGui::ListBox(const char* label, int* current_item, const char* (*getter)(void* user_data, int idx), void* user_data, int items_count, int height_in_items) +bool ImGui::ListBox(ImStrv label, int* current_item, const char* (*getter)(void* user_data, int idx), void* user_data, int items_count, int height_in_items) { ImGuiContext& g = *GImGui; @@ -9058,7 +9058,7 @@ bool ImGui::ListBox(const char* label, int* current_item, const char* (*getter)( // Consider using ImPlot (https://github.com/epezent/implot) which is much better! //------------------------------------------------------------------------- -int ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, const ImVec2& size_arg) +int ImGui::PlotEx(ImGuiPlotType plot_type, ImStrv label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, ImStrv overlay_text, float scale_min, float scale_max, const ImVec2& size_arg) { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); @@ -9193,25 +9193,25 @@ static float Plot_ArrayGetter(void* data, int idx) return v; } -void ImGui::PlotLines(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride) +void ImGui::PlotLines(ImStrv label, const float* values, int values_count, int values_offset, ImStrv overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride) { ImGuiPlotArrayGetterData data(values, stride); PlotEx(ImGuiPlotType_Lines, label, &Plot_ArrayGetter, (void*)&data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size); } -void ImGui::PlotLines(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size) +void ImGui::PlotLines(ImStrv label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, ImStrv overlay_text, float scale_min, float scale_max, ImVec2 graph_size) { PlotEx(ImGuiPlotType_Lines, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size); } // Plot Histogram (the data provided _is_ histogram data. it doesn't compute the histogram of your data) -void ImGui::PlotHistogram(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride) +void ImGui::PlotHistogram(ImStrv label, const float* values, int values_count, int values_offset, ImStrv overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride) { ImGuiPlotArrayGetterData data(values, stride); PlotEx(ImGuiPlotType_Histogram, label, &Plot_ArrayGetter, (void*)&data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size); } -void ImGui::PlotHistogram(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size) +void ImGui::PlotHistogram(ImStrv label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, ImStrv overlay_text, float scale_min, float scale_max, ImVec2 graph_size) { PlotEx(ImGuiPlotType_Histogram, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size); } @@ -9223,22 +9223,22 @@ void ImGui::PlotHistogram(const char* label, float (*values_getter)(void* data, // - Value() //------------------------------------------------------------------------- -void ImGui::Value(const char* prefix, bool b) +void ImGui::Value(ImStrv prefix, bool b) { Text("%s: %s", prefix, (b ? "true" : "false")); } -void ImGui::Value(const char* prefix, int v) +void ImGui::Value(ImStrv prefix, int v) { Text("%s: %d", prefix, v); } -void ImGui::Value(const char* prefix, unsigned int v) +void ImGui::Value(ImStrv prefix, unsigned int v) { Text("%s: %d", prefix, v); } -void ImGui::Value(const char* prefix, float v, const char* float_format) +void ImGui::Value(ImStrv prefix, float v, ImStrv float_format) { if (float_format) { @@ -9405,7 +9405,7 @@ void ImGui::EndMenuBar() // Important: calling order matters! // FIXME: Somehow overlapping with docking tech. // FIXME: The "rect-cut" aspect of this could be formalized into a lower-level helper (rect-cut: https://halt.software/dead-simple-layouts) -bool ImGui::BeginViewportSideBar(const char* name, ImGuiViewport* viewport_p, ImGuiDir dir, float axis_size, ImGuiWindowFlags window_flags) +bool ImGui::BeginViewportSideBar(ImStrv name, ImGuiViewport* viewport_p, ImGuiDir dir, float axis_size, ImGuiWindowFlags window_flags) { IM_ASSERT(dir != ImGuiDir_None); @@ -9505,7 +9505,7 @@ static bool IsRootOfOpenMenuSet() return upper_popup->Window && (upper_popup->Window->Flags & ImGuiWindowFlags_ChildMenu) && ImGui::IsWindowChildOf(upper_popup->Window, window, true); } -bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled) +bool ImGui::BeginMenuEx(ImStrv label, ImStrv icon, bool enabled) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -9730,7 +9730,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled) return menu_is_open; } -bool ImGui::BeginMenu(const char* label, bool enabled) +bool ImGui::BeginMenu(ImStrv label, bool enabled) { return BeginMenuEx(label, NULL, enabled); } @@ -9754,7 +9754,7 @@ void ImGui::EndMenu() EndPopup(); } -bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut, bool selected, bool enabled) +bool ImGui::MenuItemEx(ImStrv label, ImStrv icon, ImStrv shortcut, bool selected, bool enabled) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -9844,12 +9844,12 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut return pressed; } -bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, bool enabled) +bool ImGui::MenuItem(ImStrv label, ImStrv shortcut, bool selected, bool enabled) { return MenuItemEx(label, NULL, shortcut, selected, enabled); } -bool ImGui::MenuItem(const char* label, const char* shortcut, bool* p_selected, bool enabled) +bool ImGui::MenuItem(ImStrv label, ImStrv shortcut, bool* p_selected, bool enabled) { if (MenuItemEx(label, NULL, shortcut, p_selected ? *p_selected : false, enabled)) { @@ -9898,7 +9898,7 @@ struct ImGuiTabBarSection namespace ImGui { static void TabBarLayout(ImGuiTabBar* tab_bar); - static ImU32 TabBarCalcTabID(ImGuiTabBar* tab_bar, const char* label, ImGuiWindow* docked_window); + static ImU32 TabBarCalcTabID(ImGuiTabBar* tab_bar, ImStrv label, ImGuiWindow* docked_window); static float TabBarCalcMaxTabWidth(); static float TabBarScrollClamp(ImGuiTabBar* tab_bar, float scrolling); static void TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGuiTabBarSection* sections); @@ -9963,7 +9963,7 @@ void ImGui::TabBarRemove(ImGuiTabBar* tab_bar) g.TabBars.Remove(tab_bar->ID, tab_bar); } -bool ImGui::BeginTabBar(const char* str_id, ImGuiTabBarFlags flags) +bool ImGui::BeginTabBar(ImStrv str_id, ImGuiTabBarFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; @@ -10357,7 +10357,7 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar) } // Dockable windows uses Name/ID in the global namespace. Non-dockable items use the ID stack. -static ImU32 ImGui::TabBarCalcTabID(ImGuiTabBar* tab_bar, const char* label, ImGuiWindow* docked_window) +static ImU32 ImGui::TabBarCalcTabID(ImGuiTabBar* tab_bar, ImStrv label, ImGuiWindow* docked_window) { IM_ASSERT(docked_window == NULL); // master branch only IM_UNUSED(docked_window); @@ -10706,7 +10706,7 @@ static ImGuiTabItem* ImGui::TabBarTabListPopupButton(ImGuiTabBar* tab_bar) // - TabItemLabelAndCloseButton() [Internal] //------------------------------------------------------------------------- -bool ImGui::BeginTabItem(const char* label, bool* p_open, ImGuiTabItemFlags flags) +bool ImGui::BeginTabItem(ImStrv label, bool* p_open, ImGuiTabItemFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; @@ -10741,7 +10741,7 @@ void ImGui::EndTabItem() PopID(); } -bool ImGui::TabItemButton(const char* label, ImGuiTabItemFlags flags) +bool ImGui::TabItemButton(ImStrv label, ImGuiTabItemFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; @@ -10753,7 +10753,7 @@ bool ImGui::TabItemButton(const char* label, ImGuiTabItemFlags flags) return TabItemEx(tab_bar, label, NULL, flags | ImGuiTabItemFlags_Button | ImGuiTabItemFlags_NoReorder, NULL); } -void ImGui::TabItemSpacing(const char* str_id, ImGuiTabItemFlags flags, float width) +void ImGui::TabItemSpacing(ImStrv str_id, ImGuiTabItemFlags flags, float width) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; @@ -10766,7 +10766,7 @@ void ImGui::TabItemSpacing(const char* str_id, ImGuiTabItemFlags flags, float TabItemEx(tab_bar, str_id, NULL, flags | ImGuiTabItemFlags_Button | ImGuiTabItemFlags_NoReorder | ImGuiTabItemFlags_Invisible, NULL); } -bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImGuiTabItemFlags flags, ImGuiWindow* docked_window) +bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, ImStrv label, bool* p_open, ImGuiTabItemFlags flags, ImGuiWindow* docked_window) { // Layout whole tab bar if not already done ImGuiContext& g = *GImGui; @@ -11013,7 +11013,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, // [Public] This is call is 100% optional but it allows to remove some one-frame glitches when a tab has been unexpectedly removed. // To use it to need to call the function SetTabItemClosed() between BeginTabBar() and EndTabBar(). // Tabs closed by the close button will automatically be flagged to avoid this issue. -void ImGui::SetTabItemClosed(const char* label) +void ImGui::SetTabItemClosed(ImStrv label) { ImGuiContext& g = *GImGui; bool is_within_manual_tab_bar = g.CurrentTabBar && !(g.CurrentTabBar->Flags & ImGuiTabBarFlags_DockNode); @@ -11026,7 +11026,7 @@ void ImGui::SetTabItemClosed(const char* label) } } -ImVec2 ImGui::TabItemCalcSize(const char* label, bool has_close_button_or_unsaved_marker) +ImVec2 ImGui::TabItemCalcSize(ImStrv label, bool has_close_button_or_unsaved_marker) { ImGuiContext& g = *GImGui; ImVec2 label_size = CalcTextSize(label, NULL, true); @@ -11067,7 +11067,7 @@ void ImGui::TabItemBackground(ImDrawList* draw_list, const ImRect& bb, ImGuiTabI // Render text label (with custom clipping) + Unsaved Document marker + Close Button logic // We tend to lock style.FramePadding for a given tab-bar, hence the 'frame_padding' parameter. -void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImVec2 frame_padding, const char* label, ImGuiID tab_id, ImGuiID close_button_id, bool is_contents_visible, bool* out_just_closed, bool* out_text_clipped) +void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImVec2 frame_padding, ImStrv label, ImGuiID tab_id, ImGuiID close_button_id, bool is_contents_visible, bool* out_just_closed, bool* out_text_clipped) { ImGuiContext& g = *GImGui; const char* label_end = FindRenderedTextEnd(label); @@ -11167,5 +11167,4 @@ void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, *out_just_closed = close_button_pressed; } - #endif // #ifndef IMGUI_DISABLE From ac9042899f7f3744054821805d613137cf322d00 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 24 Aug 2020 11:37:01 +0300 Subject: [PATCH 02/15] ImStrv: Step 2 - change ImStrv typedef to struct, perform all other logic conversion. Squashed commits (initially a commit from rokups + many rework by ocornut. keeping them separate commits made rebasing unnecessarily tricking so merged from 2024/02) ImStrv: many fixes (see details), added imconfig class extension example, added natvis description. ImStrv: rework toward ensuring End is always set to constant can be compile time calculated ImStrv: using length(), fix ambiguous empty() function, fix altered behaviors, removed unused operators. ImStrv: various tweaks and fixes. removed ImGuiTextRange from ImGuiTextFilter, fix test engine hooks, removed constructor only used twice. --- imconfig.h | 9 + imgui.cpp | 335 ++++++++++++++++++------------- imgui.h | 81 +++++--- imgui_demo.cpp | 12 +- imgui_draw.cpp | 69 +++---- imgui_internal.h | 64 +++--- imgui_tables.cpp | 36 ++-- imgui_widgets.cpp | 390 +++++++++++++++++++----------------- misc/debuggers/imgui.natvis | 5 + 9 files changed, 570 insertions(+), 431 deletions(-) diff --git a/imconfig.h b/imconfig.h index d9c05692f..69f5f000a 100644 --- a/imconfig.h +++ b/imconfig.h @@ -122,6 +122,15 @@ //#endif //---- ...Or manually '#define IMGUI_DEFINE_MATH_OPERATORS' before '#include "imgui.h"' to use from one file. +//---- Define constructor to convert your string type to ImStrv (which is a non-owning begin/end pair) +// This will be inlined as part of ImStrv class declaration. +// This has two benefits: you won't need to use .c_str(), if length is already computed it is faster. +//#include +//#include +//#define IM_STRV_CLASS_EXTRA ImStrv(const std::string& s) { Begin = s.c_str(); End = Begin + s.length(); } +//#define IM_STRV_CLASS_EXTRA ImStrv(const std::string_view& s) { Begin = s.data(); End = Begin + s.length(); } +//#define IM_STRV_CLASS_EXTRA ImStrv(const MyString& s) { Begin = s.Data; End = s.end(); } + //---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices. // Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices). // Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer. diff --git a/imgui.cpp b/imgui.cpp index ebc04e8ea..21af587c1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2261,6 +2261,15 @@ ImVec2 ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, // [SECTION] MISC HELPERS/UTILITIES (String, Format, Hash functions) //----------------------------------------------------------------------------- +int ImStrcmp(ImStrv str1, ImStrv str2) +{ + size_t str1_len = str1.length(); + size_t str2_len = str2.length(); + if (str1_len != str2_len) + return (int)str1_len - (int)str2_len; + return memcmp(str1.Begin, str2.Begin, str1_len); +} + // Consider using _stricmp/_strnicmp under Windows or strcasecmp/strncasecmp. We don't actually use either ImStricmp/ImStrnicmp in the codebase any more. int ImStricmp(const char* str1, const char* str2) { @@ -2285,6 +2294,13 @@ void ImStrncpy(char* dst, const char* src, size_t count) dst[count - 1] = 0; } +void ImStrncpy(char* dst, ImStrv src, size_t count) +{ + // Even though src does not necessarily include \0 terminator it is ok to include it. ImStrncpy above does not + // actually include that in a copy operation and inserts zero terminator manually. + ImStrncpy(dst, src.Begin, ImMin(count, src.length() + 1)); +} + char* ImStrdup(const char* str) { size_t len = ImStrlen(str); @@ -2292,16 +2308,20 @@ char* ImStrdup(const char* str) return (char*)memcpy(buf, (const void*)str, len + 1); } -void* ImMemdup(const void* src, size_t size) +char* ImStrdup(ImStrv str) { - void* dst = IM_ALLOC(size); - return memcpy(dst, src, size); + size_t len = str.length(); + void* buf = IM_ALLOC(len + 1); + *((char*)buf + len) = 0; // str may not contain \0, it must be inserted manually. + if (len > 0) + return (char*)memcpy(buf, (const void*)str.Begin, len); + return (char*)buf; } -char* ImStrdupcpy(char* dst, size_t* p_dst_size, const char* src) +char* ImStrdupcpy(char* dst, size_t* p_dst_size, ImStrv src) { size_t dst_buf_size = p_dst_size ? *p_dst_size : ImStrlen(dst) + 1; - size_t src_size = ImStrlen(src) + 1; + size_t src_size = src.length() + 1; if (dst_buf_size < src_size) { IM_FREE(dst); @@ -2309,7 +2329,21 @@ char* ImStrdupcpy(char* dst, size_t* p_dst_size, const char* src) if (p_dst_size) *p_dst_size = src_size; } - return (char*)memcpy(dst, (const void*)src, src_size); + dst[src_size - 1] = 0; // str may not contain \0, it must be inserted manually. + if (src_size > 1) + return (char*)memcpy(dst, (const void*)src.Begin, src_size - 1); + return dst; +} + +char* ImStrdupcpy(char* dst, size_t* p_dst_size, const char* src) +{ + return ImStrdupcpy(dst, p_dst_size, ImStrv(src)); +} + +void* ImMemdup(const void* src, size_t size) +{ + void* dst = IM_ALLOC(size); + return memcpy(dst, src, size); } const char* ImStrchrRange(const char* str, const char* str_end, char c) @@ -2363,6 +2397,26 @@ const char* ImStristr(const char* haystack, const char* haystack_end, const char return NULL; } +// FIXME-IMSTR: probably unneeded. +const char* ImStrstr(ImStrv haystack, ImStrv needle) +{ + const char un0 = (char)*needle.Begin; + while ((!haystack.End && *haystack.Begin) || (haystack.End && haystack.Begin < haystack.End)) + { + if (*haystack.Begin == un0) + { + const char* b = needle.Begin + 1; + for (const char* a = haystack.Begin + 1; b < needle.End; a++, b++) + if (*a != *b) + break; + if (b == needle.End) + return haystack.Begin; + } + haystack.Begin++; + } + return NULL; +} + // Trim str by offsetting contents when there's leading data + writing a \0 at the trailing position. We use this in situation where the cost is negligible. void ImStrTrimBlanks(char* buf) { @@ -2444,11 +2498,11 @@ int ImFormatStringV(char* buf, size_t buf_size, const char* fmt, va_list args) } #endif // #ifdef IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS -void ImFormatStringToTempBuffer(const char** out_buf, const char** out_buf_end, const char* fmt, ...) +void ImFormatStringToTempBuffer(ImStrv* out_buf, const char* fmt, ...) { va_list args; va_start(args, fmt); - ImFormatStringToTempBufferV(out_buf, out_buf_end, fmt, args); + ImFormatStringToTempBufferV(out_buf, fmt, args); va_end(args); } @@ -2456,7 +2510,7 @@ void ImFormatStringToTempBuffer(const char** out_buf, const char** out_buf_end, // by making the caller acquire a temp buffer token, with either explicit or destructor release, e.g. // ImGuiTempBufferToken token; // ImFormatStringToTempBuffer(token, ...); -void ImFormatStringToTempBufferV(const char** out_buf, const char** out_buf_end, const char* fmt, va_list args) +void ImFormatStringToTempBufferV(ImStrv* out_buf, const char* fmt, va_list args) { ImGuiContext& g = *GImGui; if (fmt[0] == '%' && fmt[1] == 's' && fmt[2] == 0) @@ -2464,8 +2518,8 @@ void ImFormatStringToTempBufferV(const char** out_buf, const char** out_buf_end, const char* buf = va_arg(args, const char*); // Skip formatting when using "%s" if (buf == NULL) buf = "(null)"; - *out_buf = buf; - if (out_buf_end) { *out_buf_end = buf + ImStrlen(buf); } + out_buf->Begin = buf; + out_buf->End = buf + ImStrlen(buf); } else if (fmt[0] == '%' && fmt[1] == '.' && fmt[2] == '*' && fmt[3] == 's' && fmt[4] == 0) { @@ -2476,14 +2530,14 @@ void ImFormatStringToTempBufferV(const char** out_buf, const char** out_buf_end, buf = "(null)"; buf_len = ImMin(buf_len, 6); } - *out_buf = buf; - *out_buf_end = buf + buf_len; // Disallow not passing 'out_buf_end' here. User is expected to use it. + out_buf->Begin = buf; + out_buf->End = buf + buf_len; } else { int buf_len = ImFormatStringV(g.TempBuffer.Data, g.TempBuffer.Size, fmt, args); - *out_buf = g.TempBuffer.Data; - if (out_buf_end) { *out_buf_end = g.TempBuffer.Data + buf_len; } + out_buf->Begin = g.TempBuffer.Data; + out_buf->End = g.TempBuffer.Data + buf_len; } } @@ -2567,17 +2621,18 @@ ImGuiID ImHashData(const void* data_p, size_t data_size, ImGuiID seed) // Zero-terminated string hash, with support for ### to reset back to seed value. // e.g. "label###id" outputs the same hash as "id" (and "label" is generally displayed by the UI functions) // FIXME-OPT: Replace with e.g. FNV1a hash? CRC32 pretty much randomly access 1KB. Need to do proper measurements. -ImGuiID ImHashStr(const char* data_p, size_t data_size, ImGuiID seed) +ImGuiID ImHashStr(ImStrv str, ImGuiID seed) { seed = ~seed; ImU32 crc = seed; - const unsigned char* data = (const unsigned char*)data_p; + const unsigned char* data = (const unsigned char*)str.Begin; #ifndef IMGUI_ENABLE_SSE4_2_CRC const ImU32* crc32_lut = GCrc32LookupTable; #endif - if (data_size != 0) + if (str.End != NULL) { - while (data_size-- > 0) + size_t data_size = str.length(); + while (data_size-- != 0) { unsigned char c = *data++; if (c == '#' && data_size >= 2 && data[0] == '#' && data[1] == '#') @@ -2616,12 +2671,12 @@ ImGuiID ImHashStr(const char* data_p, size_t data_size, ImGuiID seed) // Skip to the "###" marker if any. We don't skip past to match the behavior of GetID() // FIXME-OPT: This is not designed to be optimal. Use with care. -const char* ImHashSkipUncontributingPrefix(const char* label) +const char* ImHashSkipUncontributingPrefix(ImStrv label) { - const char* result = label; - while (unsigned char c = *label++) - if (c == '#' && label[0] == '#' && label[1] == '#') - result = label + 2; + const char* result = label.Begin; + for (const char* p = label.Begin; p + 2 < label.End; p++) + if (p[0] == '#' && p[1] == '#' && p[2] == '#') + result = p + 3; return result; } @@ -2637,8 +2692,8 @@ ImFileHandle ImFileOpen(ImStrv filename, ImStrv mode) #if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && (defined(__MINGW32__) || (!defined(__CYGWIN__) && !defined(__GNUC__))) // We need a fopen() wrapper because MSVC/Windows fopen doesn't handle UTF-8 filenames. // Previously we used ImTextCountCharsFromUtf8/ImTextStrFromUtf8 here but we now need to support ImWchar16 and ImWchar32! - const int filename_wsize = ::MultiByteToWideChar(CP_UTF8, 0, filename, -1, NULL, 0); - const int mode_wsize = ::MultiByteToWideChar(CP_UTF8, 0, mode, -1, NULL, 0); + const int filename_wsize = ::MultiByteToWideChar(CP_UTF8, 0, filename.Begin, (int)filename.length() + 1, NULL, 0); + const int mode_wsize = ::MultiByteToWideChar(CP_UTF8, 0, mode.Begin, (int)mode.length() + 1, NULL, 0); // Use stack buffer if possible, otherwise heap buffer. Sizes include zero terminator. // We don't rely on current ImGuiContext as this is implied to be a helper function which doesn't depend on it (see #7314). @@ -2648,11 +2703,19 @@ ImFileHandle ImFileOpen(ImStrv filename, ImStrv mode) local_temp_heap.resize(filename_wsize + mode_wsize); wchar_t* filename_wbuf = local_temp_heap.Data ? local_temp_heap.Data : local_temp_stack; wchar_t* mode_wbuf = filename_wbuf + filename_wsize; - ::MultiByteToWideChar(CP_UTF8, 0, filename, -1, filename_wbuf, filename_wsize); - ::MultiByteToWideChar(CP_UTF8, 0, mode, -1, mode_wbuf, mode_wsize); + ::MultiByteToWideChar(CP_UTF8, 0, filename.Begin, (int)filename.length(), filename_wbuf, filename_wsize); + ::MultiByteToWideChar(CP_UTF8, 0, mode.Begin, (int)mode.length(), mode_wbuf, mode_wsize); + filename_wbuf[filename_wsize - 1] = mode_wbuf[mode_wsize - 1] = 0; return ::_wfopen(filename_wbuf, mode_wbuf); #else - return fopen(filename, mode); + // ImStrv is not guaranteed to be zero-terminated. + // FIXME-IMSTR: Use TempBuffer to avoid needlessly allocating. + ImStrv filename_0 = ImStrdup(filename); + ImStrv mode_0 = ImStrdup(mode); + ImFileHandle handle = fopen(filename_0.Begin, mode_0.Begin); + IM_FREE((char*)(void*)filename_0.Begin); + IM_FREE((char*)(void*)mode_0.Begin); + return handle; #endif } @@ -2907,16 +2970,13 @@ const char* ImTextFindValidUtf8CodepointEnd(const char* in_text_start, const cha return prev; } -int ImTextCountLines(const char* in_text, const char* in_text_end) +int ImTextCountLines(ImStrv in_text) { - if (in_text_end == NULL) - in_text_end = in_text + ImStrlen(in_text); // FIXME-OPT: Not optimal approach, discourage use for now. int count = 0; - while (in_text < in_text_end) + for (const char* p = in_text.Begin, * p_end = in_text.End; p < p_end; count++) { - const char* line_end = (const char*)ImMemchr(in_text, '\n', in_text_end - in_text); - in_text = line_end ? line_end + 1 : in_text_end; - count++; + const char* line_end = (const char*)ImMemchr(p, '\n', p_end - p); + p = line_end ? line_end + 1 : p_end; } return count; } @@ -3170,7 +3230,7 @@ bool ImGuiTextFilter::Draw(ImStrv label) } // Use ImGui::SetNextItemWidth() manually if you want to use this. -bool ImGuiTextFilter::DrawWithHint(const char* label, const char* hint) +bool ImGuiTextFilter::DrawWithHint(ImStrv label, ImStrv hint) { bool value_changed = ImGui::InputTextWithHint(label, hint, InputBuf, IM_COUNTOF(InputBuf)); if (value_changed) @@ -3239,18 +3299,16 @@ void ImGuiTextFilter::Build() } // FIXME: Could use a specialized ImStristr() + pre-convert our filter to uppercase. -bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const +bool ImGuiTextFilter::PassFilter(ImStrv text) const { if (_Items.Size == 0) return true; - if (text == NULL) - text = text_end = ""; // Filters are sorted so that '-' ones are always leading. ImGuiTextFilterItem* seq = _Items.Data; ImGuiTextFilterItem* seq_excl_end = _Items.Data + _CountExclude; for (; seq < seq_excl_end; seq++) - if (ImStristr(text, text_end, seq->Begin, seq->Begin + seq->Len) != NULL) + if (ImStristr(text.Begin, text.End, seq->Begin, seq->Begin + seq->Len) != NULL) return false; // Process includes @@ -3262,7 +3320,7 @@ bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const ImGuiTextFilterItem* seq_incl_end = seq + seq->CountInclude; IM_ASSERT_PARANOID(seq->CountInclude > 0 && seq_incl_end <= seq_end); for (; seq < seq_incl_end; seq++) - if (ImStristr(text, text_end, seq->Begin, seq->Begin + seq->Len) == NULL) + if (ImStristr(text.Begin, text.End, seq->Begin, seq->Begin + seq->Len) == NULL) break; if (seq == seq_incl_end) // All matched return true; @@ -3287,9 +3345,11 @@ bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const char ImGuiTextBuffer::EmptyString[1] = { 0 }; -void ImGuiTextBuffer::append(const char* str, const char* str_end) +void ImGuiTextBuffer::append(ImStrv str) { - int len = str_end ? (int)(str_end - str) : (int)ImStrlen(str); + int len = (int)str.length(); + if (len == 0) + return; // Add zero-terminator the first time const int write_off = (Buf.Size != 0) ? Buf.Size : 1; @@ -3301,7 +3361,7 @@ void ImGuiTextBuffer::append(const char* str, const char* str_end) } Buf.resize(needed_sz); - memcpy(&Buf[write_off - 1], str, (size_t)len); + memcpy(&Buf[write_off - 1], str.Begin, (size_t)len); Buf[write_off - 1 + len] = 0; } @@ -3973,58 +4033,43 @@ const char* ImGui::GetStyleColorName(ImGuiCol idx) // Also see imgui_draw.cpp for some more which have been reworked to not rely on ImGui:: context. //----------------------------------------------------------------------------- -const char* ImGui::FindRenderedTextEnd(const char* text, const char* text_end) +const char* ImGui::FindRenderedTextEnd(ImStrv text) { - const char* text_display_end = text; - if (!text_end) - text_end = (const char*)-1; - - while (text_display_end < text_end && *text_display_end != '\0' && (text_display_end[0] != '#' || text_display_end[1] != '#')) + const char* text_display_end = text.Begin; + while (text_display_end < text.End && (text_display_end[0] != '#' || text_display_end[1] != '#')) text_display_end++; return text_display_end; } // Internal ImGui functions to render text // RenderText***() functions calls ImDrawList::AddText() calls ImBitmapFont::RenderText() -void ImGui::RenderText(ImVec2 pos, const char* text, const char* text_end, bool hide_text_after_hash) +void ImGui::RenderText(ImVec2 pos, ImStrv text, bool hide_text_after_hash) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; // Hide anything after a '##' string - const char* text_display_end; if (hide_text_after_hash) - { - text_display_end = FindRenderedTextEnd(text, text_end); - } - else - { - if (!text_end) - text_end = text + ImStrlen(text); // FIXME-OPT (not reached by our internal calls) - text_display_end = text_end; - } + text.End = FindRenderedTextEnd(text); - if (text != text_display_end) + if (text.Begin != text.End) { - window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end); + window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text); if (g.LogEnabled) - LogRenderedText(&pos, text, text_display_end); + LogRenderedText(&pos, text); } } -void ImGui::RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width) +void ImGui::RenderTextWrapped(ImVec2 pos, ImStrv text, float wrap_width) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - if (!text_end) - text_end = text + ImStrlen(text); // FIXME-OPT (not reached by our internal calls) - - if (text != text_end) + if (text.Begin != text.End) { - window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_end, wrap_width); + window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, wrap_width); if (g.LogEnabled) - LogRenderedText(&pos, text, text_end); + LogRenderedText(&pos, text); } } @@ -4033,12 +4078,12 @@ void ImGui::RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end // FIXME-OPT: Since we have or calculate text_size we could coarse clip whole block immediately, especially for text above draw_list->DrawList. // Effectively as this is called from widget doing their own coarse clipping it's not very valuable presently. Next time function will take // better advantage of the render function taking size into account for coarse clipping. -void ImGui::RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_display_end, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect) // DOES NOT CALL LogRenderedText(), unlike RenderTextClipped!!! +void ImGui::RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, ImStrv text, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect) { // Perform CPU side clipping for single clipped element to avoid using scissor state ImVec2 pos = pos_min; - const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_display_end, false, 0.0f); + const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, false, 0.0f); const ImVec2* clip_min = clip_rect ? &clip_rect->Min : &pos_min; const ImVec2* clip_max = clip_rect ? &clip_rect->Max : &pos_max; @@ -4054,39 +4099,37 @@ void ImGui::RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, co if (need_clipping) { ImVec4 fine_clip_rect(clip_min->x, clip_min->y, clip_max->x, clip_max->y); - draw_list->AddText(NULL, 0.0f, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, &fine_clip_rect); + draw_list->AddText(NULL, 0.0f, pos, GetColorU32(ImGuiCol_Text), text, 0.0f, &fine_clip_rect); } else { - draw_list->AddText(NULL, 0.0f, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, NULL); + draw_list->AddText(NULL, 0.0f, pos, GetColorU32(ImGuiCol_Text), text, 0.0f, NULL); } } -void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect) +void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, ImStrv text, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect) { // Hide anything after a '##' string - const char* text_display_end = FindRenderedTextEnd(text, text_end); - const int text_len = (int)(text_display_end - text); - if (text_len == 0) + // FIXME-IMSTR: This is not new but should be moved out of there. + text.End = FindRenderedTextEnd(text); + if (text.Begin == text.End) return; ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - RenderTextClippedEx(window->DrawList, pos_min, pos_max, text, text_display_end, text_size_if_known, align, clip_rect); + RenderTextClippedEx(window->DrawList, pos_min, pos_max, text, text_size_if_known, align, clip_rect); if (g.LogEnabled) - LogRenderedText(&pos_min, text, text_display_end); + LogRenderedText(&pos_min, text); } // Another overly complex function until we reorganize everything into a nice all-in-one helper. // This is made more complex because we have dissociated the layout rectangle (pos_min..pos_max) from 'ellipsis_max_x' which may be beyond it. // This is because in the context of tabs we selectively hide part of the text when the Close Button appears, but we don't want the ellipsis to move. // (BREAKING) On 2025/04/16 we removed the 'float clip_max_x' parameters which was preceding 'float ellipsis_max' and was the same value for 99% of users. -void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float ellipsis_max_x, const char* text, const char* text_end_full, const ImVec2* text_size_if_known) +void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float ellipsis_max_x, ImStrv text, const ImVec2* text_size_if_known) { ImGuiContext& g = *GImGui; - if (text_end_full == NULL) - text_end_full = FindRenderedTextEnd(text); - const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_end_full, false, 0.0f); + const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, false, 0.0f); //draw_list->AddLineV(pos_max.x, pos_min.y - 4, pos_max.y + 6, IM_COL32(0, 0, 255, 255)); //draw_list->AddLineV(ellipsis_max_x, pos_min.y - 2, pos_max.y + 3, IM_COL32(0, 255, 0, 255)); @@ -4108,21 +4151,21 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con // We can now claim the space between pos_max.x and ellipsis_max.x const float text_avail_width = ImMax((ImMax(pos_max.x, ellipsis_max_x) - ellipsis_width) - pos_min.x, 1.0f); - const float text_size_clipped_x = font->CalcTextSizeA(font_size, text_avail_width, 0.0f, text, text_end_full, &text_end_ellipsis).x; + const float text_size_clipped_x = font->CalcTextSizeA(font_size, text_avail_width, 0.0f, text, &text_end_ellipsis).x; // Render text, render ellipsis - RenderTextClippedEx(draw_list, pos_min, pos_max, text, text_end_ellipsis, &text_size, ImVec2(0.0f, 0.0f)); + RenderTextClippedEx(draw_list, pos_min, pos_max, ImStrv(text.Begin, text_end_ellipsis), &text_size, ImVec2(0.0f, 0.0f)); ImVec4 cpu_fine_clip_rect(pos_min.x, pos_min.y, pos_max.x, pos_max.y); ImVec2 ellipsis_pos = ImTrunc(ImVec2(pos_min.x + text_size_clipped_x, pos_min.y)); font->RenderChar(draw_list, font_size, ellipsis_pos, GetColorU32(ImGuiCol_Text), font->EllipsisChar, &cpu_fine_clip_rect); } else { - RenderTextClippedEx(draw_list, pos_min, pos_max, text, text_end_full, &text_size, ImVec2(0.0f, 0.0f)); + RenderTextClippedEx(draw_list, pos_min, pos_max, text, &text_size, ImVec2(0.0f, 0.0f)); } if (g.LogEnabled) - LogRenderedText(&pos_min, text, text_end_full); + LogRenderedText(&pos_min, text); } // Render a rectangle shaped with optional rounding and borders @@ -4309,7 +4352,7 @@ static const ImGuiLocEntry GLocalizationEntriesEnUS[] = { ImGuiLocKey_WindowingMainMenuBar, "(Main menu bar)" }, { ImGuiLocKey_WindowingPopup, "(Popup)" }, { ImGuiLocKey_WindowingUntitled, "(Untitled)" }, - { ImGuiLocKey_OpenLink_s, "Open '%s'" }, + { ImGuiLocKey_OpenLink_s, "Open '%.*s'" }, { ImGuiLocKey_CopyLink, "Copy Link###CopyLink" }, }; @@ -4759,7 +4802,7 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* ctx, ImStrv name) : DrawListInst(NULL) memset((void*)this, 0, sizeof(*this)); Ctx = ctx; Name = ImStrdup(name); - NameBufLen = (int)ImStrlen(name) + 1; + NameBufLen = (int)name.length() + 1; ID = ImHashStr(name); IDStack.push_back(ID); MoveId = GetID("#MOVE"); @@ -5327,7 +5370,15 @@ void ImGui::SetClipboardText(ImStrv text) { ImGuiContext& g = *GImGui; if (g.PlatformIO.Platform_SetClipboardTextFn != NULL) - g.PlatformIO.Platform_SetClipboardTextFn(&g, text); + { + int len = (int)text.length(); + char* text_p = (char*)IM_ALLOC(len + 1); + if (len > 0) + memcpy(text_p, text.Begin, len); + text_p[len] = 0; // text may not contain \0, it must be inserted manually. + g.PlatformIO.Platform_SetClipboardTextFn(&g, text_p); + IM_FREE(text_p); + } } const char* ImGui::GetVersion() @@ -6364,21 +6415,18 @@ void ImGui::Render() // Calculate text size. Text can be multi-line. Optionally ignore text after a ## marker. // CalcTextSize("") should return ImVec2(0.0f, g.FontSize) -ImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool hide_text_after_double_hash, float wrap_width) +ImVec2 ImGui::CalcTextSize(ImStrv text, bool hide_text_after_double_hash, float wrap_width) { ImGuiContext& g = *GImGui; - const char* text_display_end; if (hide_text_after_double_hash) - text_display_end = FindRenderedTextEnd(text, text_end); // Hide anything after a '##' string - else - text_display_end = text_end; + text.End = FindRenderedTextEnd(text); // Hide anything after a '##' string ImFont* font = g.Font; const float font_size = g.FontSize; - if (text == text_display_end) + if (text.Begin == text.End) return ImVec2(0.0f, font_size); - ImVec2 text_size = font->CalcTextSizeA(font_size, FLT_MAX, wrap_width, text, text_display_end, NULL); + ImVec2 text_size = font->CalcTextSizeA(font_size, FLT_MAX, wrap_width, text, NULL); // Round // (see 7b0bf230, 4622fa4b6, #791 for details about this.) @@ -6702,14 +6750,14 @@ bool ImGui::BeginChildEx(ImStrv name, ImGuiID id, const ImVec2& size_arg, ImGuiC // Build up name. If you need to append to a same child from multiple location in the ID stack, use BeginChild(ImGuiID id) with a stable value. // FIXME: 2023/11/14: commented out shorted version. We had an issue with multiple ### in child window path names, which the trailing hash helped workaround. // e.g. "ParentName###ParentIdentifier/ChildName###ChildIdentifier" would get hashed incorrectly by ImHashStr(), trailing _%08X somehow fixes it. - const char* temp_window_name; + ImStrv temp_window_name; /*if (name && parent_window->IDStack.back() == parent_window->ID) - ImFormatStringToTempBuffer(&temp_window_name, NULL, "%s/%s", parent_window->Name, name); // May omit ID if in root of ID stack + ImFormatStringToTempBuffer(&temp_window_name, "%s/%.*s", parent_window->Name, (int)name.length(), name.Begin); // May omit ID if in root of ID stack else*/ if (name) - ImFormatStringToTempBuffer(&temp_window_name, NULL, "%s/%s_%08X", parent_window->Name, name, id); + ImFormatStringToTempBuffer(&temp_window_name, "%s/%.*s_%08X", parent_window->Name, (int)name.length(), name.Begin, id); else - ImFormatStringToTempBuffer(&temp_window_name, NULL, "%s/%08X", parent_window->Name, id); + ImFormatStringToTempBuffer(&temp_window_name, "%s/%08X", parent_window->Name, id); // Set style const float backup_border_size = g.Style.ChildBorderSize; @@ -7529,7 +7577,7 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl // Title bar text (with: horizontal alignment, avoiding collapse/close button, optional "unsaved document" marker) // FIXME: Refactor text alignment facilities along with RenderText helpers, this is WAY too much messy code.. const float marker_size_x = (flags & ImGuiWindowFlags_UnsavedDocument) ? button_sz * 0.80f : 0.0f; - const ImVec2 text_size = CalcTextSize(name, NULL, true) + ImVec2(marker_size_x, 0.0f); + const ImVec2 text_size = CalcTextSize(name, true) + ImVec2(marker_size_x, 0.0f); // As a nice touch we try to ensure that centered title text doesn't get affected by visibility of Close/Collapse button, // while uncentered title text will still reach edges correctly. @@ -7560,7 +7608,7 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl } //if (g.IO.KeyShift) window->DrawList->AddRect(layout_r.Min, layout_r.Max, IM_COL32(255, 128, 0, 255)); // [DEBUG] //if (g.IO.KeyCtrl) window->DrawList->AddRect(clip_r.Min, clip_r.Max, IM_COL32(255, 128, 0, 255)); // [DEBUG] - RenderTextClipped(layout_r.Min, layout_r.Max, name, NULL, &text_size, style.WindowTitleAlign, &clip_r); + RenderTextClipped(layout_r.Min, layout_r.Max, name, &text_size, style.WindowTitleAlign, &clip_r); } void ImGui::UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window) @@ -7628,7 +7676,7 @@ bool ImGui::Begin(ImStrv name, bool* p_open, ImGuiWindowFlags flags) { ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; - IM_ASSERT(name != NULL && name[0] != '\0'); // Window name required + IM_ASSERT(name.Begin != name.End); // Window name required IM_ASSERT(g.WithinFrameScope); // Forgot to call ImGui::NewFrame() IM_ASSERT(g.FrameCountEnded != g.FrameCount); // Called ImGui::Render() or ImGui::EndFrame() and haven't called ImGui::NewFrame() again yet @@ -7819,7 +7867,7 @@ bool ImGui::Begin(ImStrv name, bool* p_open, ImGuiWindowFlags flags) window_title_visible_elsewhere = true; if (flags & ImGuiWindowFlags_ChildMenu) window_title_visible_elsewhere = true; - if ((window_title_visible_elsewhere || window_just_activated_by_user) && !window_just_created && strcmp(name, window->Name) != 0) + if ((window_title_visible_elsewhere || window_just_activated_by_user) && !window_just_created && ImStrcmp(name, window->Name) != 0) { size_t buf_len = (size_t)window->NameBufLen; window->Name = ImStrdupcpy(window->Name, &buf_len, name); @@ -9424,14 +9472,14 @@ void ImGui::PopFont() // This is one of the very rare legacy case where we use ImGuiWindow methods, // it should ideally be flattened at some point but it's been used a lots by widgets. IM_MSVC_RUNTIME_CHECKS_OFF -ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end) +ImGuiID ImGuiWindow::GetID(ImStrv str) { ImGuiID seed = IDStack.back(); - ImGuiID id = ImHashStr(str, str_end ? (str_end - str) : 0, seed); + ImGuiID id = ImHashStr(str, seed); #ifndef IMGUI_DISABLE_DEBUG_TOOLS ImGuiContext& g = *Ctx; if (g.DebugHookIdInfoId == id) - ImGui::DebugHookIdInfo(id, ImGuiDataType_String, str, str_end); + ImGui::DebugHookIdInfo(id, ImGuiDataType_String, str.Begin, str.End); #endif return id; } @@ -9491,7 +9539,7 @@ void ImGui::PushID(const char* str_id_begin, const char* str_id_end) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - ImGuiID id = window->GetID(str_id_begin, str_id_end); + ImGuiID id = window->GetID(ImStrv(str_id_begin, str_id_end)); window->IDStack.push_back(id); } @@ -9564,7 +9612,7 @@ ImGuiID ImGui::GetID(ImStrv str_id) ImGuiID ImGui::GetID(const char* str_id_begin, const char* str_id_end) { ImGuiWindow* window = GImGui->CurrentWindow; - return window->GetID(str_id_begin, str_id_end); + return window->GetID(ImStrv(str_id_begin, str_id_end)); } ImGuiID ImGui::GetID(const void* ptr_id) @@ -11146,7 +11194,7 @@ bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID own bool ImGui::DebugCheckVersionAndDataLayout(ImStrv version, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_vert, size_t sz_idx) { bool error = false; - if (strcmp(version, IMGUI_VERSION) != 0) { error = true; IM_ASSERT(strcmp(version, IMGUI_VERSION) == 0 && "Mismatched version string!"); } + if (ImStrcmp(version, IMGUI_VERSION) != 0) { error = true; IM_ASSERT(0 && "Mismatched version string!"); } if (sz_io != sizeof(ImGuiIO)) { error = true; IM_ASSERT(sz_io == sizeof(ImGuiIO) && "Mismatched struct layout!"); } if (sz_style != sizeof(ImGuiStyle)) { error = true; IM_ASSERT(sz_style == sizeof(ImGuiStyle) && "Mismatched struct layout!"); } if (sz_vec2 != sizeof(ImVec2)) { error = true; IM_ASSERT(sz_vec2 == sizeof(ImVec2) && "Mismatched struct layout!"); } @@ -12574,7 +12622,7 @@ bool ImGui::OpenPopup(ImStrv str_id, ImGuiPopupFlags popup_flags) { ImGuiContext& g = *GImGui; ImGuiID id = g.CurrentWindow->GetID(str_id); - IMGUI_DEBUG_LOG_POPUP("[popup] OpenPopup(\"%s\" -> 0x%08X)\n", str_id, id); + IMGUI_DEBUG_LOG_POPUP("[popup] OpenPopup(\"%.*s\" -> 0x%08X\n", (int)(str_id.End - str_id.Begin), str_id, id); return OpenPopupEx(id, popup_flags); } @@ -12801,7 +12849,7 @@ bool ImGui::BeginPopupMenuEx(ImGuiID id, ImStrv label, ImGuiWindowFlags extra_wi char name[128]; IM_ASSERT(extra_window_flags & ImGuiWindowFlags_ChildMenu); - ImFormatString(name, IM_COUNTOF(name), "%s###Menu_%02d", label, g.BeginMenuDepth); // Recycle windows based on depth + ImFormatString(name, IM_COUNTOF(name), "%.*s###Menu_%02d", (int)label.length(), label.Begin, g.BeginMenuDepth); // Recycle windows based on depth bool is_open = Begin(name, NULL, extra_window_flags | ImGuiWindowFlags_Popup); if (!is_open) // NB: Begin can return false when the popup is completely clipped (e.g. zero size display) EndPopup(); @@ -15309,8 +15357,8 @@ bool ImGui::SetDragDropPayload(ImStrv type, const void* data, size_t data_size, if (cond == 0) cond = ImGuiCond_Always; - IM_ASSERT(type != NULL); - IM_ASSERT(ImStrlen(type) < IM_COUNTOF(payload.DataType) && "Payload type can be at most 32 characters long"); + IM_ASSERT(type.length() > 0 && "Payload type can not be empty"); + IM_ASSERT(type.length() < IM_COUNTOF(payload.DataType) && "Payload type can be at most 32 characters long"); IM_ASSERT((data != NULL && data_size > 0) || (data == NULL && data_size == 0)); IM_ASSERT(cond == ImGuiCond_Always || cond == ImGuiCond_Once); IM_ASSERT(payload.SourceId != 0); // Not called between BeginDragDropSource() and EndDragDropSource() @@ -15442,7 +15490,7 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(ImStrv type, ImGuiDragDropFlags ImGuiPayload& payload = g.DragDropPayload; IM_ASSERT(g.DragDropActive); // Not called between BeginDragDropTarget() and EndDragDropTarget() ? IM_ASSERT(payload.DataFrameCount != -1); // Forgot to call EndDragDropTarget() ? - if (type != NULL && !payload.IsDataType(type)) + if (type && !payload.IsDataType(type)) return NULL; // Accept smallest drag target bounding box, this allows us to nest drag targets conveniently without ordering constraints. @@ -15578,7 +15626,7 @@ void ImGui::LogTextV(const char* fmt, va_list args) // Internal version that takes a position to decide on newline placement and pad items according to their depth. // We split text into individual lines to add current tree level padding // FIXME: This code is a little complicated perhaps, considering simplifying the whole system. -void ImGui::LogRenderedText(const ImVec2* ref_pos, const char* text, const char* text_end) +void ImGui::LogRenderedText(const ImVec2* ref_pos, ImStrv text) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; @@ -15587,8 +15635,8 @@ void ImGui::LogRenderedText(const ImVec2* ref_pos, const char* text, const char* const char* suffix = g.LogNextSuffix; g.LogNextPrefix = g.LogNextSuffix = NULL; - if (!text_end) - text_end = FindRenderedTextEnd(text, text_end); + if (!text.End) + text.End = FindRenderedTextEnd(text); const bool log_new_line = ref_pos && (ref_pos->y > g.LogLinePosY + ImMax(g.Style.FramePadding.y, g.Style.ItemSpacing.y) + 1); if (ref_pos) @@ -15607,14 +15655,14 @@ void ImGui::LogRenderedText(const ImVec2* ref_pos, const char* text, const char* g.LogDepthRef = window->DC.TreeDepth; const int tree_depth = (window->DC.TreeDepth - g.LogDepthRef); - const char* text_remaining = text; + const char* text_remaining = text.Begin; for (;;) { // Split the string. Each new line (after a '\n') is followed by indentation corresponding to the current depth of our log entry. // We don't add a trailing \n yet to allow a subsequent item on the same line to be captured. const char* line_start = text_remaining; - const char* line_end = ImStreolRange(line_start, text_end); - const bool is_last_line = (line_end == text_end); + const char* line_end = ImStreolRange(line_start, text.End); + const bool is_last_line = (line_end == text.End); if (line_start != line_end || !is_last_line) { const int line_length = (int)(line_end - line_start); @@ -15687,7 +15735,7 @@ void ImGui::LogToFile(int auto_open_depth, ImStrv filename) // By opening the file in binary mode "ab" we have consistent output everywhere. if (!filename) filename = g.IO.LogFilename; - if (!filename || !filename[0]) + if (filename.empty()) return; ImFileHandle f = ImFileOpen(filename, "ab"); if (!f) @@ -15903,13 +15951,12 @@ void ImGui::LoadIniSettingsFromDisk(ImStrv ini_filename) if (!file_data) return; if (file_data_size > 0) - LoadIniSettingsFromMemory(file_data, (size_t)file_data_size); + LoadIniSettingsFromMemory(ImStrv(file_data, file_data + file_data_size)); IM_FREE(file_data); } // Zero-tolerance, no error reporting, cheap .ini parsing -// Set ini_size==0 to let us use strlen(ini_data). Do not call this function with a 0 if your buffer is actually empty! -void ImGui::LoadIniSettingsFromMemory(ImStrv ini_data, size_t ini_size) +void ImGui::LoadIniSettingsFromMemory(ImStrv ini_data) { ImGuiContext& g = *GImGui; IM_ASSERT(g.Initialized); @@ -15918,12 +15965,11 @@ void ImGui::LoadIniSettingsFromMemory(ImStrv ini_data, size_t ini_size) // For user convenience, we allow passing a non zero-terminated string (hence the ini_size parameter). // For our convenience and to make the code simpler, we'll also write zero-terminators within the buffer. So let's create a writable copy.. - if (ini_size == 0) - ini_size = ImStrlen(ini_data); + const int ini_size = (int)ini_data.length(); g.SettingsIniData.Buf.resize((int)ini_size + 1); char* const buf = g.SettingsIniData.Buf.Data; char* const buf_end = buf + ini_size; - memcpy(buf, ini_data, ini_size); + memcpy(buf, ini_data.Begin, ini_size); buf_end[0] = 0; // Call pre-read handlers @@ -15971,7 +16017,7 @@ void ImGui::LoadIniSettingsFromMemory(ImStrv ini_data, size_t ini_size) g.SettingsLoaded = true; // [DEBUG] Restore untouched copy so it can be browsed in Metrics (not strictly necessary) - memcpy(buf, ini_data, ini_size); + memcpy(buf, ini_data.Begin, ini_size); // Call post-read handlers ImGuiSettingsCleanupArgs cleanup_args; @@ -16021,15 +16067,21 @@ ImGuiWindowSettings* ImGui::CreateNewWindowSettings(ImStrv name) // Preserve the full string when ConfigDebugVerboseIniSettings is set to make .ini inspection easier. if (g.IO.ConfigDebugIniSettings == false) - name = ImHashSkipUncontributingPrefix(name); - const size_t name_len = ImStrlen(name); + name.Begin = ImHashSkipUncontributingPrefix(name); + const size_t name_len = name.length(); + if (name_len == 0) + { + IM_ASSERT(false && "Name must not be empty."); + return NULL; + } // Allocate chunk const size_t chunk_size = sizeof(ImGuiWindowSettings) + name_len + 1; ImGuiWindowSettings* settings = g.SettingsWindows.alloc_chunk(chunk_size); IM_PLACEMENT_NEW(settings) ImGuiWindowSettings(); - settings->ID = ImHashStr(name, name_len); - memcpy(settings->GetName(), name, name_len + 1); // Store with zero terminator + settings->ID = ImHashStr(name); + memcpy(settings->GetName(), name.Begin, name_len); + settings->GetName()[name_len] = 0; // name may not contain \0, it must be inserted manually. return settings; } @@ -16689,13 +16741,12 @@ void ImGui::DebugTextEncoding(ImStrv str) TableSetupColumn("Glyph"); TableSetupColumn("Codepoint"); TableHeadersRow(); - const char* str_end = str + strlen(str); // As we may receive malformed UTF-8, pass an explicit end instead of relying on ImTextCharFromUtf8() assuming enough space. - for (const char* p = str; *p != 0; ) + for (const char* p = str.Begin; p != str.End; ) { unsigned int c; - const int c_utf8_len = ImTextCharFromUtf8(&c, p, str_end); + const int c_utf8_len = ImTextCharFromUtf8(&c, p, str.End); // As we may receive malformed UTF-8, pass an explicit end instead of relying on ImTextCharFromUtf8() assuming enough space. TableNextColumn(); - Text("%d", (int)(p - str)); + Text("%d", (int)(size_t)(p - str)); TableNextColumn(); for (int byte_index = 0; byte_index < c_utf8_len; byte_index++) { @@ -17045,7 +17096,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) { // Debug Break features // The Item Picker tool is super useful to visually select an item and break into the call-stack of where it was submitted. - SeparatorTextEx(0, "Debug breaks", NULL, CalcTextSize("(?)").x + g.Style.SeparatorTextPadding.x); + SeparatorTextEx(0, "Debug breaks", CalcTextSize("(?)").x + g.Style.SeparatorTextPadding.x); SameLine(); MetricsHelpMarker("Will call the IM_DEBUG_BREAK() macro to break in debugger.\nWarning: If you don't have a debugger attached, this will probably crash."); if (Checkbox("Show Item Picker", &g.DebugItemPickerActive) && g.DebugItemPickerActive) diff --git a/imgui.h b/imgui.h index 16773381a..19caf29bb 100644 --- a/imgui.h +++ b/imgui.h @@ -58,6 +58,8 @@ Index of this file: */ +#define IMGUI_HAS_IMSTR + #pragma once // Configuration file with compile-time options @@ -325,9 +327,27 @@ struct ImVec4 IM_VEC4_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h to convert back and forth between your math types and ImVec4. #endif }; -IM_MSVC_RUNTIME_CHECKS_RESTORE -typedef const char* ImStrv; +// String view (non-owning pair of begin/end pointers, not necessarily zero-terminated) +// ImStrv are used as function parameters instead of passing a pair of const char*. +struct ImStrv +{ + const char* Begin; + const char* End; + ImStrv() { Begin = End = NULL; } + ImStrv(const char* b) { Begin = b; End = b ? b + strlen(b) : NULL; } + ImStrv(const char* b, const char* e){ Begin = b; End = e ? e : b + strlen(b); } + inline size_t length() const { return (size_t)(End - Begin); } + inline bool empty() const { return Begin == End; } // == "" or == NULL + inline operator bool() const { return Begin != NULL; } // return true when valid ("" is valid, NULL construction is not) +#ifdef IM_STRV_CLASS_EXTRA + IM_STRV_CLASS_EXTRA // Define additional constructor in imconfig.h to convert your string types (e.g. std::string, std::string_view) to ImStrV. +#endif + // private: bool operator==(ImStrv) { return false; } // [DEBUG] Uncomment to catch undesirable uses of operators + // private: bool operator!=(ImStrv) { return false; } +}; + +IM_MSVC_RUNTIME_CHECKS_RESTORE //----------------------------------------------------------------------------- // [SECTION] Texture identifiers (ImTextureID, ImTextureRef) @@ -616,18 +636,20 @@ namespace ImGui // - In this header file we use the "label"/"name" terminology to denote a string that will be displayed + used as an ID, // whereas "str_id" denote a string that is only used as an ID and not normally displayed. IMGUI_API void PushID(ImStrv str_id); // push string into the ID stack (will hash string). - IMGUI_API void PushID(const char* str_id_begin, const char* str_id_end); // push string into the ID stack (will hash string). + IMGUI_API void PushID(const char* str_id_begin, const char* str_id_end = NULL);// push string into the ID stack (will hash string). IMGUI_API void PushID(const void* ptr_id); // push pointer into the ID stack (will hash pointer). IMGUI_API void PushID(int int_id); // push integer into the ID stack (will hash integer). IMGUI_API void PopID(); // pop from the ID stack. IMGUI_API ImGuiID GetID(ImStrv str_id); // calculate unique ID (hash of whole ID stack + given parameter). e.g. if you want to query into ImGuiStorage yourself - IMGUI_API ImGuiID GetID(const char* str_id_begin, const char* str_id_end); + IMGUI_API ImGuiID GetID(const char* str_id_begin, const char* str_id_end = NULL); IMGUI_API ImGuiID GetID(const void* ptr_id); IMGUI_API ImGuiID GetID(int int_id); // Widgets: Text // - Note that all functions taking format strings in the API may be passed ("%s", text) or ("%.*s", text_len, text): which will automatically bypass the formatter. - IMGUI_API void TextUnformatted(const char* text, const char* text_end = NULL); // raw text without formatting. Practically equivalent to 'Text("%s", text)' but doesn't require null terminated string if 'text_end' is specified. + // FIXME-IMSTR: Functions taking format should use ImStrv. It will however break the IM_FMTARGS() macros. + IMGUI_API void TextUnformatted(ImStrv text); // raw text without formatting. Practically equivalent to 'Text("%s", text)' but doesn't require null terminated string if 'text_end' is specified. + inline void TextUnformatted(const char* text, const char* text_end) { TextUnformatted(ImStrv(text, text_end)); } IMGUI_API void Text(const char* fmt, ...) IM_FMTARGS(1); // formatted text IMGUI_API void TextV(const char* fmt, va_list args) IM_FMTLIST(1); IMGUI_API void TextColored(const ImVec4& col, const char* fmt, ...) IM_FMTARGS(2); // shortcut for PushStyleColor(ImGuiCol_Text, col); Text(fmt, ...); PopStyleColor(); @@ -645,15 +667,15 @@ namespace ImGui // Widgets: Main // - Most widgets return true when the value has been changed or when pressed/selected // - You may also use one of the many IsItemXXX functions (e.g. IsItemActive, IsItemHovered, etc.) to query widget state. - IMGUI_API bool Button(const ImStrv label, const ImVec2& size = ImVec2(0, 0)); // button - IMGUI_API bool SmallButton(ImStrv label); // button with (FramePadding.y == 0) to easily embed within text + IMGUI_API bool Button(ImStrv label, const ImVec2& size = ImVec2(0, 0)); // button + IMGUI_API bool SmallButton(ImStrv label); // button with (FramePadding.y == 0) to easily embed within text IMGUI_API bool InvisibleButton(ImStrv str_id, const ImVec2& size, ImGuiButtonFlags flags = 0); // flexible button behavior without the visuals, frequently useful to build custom behaviors using the public api (along with IsItemActive, IsItemHovered, etc.) IMGUI_API bool ArrowButton(ImStrv str_id, ImGuiDir dir); // square button with an arrow shape IMGUI_API bool Checkbox(ImStrv label, bool* v); IMGUI_API bool CheckboxFlags(ImStrv label, int* flags, int flags_value); IMGUI_API bool CheckboxFlags(ImStrv label, unsigned int* flags, unsigned int flags_value); - IMGUI_API bool RadioButton(ImStrv label, bool active); // use with e.g. if (RadioButton("one", my_value==1)) { my_value = 1; } - IMGUI_API bool RadioButton(ImStrv label, int* v, int v_button); // shortcut to handle the above pattern when value is an integer + IMGUI_API bool RadioButton(ImStrv label, bool active); // use with e.g. if (RadioButton("one", my_value==1)) { my_value = 1; } + IMGUI_API bool RadioButton(ImStrv label, int* v, int v_button); // shortcut to handle the above pattern when value is an integer IMGUI_API void ProgressBar(float fraction, const ImVec2& size_arg = ImVec2(-FLT_MIN, 0), ImStrv overlay = NULL); IMGUI_API void Bullet(); // draw a small circle + keep the cursor on the same line. advance cursor x position by GetTreeNodeToLabelSpacing(), same distance that TreeNode() uses IMGUI_API bool TextLink(ImStrv label); // hyperlink text button, return true when clicked @@ -1064,7 +1086,8 @@ namespace ImGui IMGUI_API ImGuiStorage* GetStateStorage(); // Text Utilities - IMGUI_API ImVec2 CalcTextSize(const char* text, const char* text_end = NULL, bool hide_text_after_double_hash = false, float wrap_width = -1.0f); + IMGUI_API ImVec2 CalcTextSize(ImStrv text, bool hide_text_after_double_hash = false, float wrap_width = -1.0f); + inline ImVec2 CalcTextSize(const char* text, const char* text_end, bool hide_text_after_double_hash = false, float wrap_width = -1.0f) { return CalcTextSize(ImStrv(text, text_end), hide_text_after_double_hash, wrap_width); } // Color Utilities IMGUI_API ImVec4 ColorConvertU32ToFloat4(ImU32 in); @@ -1148,7 +1171,7 @@ namespace ImGui // - Set io.IniFilename to NULL to load/save manually. Read io.WantSaveIniSettings description about handling .ini saving manually. // - Important: default value "imgui.ini" is relative to current working dir! Most apps will want to lock this to an absolute path (e.g. same path as executables). IMGUI_API void LoadIniSettingsFromDisk(ImStrv ini_filename); // call after CreateContext() and before the first call to NewFrame(). NewFrame() automatically calls LoadIniSettingsFromDisk(io.IniFilename). - IMGUI_API void LoadIniSettingsFromMemory(ImStrv ini_data, size_t ini_size= 0); // call after CreateContext() and before the first call to NewFrame() to provide .ini data from your own data source. + IMGUI_API void LoadIniSettingsFromMemory(ImStrv ini_data); // call after CreateContext() and before the first call to NewFrame() to provide .ini data from your own data source. IMGUI_API void SaveIniSettingsToDisk(ImStrv ini_filename); // this is automatically called (if io.IniFilename is not empty) a few seconds after any modification that should be reflected in the .ini file (and also by DestroyContext). IMGUI_API const char* SaveIniSettingsToMemory(size_t* out_ini_size = NULL); // return a zero-terminated string with the .ini data which you can save by your own mean. call when io.WantSaveIniSettings is set, then save data by your own mean and clear io.WantSaveIniSettings. @@ -2736,8 +2759,9 @@ struct ImGuiInputTextCallbackData // Use those function to benefit from the CallbackResize behaviors. Calling those function reset the selection. IMGUI_API ImGuiInputTextCallbackData(); IMGUI_API void DeleteChars(int pos, int bytes_count); - IMGUI_API void InsertChars(int pos, const char* text, const char* text_end = NULL); - void SelectAll() { SelectionStart = 0; CursorPos = SelectionEnd = BufTextLen; } + IMGUI_API void InsertChars(int pos, ImStrv text); + inline void InsertChars(int pos, const char* text, const char* text_end) { InsertChars(pos, ImStrv(text, text_end)); } + void SelectAll() { SelectionStart = 0; SelectionEnd = BufTextLen; } void SetSelection(int s, int e) { IM_ASSERT(s >= 0 && s <= BufTextLen); IM_ASSERT(e >= 0 && e <= BufTextLen); SelectionStart = s; CursorPos = SelectionEnd = e; } void ClearSelection() { SelectionStart = SelectionEnd = BufTextLen; } bool HasSelection() const { return SelectionStart != SelectionEnd; } @@ -2770,7 +2794,7 @@ struct ImGuiPayload ImGuiPayload() { Clear(); } void Clear() { SourceId = SourceParentId = 0; Data = NULL; DataSize = 0; memset(DataType, 0, sizeof(DataType)); DataFrameCount = -1; Preview = Delivery = false; } - bool IsDataType(ImStrv type) const { return DataFrameCount != -1 && strcmp(type, DataType) == 0; } + bool IsDataType(ImStrv type) const { size_t len = type.length(); return DataFrameCount != -1 && memcmp(DataType, type.Begin, len) == 0 && DataType[len] == 0; } bool IsPreview() const { return Preview; } bool IsDelivery() const { return Delivery; } }; @@ -2801,7 +2825,7 @@ struct ImGuiTextFilterItem; struct ImGuiTextFilter { IMGUI_API ImGuiTextFilter(ImStrv default_filter = ""); - IMGUI_API bool PassFilter(const char* text, const char* text_end = NULL) const; + IMGUI_API bool PassFilter(ImStrv label) const; IMGUI_API void Build(); // Update internal data when filter changes inline void Clear() { InputBuf[0] = 0; Build(); } // Clear filter inline bool IsActive() const { return _Items.Size != 0; } // Useful if you need e.g. an alternative code-path when there are no filters @@ -2810,7 +2834,8 @@ struct ImGuiTextFilter IMGUI_API bool Draw(ImStrv label = "Filter"); IMGUI_API bool DrawWithHint(ImStrv label = "Filter", ImStrv hint = "incl -excl"); #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - inline bool Draw(ImStrv label, float width) { if (width != 0.0f) ImGui::SetNextItemWidth(width); return Draw(label); } + inline bool Draw(ImStrv label, float width) { if (width != 0.0f) ImGui::SetNextItemWidth(width); return Draw(label); } + inline bool PassFilter(const char* text, const char* text_end = NULL) const { return PassFilter(ImStrv(text, text_end)); } #endif // Members @@ -2836,7 +2861,8 @@ struct ImGuiTextBuffer void resize(int size) { if (Buf.Size > size) Buf.Data[size] = 0; Buf.resize(size ? size + 1 : 0, 0); } // Similar to resize(0) on ImVector: empty string but don't free buffer. void reserve(int capacity) { Buf.reserve(capacity); } const char* c_str() const { return Buf.Data ? Buf.Data : EmptyString; } - IMGUI_API void append(const char* str, const char* str_end = NULL); + IMGUI_API void append(ImStrv str); + inline void append(const char* str, const char* str_end) { append(ImStrv(str, str_end)); } IMGUI_API void appendf(const char* fmt, ...) IM_FMTARGS(2); IMGUI_API void appendfv(const char* fmt, va_list args) IM_FMTLIST(2); }; @@ -3471,8 +3497,10 @@ struct ImDrawList IMGUI_API void AddNgonFilled(const ImVec2& center, float radius, ImU32 col, int num_segments); IMGUI_API void AddEllipse(const ImVec2& center, const ImVec2& radius, ImU32 col, float rot = 0.0f, int num_segments = 0, float thickness = 1.0f, ImDrawFlags flags = 0); IMGUI_API void AddEllipseFilled(const ImVec2& center, const ImVec2& radius, ImU32 col, float rot = 0.0f, int num_segments = 0); - IMGUI_API void AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL); - IMGUI_API void AddText(ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL); + IMGUI_API void AddText(const ImVec2& pos, ImU32 col, ImStrv text); + inline void AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end) { AddText(NULL, 0.0f, pos, col, ImStrv(text_begin, text_end)); } + IMGUI_API void AddText(ImFont* font, float font_size, const ImVec2& pos, ImU32 col, ImStrv text, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL); + inline void AddText(ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL) { AddText(font, font_size, pos, col, ImStrv(text_begin, text_end), wrap_width, cpu_fine_clip_rect); } IMGUI_API void AddBezierCubic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments = 0, ImDrawFlags flags = 0); // Cubic Bezier (4 control points) IMGUI_API void AddBezierQuadratic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col, float thickness, int num_segments = 0, ImDrawFlags flags = 0); // Quadratic Bezier (3 control points) @@ -3772,7 +3800,8 @@ struct ImFontGlyphRangesBuilder inline bool GetBit(size_t n) const { int off = (int)(n >> 5); ImU32 mask = 1u << (n & 31); return (UsedChars[off] & mask) != 0; } // Get bit n in the array inline void SetBit(size_t n) { int off = (int)(n >> 5); ImU32 mask = 1u << (n & 31); UsedChars[off] |= mask; } // Set bit n in the array inline void AddChar(ImWchar c) { SetBit(c); } // Add character - IMGUI_API void AddText(const char* text, const char* text_end = NULL); // Add string (each character of the UTF-8 string are added) + IMGUI_API void AddText(ImStrv text); // Add string (each character of the UTF-8 string are added) + inline void AddText(const char* text, const char* text_end = NULL) { AddText(ImStrv(text, text_end)); } IMGUI_API void AddRanges(const ImWchar* ranges); // Add ranges, e.g. builder.AddRanges(ImFontAtlas::GetGlyphRangesDefault()) to force add all of ASCII/Latin+Ext IMGUI_API void BuildRanges(ImVector* out_ranges); // Output new ranges }; @@ -4058,12 +4087,16 @@ struct ImFont // 'max_width' stops rendering after a certain width (could be turned into a 2d size). FLT_MAX to disable. // 'wrap_width' enable automatic word-wrapping across multiple lines to fit into given width. 0.0f to disable. IMGUI_API ImFontBaked* GetFontBaked(float font_size, float density = -1.0f); // Get or create baked data for given size - IMGUI_API ImVec2 CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end = NULL, const char** out_remaining = NULL); - IMGUI_API const char* CalcWordWrapPosition(float size, const char* text, const char* text_end, float wrap_width); IMGUI_API void RenderChar(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, ImWchar c, const ImVec4* cpu_fine_clip = NULL); - IMGUI_API void RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width = 0.0f, ImDrawTextFlags flags = 0); + IMGUI_API void RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, const ImVec4& clip_rect, ImStrv text, float wrap_width = 0.0f, ImDrawTextFlags flags = 0); + inline void RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width = 0.0f, ImDrawTextFlags flags = 0) { RenderText(draw_list, size, pos, col, clip_rect, ImStrv(text_begin, text_end), wrap_width, flags); } + IMGUI_API ImVec2 CalcTextSizeA(float size, float max_width, float wrap_width, ImStrv text, const char** remaining = NULL); // utf8 + IMGUI_API const char* CalcWordWrapPosition(float scale, ImStrv text, float wrap_width); + #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - inline const char* CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) { return CalcWordWrapPosition(LegacySize * scale, text, text_end, wrap_width); } // Obsoleted old name in 1.92.0. Note how `scale` was to `size`. + inline ImVec2 CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end, const char** remaining = NULL) { return CalcTextSizeA(size, max_width, wrap_width, ImStrv(text_begin, text_end), remaining); } + inline const char* CalcWordWrapPosition(float size, const char* text, const char* text_end, float wrap_width) { return CalcWordWrapPosition(size, ImStrv(text, text_end), wrap_width); } + inline const char* CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) { return CalcWordWrapPosition(LegacySize * scale, ImStrv(text, text_end), wrap_width); } // Obsoleted old name in 1.92.0. Note how `scale` was to `size`. #endif // [Internal] Don't use! diff --git a/imgui_demo.cpp b/imgui_demo.cpp index b1ac4d9e6..504cc5d62 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -5482,7 +5482,7 @@ static void DemoWindowLayout() case 2: ImVec4 clip_rect(p0.x, p0.y, p1.x, p1.y); // AddText() takes a ImVec4* here so let's convert. draw_list->AddRectFilled(p0, p1, IM_COL32(90, 90, 120, 255)); - draw_list->AddText(ImGui::GetFont(), ImGui::GetFontSize(), text_pos, IM_COL32_WHITE, text_str, NULL, 0.0f, &clip_rect); + draw_list->AddText(ImGui::GetFont(), ImGui::GetFontSize(), text_pos, IM_COL32_WHITE, text_str, 0.0f, &clip_rect); break; } } @@ -9490,7 +9490,7 @@ struct ExampleAppConsole if (match_len > 0) { data->DeleteChars((int)(word_start - data->Buf), (int)(word_end - word_start)); - data->InsertChars(data->CursorPos, candidates[0], candidates[0] + match_len); + data->InsertChars(data->CursorPos, ImStrv(candidates[0], candidates[0] + match_len)); } // List matches @@ -9648,8 +9648,8 @@ struct ExampleAppLog { const char* line_start = buf + LineOffsets[line_no]; const char* line_end = (line_no + 1 < LineOffsets.Size) ? (buf + LineOffsets[line_no + 1] - 1) : buf_end; - if (Filter.PassFilter(line_start, line_end)) - ImGui::TextUnformatted(line_start, line_end); + if (Filter.PassFilter(ImStrv(line_start, line_end))) + ImGui::TextUnformatted(ImStrv(line_start, line_end)); } } else @@ -9675,7 +9675,7 @@ struct ExampleAppLog { const char* line_start = buf + LineOffsets[line_no]; const char* line_end = (line_no + 1 < LineOffsets.Size) ? (buf + LineOffsets[line_no + 1] - 1) : buf_end; - ImGui::TextUnformatted(line_start, line_end); + ImGui::TextUnformatted(ImStrv(line_start, line_end)); } } clipper.End(); @@ -10075,7 +10075,7 @@ static void ShowExampleAppLongText(bool* p_open) { case 0: // Single call to TextUnformatted() with a big buffer - ImGui::TextUnformatted(log.begin(), log.end()); + ImGui::TextUnformatted(ImStrv(log.begin(), log.end())); break; case 1: { diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 3bddfabe8..84f61e426 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2947,15 +2947,14 @@ void ImDrawList::AddBezierQuadratic(const ImVec2& p1, const ImVec2& p2, const Im PathStroke(col, thickness, flags); } -void ImDrawList::AddText(ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end, float wrap_width, const ImVec4* cpu_fine_clip_rect) +void ImDrawList::AddText(ImFont* font, float font_size, const ImVec2& pos, ImU32 col, ImStrv text, float wrap_width, const ImVec4* cpu_fine_clip_rect) { if ((col & IM_COL32_A_MASK) == 0) return; // Accept null ranges - if (text_begin == text_end || text_begin[0] == 0) + if (text.Begin == text.End) return; - // No need to strlen() here: font->RenderText() will do it and may early out. // Pull default font/size from the shared ImDrawListSharedData instance if (font == NULL) @@ -2971,12 +2970,12 @@ void ImDrawList::AddText(ImFont* font, float font_size, const ImVec2& pos, ImU32 clip_rect.z = ImMin(clip_rect.z, cpu_fine_clip_rect->z); clip_rect.w = ImMin(clip_rect.w, cpu_fine_clip_rect->w); } - font->RenderText(this, font_size, pos, col, clip_rect, text_begin, text_end, wrap_width, (cpu_fine_clip_rect != NULL) ? ImDrawTextFlags_CpuFineClip : ImDrawTextFlags_None); + font->RenderText(this, font_size, pos, col, clip_rect, text, wrap_width, (cpu_fine_clip_rect != NULL) ? ImDrawTextFlags_CpuFineClip : ImDrawTextFlags_None); } -void ImDrawList::AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end) +void ImDrawList::AddText(const ImVec2& pos, ImU32 col, ImStrv text) { - AddText(_Data->Font, _Data->FontSize, pos, col, text_begin, text_end); + AddText(_Data->Font, _Data->FontSize, pos, col, text); } void ImDrawList::AddImage(ImTextureRef tex_ref, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col) @@ -4373,11 +4372,13 @@ static unsigned int stb_decompress(unsigned char* output, const unsigned char* i static unsigned int Decode85Byte(char c) { return c >= '\\' ? c-36 : c-35; } static void Decode85(ImStrv src, unsigned char* dst) { - while (*src) + const char* p = src.Begin; + const char* p_end = src.End; + while (p < p_end) { - unsigned int tmp = Decode85Byte(src[0]) + 85 * (Decode85Byte(src[1]) + 85 * (Decode85Byte(src[2]) + 85 * (Decode85Byte(src[3]) + 85 * Decode85Byte(src[4])))); + unsigned int tmp = Decode85Byte(p[0]) + 85 * (Decode85Byte(p[1]) + 85 * (Decode85Byte(p[2]) + 85 * (Decode85Byte(p[3]) + 85 * Decode85Byte(p[4])))); dst[0] = ((tmp >> 0) & 0xFF); dst[1] = ((tmp >> 8) & 0xFF); dst[2] = ((tmp >> 16) & 0xFF); dst[3] = ((tmp >> 24) & 0xFF); // We can't assume little-endianness. - src += 5; + p += 5; dst += 4; } } @@ -4484,8 +4485,9 @@ ImFont* ImFontAtlas::AddFontFromFileTTF(ImStrv filename, float size_pixels, cons { // Store a short copy of filename into the font name for convenience const char* p; - for (p = filename + ImStrlen(filename); p > filename && p[-1] != '/' && p[-1] != '\\'; p--) {} - ImFormatString(font_cfg.Name, IM_COUNTOF(font_cfg.Name), "%s", p); + for (p = filename.End; p > filename.Begin && p[-1] != '/' && p[-1] != '\\'; p--) {} + filename.Begin = p; + ImFormatString(font_cfg.Name, IM_COUNTOF(font_cfg.Name), "%.*s", (int)filename.length(), filename.Begin); } return AddFontFromMemoryTTF(data, (int)data_size, size_pixels, &font_cfg, glyph_ranges); } @@ -4519,7 +4521,7 @@ ImFont* ImFontAtlas::AddFontFromMemoryCompressedTTF(const void* compressed_ttf_d ImFont* ImFontAtlas::AddFontFromMemoryCompressedBase85TTF(ImStrv compressed_ttf_data_base85, float size_pixels, const ImFontConfig* font_cfg, const ImWchar* glyph_ranges) { - int compressed_ttf_size = (((int)ImStrlen(compressed_ttf_data_base85) + 4) / 5) * 4; + int compressed_ttf_size = (((int)compressed_ttf_data_base85.length() + 4) / 5) * 4; void* compressed_ttf = IM_ALLOC((size_t)compressed_ttf_size); Decode85(compressed_ttf_data_base85, (unsigned char*)compressed_ttf); ImFont* font = AddFontFromMemoryCompressedTTF(compressed_ttf, compressed_ttf_size, size_pixels, font_cfg, glyph_ranges); @@ -6676,15 +6678,13 @@ const ImWchar* ImFontAtlas::GetGlyphRangesVietnamese() // [SECTION] ImFontGlyphRangesBuilder //----------------------------------------------------------------------------- -void ImFontGlyphRangesBuilder::AddText(const char* text, const char* text_end) +void ImFontGlyphRangesBuilder::AddText(ImStrv text) { - if (text_end == NULL) - text_end = text + strlen(text); - while (text < text_end) + while (text.Begin < text.End) { unsigned int c = 0; - int c_len = ImTextCharFromUtf8(&c, text, text_end); - text += c_len; + int c_len = ImTextCharFromUtf8(&c, text.Begin, text.End); + text.Begin += c_len; if (c_len == 0) break; AddChar((ImWchar)c); @@ -7071,7 +7071,7 @@ void ImTextInitClassifiers() // Simple word-wrapping for English, not full-featured. Please submit failing cases! // This will return the next location to wrap from. If no wrapping if necessary, this will fast-forward to e.g. text_end. // Refer to imgui_test_suite's "drawlist_text_wordwrap_1" for tests. -const char* ImFontCalcWordWrapPositionEx(ImFont* font, float size, const char* text, const char* text_end, float wrap_width, ImDrawTextFlags flags) +const char* ImFontCalcWordWrapPositionEx(ImFont* font, float size, const char* text_begin, const char* text_end, float wrap_width, ImDrawTextFlags flags) { // For references, possible wrap point marked with ^ // "aaa bbb, ccc,ddd. eee fff. ggg!" @@ -7090,7 +7090,7 @@ const char* ImFontCalcWordWrapPositionEx(ImFont* font, float size, const char* t float blank_width = 0.0f; wrap_width /= scale; // We work with unscaled widths to avoid scaling every characters - const char* s = text; + const char* s = text_begin; IM_ASSERT(text_end != NULL); int prev_type = ImWcharClass_Other; @@ -7181,30 +7181,29 @@ const char* ImFontCalcWordWrapPositionEx(ImFont* font, float size, const char* t // Wrap_width is too small to fit anything. Force displaying 1 character to minimize the height discontinuity. // +1 may not be a character start point in UTF-8 but it's ok because caller loops use (text >= word_wrap_eol). - if (s == text && text < text_end) + if (s == text_begin && text_begin < text_end) return s + ImTextCountUtf8BytesFromChar(s, text_end); return s; } -const char* ImFont::CalcWordWrapPosition(float size, const char* text, const char* text_end, float wrap_width) +const char* ImFont::CalcWordWrapPosition(float size, ImStrv text, float wrap_width) { - return ImFontCalcWordWrapPositionEx(this, size, text, text_end, wrap_width, ImDrawTextFlags_None); + return ImFontCalcWordWrapPositionEx(this, size, text.Begin, text.End, wrap_width, ImDrawTextFlags_None); } ImVec2 ImFontCalcTextSizeEx(ImFont* font, float size, float max_width, float wrap_width, const char* text_begin, const char* text_end_display, const char* text_end, const char** out_remaining, ImVec2* out_offset, ImDrawTextFlags flags) { - if (!text_end) - text_end = text_begin + ImStrlen(text_begin); // FIXME-OPT: Need to avoid this. - if (!text_end_display) - text_end_display = text_end; - ImFontBaked* baked = font->GetFontBaked(size); + const float line_height = size; const float scale = line_height / baked->Size; ImVec2 text_size = ImVec2(0, 0); float line_width = 0.0f; + if (!text_end_display) + text_end_display = text_end; + const bool word_wrap_enabled = (wrap_width > 0.0f); const char* word_wrap_eol = NULL; @@ -7282,9 +7281,9 @@ ImVec2 ImFontCalcTextSizeEx(ImFont* font, float size, float max_width, float wra return text_size; } -ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end, const char** out_remaining) +ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, ImStrv text, const char** out_remaining) { - return ImFontCalcTextSizeEx(this, size, max_width, wrap_width, text_begin, text_end, text_end, out_remaining, NULL, ImDrawTextFlags_None); + return ImFontCalcTextSizeEx(this, size, max_width, wrap_width, text.Begin, text.End, text.End, out_remaining, NULL, ImDrawTextFlags_None); } // Note: as with every ImDrawList drawing function, this expects that the font atlas texture is bound. @@ -7333,7 +7332,7 @@ void ImFont::RenderChar(ImDrawList* draw_list, float size, const ImVec2& pos, Im // Note: as with every ImDrawList drawing function, this expects that the font atlas texture is bound. // DO NOT CALL DIRECTLY THIS WILL CHANGE WILDLY IN 2026. Use ImDrawList::AddText(). -void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width, ImDrawTextFlags flags) +void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, const ImVec4& clip_rect, ImStrv text, float wrap_width, ImDrawTextFlags flags) { begin: // Align to be pixel perfect @@ -7348,9 +7347,6 @@ begin: y = IM_TRUNC(y); } - if (!text_end) - text_end = text_begin + ImStrlen(text_begin); // ImGui:: functions generally already provides a valid text_end, so this is merely to handle direct calls. - const float line_height = size; ImFontBaked* baked = GetFontBaked(size); @@ -7359,7 +7355,8 @@ begin: const bool word_wrap_enabled = (wrap_width > 0.0f); // Fast-forward to first visible line - const char* s = text_begin; + const char* s = text.Begin; + const char* text_end = text.End; if (y + line_height < clip_rect.y) while (y + line_height < clip_rect.y && s < text_end) { @@ -7374,7 +7371,7 @@ begin: } else { - s = line_end ? line_end + 1 : text_end; + s = line_end ? line_end + 1 : text.End; } y += line_height; } diff --git a/imgui_internal.h b/imgui_internal.h index 7c8aca3ad..7322fb0f0 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -374,8 +374,9 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer // Helpers: Hashing IMGUI_API ImGuiID ImHashData(const void* data, size_t data_size, ImGuiID seed = 0); -IMGUI_API ImGuiID ImHashStr(const char* data, size_t data_size = 0, ImGuiID seed = 0); -IMGUI_API const char* ImHashSkipUncontributingPrefix(const char* label); +IMGUI_API ImGuiID ImHashStr(ImStrv str, ImGuiID seed = 0); +static inline ImGuiID ImHashStr(const char* data, size_t data_size = 0, ImGuiID seed = 0) { return ImHashStr(ImStrv(data, data_size ? data + data_size : NULL), seed); } +IMGUI_API const char* ImHashSkipUncontributingPrefix(ImStrv label); // Helpers: Sorting #ifndef ImQsort @@ -394,20 +395,26 @@ inline unsigned int ImCountSetBits(unsigned int v) { unsigned int count // Helpers: String #define ImStrlen strlen #define ImMemchr memchr +IMGUI_API int ImStrcmp(ImStrv str1, ImStrv str2); IMGUI_API int ImStricmp(const char* str1, const char* str2); // Case insensitive compare. IMGUI_API int ImStrnicmp(const char* str1, const char* str2, size_t count); // Case insensitive compare to a certain count. -IMGUI_API void ImStrncpy(char* dst, const char* src, size_t count); // Copy to a certain count and always zero terminate (strncpy doesn't). -IMGUI_API char* ImStrdup(const char* str); // Duplicate a string. +IMGUI_API void ImStrncpy(char* dst, ImStrv src, size_t count); // Copy to a certain count and always zero terminate (strncpy doesn't). +IMGUI_API void ImStrncpy(char* dst, const char* src, size_t count); +IMGUI_API char* ImStrdup(ImStrv str); // Duplicate a string. +IMGUI_API char* ImStrdup(const char* str); +IMGUI_API char* ImStrdupcpy(char* dst, size_t* p_dst_size, ImStrv str); // Copy in provided buffer, recreate buffer if needed. +IMGUI_API char* ImStrdupcpy(char* dst, size_t* p_dst_size, const char* str); IMGUI_API void* ImMemdup(const void* src, size_t size); // Duplicate a chunk of memory. -IMGUI_API char* ImStrdupcpy(char* dst, size_t* p_dst_size, const char* str); // Copy in provided buffer, recreate buffer if needed. IMGUI_API const char* ImStrchrRange(const char* str_begin, const char* str_end, char c); // Find first occurrence of 'c' in string range. IMGUI_API const char* ImStreolRange(const char* str, const char* str_end); // End end-of-line -IMGUI_API const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end); // Find a substring in a string range. +IMGUI_API const char* ImStrstr(ImStrv haystack, ImStrv needle); // Find a substring in a string range. +IMGUI_API const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_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 char* ImStrbol(const char* buf_mid_line, const char* buf_begin); // Find beginning-of-line IM_MSVC_RUNTIME_CHECKS_OFF +inline int ImStrcmp(const char* str1, const char* str2) { return strcmp(str1, str2); } inline char ImToUpper(char c) { return (c >= 'a' && c <= 'z') ? c & ~32 : c; } inline bool ImCharIsBlankA(char c) { return c == ' ' || c == '\t'; } inline bool ImCharIsBlankW(unsigned int c) { return c == ' ' || c == '\t' || c == 0x3000; } @@ -417,8 +424,8 @@ IM_MSVC_RUNTIME_CHECKS_RESTORE // Helpers: Formatting IMGUI_API int ImFormatString(char* buf, size_t buf_size, const char* fmt, ...) IM_FMTARGS(3); IMGUI_API int ImFormatStringV(char* buf, size_t buf_size, const char* fmt, va_list args) IM_FMTLIST(3); -IMGUI_API void ImFormatStringToTempBuffer(const char** out_buf, const char** out_buf_end, const char* fmt, ...) IM_FMTARGS(3); -IMGUI_API void ImFormatStringToTempBufferV(const char** out_buf, const char** out_buf_end, const char* fmt, va_list args) IM_FMTLIST(3); +IMGUI_API void ImFormatStringToTempBuffer(ImStrv* out_buf, const char* fmt, ...) IM_FMTARGS(2); +IMGUI_API void ImFormatStringToTempBufferV(ImStrv* out_buf, const char* fmt, va_list args) IM_FMTLIST(2); IMGUI_API const char* ImParseFormatFindStart(const char* format); IMGUI_API const char* ImParseFormatFindEnd(const char* format); IMGUI_API const char* ImParseFormatTrimDecorations(const char* format, char* buf, size_t buf_size); @@ -436,7 +443,7 @@ IMGUI_API int ImTextCountUtf8BytesFromChar(const char* in_text, const IMGUI_API int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end); // return number of bytes to express string in UTF-8 IMGUI_API const char* ImTextFindPreviousUtf8Codepoint(const char* in_text_start, const char* in_p); // return previous UTF-8 code-point. IMGUI_API const char* ImTextFindValidUtf8CodepointEnd(const char* in_text_start, const char* in_text_end, const char* in_p); // return previous UTF-8 code-point if 'in_p' is not the end of a valid one. -IMGUI_API int ImTextCountLines(const char* in_text, const char* in_text_end); // return number of lines taken by text. trailing carriage return doesn't count as an extra line. +IMGUI_API int ImTextCountLines(ImStrv in_text); // return number of lines taken by text. trailing carriage return doesn't count as an extra line. // Helpers: High-level text functions (DO NOT USE!!! THIS IS A MINIMAL SUBSET OF LARGER UPCOMING CHANGES) enum ImDrawTextFlags_ @@ -2893,7 +2900,9 @@ public: ImGuiWindow(ImGuiContext* context, ImStrv name); ~ImGuiWindow(); - ImGuiID GetID(const char* str, const char* str_end = NULL); + ImGuiID GetID(ImStrv str); + ImGuiID GetID(const char* str) { return GetID(ImStrv(str)); } + ImGuiID GetID(const char* str, const char* str_end) { return GetID(ImStrv(str, str_end)); } ImGuiID GetID(const void* ptr); ImGuiID GetID(int n); ImGuiID GetIDFromPos(const ImVec2& p_abs); @@ -3564,7 +3573,8 @@ namespace ImGui // Logging/Capture IMGUI_API void LogBegin(ImGuiLogFlags flags, int auto_open_depth); // -> BeginCapture() when we design v2 api, for now stay under the radar by using the old name. IMGUI_API void LogToBuffer(int auto_open_depth = -1); // Start logging/capturing to internal buffer - IMGUI_API void LogRenderedText(const ImVec2* ref_pos, const char* text, const char* text_end = NULL); + IMGUI_API void LogRenderedText(const ImVec2* ref_pos, ImStrv text); + inline void LogRenderedText(const ImVec2* ref_pos, const char* text, const char* text_end) { LogRenderedText(ref_pos, ImStrv(text, text_end)); } IMGUI_API void LogSetNextTextDecoration(const char* prefix, const char* suffix); // Childs @@ -3784,11 +3794,15 @@ namespace ImGui // Render helpers // AVOID USING OUTSIDE OF IMGUI.CPP! NOT FOR PUBLIC CONSUMPTION. THOSE FUNCTIONS ARE A MESS. THEIR SIGNATURE AND BEHAVIOR WILL CHANGE, THEY NEED TO BE REFACTORED INTO SOMETHING DECENT. // NB: All position are in absolute pixels coordinates (we are never using window coordinates internally) - IMGUI_API void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true); - IMGUI_API void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width); - IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL); - IMGUI_API void RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL); - IMGUI_API void RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float ellipsis_max_x, const char* text, const char* text_end, const ImVec2* text_size_if_known); + IMGUI_API void RenderText(ImVec2 pos, ImStrv text, bool hide_text_after_hash = true); + inline void RenderText(ImVec2 pos, const char* text, const char* text_end, bool hide_text_after_hash = true) { RenderText(pos, ImStrv(text, text_end), hide_text_after_hash); } + IMGUI_API void RenderTextWrapped(ImVec2 pos, ImStrv text, float wrap_width); + inline void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width) { RenderTextWrapped(pos, ImStrv(text, text_end), wrap_width); } + IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, ImStrv text, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL); + inline void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0,0), const ImRect* clip_rect = NULL) { RenderTextClipped(pos_min, pos_max, ImStrv(text, text_end), text_size_if_known, align, clip_rect); } + IMGUI_API void RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, ImStrv text, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL); + inline void RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL) { RenderTextClippedEx(draw_list, pos_min, pos_max, ImStrv(text, text_end), text_size_if_known, align, clip_rect); } + IMGUI_API void RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float ellipsis_max_x, ImStrv text, const ImVec2* text_size_if_known); IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool borders = true, float rounding = 0.0f); IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f); IMGUI_API void RenderColorComponentMarker(const ImRect& bb, ImU32 col, float rounding); @@ -3797,7 +3811,8 @@ namespace ImGui #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS inline void RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFlags flags = ImGuiNavRenderCursorFlags_None) { RenderNavCursor(bb, id, flags); } // Renamed in 1.91.4 #endif - IMGUI_API const char* FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text. + IMGUI_API const char* FindRenderedTextEnd(ImStrv text); // Find the optional ## from which we stop displaying text. + inline const char* FindRenderedTextEnd(const char* text, const char* text_end) { return FindRenderedTextEnd(ImStrv(text, text_end)); } IMGUI_API void RenderMouseCursor(ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow); // Render helpers (those functions don't access any ImGui state!) @@ -3810,16 +3825,17 @@ namespace ImGui IMGUI_API ImDrawFlags CalcRoundingFlagsForRectInRect(const ImRect& r_in, const ImRect& r_outer, float threshold); // Widgets: Text - IMGUI_API void TextEx(const char* text, const char* text_end = NULL, ImGuiTextFlags flags = 0); - IMGUI_API void TextAligned(float align_x, float width, const char* fmt, ...) IM_FMTARGS(3); // FIXME-WIP: Works but API is likely to be reworked. - IMGUI_API void TextAlignedV(float align_x, float width, const char* fmt, va_list args) IM_FMTLIST(3); + IMGUI_API void TextEx(ImStrv text, ImGuiTextFlags flags = 0); + inline void TextEx(const char* text, const char* text_end, ImGuiTextFlags flags = 0) { TextEx(ImStrv(text, text_end), flags); } + IMGUI_API void TextAligned(float align_x, float size_x, const char* fmt, ...); // FIXME-WIP: Works but API is likely to be reworked. + IMGUI_API void TextAlignedV(float align_x, float size_x, const char* fmt, va_list args); // Widgets IMGUI_API bool ButtonEx(ImStrv label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0); IMGUI_API bool ArrowButtonEx(ImStrv str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags = 0); IMGUI_API bool ImageButtonEx(ImGuiID id, ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags = 0); IMGUI_API void SeparatorEx(ImGuiSeparatorFlags flags, float thickness = 1.0f); - IMGUI_API void SeparatorTextEx(ImGuiID id, const char* label, const char* label_end, float extra_width); + IMGUI_API void SeparatorTextEx(ImGuiID id, ImStrv label, float extra_width); IMGUI_API bool CheckboxFlags(ImStrv label, ImS64* flags, ImS64 flags_value); IMGUI_API bool CheckboxFlags(ImStrv label, ImU64* flags, ImU64 flags_value); @@ -3841,7 +3857,7 @@ namespace ImGui IMGUI_API bool SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend = 0.0f, float hover_visibility_delay = 0.0f, ImU32 bg_col = 0); // Widgets: Tree Nodes - IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL); + IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, ImStrv label); IMGUI_API void TreeNodeDrawLineToChildNode(const ImVec2& target_pos); IMGUI_API void TreeNodeDrawLineToTreePop(const ImGuiTreeNodeStackData* data); IMGUI_API void TreePushOverrideID(ImGuiID id); @@ -3856,7 +3872,7 @@ namespace ImGui template IMGUI_API bool DragBehaviorT(ImGuiDataType data_type, T* v, float v_speed, T v_min, T v_max, const char* format, ImGuiSliderFlags flags); template IMGUI_API bool SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, T* v, T v_min, T v_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb); template IMGUI_API T RoundScalarWithFormatT(const char* format, ImGuiDataType data_type, T v); - template IMGUI_API bool CheckboxFlagsT(const char* label, T* flags, T flags_value); + template IMGUI_API bool CheckboxFlagsT(ImStrv label, T* flags, T flags_value); // Data type helpers IMGUI_API const ImGuiDataTypeInfo* DataTypeGetInfo(ImGuiDataType data_type); @@ -4171,7 +4187,7 @@ IMGUI_API bool ImFontAtlasGetMouseCursorTexData(ImFontAtlas* atlas, ImGuiMo #ifdef IMGUI_ENABLE_TEST_ENGINE extern void ImGuiTestEngineHook_ItemAdd(ImGuiContext* ctx, ImGuiID id, const ImRect& bb, const ImGuiLastItemData* item_data); // item_data may be NULL -extern void ImGuiTestEngineHook_ItemInfo(ImGuiContext* ctx, ImGuiID id, const char* label, ImGuiItemStatusFlags flags); +extern void ImGuiTestEngineHook_ItemInfo(ImGuiContext* ctx, ImGuiID id, ImStrv label, ImGuiItemStatusFlags flags); extern void ImGuiTestEngineHook_Log(ImGuiContext* ctx, const char* fmt, ...); extern const char* ImGuiTestEngine_FindItemDebugLabel(ImGuiContext* ctx, ImGuiID id); diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 1f2fc1ea7..4fda9eef9 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1744,12 +1744,14 @@ void ImGui::TableSetupColumn(ImStrv label, ImGuiTableColumnFlags flags, float in // Store name (append with zero-terminator in contiguous buffer) // FIXME: If we recorded the number of \n in names we could compute header row height ImS16 name_offset = -1; - if (label != NULL && label[0] != 0) + if (!label.empty()) { + char zero_terminator = 0; name_offset = (ImS16)table->ColumnsNames.size(); - table->ColumnsNames.append(label, label + ImStrlen(label) + 1); + table->ColumnsNames.append(label.Begin, label.End); + table->ColumnsNames.append(&zero_terminator, &zero_terminator + 1); } - const ImGuiID column_id = (label != NULL && label[0] != 0) ? ImHashStr(label) : 0; + const ImGuiID column_id = label ? ImHashStr(label) : 0; // When ID changed or a column moved: defer the request until layout where we will process full reconcile. const int column_idx = table->DeclColumnsCount++; @@ -3334,10 +3336,11 @@ void ImGui::TableHeader(ImStrv label) ImGuiTableColumn* column = &table->Columns[column_n]; // Label - if (label == NULL) + if (!label) label = ""; - const char* label_end = FindRenderedTextEnd(label); - ImVec2 label_size = CalcTextSize(label, label_end, false); + ImGuiID id = window->GetID(label); + ImStrv label_for_display(label.Begin, FindRenderedTextEnd(label)); + ImVec2 label_size = CalcTextSize(label_for_display, false); ImVec2 label_pos = window->DC.CursorPos; // If we already got a row height, there's use that. @@ -3369,7 +3372,6 @@ void ImGui::TableHeader(ImStrv label) column->ContentMaxXHeadersIdeal = ImMax(column->ContentMaxXHeadersIdeal, max_pos_x); // Keep header highlighted when context menu is open. - ImGuiID id = window->GetID(label); ImRect bb(cell_r.Min.x, cell_r.Min.y, cell_r.Max.x, ImMax(cell_r.Max.y, cell_r.Min.y + label_height + g.Style.CellPadding.y * 2.0f)); ItemSize(ImVec2(0.0f, label_height)); // Don't declare unclipped width, it'll be fed ContentMaxPosHeadersIdeal if (!ItemAdd(bb, id)) @@ -3449,11 +3451,11 @@ void ImGui::TableHeader(ImStrv label) // Render clipped label. Clipping here ensure that in the majority of situations, all our header cells will // be merged into a single draw call. //window->DrawList->AddCircleFilled(ImVec2(ellipsis_max, label_pos.y), 40, IM_COL32_WHITE); - RenderTextEllipsis(window->DrawList, label_pos, ImVec2(ellipsis_max, bb.Max.y), ellipsis_max, label, label_end, &label_size); + RenderTextEllipsis(window->DrawList, label_pos, ImVec2(ellipsis_max, bb.Max.y), ellipsis_max, label_for_display, &label_size); const bool text_clipped = label_size.x > (ellipsis_max - label_pos.x); if (text_clipped && hovered && g.ActiveId == 0) - SetItemTooltip("%.*s", (int)(label_end - label), label); + SetItemTooltip("%.*s", (int)(label_for_display.End - label_for_display.Begin), label_for_display.Begin); // We don't use BeginPopupContextItem() because we want the popup to stay up even after the column is hidden if (IsPopupOpenRequestForItem(ImGuiPopupFlags_None, id)) @@ -3574,10 +3576,10 @@ void ImGui::TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label // Draw label // - First draw at an offset where RenderTextXXX() function won't meddle with applying current ClipRect, then transform to final offset. // - Handle multiple lines manually, as we want each lines to follow on the horizontal border, rather than see a whole block rotated. - const char* label_name = TableGetColumnName(table, column_n); - const char* label_name_end = FindRenderedTextEnd(label_name); + const char* label_name_s = TableGetColumnName(table, column_n); + ImStrv label_name(label_name_s, FindRenderedTextEnd(label_name_s)); const float line_off_step_x = (g.FontSize / -sin_a); - const int label_lines = ImTextCountLines(label_name, label_name_end); + const int label_lines = ImTextCountLines(label_name); // Left<>Right alignment float line_off_curr_x = flip_label ? (label_lines - 1) * line_off_step_x : 0.0f; @@ -3587,20 +3589,20 @@ void ImGui::TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label // Register header width column->ContentMaxXHeadersUsed = column->ContentMaxXHeadersIdeal = column->WorkMinX + ImCeil(label_lines * line_off_step_x - line_off_for_align_x); - while (label_name < label_name_end) + while (label_name.Begin < label_name.End) { - const char* label_name_eol = strchr(label_name, '\n'); + const char* label_name_eol = ImStrchrRange(label_name.Begin, label_name.End, '\n'); if (label_name_eol == NULL) - label_name_eol = label_name_end; + label_name_eol = label_name.End; // FIXME: Individual line clipping for right-most column is broken for negative angles. - ImVec2 label_size = CalcTextSize(label_name, label_name_eol); + ImVec2 label_size = CalcTextSize(ImStrv(label_name.Begin, label_name_eol)); float clip_width = max_label_width - padding.y; // Using padding.y*2.0f would be symmetrical but hide more text. float clip_height = ImMin(label_size.y, column->ClipRect.Max.x - column->WorkMinX - line_off_curr_x); ImRect clip_r(window->ClipRect.Min, window->ClipRect.Min + ImVec2(clip_width, clip_height)); int vtx_idx_begin = draw_list->_VtxCurrentIdx; PushStyleColor(ImGuiCol_Text, request->TextColor); - RenderTextEllipsis(draw_list, clip_r.Min, clip_r.Max, clip_r.Max.x, label_name, label_name_eol, &label_size); + RenderTextEllipsis(draw_list, clip_r.Min, clip_r.Max, clip_r.Max.x, ImStrv(label_name.Begin, label_name_eol), &label_size); PopStyleColor(); int vtx_idx_end = draw_list->_VtxCurrentIdx; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index cd60c15cb..1fcabad93 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -158,30 +158,24 @@ static ImVec2 InputTextCalcTextSize(ImGuiContext* ctx, const char* text_begin, // - BulletTextV() //------------------------------------------------------------------------- -void ImGui::TextEx(const char* text, const char* text_end, ImGuiTextFlags flags) +void ImGui::TextEx(ImStrv text, ImGuiTextFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return; ImGuiContext& g = *GImGui; - // Accept null ranges - if (text == text_end) - text = text_end = ""; - - // Calculate length - const char* text_begin = text; - if (text_end == NULL) - text_end = text + ImStrlen(text); // FIXME-OPT + const char* text_begin = text.Begin; + const char* text_end = text.End; const ImVec2 text_pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset); const float wrap_pos_x = window->DC.TextWrapPos; const bool wrap_enabled = (wrap_pos_x >= 0.0f); - if (text_end - text <= 2000 || wrap_enabled) + if (text_end - text_begin <= 2000 || wrap_enabled) { // Common case const float wrap_width = wrap_enabled ? CalcWrapWidthForPos(window->DC.CursorPos, wrap_pos_x) : 0.0f; - const ImVec2 text_size = CalcTextSize(text_begin, text_end, false, wrap_width); + const ImVec2 text_size = CalcTextSize(text, false, wrap_width); ImRect bb(text_pos, text_pos + text_size); ItemSize(text_size, 0.0f); @@ -189,7 +183,7 @@ void ImGui::TextEx(const char* text, const char* text_end, ImGuiTextFlags flags) return; // Render (we don't hide text after ## in this end-user function) - RenderTextWrapped(bb.Min, text_begin, text_end, wrap_width); + RenderTextWrapped(bb.Min, text, wrap_width); } else { @@ -198,7 +192,7 @@ void ImGui::TextEx(const char* text, const char* text_end, ImGuiTextFlags flags) // - From this point we will only compute the width of lines that are visible. Optimization only available when word-wrapping is disabled. // - We also don't vertically center the text within the line full height, which is unlikely to matter because we are likely the biggest and only item on the line. // - We use memchr(), pay attention that well optimized versions of those str/mem functions are much faster than a casually written loop. - const char* line = text; + const char* line = text_begin; const float line_height = GetTextLineHeight(); ImVec2 text_size(0, 0); @@ -237,7 +231,7 @@ void ImGui::TextEx(const char* text, const char* text_end, ImGuiTextFlags flags) if (!line_end) line_end = text_end; text_size.x = ImMax(text_size.x, CalcTextSize(line, line_end).x); - RenderText(pos, line, line_end, false); + RenderText(pos, ImStrv(line, line_end), false); line = line_end + 1; line_rect.Min.y += line_height; line_rect.Max.y += line_height; @@ -268,9 +262,9 @@ void ImGui::TextEx(const char* text, const char* text_end, ImGuiTextFlags flags) // Note that all functions taking format strings in the API may be passed ("%s", text) or ("%.*s", text_len, text), // which will automatically bypass the formatter. -void ImGui::TextUnformatted(const char* text, const char* text_end) +void ImGui::TextUnformatted(ImStrv text) { - TextEx(text, text_end, ImGuiTextFlags_NoWidthForLargeClippedText); + TextEx(text, ImGuiTextFlags_NoWidthForLargeClippedText); } void ImGui::Text(const char* fmt, ...) @@ -287,9 +281,9 @@ void ImGui::TextV(const char* fmt, va_list args) if (window->SkipItems) return; - const char* text, *text_end; - ImFormatStringToTempBufferV(&text, &text_end, fmt, args); - TextEx(text, text_end, ImGuiTextFlags_NoWidthForLargeClippedText); + ImStrv text; + ImFormatStringToTempBufferV(&text, fmt, args); + TextEx(text, ImGuiTextFlags_NoWidthForLargeClippedText); } void ImGui::TextColored(const ImVec4& col, const char* fmt, ...) @@ -359,9 +353,9 @@ void ImGui::TextAlignedV(float align_x, float width, const char* fmt, va_list ar if (window->SkipItems) return; - const char* text, *text_end; - ImFormatStringToTempBufferV(&text, &text_end, fmt, args); - const ImVec2 text_size = CalcTextSize(text, text_end); + ImStrv text; + ImFormatStringToTempBufferV(&text, fmt, args); + const ImVec2 text_size = CalcTextSize(text); const ImVec2 size = CalcItemSize(ImVec2(width, 0.0f), 0.0f, text_size.y); ImVec2 pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset); @@ -378,10 +372,10 @@ void ImGui::TextAlignedV(float align_x, float width, const char* fmt, va_list ar if (align_x > 0.0f && text_size.x < size.x) pos.x += ImTrunc((size.x - text_size.x) * align_x); - RenderTextEllipsis(window->DrawList, pos, pos_max, pos_max.x, text, text_end, &text_size); + RenderTextEllipsis(window->DrawList, pos, pos_max, pos_max.x, text, &text_size); if (size.x < text_size.x && IsItemHovered(ImGuiHoveredFlags_NoNavOverride | ImGuiHoveredFlags_AllowWhenDisabled | ImGuiHoveredFlags_ForTooltip)) - SetTooltip("%.*s", (int)(text_end - text), text); + SetTooltip("%.*s", (int)(text.End - text.Begin), text.Begin); } void ImGui::LabelText(ImStrv label, const char* fmt, ...) @@ -403,12 +397,11 @@ void ImGui::LabelTextV(ImStrv label, const char* fmt, va_list args) const ImGuiStyle& style = g.Style; const float w = CalcItemWidth(); - const char* value_text_begin, *value_text_end; - ImFormatStringToTempBufferV(&value_text_begin, &value_text_end, fmt, args); - const ImVec2 value_size = CalcTextSize(value_text_begin, value_text_end, false); - const char* label_end = FindRenderedTextEnd(label); - const ImVec2 label_size = CalcTextSize(label, label_end, false); - + ImStrv value_text; + ImFormatStringToTempBufferV(&value_text, fmt, args); + const ImVec2 value_size = CalcTextSize(value_text, false); + const ImStrv label_for_display(label.Begin, FindRenderedTextEnd(label)); + const ImVec2 label_size = CalcTextSize(label_for_display, false); const ImVec2 pos = window->DC.CursorPos; const ImRect value_bb(pos, pos + ImVec2(w, value_size.y + style.FramePadding.y * 2)); const ImRect total_bb(pos, pos + ImVec2(w + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), ImMax(value_size.y, label_size.y) + style.FramePadding.y * 2)); @@ -417,9 +410,9 @@ void ImGui::LabelTextV(ImStrv label, const char* fmt, va_list args) return; // Render - RenderTextClipped(value_bb.Min + style.FramePadding, value_bb.Max, value_text_begin, value_text_end, &value_size, ImVec2(0.0f, 0.0f)); + RenderTextClipped(value_bb.Min + style.FramePadding, value_bb.Max, value_text, &value_size, ImVec2(0.0f, 0.0f)); if (label_size.x > 0.0f) - RenderText(ImVec2(value_bb.Max.x + style.ItemInnerSpacing.x, value_bb.Min.y + style.FramePadding.y), label, label_end, false); + RenderText(ImVec2(value_bb.Max.x + style.ItemInnerSpacing.x, value_bb.Min.y + style.FramePadding.y), label_for_display, false); } void ImGui::BulletText(const char* fmt, ...) @@ -440,9 +433,9 @@ void ImGui::BulletTextV(const char* fmt, va_list args) ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; - const char* text_begin, *text_end; - ImFormatStringToTempBufferV(&text_begin, &text_end, fmt, args); - const ImVec2 label_size = CalcTextSize(text_begin, text_end, false); + ImStrv text; + ImFormatStringToTempBufferV(&text, fmt, args); + const ImVec2 label_size = CalcTextSize(text, false); const ImVec2 total_size = ImVec2(g.FontSize + (label_size.x > 0.0f ? (label_size.x + style.FramePadding.x * 2) : 0.0f), label_size.y); // Empty text doesn't add padding ImVec2 pos = window->DC.CursorPos; pos.y += window->DC.CurrLineTextBaseOffset; @@ -454,7 +447,7 @@ void ImGui::BulletTextV(const char* fmt, va_list args) // Render ImU32 text_col = GetColorU32(ImGuiCol_Text); RenderBullet(window->DrawList, bb.Min + ImVec2(style.FramePadding.x + g.FontSize * 0.5f, g.FontSize * 0.5f), text_col); - RenderText(bb.Min + ImVec2(g.FontSize + style.FramePadding.x * 2, 0.0f), text_begin, text_end, false); + RenderText(bb.Min + ImVec2(g.FontSize + style.FramePadding.x * 2, 0.0f), text, false); } //------------------------------------------------------------------------- @@ -794,8 +787,8 @@ bool ImGui::ButtonEx(ImStrv label, const ImVec2& size_arg, ImGuiButtonFlags flag ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label); - const char* label_end = FindRenderedTextEnd(label); - const ImVec2 label_size = CalcTextSize(label, label_end, false); + const ImStrv label_for_display(label.Begin, FindRenderedTextEnd(label)); + const ImVec2 label_size = CalcTextSize(label_for_display, false); ImVec2 pos = window->DC.CursorPos; if ((flags & ImGuiButtonFlags_AlignTextBaseLine) && style.FramePadding.y < window->DC.CurrLineTextBaseOffset) // Try to vertically align buttons that are smaller/have no padding so that text baseline matches (bit hacky, since it shouldn't be a flag) @@ -817,7 +810,7 @@ bool ImGui::ButtonEx(ImStrv label, const ImVec2& size_arg, ImGuiButtonFlags flag if (g.LogEnabled) LogSetNextTextDecoration("[", "]"); - RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label, label_end, &label_size, style.ButtonTextAlign, &bb); + RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label_for_display, &label_size, style.ButtonTextAlign, &bb); // Automatically close popups //if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup)) @@ -1250,8 +1243,9 @@ bool ImGui::Checkbox(ImStrv label, bool* v) ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label); - const char* label_end = FindRenderedTextEnd(label); - const ImVec2 label_size = CalcTextSize(label, label_end, false); + + const ImStrv label_for_display(label.Begin, FindRenderedTextEnd(label)); + const ImVec2 label_size = CalcTextSize(label_for_display, false); const float square_sz = GetFrameHeight(); const ImVec2 pos = window->DC.CursorPos; @@ -1312,7 +1306,7 @@ bool ImGui::Checkbox(ImStrv label, bool* v) if (g.LogEnabled) LogRenderedText(&label_pos, mixed_value ? "[~]" : *v ? "[x]" : "[ ]"); if (is_visible && label_size.x > 0.0f) - RenderText(label_pos, label, label_end, false); + RenderText(label_pos, label_for_display, false); IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0)); return pressed; @@ -1374,8 +1368,9 @@ bool ImGui::RadioButton(ImStrv label, bool active) ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label); - const char* label_end = FindRenderedTextEnd(label); - const ImVec2 label_size = CalcTextSize(label, label_end, false); + + const ImStrv label_for_display(label.Begin, FindRenderedTextEnd(label)); + const ImVec2 label_size = CalcTextSize(label_for_display, false); const float square_sz = GetFrameHeight(); const ImVec2 pos = window->DC.CursorPos; @@ -1414,7 +1409,7 @@ bool ImGui::RadioButton(ImStrv label, bool active) if (g.LogEnabled) LogRenderedText(&label_pos, active ? "(x)" : "( )"); if (label_size.x > 0.0f) - RenderText(label_pos, label, label_end, false); + RenderText(label_pos, label_for_display, false); IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags); return pressed; @@ -1475,7 +1470,7 @@ void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, ImStrv overlay) // Default displaying the fraction as percentage string, but user can override it // Don't display text for indeterminate bars by default char overlay_buf[32]; - if (!is_indeterminate || overlay != NULL) + if (!is_indeterminate || overlay) { if (!overlay) { @@ -1483,11 +1478,11 @@ void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, ImStrv overlay) overlay = overlay_buf; } - ImVec2 overlay_size = CalcTextSize(overlay, NULL); + ImVec2 overlay_size = CalcTextSize(overlay); if (overlay_size.x > 0.0f) { float text_x = is_indeterminate ? (bb.Min.x + bb.Max.x - overlay_size.x) * 0.5f : fill_x1 + style.ItemSpacing.x; - RenderTextClipped(ImVec2(ImClamp(text_x, bb.Min.x, bb.Max.x - overlay_size.x - style.ItemInnerSpacing.x), bb.Min.y), bb.Max, overlay, NULL, &overlay_size, ImVec2(0.0f, 0.5f), &bb); + RenderTextClipped(ImVec2(ImClamp(text_x, bb.Min.x, bb.Max.x - overlay_size.x - style.ItemInnerSpacing.x), bb.Min.y), bb.Max, overlay, &overlay_size, ImVec2(0.0f, 0.5f), &bb); } } } @@ -1527,10 +1522,10 @@ bool ImGui::TextLink(ImStrv label) ImGuiContext& g = *GImGui; const ImGuiID id = window->GetID(label); - const char* label_end = FindRenderedTextEnd(label); + const ImStrv label_for_display(label.Begin, FindRenderedTextEnd(label)); ImVec2 pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset); - ImVec2 size = CalcTextSize(label, label_end, false); + ImVec2 size = CalcTextSize(label_for_display, false); ImRect bb(pos, pos + size); ItemSize(size, 0.0f); if (!ItemAdd(bb, id)) @@ -1564,7 +1559,7 @@ bool ImGui::TextLink(ImStrv label) window->DrawList->AddLineH(bb.Min.x, bb.Max.x, line_y, GetColorU32(line_colf), 1.0f * (float)(int)g.Style._MainScale); // FIXME-TEXT: Underline mode // FIXME-DPI PushStyleColor(ImGuiCol_Text, GetColorU32(text_colf)); - RenderText(bb.Min, label, label_end, false); + RenderText(bb.Min, label_for_display, false); PopStyleColor(); IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags); @@ -1574,12 +1569,17 @@ bool ImGui::TextLink(ImStrv label) bool ImGui::TextLinkOpenURL(ImStrv label, ImStrv url) { ImGuiContext& g = *GImGui; - if (url == NULL) - url = label; bool pressed = TextLink(label); + label.End = FindRenderedTextEnd(label.Begin); + if (!url) + url = label; if (pressed && g.PlatformIO.Platform_OpenInShellFn != NULL) - g.PlatformIO.Platform_OpenInShellFn(&g, url); - SetItemTooltip(LocalizeGetMsg(ImGuiLocKey_OpenLink_s), url); // It is more reassuring for user to _always_ display URL when it is the same as the label. + { + ImStrv url_zt; + ImFormatStringToTempBuffer(&url_zt, "%.*s", (int)url.length(), url.Begin); + g.PlatformIO.Platform_OpenInShellFn(&g, url_zt.Begin); + } + SetItemTooltip(LocalizeGetMsg(ImGuiLocKey_OpenLink_s), (int)url.length(), url.Begin); // It is more reassuring for user to _always_ display URL when it is the same as the label. if (BeginPopupContextItem()) { if (MenuItem(LocalizeGetMsg(ImGuiLocKey_CopyLink))) @@ -1737,13 +1737,13 @@ void ImGui::Separator() SeparatorEx(flags, ImMax(g.Style.SeparatorSize, 1.0f)); } -void ImGui::SeparatorTextEx(ImGuiID id, const char* label, const char* label_end, float extra_w) +void ImGui::SeparatorTextEx(ImGuiID id, ImStrv label, float extra_w) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImGuiStyle& style = g.Style; - const ImVec2 label_size = CalcTextSize(label, label_end, false); + const ImVec2 label_size = CalcTextSize(label, false); const ImVec2 pos = window->DC.CursorPos; const ImVec2 padding = style.SeparatorTextPadding; @@ -1776,7 +1776,7 @@ void ImGui::SeparatorTextEx(ImGuiID id, const char* label, const char* label_end window->DrawList->AddLineH(sep2_x1, sep2_x2, seps_y, separator_col, separator_thickness, ImDrawFlags_StrokeCenterBiased); if (g.LogEnabled) LogSetNextTextDecoration("---", NULL); - RenderTextEllipsis(window->DrawList, label_pos, ImVec2(bb.Max.x, bb.Max.y + style.ItemSpacing.y), bb.Max.x, label, label_end, &label_size); + RenderTextEllipsis(window->DrawList, label_pos, ImVec2(bb.Max.x, bb.Max.y + style.ItemSpacing.y), bb.Max.x, label, &label_size); } else { @@ -1799,7 +1799,7 @@ void ImGui::SeparatorText(ImStrv label) // - because of this we probably can't turn 'const char* label' into 'const char* fmt, ...' // Otherwise, we can decide that users wanting to drag this would layout a dedicated drag-item, // and then we can turn this into a format function. - SeparatorTextEx(0, label, FindRenderedTextEnd(label), 0.0f); + SeparatorTextEx(0, ImStrv(label.Begin, FindRenderedTextEnd(label)), 0.0f); } // Using 'hover_visibility_delay' allows us to hide the highlight and mouse cursor for a short time, which can be convenient to reduce visual noise. @@ -1954,9 +1954,9 @@ bool ImGui::BeginCombo(ImStrv label, ImStrv preview_value, ImGuiComboFlags flags IM_ASSERT((flags & ImGuiComboFlags_NoPreview) == 0); const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight(); - const char* label_end = FindRenderedTextEnd(label); - const ImVec2 label_size = CalcTextSize(label, label_end, false); - const float preview_width = ((flags & ImGuiComboFlags_WidthFitPreview) && (preview_value != NULL)) ? CalcTextSize(preview_value, NULL, false).x : 0.0f; + const ImStrv label_for_display(label.Begin, FindRenderedTextEnd(label)); + const ImVec2 label_size = CalcTextSize(label_for_display, false); + const float preview_width = ((flags & ImGuiComboFlags_WidthFitPreview) && preview_value) ? CalcTextSize(preview_value, false).x : 0.0f; const float w = (flags & ImGuiComboFlags_NoPreview) ? arrow_size : ((flags & ImGuiComboFlags_WidthFitPreview) ? (arrow_size + preview_width + style.FramePadding.x * 2.0f) : CalcItemWidth()); const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f)); const ImRect total_bb(bb.Min, bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); @@ -1995,14 +1995,14 @@ bool ImGui::BeginCombo(ImStrv label, ImStrv preview_value, ImGuiComboFlags flags g.ComboPreviewData.PreviewRect = (flags & ImGuiComboFlags_NoPreview) ? ImRect() : ImRect(bb.Min.x, bb.Min.y, value_x2, bb.Max.y); // Render preview and label - if (preview_value != NULL && !(flags & ImGuiComboFlags_NoPreview)) + if (!preview_value.empty() && !(flags & ImGuiComboFlags_NoPreview)) { if (g.LogEnabled) LogSetNextTextDecoration("{", "}"); - RenderTextClipped(bb.Min + style.FramePadding, ImVec2(value_x2, bb.Max.y), preview_value, NULL, NULL); + RenderTextClipped(bb.Min + style.FramePadding, ImVec2(value_x2, bb.Max.y), preview_value, NULL); } if (label_size.x > 0) - RenderText(ImVec2(bb.Max.x + style.ItemInnerSpacing.x, bb.Min.y + style.FramePadding.y), label, label_end, false); + RenderText(ImVec2(bb.Max.x + style.ItemInnerSpacing.x, bb.Min.y + style.FramePadding.y), label_for_display, false); if (!popup_open) return false; @@ -2745,7 +2745,7 @@ static bool TempInputIsClampEnabled(ImGuiSliderFlags flags, ImGuiDataType data_t // Note: p_data, p_min and p_max are _pointers_ to a memory address holding the data. For a Drag widget, p_min and p_max are optional. // Read code of e.g. DragFloat(), DragInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly. -bool ImGui::DragScalar(ImStrv label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min, const void* p_max, ImStrv format, ImGuiSliderFlags flags) +bool ImGui::DragScalar(ImStrv label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min, const void* p_max, ImStrv format_p, ImGuiSliderFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -2757,8 +2757,8 @@ bool ImGui::DragScalar(ImStrv label, ImGuiDataType data_type, void* p_data, floa const float w = CalcItemWidth(); const ImU32 color_marker = (g.NextItemData.HasFlags & ImGuiNextItemDataFlags_HasColorMarker) ? g.NextItemData.ColorMarker : 0; - const char* label_end = FindRenderedTextEnd(label); - const ImVec2 label_size = CalcTextSize(label, label_end, false); + const ImStrv label_for_display(label.Begin, FindRenderedTextEnd(label)); + const ImVec2 label_size = CalcTextSize(label_for_display, false); const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f)); const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); @@ -2767,8 +2767,14 @@ bool ImGui::DragScalar(ImStrv label, ImGuiDataType data_type, void* p_data, floa if (!ItemAdd(total_bb, id, &frame_bb, temp_input_allowed ? ImGuiItemFlags_Inputable : 0)) return false; + // FIXME-IMSTR + char format_0[64]; // format may not end with \0 + const char* format = format_0; + IM_ASSERT(format_p.End - format_p.Begin < IM_ARRAYSIZE(format_0)); + ImStrncpy(format_0, format_p, IM_ARRAYSIZE(format_0)); + // Default format string when passing NULL - if (format == NULL) + if (!format_p) format = DataTypeGetInfo(data_type)->PrintFmt; const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.ItemFlags); @@ -2834,12 +2840,12 @@ bool ImGui::DragScalar(ImStrv label, ImGuiDataType data_type, void* p_data, floa LogSetNextTextDecoration("{", "}"); if (is_mixed) PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextMixedValue]); - RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f)); + RenderTextClipped(frame_bb.Min, frame_bb.Max, ImStrv(value_buf, value_buf_end), NULL, ImVec2(0.5f, 0.5f)); if (is_mixed) PopStyleColor(); if (label_size.x > 0.0f) - RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, label_end, false); + RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label_for_display, false); IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | (temp_input_allowed ? ImGuiItemStatusFlags_Inputable : 0)); return value_changed; @@ -2871,11 +2877,11 @@ bool ImGui::DragScalarN(ImStrv label, ImGuiDataType data_type, void* p_data, int } PopID(); - const char* label_end = FindRenderedTextEnd(label); - if (label != label_end) + label.End = FindRenderedTextEnd(label); + if (label.Begin != label.End) { SameLine(0, g.Style.ItemInnerSpacing.x); - TextEx(label, label_end); + TextEx(label); } EndGroup(); @@ -2928,7 +2934,8 @@ bool ImGui::DragFloatRange2(ImStrv label, float* v_current_min, float* v_current PopItemWidth(); SameLine(0, g.Style.ItemInnerSpacing.x); - TextEx(label, FindRenderedTextEnd(label)); + label.End = FindRenderedTextEnd(label); + TextEx(label); EndGroup(); PopID(); @@ -2982,7 +2989,8 @@ bool ImGui::DragIntRange2(ImStrv label, int* v_current_min, int* v_current_max, PopItemWidth(); SameLine(0, g.Style.ItemInnerSpacing.x); - TextEx(label, FindRenderedTextEnd(label)); + label.End = FindRenderedTextEnd(label); + TextEx(label); EndGroup(); PopID(); @@ -3361,7 +3369,7 @@ bool ImGui::SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type // Note: p_data, p_min and p_max are _pointers_ to a memory address holding the data. For a slider, they are all required. // Read code of e.g. SliderFloat(), SliderInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly. -bool ImGui::SliderScalar(ImStrv label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, ImStrv format, ImGuiSliderFlags flags) +bool ImGui::SliderScalar(ImStrv label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, ImStrv format_p, ImGuiSliderFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -3373,8 +3381,8 @@ bool ImGui::SliderScalar(ImStrv label, ImGuiDataType data_type, void* p_data, co const float w = CalcItemWidth(); const ImU32 color_marker = (g.NextItemData.HasFlags & ImGuiNextItemDataFlags_HasColorMarker) ? g.NextItemData.ColorMarker : 0; - const char* label_end = FindRenderedTextEnd(label); - const ImVec2 label_size = CalcTextSize(label, label_end, false); + const ImStrv label_for_display(label.Begin, FindRenderedTextEnd(label)); + const ImVec2 label_size = CalcTextSize(label_for_display, false); const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f)); const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); @@ -3383,8 +3391,13 @@ bool ImGui::SliderScalar(ImStrv label, ImGuiDataType data_type, void* p_data, co if (!ItemAdd(total_bb, id, &frame_bb, temp_input_allowed ? ImGuiItemFlags_Inputable : 0)) return false; + // FIXME-IMSTR + char format_0[64]; // format may not end with \0 + const char* format = format_0; + IM_ASSERT(format_p.End - format_p.Begin < IM_ARRAYSIZE(format_0)); + // Default format string when passing NULL - if (format == NULL) + if (!format_p) format = DataTypeGetInfo(data_type)->PrintFmt; const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.ItemFlags); @@ -3446,12 +3459,12 @@ bool ImGui::SliderScalar(ImStrv label, ImGuiDataType data_type, void* p_data, co LogSetNextTextDecoration("{", "}"); if (is_mixed) PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextMixedValue]); - RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f)); + RenderTextClipped(frame_bb.Min, frame_bb.Max, ImStrv(value_buf, value_buf_end), NULL, ImVec2(0.5f, 0.5f)); if (is_mixed) PopStyleColor(); if (label_size.x > 0.0f) - RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, label_end, false); + RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label_for_display, false); IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | (temp_input_allowed ? ImGuiItemStatusFlags_Inputable : 0)); return value_changed; @@ -3484,11 +3497,11 @@ bool ImGui::SliderScalarN(ImStrv label, ImGuiDataType data_type, void* v, int co } PopID(); - const char* label_end = FindRenderedTextEnd(label); - if (label != label_end) + label.End = FindRenderedTextEnd(label); + if (label.Begin != label.End) { SameLine(0, g.Style.ItemInnerSpacing.x); - TextEx(label, label_end); + TextEx(label); } EndGroup(); @@ -3517,7 +3530,7 @@ bool ImGui::SliderFloat4(ImStrv label, float v[4], float v_min, float v_max, ImS bool ImGui::SliderAngle(ImStrv label, float* v_rad, float v_degrees_min, float v_degrees_max, ImStrv format, ImGuiSliderFlags flags) { - if (format == NULL) + if (!format) format = "%.0f deg"; float v_deg = (*v_rad) * 360.0f / (2 * IM_PI); bool value_changed = SliderFloat(label, &v_deg, v_degrees_min, v_degrees_max, format, flags); @@ -3546,7 +3559,7 @@ bool ImGui::SliderInt4(ImStrv label, int v[4], int v_min, int v_max, ImStrv form return SliderScalarN(label, ImGuiDataType_S32, v, 4, &v_min, &v_max, format, flags); } -bool ImGui::VSliderScalar(ImStrv label, const ImVec2& size, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, ImStrv format, ImGuiSliderFlags flags) +bool ImGui::VSliderScalar(ImStrv label, const ImVec2& size, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, ImStrv format_p, ImGuiSliderFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -3556,8 +3569,8 @@ bool ImGui::VSliderScalar(ImStrv label, const ImVec2& size, ImGuiDataType data_t const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label); - const char* label_end = FindRenderedTextEnd(label); - const ImVec2 label_size = CalcTextSize(label, label_end, false); + const ImStrv label_for_display(label.Begin, FindRenderedTextEnd(label)); + const ImVec2 label_size = CalcTextSize(label_for_display, false); const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size); const ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); @@ -3565,8 +3578,13 @@ bool ImGui::VSliderScalar(ImStrv label, const ImVec2& size, ImGuiDataType data_t if (!ItemAdd(frame_bb, id)) return false; + // FIXME-IMSTR + char format_0[64]; // format may not end with \0 + const char* format = format_0; + IM_ASSERT(format_p.End - format_p.Begin < IM_ARRAYSIZE(format_0)); + // Default format string when passing NULL - if (format == NULL) + if (!format_p) format = DataTypeGetInfo(data_type)->PrintFmt; const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.ItemFlags); @@ -3603,12 +3621,12 @@ bool ImGui::VSliderScalar(ImStrv label, const ImVec2& size, ImGuiDataType data_t const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_COUNTOF(value_buf), data_type, p_data, (is_mixed && g.MixedValueLabel != NULL) ? g.MixedValueLabel : format); if (is_mixed) PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextMixedValue]); - RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.0f)); + RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, ImStrv(value_buf, value_buf_end), NULL, ImVec2(0.5f, 0.0f)); if (is_mixed) PopStyleColor(); if (label_size.x > 0.0f) - RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, label_end, false); + RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label_for_display, false); IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags); return value_changed; @@ -3862,7 +3880,7 @@ void ImGui::SetNextItemRefVal(ImGuiDataType data_type, void* p_data) // Note: p_data, p_step, p_step_fast are _pointers_ to a memory address holding the data. For an Input widget, p_step and p_step_fast are optional. // Read code of e.g. InputFloat(), InputInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly. -bool ImGui::InputScalar(ImStrv label, ImGuiDataType data_type, void* p_data, const void* p_step, const void* p_step_fast, ImStrv format, ImGuiInputTextFlags flags) +bool ImGui::InputScalar(ImStrv label, ImGuiDataType data_type, void* p_data, const void* p_step, const void* p_step_fast, ImStrv format_p, ImGuiInputTextFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -3872,7 +3890,13 @@ bool ImGui::InputScalar(ImStrv label, ImGuiDataType data_type, void* p_data, con ImGuiStyle& style = g.Style; //IM_ASSERT((flags & ImGuiInputTextFlags_EnterReturnsTrue) == 0); // Not supported by InputScalar(). Please open an issue if you this would be useful to you. Otherwise use IsItemDeactivatedAfterEdit()! - if (format == NULL) + // FIXME-IMSTR + char format_0[64]; // format may not end with \0 + const char* format = format_0; + IM_ASSERT(format_p.End - format_p.Begin < IM_ARRAYSIZE(format_0)); + ImStrncpy(format_0, format_p, IM_ARRAYSIZE(format_0)); + + if (!format_p) format = DataTypeGetInfo(data_type)->PrintFmt; void* p_data_default = (g.NextItemData.HasFlags & ImGuiNextItemDataFlags_HasRefVal) ? &g.NextItemData.RefVal : &g.DataTypeZeroValue; @@ -3952,11 +3976,11 @@ bool ImGui::InputScalar(ImStrv label, ImGuiDataType data_type, void* p_data, con if (flags & ImGuiInputTextFlags_ReadOnly) EndDisabled(); - const char* label_end = FindRenderedTextEnd(label); - if (label != label_end) + label.End = FindRenderedTextEnd(label); + if (label.Begin != label.End) { SameLine(0, style.ItemInnerSpacing.x); - TextEx(label, label_end); + TextEx(label); } style.FramePadding = backup_frame_padding; @@ -3997,11 +4021,11 @@ bool ImGui::InputScalarN(ImStrv label, ImGuiDataType data_type, void* p_data, in } PopID(); - const char* label_end = FindRenderedTextEnd(label); - if (label != label_end) + label.End = FindRenderedTextEnd(label); + if (label.Begin != label.End) { SameLine(0.0f, g.Style.ItemInnerSpacing.x); - TextEx(label, label_end); + TextEx(label); } EndGroup(); @@ -4447,10 +4471,10 @@ void ImGuiInputTextCallbackData::DeleteChars(int pos, int bytes_count) BufTextLen -= bytes_count; } -void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, const char* new_text_end) +void ImGuiInputTextCallbackData::InsertChars(int pos, ImStrv new_text) { // Accept null ranges - if (new_text == new_text_end) + if (new_text.Begin == new_text.End) return; ImGuiContext& g = *Ctx; @@ -4458,14 +4482,15 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons IM_ASSERT(obj->ID != 0 && g.ActiveId == obj->ID); const bool is_resizable = (Flags & ImGuiInputTextFlags_CallbackResize) != 0; const bool is_readonly = (Flags & ImGuiInputTextFlags_ReadOnly) != 0; - int new_text_len = new_text_end ? (int)(new_text_end - new_text) : (int)ImStrlen(new_text); + int new_text_len = (int)new_text.length(); // We support partial insertion (with a mod in stb_textedit.h) const int avail = BufSize - 1 - BufTextLen; if (!is_resizable && new_text_len > avail) - new_text_len = (int)(ImTextFindValidUtf8CodepointEnd(new_text, new_text + new_text_len, new_text + avail) - new_text); // Truncate to closest UTF-8 codepoint. Alternative: return 0 to cancel insertion. + new_text_len = (int)(ImTextFindValidUtf8CodepointEnd(new_text.Begin, new_text.Begin + new_text_len, new_text.Begin + avail) - new_text.Begin); // Truncate to closest UTF-8 codepoint. Alternative: return 0 to cancel insertion. if (new_text_len == 0) return; + new_text.End = new_text.Begin + new_text_len; // Grow internal buffer if needed if (new_text_len + BufTextLen + 1 > obj->TextA.Size && is_resizable && !is_readonly) @@ -4480,7 +4505,8 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons if (BufTextLen != 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)); + if (new_text_len > 0) + memcpy(Buf + pos, new_text.Begin, (size_t)new_text_len * sizeof(char)); Buf[BufTextLen + new_text_len] = '\0'; BufDirty = true; @@ -4809,8 +4835,8 @@ bool ImGui::InputTextEx(ImStrv label, ImStrv hint, char* buf, int buf_size, cons if (is_multiline) // Open group before calling GetID() because groups tracks id created within their scope (including the scrollbar) BeginGroup(); const ImGuiID id = window->GetID(label); - const char* label_end = FindRenderedTextEnd(label); - const ImVec2 label_size = CalcTextSize(label, label_end, false); + const ImStrv label_for_display(label.Begin, FindRenderedTextEnd(label)); + const ImVec2 label_size = CalcTextSize(label_for_display, false); const ImVec2 frame_size = CalcItemSize(size_arg, CalcItemWidth(), (is_multiline ? g.FontSize * 8.0f : label_size.y) + style.FramePadding.y * 2.0f); // Arbitrary default of 8 lines high for multi-line const ImVec2 total_size = ImVec2(frame_size.x + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), frame_size.y); @@ -5057,7 +5083,7 @@ bool ImGui::InputTextEx(ImStrv label, ImStrv hint, char* buf, int buf_size, cons // Select the buffer to render. const bool buf_display_from_state = (render_cursor || render_selection || g.ActiveId == id) && !is_readonly && state; - bool is_displaying_hint = (hint != NULL && (buf_display_from_state ? state->TextSrc : buf)[0] == 0) && !is_mixed; + bool is_displaying_hint = (!hint.empty() && (buf_display_from_state ? state->TextSrc : buf)[0] == 0) && !is_mixed; // Password pushes a temporary font with only a fallback glyph if (is_password && !is_displaying_hint) @@ -5332,17 +5358,16 @@ bool ImGui::InputTextEx(ImStrv label, ImStrv hint, char* buf, int buf_size, cons } else if (is_paste) { - if (const char* clipboard = GetClipboardText()) + if (ImStrv clipboard = GetClipboardText()) { // Filter pasted buffer - const int clipboard_len = (int)ImStrlen(clipboard); - const char* clipboard_end = clipboard + clipboard_len; + const int clipboard_len = (int)clipboard.length(); ImVector clipboard_filtered; clipboard_filtered.reserve(clipboard_len + 1); - for (const char* s = clipboard; *s != 0; ) + for (const char* s = clipboard.Begin; *s != 0; ) { unsigned int c; - int in_len = ImTextCharFromUtf8(&c, s, clipboard_end); + int in_len = ImTextCharFromUtf8(&c, s, clipboard.End); s += in_len; if (!InputTextFilterCharacter(&g, state, &c, callback, callback_user_data, true)) continue; @@ -5579,7 +5604,7 @@ bool ImGui::InputTextEx(ImStrv label, ImStrv hint, char* buf, int buf_size, cons // Display hint when contents is empty // At this point we need to handle the possibility that a callback could have modified the underlying buffer (#8368) - const bool new_is_displaying_hint = (hint != NULL && (buf_display_from_state ? state->TextA.Data : buf)[0] == 0) && !is_mixed; + const bool new_is_displaying_hint = (!hint.empty() && (buf_display_from_state ? state->TextA.Data : buf)[0] == 0) && !is_mixed; if (new_is_displaying_hint != is_displaying_hint) { if (is_password && !is_displaying_hint) @@ -5597,8 +5622,8 @@ bool ImGui::InputTextEx(ImStrv label, ImStrv hint, char* buf, int buf_size, cons } else if (is_displaying_hint) { - buf_display = hint; - buf_display_end = buf_display + ImStrlen(buf_display); + buf_display = hint.Begin; + buf_display_end = hint.End; } else { @@ -5749,8 +5774,7 @@ bool ImGui::InputTextEx(ImStrv label, ImStrv hint, char* buf, int buf_size, cons g.Font->RenderText(draw_window->DrawList, g.FontSize, draw_pos - draw_scroll + ImVec2(0.0f, line_visible_n0 * g.FontSize), text_col, clip_rect.AsVec4(), - line_index->get_line_begin(buf_display, line_visible_n0), - line_index->get_line_end(buf_display, line_visible_n1 - 1), + ImStrv(line_index->get_line_begin(buf_display, line_visible_n0), line_index->get_line_end(buf_display, line_visible_n1 - 1)), wrap_width, ImDrawTextFlags_WrapKeepBlanks | ImDrawTextFlags_CpuFineClip); // Render blinking cursor @@ -5805,11 +5829,11 @@ bool ImGui::InputTextEx(ImStrv label, ImStrv hint, char* buf, int buf_size, cons if (g.LogEnabled && (!is_password || is_displaying_hint)) { LogSetNextTextDecoration("{", "}"); - LogRenderedText(&draw_pos, buf_display, buf_display_end); + LogRenderedText(&draw_pos, ImStrv(buf_display, buf_display_end)); } if (label_size.x > 0) - RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, label_end, false); + RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label_for_display, false); if (state && validated) state->ValidatedThisFrame = true; @@ -5921,7 +5945,6 @@ bool ImGui::ColorEdit4(ImStrv label, float col[4], ImGuiColorEditFlags flags) ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const float square_sz = GetFrameHeight(); - const char* label_display_end = FindRenderedTextEnd(label); float w_full = CalcItemWidth(); g.NextItemData.ClearFlags(); @@ -5930,6 +5953,7 @@ bool ImGui::ColorEdit4(ImStrv label, float col[4], ImGuiColorEditFlags flags) const bool set_current_color_edit_id = (g.ColorEditCurrentID == 0); if (set_current_color_edit_id) g.ColorEditCurrentID = window->IDStack.back(); + const ImStrv label_for_display(label.Begin, FindRenderedTextEnd(label)); // If we're not showing any slider there's no point in doing any HSV conversions const ImGuiColorEditFlags flags_untouched = flags; @@ -6081,9 +6105,9 @@ bool ImGui::ColorEdit4(ImStrv label, float col[4], ImGuiColorEditFlags flags) if (g.CurrentWindow->BeginCount == 1) { picker_active_window = g.CurrentWindow; - if (label != label_display_end) + if (label_for_display.Begin != label_for_display.End) { - TextEx(label, label_display_end); + TextEx(label_for_display); Spacing(); } ImGuiColorEditFlags picker_flags_to_forward = ImGuiColorEditFlags_DataTypeMask_ | ImGuiColorEditFlags_PickerMask_ | ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaBar; @@ -6097,13 +6121,13 @@ bool ImGui::ColorEdit4(ImStrv label, float col[4], ImGuiColorEditFlags flags) } } - if (label != label_display_end && !(flags & ImGuiColorEditFlags_NoLabel)) + if (label_for_display.Begin != label_for_display.End && !(flags & ImGuiColorEditFlags_NoLabel)) { // Position not necessarily next to last submitted button (e.g. if style.ColorButtonPosition == ImGuiDir_Left), // but we need to use SameLine() to setup baseline correctly. Might want to refactor SameLine() to simplify this. SameLine(0.0f, style.ItemInnerSpacing.x); window->DC.CursorPos.x = pos.x + ((flags & ImGuiColorEditFlags_NoInputs) ? w_button : w_full + style.ItemInnerSpacing.x); - TextEx(label, label_display_end); + TextEx(label_for_display); } // Convert back @@ -6354,12 +6378,12 @@ bool ImGui::ColorPicker4(ImStrv label, float col[4], ImGuiColorEditFlags flags, if (!(flags & ImGuiColorEditFlags_NoLabel)) { - const char* label_display_end = FindRenderedTextEnd(label); - if (label != label_display_end) + const ImStrv label_for_display(label.Begin, FindRenderedTextEnd(label)); + if (!label_for_display.empty()) { if ((flags & ImGuiColorEditFlags_NoSidePreview)) SameLine(0, style.ItemInnerSpacing.x); - TextEx(label, label_display_end); + TextEx(label_for_display); } } @@ -6691,10 +6715,10 @@ void ImGui::ColorTooltip(ImStrv text, const float* col, ImGuiColorEditFlags flag if (!BeginTooltipEx(ImGuiTooltipFlags_OverridePrevious, ImGuiWindowFlags_None)) return; - const char* text_end = text ? FindRenderedTextEnd(text, NULL) : text; - if (text_end > text) + text.End = FindRenderedTextEnd(text); + if (text.Begin != text.End) { - TextEx(text, text_end); + TextEx(text); Separator(); } @@ -6858,7 +6882,7 @@ bool ImGui::TreeNode(ImStrv label) if (window->SkipItems) return false; ImGuiID id = window->GetID(label); - return TreeNodeBehavior(id, ImGuiTreeNodeFlags_None, label, NULL); + return TreeNodeBehavior(id, ImGuiTreeNodeFlags_None, label); } bool ImGui::TreeNodeV(ImStrv str_id, const char* fmt, va_list args) @@ -6877,7 +6901,7 @@ bool ImGui::TreeNodeEx(ImStrv label, ImGuiTreeNodeFlags flags) if (window->SkipItems) return false; ImGuiID id = window->GetID(label); - return TreeNodeBehavior(id, flags, label, NULL); + return TreeNodeBehavior(id, flags, label); } bool ImGui::TreeNodeEx(ImStrv str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) @@ -6905,9 +6929,9 @@ bool ImGui::TreeNodeExV(ImStrv str_id, ImGuiTreeNodeFlags flags, const char* fmt return false; ImGuiID id = window->GetID(str_id); - const char* label, *label_end; - ImFormatStringToTempBufferV(&label, &label_end, fmt, args); - return TreeNodeBehavior(id, flags, label, label_end); + ImStrv label; + ImFormatStringToTempBufferV(&label, fmt, args); + return TreeNodeBehavior(id, flags, label); } bool ImGui::TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) @@ -6917,9 +6941,9 @@ bool ImGui::TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char return false; ImGuiID id = window->GetID(ptr_id); - const char* label, *label_end; - ImFormatStringToTempBufferV(&label, &label_end, fmt, args); - return TreeNodeBehavior(id, flags, label, label_end); + ImStrv label; + ImFormatStringToTempBufferV(&label, fmt, args); + return TreeNodeBehavior(id, flags, label); } // The reason those two functions are not yet in public API is because I would like to design a more feature-full and generic API for this. @@ -7012,7 +7036,7 @@ static void TreeNodeStoreStackData(ImGuiTreeNodeFlags flags, float x1) #define TREE_NODE_MAX_DEPTH 32 #define TREE_NODE_GET_DEPTH_MASK(_DEPTH) (((ImU32)(_DEPTH) < TREE_NODE_MAX_DEPTH) ? (1u << (_DEPTH)) : 0u) -bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end) +bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, ImStrv label) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -7026,9 +7050,8 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l const bool use_frame_padding = (display_frame || (flags & ImGuiTreeNodeFlags_FramePadding)); const ImVec2 padding = use_frame_padding ? style.FramePadding : ImVec2(style.FramePadding.x, ImMin(window->DC.CurrLineTextBaseOffset, style.FramePadding.y)); - if (!label_end) - label_end = FindRenderedTextEnd(label); - const ImVec2 label_size = CalcTextSize(label, label_end, false); + const ImStrv label_for_display(label.Begin, FindRenderedTextEnd(label)); + const ImVec2 label_size = CalcTextSize(label_for_display, false); const float text_offset_x = g.FontSize + (display_frame ? padding.x * 3 : padding.x * 2); // Collapsing arrow width + Spacing const float text_offset_y = use_frame_padding ? ImMax(style.FramePadding.y, window->DC.CurrLineTextBaseOffset) : window->DC.CurrLineTextBaseOffset; // Latch before ItemSize changes it @@ -7282,9 +7305,9 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l // Label if (display_frame) - RenderTextClipped(text_pos, frame_bb.Max, label, label_end, &label_size); + RenderTextClipped(text_pos, frame_bb.Max, label_for_display, &label_size); else - RenderText(text_pos, label, label_end, false); + RenderText(text_pos, label_for_display, false); if (span_all_columns_label) TablePopBackgroundChannel(); @@ -7517,8 +7540,9 @@ bool ImGui::Selectable(ImStrv label, bool selected, ImGuiSelectableFlags flags, // Submit label or explicit size to ItemSize(), whereas ItemAdd() will submit a larger/spanning rectangle. ImGuiID id = window->GetID(label); - const char* label_end = FindRenderedTextEnd(label); - ImVec2 label_size = CalcTextSize(label, label_end, false); + + const ImStrv label_for_display(label.Begin, FindRenderedTextEnd(label)); + ImVec2 label_size = CalcTextSize(label_for_display, false); ImVec2 size(size_arg.x != 0.0f ? size_arg.x : label_size.x, size_arg.y != 0.0f ? size_arg.y : label_size.y); ImVec2 pos = window->DC.CursorPos; pos.y += window->DC.CurrLineTextBaseOffset; @@ -7678,10 +7702,10 @@ bool ImGui::Selectable(ImStrv label, bool selected, ImGuiSelectableFlags flags, // Text stays at the submission position. Alignment/clipping extents ignore SpanAllColumns. if (is_visible) - RenderTextClipped(pos, ImVec2(ImMin(pos.x + size.x, window->WorkRect.Max.x), pos.y + size.y), label, label_end, &label_size, style.SelectableTextAlign, &bb); + RenderTextClipped(pos, ImVec2(ImMin(pos.x + size.x, window->WorkRect.Max.x), pos.y + size.y), label_for_display, &label_size, style.SelectableTextAlign, &bb); #ifdef IMGUI_DEBUG_BOXSELECT - if (g.BoxSelectState.UnclipMode) { GetForegroundDrawList()->AddText(pos, IM_COL32(255,255,0,200), label, label_end); } + if (g.BoxSelectState.UnclipMode) { GetForegroundDrawList()->AddText(pos, IM_COL32(255,255,0,200), label_for_display); } #endif // Automatically close popups @@ -8950,8 +8974,8 @@ bool ImGui::BeginListBox(ImStrv label, const ImVec2& size_arg) const ImGuiStyle& style = g.Style; const ImGuiID id = GetID(label); - const char* label_end = FindRenderedTextEnd(label); - const ImVec2 label_size = CalcTextSize(label, label_end, false); + const ImStrv label_for_display(label.Begin, FindRenderedTextEnd(label)); + const ImVec2 label_size = CalcTextSize(label_for_display, false); // Size default to hold ~7.25 items. // Fractional number of items helps seeing that we can scroll down/up without looking at scrollbar. @@ -8974,7 +8998,7 @@ bool ImGui::BeginListBox(ImStrv label, const ImVec2& size_arg) if (label_size.x > 0.0f) { ImVec2 label_pos = ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y); - RenderText(label_pos, label, label_end, false); + RenderText(label_pos, label_for_display, false); window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, label_pos + label_size); AlignTextToFramePadding(); } @@ -9067,9 +9091,8 @@ int ImGui::PlotEx(ImGuiPlotType plot_type, ImStrv label, float (*values_getter)( const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label); - - const char* label_end = FindRenderedTextEnd(label); - const ImVec2 label_size = CalcTextSize(label, label_end, false); + const ImStrv label_for_display(label.Begin, FindRenderedTextEnd(label)); + const ImVec2 label_size = CalcTextSize(label_for_display, false); const ImVec2 frame_size = CalcItemSize(size_arg, CalcItemWidth(), label_size.y + style.FramePadding.y * 2.0f); const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size); @@ -9167,10 +9190,10 @@ int ImGui::PlotEx(ImGuiPlotType plot_type, ImStrv label, float (*values_getter)( // Text overlay if (overlay_text) - RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, overlay_text, NULL, NULL, ImVec2(0.5f, 0.0f)); + RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, overlay_text, NULL, ImVec2(0.5f, 0.0f)); if (label_size.x > 0.0f) - RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label, label_end, false); + RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label_for_display, false); // Return hovered index or -1 if none are hovered. // This is currently not exposed in the public API because we need a larger redesign of the whole thing, but in the short-term we are making it available in PlotEx(). @@ -9225,17 +9248,17 @@ void ImGui::PlotHistogram(ImStrv label, float (*values_getter)(void* data, int i void ImGui::Value(ImStrv prefix, bool b) { - Text("%s: %s", prefix, (b ? "true" : "false")); + Text("%.*s: %s", (int)prefix.length(), prefix.Begin, (b ? "true" : "false")); } void ImGui::Value(ImStrv prefix, int v) { - Text("%s: %d", prefix, v); + Text("%.*s: %d", (int)prefix.length(), prefix.Begin, v); } void ImGui::Value(ImStrv prefix, unsigned int v) { - Text("%s: %d", prefix, v); + Text("%.*s: %d", (int)prefix.length(), prefix.Begin, v); } void ImGui::Value(ImStrv prefix, float v, ImStrv float_format) @@ -9243,12 +9266,12 @@ void ImGui::Value(ImStrv prefix, float v, ImStrv float_format) if (float_format) { char fmt[64]; - ImFormatString(fmt, IM_COUNTOF(fmt), "%%s: %s", float_format); - Text(fmt, prefix, v); + ImFormatString(fmt, IM_COUNTOF(fmt), "%%.*s: %.*s", (int)float_format.length(), float_format.Begin); + Text(fmt, (int)prefix.length(), prefix.Begin, v); } else { - Text("%s: %.3f", prefix, v); + Text("%.*s: %.3f", (int)prefix.length(), prefix.Begin, v); } } @@ -9537,8 +9560,8 @@ bool ImGui::BeginMenuEx(ImStrv label, ImStrv icon, bool enabled) // Tag menu as used. Next time BeginMenu() with same ID is called it will append to existing menu g.MenusIdSubmittedThisFrame.push_back(id); - const char* label_end = FindRenderedTextEnd(label); - ImVec2 label_size = CalcTextSize(label, label_end, false); + const ImStrv label_for_display(label.Begin, FindRenderedTextEnd(label)); + ImVec2 label_size = CalcTextSize(label, false); // Odd hack to allow hovering across menus of a same menu-set (otherwise we wouldn't be able to hover parent without always being a Child window) // This is only done for items for the menu set and not the full parent window. @@ -9571,7 +9594,7 @@ bool ImGui::BeginMenuEx(ImStrv label, ImStrv icon, bool enabled) ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, pos.y + window->DC.CurrLineTextBaseOffset); pressed = Selectable("", menu_is_open, selectable_flags, label_size); LogSetNextTextDecoration("[", "]"); - RenderText(text_pos, label, label_end, false); + RenderText(text_pos, label_for_display, false); PopStyleVar(); window->DC.CursorPos.x += IM_TRUNC(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar(). popup_pos = ImVec2(pos.x - 1.0f - IM_TRUNC(style.ItemSpacing.x * 0.5f), text_pos.y - style.FramePadding.y + window->MenuBarHeight); @@ -9581,14 +9604,14 @@ bool ImGui::BeginMenuEx(ImStrv label, ImStrv icon, bool enabled) // Menu inside a regular/vertical menu // (In a typical menu window where all items are BeginMenu() or MenuItem() calls, extra_w will always be 0.0f. // Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system.) - float icon_w = (icon && icon[0]) ? CalcTextSize(icon, NULL).x : 0.0f; + float icon_w = !icon.empty() ? CalcTextSize(icon, NULL).x : 0.0f; float checkmark_w = IM_TRUNC(g.FontSize * 1.20f); float min_w = offsets->DeclColumns(icon_w, label_size.x, 0.0f, checkmark_w); // Feedback to next frame float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w); ImVec2 text_pos(window->DC.CursorPos.x, pos.y + window->DC.CurrLineTextBaseOffset); pressed = Selectable("", menu_is_open, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, label_size.y)); LogSetNextTextDecoration("", ">"); - RenderText(ImVec2(text_pos.x + offsets->OffsetLabel, text_pos.y), label, label_end, false); + RenderText(ImVec2(text_pos.x + offsets->OffsetLabel, text_pos.y), label_for_display, false); if (icon_w > 0.0f) RenderText(ImVec2(text_pos.x + offsets->OffsetIcon, text_pos.y), icon); RenderArrow(window->DrawList, ImVec2(text_pos.x + offsets->OffsetMark + extra_w + g.FontSize * 0.30f, text_pos.y), GetColorU32(ImGuiCol_Text), ImGuiDir_Right); @@ -9763,8 +9786,8 @@ bool ImGui::MenuItemEx(ImStrv label, ImStrv icon, ImStrv shortcut, bool selected ImGuiContext& g = *GImGui; ImGuiStyle& style = g.Style; ImVec2 pos = window->DC.CursorPos; - const char* label_end = FindRenderedTextEnd(label); - ImVec2 label_size = CalcTextSize(label, label_end, false); + const ImStrv label_for_display(label.Begin, FindRenderedTextEnd(label)); + ImVec2 label_size = CalcTextSize(label, false); // See BeginMenuEx() for comments about this. const bool menuset_is_open = IsRootOfOpenMenuSet(); @@ -9793,7 +9816,7 @@ bool ImGui::MenuItemEx(ImStrv label, ImStrv icon, ImStrv shortcut, bool selected pressed = Selectable("", selected, selectable_flags, ImVec2(label_size.x, 0.0f)); PopStyleVar(); if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible) - RenderText(text_pos, label, label_end, false); + RenderText(text_pos, label_for_display, false); window->DC.CursorPos.x += IM_TRUNC(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar(). } else @@ -9801,8 +9824,8 @@ bool ImGui::MenuItemEx(ImStrv label, ImStrv icon, ImStrv shortcut, bool selected // Menu item inside a vertical menu // (In a typical menu window where all items are BeginMenu() or MenuItem() calls, extra_w will always be 0.0f. // Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system.) - float icon_w = (icon && icon[0]) ? CalcTextSize(icon, NULL).x : 0.0f; - float shortcut_w = (shortcut && shortcut[0]) ? CalcTextSize(shortcut, NULL).x : 0.0f; + float icon_w = !icon.empty() ? CalcTextSize(icon).x : 0.0f; + float shortcut_w = !shortcut.empty() ? CalcTextSize(shortcut).x : 0.0f; float checkmark_w = IM_TRUNC(g.FontSize * 1.20f); // FIXME: Always accounted for, even in a menu with none, because 'selected' has no neutral setting. float min_w = offsets->DeclColumns(icon_w, label_size.x, shortcut_w, checkmark_w); // Feedback for next frame float stretch_w = ImMax(0.0f, GetContentRegionAvail().x - min_w); @@ -9810,14 +9833,14 @@ bool ImGui::MenuItemEx(ImStrv label, ImStrv icon, ImStrv shortcut, bool selected pressed = Selectable("", false, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, label_size.y)); if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible) { - RenderText(text_pos + ImVec2(offsets->OffsetLabel, 0.0f), label, label_end, false); + RenderText(text_pos + ImVec2(offsets->OffsetLabel, 0.0f), label_for_display, false); if (icon_w > 0.0f) RenderText(text_pos + ImVec2(offsets->OffsetIcon, 0.0f), icon); if (shortcut_w > 0.0f) { PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]); LogSetNextTextDecoration("(", ")"); - RenderText(text_pos + ImVec2(offsets->OffsetShortcut + stretch_w, 0.0f), shortcut, NULL, false); + RenderText(text_pos + ImVec2(offsets->OffsetShortcut + stretch_w, 0.0f), shortcut, false); PopStyleColor(); } if (selected) @@ -10814,7 +10837,8 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, ImStrv label, bool* p_open, ImGui tab_bar->LastTabItemIdx = (ImS16)tab_bar->Tabs.index_from_ptr(tab); // Calculate tab contents size - ImVec2 size = TabItemCalcSize(label, (p_open != NULL) || (flags & ImGuiTabItemFlags_UnsavedDocument)); + ImStrv label_for_display(label.Begin, FindRenderedTextEnd(label)); + ImVec2 size = TabItemCalcSize(label_for_display, (p_open != NULL) || (flags & ImGuiTabItemFlags_UnsavedDocument)); tab->RequestedWidth = -1.0f; if (g.NextItemData.HasFlags & ImGuiNextItemDataFlags_HasWidth) size.x = tab->RequestedWidth = g.NextItemData.Width; @@ -10839,7 +10863,9 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, ImStrv label, bool* p_open, ImGui else { tab->NameOffset = (ImS32)tab_bar->TabsNames.size(); - tab_bar->TabsNames.append(label, label + ImStrlen(label) + 1); + tab_bar->TabsNames.append(label_for_display); + char zero_c = 0; + tab_bar->TabsNames.append(ImStrv(&zero_c, &zero_c + 1)); } // Update selected tab @@ -10996,7 +11022,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, ImStrv label, bool* p_open, ImGui // FIXME: We may want disabled tab to still display the tooltip? if (text_clipped && g.HoveredId == id && !held) if (!(tab_bar->Flags & ImGuiTabBarFlags_NoTooltip) && !(tab->Flags & ImGuiTabItemFlags_NoTooltip)) - SetItemTooltip("%.*s", (int)(FindRenderedTextEnd(label) - label), label); + SetItemTooltip("%.*s", (int)(label_for_display.End - label_for_display.Begin), label_for_display.Begin); } // Restore main window position so user can draw there @@ -11029,7 +11055,7 @@ void ImGui::SetTabItemClosed(ImStrv label) ImVec2 ImGui::TabItemCalcSize(ImStrv label, bool has_close_button_or_unsaved_marker) { ImGuiContext& g = *GImGui; - ImVec2 label_size = CalcTextSize(label, NULL, true); + ImVec2 label_size = CalcTextSize(label, true); ImVec2 size = ImVec2(label_size.x + g.Style.FramePadding.x, label_size.y + g.Style.FramePadding.y * 2.0f); if (has_close_button_or_unsaved_marker) size.x += g.Style.FramePadding.x + (g.Style.ItemInnerSpacing.x + g.FontSize); // We use Y intentionally to fit the close button circle. @@ -11070,8 +11096,8 @@ void ImGui::TabItemBackground(ImDrawList* draw_list, const ImRect& bb, ImGuiTabI void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImVec2 frame_padding, ImStrv label, ImGuiID tab_id, ImGuiID close_button_id, bool is_contents_visible, bool* out_just_closed, bool* out_text_clipped) { ImGuiContext& g = *GImGui; - const char* label_end = FindRenderedTextEnd(label); - ImVec2 label_size = CalcTextSize(label, label_end, false); + label.End = FindRenderedTextEnd(label); + ImVec2 label_size = CalcTextSize(label, false); if (out_just_closed) *out_just_closed = false; @@ -11156,7 +11182,7 @@ void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, } } LogSetNextTextDecoration("/", "\\"); - RenderTextEllipsis(draw_list, text_ellipsis_clip_bb.Min, text_ellipsis_clip_bb.Max, ellipsis_max_x, label, label_end, &label_size); + RenderTextEllipsis(draw_list, text_ellipsis_clip_bb.Min, text_ellipsis_clip_bb.Max, ellipsis_max_x, label, &label_size); #if 0 if (!is_contents_visible) diff --git a/misc/debuggers/imgui.natvis b/misc/debuggers/imgui.natvis index 13b636008..7d0c9dd1a 100644 --- a/misc/debuggers/imgui.natvis +++ b/misc/debuggers/imgui.natvis @@ -51,6 +51,11 @@ More information at: https://docs.microsoft.com/en-us/visualstudio/debugger/crea + + + {Begin,[End-Begin]s} ({End-Begin,d}) + + {{Name {Name,s} Active {(Active||WasActive)?1:0,d} Child {(Flags & 0x01000000)?1:0,d} Popup {(Flags & 0x04000000)?1:0,d} Hidden {(Hidden)?1:0,d}} From 3de2c4b14c34afec75699acd83e5afa8c3210ac3 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 1 Feb 2021 17:04:50 +0100 Subject: [PATCH 03/15] ImStrv: changed ImStrv xxx=NULL args to an explicit xxx=ImStrv() This is mostly for the benefit of cimgui parser, ideally we would do without. --- imgui.h | 52 +++++++++++++++++++++++------------------------ imgui_internal.h | 2 +- imgui_widgets.cpp | 2 +- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/imgui.h b/imgui.h index 19caf29bb..a146f841a 100644 --- a/imgui.h +++ b/imgui.h @@ -676,10 +676,10 @@ namespace ImGui IMGUI_API bool CheckboxFlags(ImStrv label, unsigned int* flags, unsigned int flags_value); IMGUI_API bool RadioButton(ImStrv label, bool active); // use with e.g. if (RadioButton("one", my_value==1)) { my_value = 1; } IMGUI_API bool RadioButton(ImStrv label, int* v, int v_button); // shortcut to handle the above pattern when value is an integer - IMGUI_API void ProgressBar(float fraction, const ImVec2& size_arg = ImVec2(-FLT_MIN, 0), ImStrv overlay = NULL); + IMGUI_API void ProgressBar(float fraction, const ImVec2& size_arg = ImVec2(-FLT_MIN, 0), ImStrv overlay = ImStrv()); IMGUI_API void Bullet(); // draw a small circle + keep the cursor on the same line. advance cursor x position by GetTreeNodeToLabelSpacing(), same distance that TreeNode() uses IMGUI_API bool TextLink(ImStrv label); // hyperlink text button, return true when clicked - IMGUI_API bool TextLinkOpenURL(ImStrv label, ImStrv url = NULL); // hyperlink text button, automatically open file/url when clicked + IMGUI_API bool TextLinkOpenURL(ImStrv label, ImStrv url = ImStrv()); // hyperlink text button, automatically open file/url when clicked // Widgets: Images // - Read about ImTextureID/ImTextureRef here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples @@ -716,14 +716,14 @@ namespace ImGui IMGUI_API bool DragFloat2(ImStrv label, float v[2], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, ImStrv format = "%.3f", ImGuiSliderFlags flags = 0); IMGUI_API bool DragFloat3(ImStrv label, float v[3], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, ImStrv format = "%.3f", ImGuiSliderFlags flags = 0); IMGUI_API bool DragFloat4(ImStrv label, float v[4], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, ImStrv format = "%.3f", ImGuiSliderFlags flags = 0); - IMGUI_API bool DragFloatRange2(ImStrv label, float* v_current_min, float* v_current_max, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, ImStrv format = "%.3f", ImStrv format_max = NULL, ImGuiSliderFlags flags = 0); + IMGUI_API bool DragFloatRange2(ImStrv label, float* v_current_min, float* v_current_max, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, ImStrv format = "%.3f", ImStrv format_max = ImStrv(), ImGuiSliderFlags flags = 0); IMGUI_API bool DragInt(ImStrv label, int* v, float v_speed = 1.0f, int v_min = 0, int v_max = 0, ImStrv format = "%d", ImGuiSliderFlags flags = 0); // If v_min >= v_max we have no bound IMGUI_API bool DragInt2(ImStrv label, int v[2], float v_speed = 1.0f, int v_min = 0, int v_max = 0, ImStrv format = "%d", ImGuiSliderFlags flags = 0); IMGUI_API bool DragInt3(ImStrv label, int v[3], float v_speed = 1.0f, int v_min = 0, int v_max = 0, ImStrv format = "%d", ImGuiSliderFlags flags = 0); IMGUI_API bool DragInt4(ImStrv label, int v[4], float v_speed = 1.0f, int v_min = 0, int v_max = 0, ImStrv format = "%d", ImGuiSliderFlags flags = 0); - IMGUI_API bool DragIntRange2(ImStrv label, int* v_current_min, int* v_current_max, float v_speed = 1.0f, int v_min = 0, int v_max = 0, ImStrv format = "%d", ImStrv format_max = NULL, ImGuiSliderFlags flags = 0); - IMGUI_API bool DragScalar(ImStrv label, ImGuiDataType data_type, void* p_data, float v_speed = 1.0f, const void* p_min = NULL, const void* p_max = NULL, ImStrv format = NULL, ImGuiSliderFlags flags = 0); - IMGUI_API bool DragScalarN(ImStrv label, ImGuiDataType data_type, void* p_data, int components, float v_speed = 1.0f, const void* p_min = NULL, const void* p_max = NULL, ImStrv format = NULL, ImGuiSliderFlags flags = 0); + IMGUI_API bool DragIntRange2(ImStrv label, int* v_current_min, int* v_current_max, float v_speed = 1.0f, int v_min = 0, int v_max = 0, ImStrv format = "%d", ImStrv format_max = ImStrv(), ImGuiSliderFlags flags = 0); + IMGUI_API bool DragScalar(ImStrv label, ImGuiDataType data_type, void* p_data, float v_speed = 1.0f, const void* p_min = NULL, const void* p_max = NULL, ImStrv format = ImStrv(), ImGuiSliderFlags flags = 0); + IMGUI_API bool DragScalarN(ImStrv label, ImGuiDataType data_type, void* p_data, int components, float v_speed = 1.0f, const void* p_min = NULL, const void* p_max = NULL, ImStrv format = ImStrv(), ImGuiSliderFlags flags = 0); // Widgets: Regular Sliders // - Ctrl+Click on any slider to turn them into an input box. Manually input values aren't clamped by default and can go off-bounds. Use ImGuiSliderFlags_AlwaysClamp to always clamp. @@ -740,11 +740,11 @@ namespace ImGui IMGUI_API bool SliderInt2(ImStrv label, int v[2], int v_min, int v_max, ImStrv format = "%d", ImGuiSliderFlags flags = 0); IMGUI_API bool SliderInt3(ImStrv label, int v[3], int v_min, int v_max, ImStrv format = "%d", ImGuiSliderFlags flags = 0); IMGUI_API bool SliderInt4(ImStrv label, int v[4], int v_min, int v_max, ImStrv format = "%d", ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderScalar(ImStrv label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, ImStrv format = NULL, ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderScalarN(ImStrv label, ImGuiDataType data_type, void* p_data, int components, const void* p_min, const void* p_max, ImStrv format = NULL, ImGuiSliderFlags flags = 0); + IMGUI_API bool SliderScalar(ImStrv label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, ImStrv format = ImStrv(), ImGuiSliderFlags flags = 0); + IMGUI_API bool SliderScalarN(ImStrv label, ImGuiDataType data_type, void* p_data, int components, const void* p_min, const void* p_max, ImStrv format = ImStrv(), ImGuiSliderFlags flags = 0); IMGUI_API bool VSliderFloat(ImStrv label, const ImVec2& size, float* v, float v_min, float v_max, ImStrv format = "%.3f", ImGuiSliderFlags flags = 0); IMGUI_API bool VSliderInt(ImStrv label, const ImVec2& size, int* v, int v_min, int v_max, ImStrv format = "%d", ImGuiSliderFlags flags = 0); - IMGUI_API bool VSliderScalar(ImStrv label, const ImVec2& size, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, ImStrv format = NULL, ImGuiSliderFlags flags = 0); + IMGUI_API bool VSliderScalar(ImStrv label, const ImVec2& size, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, ImStrv format = ImStrv(), ImGuiSliderFlags flags = 0); // Widgets: Input with Keyboard // - If you want to use InputText() with std::string or any custom dynamic string type, use the wrapper in misc/cpp/imgui_stdlib.h/.cpp! @@ -762,8 +762,8 @@ namespace ImGui IMGUI_API bool InputInt3(ImStrv label, int v[3], ImGuiInputTextFlags flags = 0); IMGUI_API bool InputInt4(ImStrv label, int v[4], ImGuiInputTextFlags flags = 0); IMGUI_API bool InputDouble(ImStrv label, double* v, double step = 0.0, double step_fast = 0.0, ImStrv format = "%.6f", ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputScalar(ImStrv label, ImGuiDataType data_type, void* p_data, const void* p_step = NULL, const void* p_step_fast = NULL, ImStrv format = NULL, ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputScalarN(ImStrv label, ImGuiDataType data_type, void* p_data, int components, const void* p_step = NULL, const void* p_step_fast = NULL, ImStrv format = NULL, ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputScalar(ImStrv label, ImGuiDataType data_type, void* p_data, const void* p_step = NULL, const void* p_step_fast = NULL, ImStrv format = ImStrv(), ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputScalarN(ImStrv label, ImGuiDataType data_type, void* p_data, int components, const void* p_step = NULL, const void* p_step_fast = NULL, ImStrv format = ImStrv(), ImGuiInputTextFlags flags = 0); // Widgets: Color Editor/Picker (tip: the ColorEdit* functions have a little color square that can be left-clicked to open a picker, and right-clicked to open an option menu.) // - Note that in C++ a 'float v[X]' function argument is the _same_ as 'float* v', the array syntax is just a way to document the number of elements that are expected to be accessible. @@ -828,17 +828,17 @@ namespace ImGui // Widgets: Data Plotting // - Consider using ImPlot (https://github.com/epezent/implot) which is much better! - IMGUI_API void PlotLines(ImStrv label, const float* values, int values_count, int values_offset = 0, ImStrv overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0), int stride = sizeof(float)); - IMGUI_API void PlotLines(ImStrv label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, ImStrv overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0)); - IMGUI_API void PlotHistogram(ImStrv label, const float* values, int values_count, int values_offset = 0, ImStrv overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0), int stride = sizeof(float)); - IMGUI_API void PlotHistogram(ImStrv label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, ImStrv overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0)); + IMGUI_API void PlotLines(ImStrv label, const float* values, int values_count, int values_offset = 0, ImStrv overlay_text = ImStrv(), float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0), int stride = sizeof(float)); + IMGUI_API void PlotLines(ImStrv label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, ImStrv overlay_text = ImStrv(), float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0)); + IMGUI_API void PlotHistogram(ImStrv label, const float* values, int values_count, int values_offset = 0, ImStrv overlay_text = ImStrv(), float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0), int stride = sizeof(float)); + IMGUI_API void PlotHistogram(ImStrv label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, ImStrv overlay_text = ImStrv(), float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0)); // Widgets: Value() Helpers. // - Those are merely shortcut to calling Text() with a format string. Output single value in "name: value" format (tip: freely declare more in your code to handle your types. you can add functions to the ImGui namespace) IMGUI_API void Value(ImStrv prefix, bool b); IMGUI_API void Value(ImStrv prefix, int v); IMGUI_API void Value(ImStrv prefix, unsigned int v); - IMGUI_API void Value(ImStrv prefix, float v, ImStrv float_format = NULL); + IMGUI_API void Value(ImStrv prefix, float v, ImStrv float_format = ImStrv()); // Widgets: Menus // - Use BeginMenuBar() on a window ImGuiWindowFlags_MenuBar to append to its menu bar. @@ -851,8 +851,8 @@ namespace ImGui IMGUI_API void EndMainMenuBar(); // only call EndMainMenuBar() if BeginMainMenuBar() returns true! IMGUI_API bool BeginMenu(ImStrv label, bool enabled = true); // create a sub-menu entry. only call EndMenu() if this returns true! IMGUI_API void EndMenu(); // only call EndMenu() if BeginMenu() returns true! - IMGUI_API bool MenuItem(ImStrv label, ImStrv shortcut = NULL, bool selected = false, bool enabled = true); // return true when activated. - IMGUI_API bool MenuItem(ImStrv label, ImStrv shortcut, bool* p_selected, bool enabled = true); // return true when activated + toggle (*p_selected) if p_selected != NULL + IMGUI_API bool MenuItem(ImStrv label, ImStrv shortcut = ImStrv(), bool selected = false, bool enabled = true); // return true when activated. + IMGUI_API bool MenuItem(ImStrv label, ImStrv shortcut, bool* p_selected, bool enabled = true); // return true when activated + toggle (*p_selected) if p_selected != NULL // Tooltips // - Tooltips are windows following the mouse. They do not take focus away. @@ -896,7 +896,7 @@ namespace ImGui // - Use IsWindowAppearing() after BeginPopup() to tell if a window just opened. IMGUI_API bool OpenPopup(ImStrv str_id, ImGuiPopupFlags popup_flags = 0); // call to mark popup as open (don't call every frame!). IMGUI_API bool OpenPopup(ImGuiID id, ImGuiPopupFlags popup_flags = 0); // id overload to facilitate calling from nested stacks - IMGUI_API bool OpenPopupOnItemClick(ImStrv str_id = NULL, ImGuiPopupFlags popup_flags = 0); // helper to open popup when clicked on last item. Default to ImGuiPopupFlags_MouseButtonRight == 1. (note: actually triggers on the mouse _released_ event to be consistent with popup behaviors) + IMGUI_API bool OpenPopupOnItemClick(ImStrv str_id = ImStrv(), ImGuiPopupFlags popup_flags = 0); // helper to open popup when clicked on last item. Default to ImGuiPopupFlags_MouseButtonRight == 1. (note: actually triggers on the mouse _released_ event to be consistent with popup behaviors) IMGUI_API void CloseCurrentPopup(); // manually close the popup we have begin-ed into. // Popups: Open+Begin popup combined functions helpers to create context menus. @@ -908,15 +908,15 @@ namespace ImGui // - After: The default = 0 means ImGuiPopupFlags_MouseButtonRight. Explicitly passing a literal 1 also means ImGuiPopupFlags_MouseButtonRight (if legacy behavior are enabled) or will assert (if legacy behavior are disabled). // - TL;DR: if you don't want to use right mouse button for popups, always specify it explicitly using a named ImGuiPopupFlags_MouseButtonXXXX value. // - Read "API BREAKING CHANGES" 2026/01/07 (1.92.6) entry in imgui.cpp or GitHub topic #9157 for all details. - IMGUI_API bool BeginPopupContextItem(ImStrv str_id = NULL, ImGuiPopupFlags popup_flags = 0); // open+begin popup when clicked on last item. Use str_id==NULL to associate the popup to previous item. If you want to use that on a non-interactive item such as Text() you need to pass in an explicit ID here. read comments in .cpp! - IMGUI_API bool BeginPopupContextWindow(ImStrv str_id = NULL, ImGuiPopupFlags popup_flags = 0); // open+begin popup when clicked on current window. - IMGUI_API bool BeginPopupContextVoid(ImStrv str_id = NULL, ImGuiPopupFlags popup_flags = 0); // open+begin popup when clicked in void (where there are no windows). + IMGUI_API bool BeginPopupContextItem(ImStrv str_id = ImStrv(), ImGuiPopupFlags popup_flags = 0); // open+begin popup when clicked on last item. Use str_id==NULL to associate the popup to previous item. If you want to use that on a non-interactive item such as Text() you need to pass in an explicit ID here. read comments in .cpp! + IMGUI_API bool BeginPopupContextWindow(ImStrv str_id = ImStrv(), ImGuiPopupFlags popup_flags = 0); // open+begin popup when clicked on current window. + IMGUI_API bool BeginPopupContextVoid(ImStrv str_id = ImStrv(), ImGuiPopupFlags popup_flags = 0); // open+begin popup when clicked in void (where there are no windows). // Popups: query functions // - IsPopupOpen(): return true if the popup is open at the current BeginPopup() level of the popup stack. // - IsPopupOpen() with ImGuiPopupFlags_AnyPopupId: return true if any popup is open at the current BeginPopup() level of the popup stack. // - IsPopupOpen() with ImGuiPopupFlags_AnyPopupId + ImGuiPopupFlags_AnyPopupLevel: return true if any popup is open. - IMGUI_API bool IsPopupOpen(ImStrv str_id, ImGuiPopupFlags flags = 0); // return true if the popup is open. + IMGUI_API bool IsPopupOpen(ImStrv str_id, ImGuiPopupFlags flags = 0); // return true if the popup is open. // Tables // - Full-featured replacement for old Columns API. @@ -978,7 +978,7 @@ namespace ImGui // Legacy Columns API (prefer using Tables!) // - You can also use SameLine(pos_x) to mimic simplified columns. - IMGUI_API void Columns(int count = 1, ImStrv id = NULL, bool borders = true); + IMGUI_API void Columns(int count = 1, ImStrv id = ImStrv(), bool borders = true); IMGUI_API void NextColumn(); // next column, defaults to current row or next row if the current row is finished IMGUI_API int GetColumnIndex(); // get current column index IMGUI_API float GetColumnWidth(int column_index = -1); // get column width (in pixels). pass -1 to use current column @@ -999,7 +999,7 @@ namespace ImGui // Logging/Capture // - All text output from the interface can be captured into tty/file/clipboard. By default, tree nodes are automatically opened during logging. IMGUI_API void LogToTTY(int auto_open_depth = -1); // start logging to tty (stdout) - IMGUI_API void LogToFile(int auto_open_depth = -1, ImStrv filename = NULL); // start logging to file + IMGUI_API void LogToFile(int auto_open_depth = -1, ImStrv filename = ImStrv()); // start logging to file IMGUI_API void LogToClipboard(int auto_open_depth = -1); // start logging to OS clipboard IMGUI_API void LogFinish(); // stop logging (close file, etc.) IMGUI_API void LogButtons(); // helper to display buttons for logging to tty/file/clipboard @@ -4310,7 +4310,7 @@ namespace ImGui //static inline bool ListBoxHeader(const char* label, int items_count, int height_in_items = -1) { float height = GetTextLineHeightWithSpacing() * ((height_in_items < 0 ? ImMin(items_count, 7) : height_in_items) + 0.25f) + GetStyle().FramePadding.y * 2.0f; return BeginListBox(label, ImVec2(0.0f, height)); } // Helper to calculate size from items_count and height_in_items //static inline void ListBoxFooter() { EndListBox(); } //-- OBSOLETED in 1.79 (from August 2020) - //static inline void OpenPopupContextItem(ImStrv str_id = NULL, ImGuiMouseButton mb = 1) { OpenPopupOnItemClick(str_id, mb); } // Bool return value removed. Use IsWindowAppearing() in BeginPopup() instead. Renamed in 1.77, renamed back in 1.79. Sorry! + //static inline void OpenPopupContextItem(ImStrv str_id = ImStrv(), ImGuiMouseButton mb = 1) { OpenPopupOnItemClick(str_id, mb); } // Bool return value removed. Use IsWindowAppearing() in BeginPopup() instead. Renamed in 1.77, renamed back in 1.79. Sorry! //-- OBSOLETED in 1.78 (from June 2020): Old drag/sliders functions that took a 'float power > 1.0f' argument instead of ImGuiSliderFlags_Logarithmic. See github.com/ocornut/imgui/issues/3361 for details. //IMGUI_API bool DragScalar(const char* label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min, const void* p_max, const char* format, float power = 1.0f) // OBSOLETED in 1.78 (from June 2020) //IMGUI_API bool DragScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, float v_speed, const void* p_min, const void* p_max, const char* format, float power = 1.0f); // OBSOLETED in 1.78 (from June 2020) diff --git a/imgui_internal.h b/imgui_internal.h index 7322fb0f0..268d4c415 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3606,7 +3606,7 @@ namespace ImGui // Menus IMGUI_API bool BeginViewportSideBar(ImStrv name, ImGuiViewport* viewport, ImGuiDir dir, float size, ImGuiWindowFlags window_flags); IMGUI_API bool BeginMenuEx(ImStrv label, ImStrv icon, bool enabled = true); - IMGUI_API bool MenuItemEx(ImStrv label, ImStrv icon, ImStrv shortcut = NULL, bool selected = false, bool enabled = true); + IMGUI_API bool MenuItemEx(ImStrv label, ImStrv icon, ImStrv shortcut = ImStrv(), bool selected = false, bool enabled = true); // Combos IMGUI_API bool BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags flags); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 1fcabad93..1718e3e07 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -9604,7 +9604,7 @@ bool ImGui::BeginMenuEx(ImStrv label, ImStrv icon, bool enabled) // Menu inside a regular/vertical menu // (In a typical menu window where all items are BeginMenu() or MenuItem() calls, extra_w will always be 0.0f. // Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system.) - float icon_w = !icon.empty() ? CalcTextSize(icon, NULL).x : 0.0f; + float icon_w = !icon.empty() ? CalcTextSize(icon).x : 0.0f; float checkmark_w = IM_TRUNC(g.FontSize * 1.20f); float min_w = offsets->DeclColumns(icon_w, label_size.x, 0.0f, checkmark_w); // Feedback to next frame float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w); From 1845eabf8626f861b9abfc4a7a3fd9ca36a7eb0c Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 31 Mar 2021 15:06:32 +0200 Subject: [PATCH 04/15] ImStrv: moved double char* function signatures under #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS blocks + fixed various compiles errors/warnings. --- imgui.cpp | 48 ++++++++++++++++++----------------------------- imgui.h | 45 ++++++++++++++++++++++++++++---------------- imgui_draw.cpp | 4 ++-- imgui_tables.cpp | 8 ++++---- imgui_widgets.cpp | 8 ++++---- 5 files changed, 57 insertions(+), 56 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 21af587c1..27891609f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9535,14 +9535,6 @@ void ImGui::PushID(ImStrv str_id) window->IDStack.push_back(id); } -void ImGui::PushID(const char* str_id_begin, const char* str_id_end) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - ImGuiID id = window->GetID(ImStrv(str_id_begin, str_id_end)); - window->IDStack.push_back(id); -} - void ImGui::PushID(const void* ptr_id) { ImGuiContext& g = *GImGui; @@ -9609,12 +9601,6 @@ ImGuiID ImGui::GetID(ImStrv str_id) return window->GetID(str_id); } -ImGuiID ImGui::GetID(const char* str_id_begin, const char* str_id_end) -{ - ImGuiWindow* window = GImGui->CurrentWindow; - return window->GetID(ImStrv(str_id_begin, str_id_end)); -} - ImGuiID ImGui::GetID(const void* ptr_id) { ImGuiWindow* window = GImGui->CurrentWindow; @@ -12622,7 +12608,7 @@ bool ImGui::OpenPopup(ImStrv str_id, ImGuiPopupFlags popup_flags) { ImGuiContext& g = *GImGui; ImGuiID id = g.CurrentWindow->GetID(str_id); - IMGUI_DEBUG_LOG_POPUP("[popup] OpenPopup(\"%.*s\" -> 0x%08X\n", (int)(str_id.End - str_id.Begin), str_id, id); + IMGUI_DEBUG_LOG_POPUP("[popup] OpenPopup(\"%.*s\" -> 0x%08X\n", (int)(str_id.End - str_id.Begin), str_id.Begin, id); return OpenPopupEx(id, popup_flags); } @@ -16654,7 +16640,8 @@ void ImGui::DebugRenderViewportThumbnail(ImDrawList* draw_list, ImGuiViewportP* window->DrawList->AddRectFilled(thumb_r.Min, thumb_r.Max, GetColorU32(ImGuiCol_WindowBg, alpha_mul)); window->DrawList->AddRectFilled(title_r.Min, title_r.Max, GetColorU32(window_is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg, alpha_mul)); window->DrawList->AddRect(thumb_r.Min, thumb_r.Max, GetColorU32(ImGuiCol_Border, alpha_mul)); - window->DrawList->AddText(g.Font, g.FontSize * 1.0f, title_r.Min, GetColorU32(ImGuiCol_Text, alpha_mul), thumb_window->Name, FindRenderedTextEnd(thumb_window->Name)); + ImStrv label(thumb_window->Name, FindRenderedTextEnd(thumb_window->Name)); + window->DrawList->AddText(g.Font, g.FontSize * 1.0f, title_r.Min, GetColorU32(ImGuiCol_Text, alpha_mul), label); } draw_list->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border, alpha_mul)); if (viewport->ID == g.DebugMetricsConfig.HighlightViewportID) @@ -16733,7 +16720,7 @@ void ImGui::DebugRenderKeyboardPreview(ImDrawList* draw_list) // Helper tool to diagnose between text encoding issues and font loading issues. Pass your UTF-8 string and verify that there are correct. void ImGui::DebugTextEncoding(ImStrv str) { - Text("Text: \"%s\"", str); + Text("Text: \"%.*s\"", (int)str.length(), str.Begin); if (!BeginTable("##DebugTextEncoding", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable)) return; TableSetupColumn("Offset"); @@ -16746,7 +16733,7 @@ void ImGui::DebugTextEncoding(ImStrv str) unsigned int c; const int c_utf8_len = ImTextCharFromUtf8(&c, p, str.End); // As we may receive malformed UTF-8, pass an explicit end instead of relying on ImTextCharFromUtf8() assuming enough space. TableNextColumn(); - Text("%d", (int)(size_t)(p - str)); + Text("%d", (int)(p - str.Begin)); TableNextColumn(); for (int byte_index = 0; byte_index < c_utf8_len; byte_index++) { @@ -16755,7 +16742,7 @@ void ImGui::DebugTextEncoding(ImStrv str) Text("0x%02X", (int)(unsigned char)p[byte_index]); } TableNextColumn(); - TextUnformatted(p, p + c_utf8_len); + TextUnformatted(ImStrv(p, p + c_utf8_len)); if (!GetFont()->IsGlyphInFont((ImWchar)c)) { SameLine(); @@ -16945,10 +16932,10 @@ void ImGui::ShowFontAtlas(ImFontAtlas* atlas) ImFontAtlasRectId id = ImFontAtlasRectId_Make(atlas->Builder->RectsIndex.index_from_ptr(&entry), entry.Generation); ImFontAtlasRect r = {}; atlas->GetCustomRect(id, &r); - const char* buf; - ImFormatStringToTempBuffer(&buf, NULL, "ID:%08X, used:%d, { w:%3d, h:%3d } { x:%4d, y:%4d }", id, entry.IsUsed, r.w, r.h, r.x, r.y); + ImStrv buf; + ImFormatStringToTempBuffer(&buf, "ID:%08X, used:%d, { w:%3d, h:%3d } { x:%4d, y:%4d }", id, entry.IsUsed, r.w, r.h, r.x, r.y); TableNextColumn(); - Selectable(buf); + Selectable(buf.Begin); if (IsItemHovered()) highlight_r_id = id; TableNextColumn(); @@ -18620,28 +18607,28 @@ void ImGui::DebugHookIdInfo(ImGuiID id, ImGuiDataType data_type, const void* dat if (info->DescOffset == -1) { - const char* result = NULL; - const char* result_end = NULL; + ImStrv result; switch (data_type) { case ImGuiDataType_S32: - ImFormatStringToTempBuffer(&result, &result_end, "%d", (int)(intptr_t)data_id); + ImFormatStringToTempBuffer(&result, "%d", (int)(intptr_t)data_id); break; case ImGuiDataType_String: - ImFormatStringToTempBuffer(&result, &result_end, "%.*s", data_id_end ? (int)((const char*)data_id_end - (const char*)data_id) : (int)ImStrlen((const char*)data_id), (const char*)data_id); + ImFormatStringToTempBuffer(&result, "%.*s", data_id_end ? (int)((const char*)data_id_end - (const char*)data_id) : (int)ImStrlen((const char*)data_id), (const char*)data_id); break; case ImGuiDataType_Pointer: - ImFormatStringToTempBuffer(&result, &result_end, "(void*)0x%p", data_id); + ImFormatStringToTempBuffer(&result, "(void*)0x%p", data_id); break; case ImGuiDataType_ID: // PushOverrideID() is often used to avoid hashing twice, which would lead to 2 calls to DebugHookIdInfo(). We prioritize the first one. - ImFormatStringToTempBuffer(&result, &result_end, "0x%08X [override]", id); + ImFormatStringToTempBuffer(&result, "0x%08X [override]", id); break; default: IM_ASSERT(0); } info->DescOffset = query->ResultsDescBuf.size(); - query->ResultsDescBuf.append(result, result_end + 1); // Include zero terminator + result.End++; // Include zero terminator + query->ResultsDescBuf.append(result); } info->QuerySuccess = true; if (info->DataType == -1) @@ -18681,7 +18668,7 @@ static const char* DebugItemPathQuery_GetResultAsPath(ImGuiDebugItemPathQuery* q if (c == '/') buf->append("\\"); if (c < 256 || !hex_encode_non_ascii_chars) - buf->append(p, p_next); + buf->append(ImStrv(p, p_next)); else for (; p < p_next; p++) buf->appendf("\\x%02x", (unsigned char)*p); p = p_next; @@ -18707,6 +18694,7 @@ void ImGui::ShowIDStackToolWindow(bool* p_open) tool->LastActiveFrame = g.FrameCount; const char* result_path = DebugItemPathQuery_GetResultAsPath(query, tool->OptHexEncodeNonAsciiChars); Text("0x%08X", query->MainID); + SameLine(); MetricsHelpMarker("Hover an item with the mouse to display elements of the ID Stack leading to the item's final ID.\nEach level of the stack correspond to a PushID() call.\nAll levels of the stack are hashed together to make the final ID of a widget (ID displayed at the bottom level of the stack).\nRead FAQ entry about the ID stack for details."); diff --git a/imgui.h b/imgui.h index a146f841a..c5be3af37 100644 --- a/imgui.h +++ b/imgui.h @@ -636,12 +636,10 @@ namespace ImGui // - In this header file we use the "label"/"name" terminology to denote a string that will be displayed + used as an ID, // whereas "str_id" denote a string that is only used as an ID and not normally displayed. IMGUI_API void PushID(ImStrv str_id); // push string into the ID stack (will hash string). - IMGUI_API void PushID(const char* str_id_begin, const char* str_id_end = NULL);// push string into the ID stack (will hash string). IMGUI_API void PushID(const void* ptr_id); // push pointer into the ID stack (will hash pointer). IMGUI_API void PushID(int int_id); // push integer into the ID stack (will hash integer). IMGUI_API void PopID(); // pop from the ID stack. IMGUI_API ImGuiID GetID(ImStrv str_id); // calculate unique ID (hash of whole ID stack + given parameter). e.g. if you want to query into ImGuiStorage yourself - IMGUI_API ImGuiID GetID(const char* str_id_begin, const char* str_id_end = NULL); IMGUI_API ImGuiID GetID(const void* ptr_id); IMGUI_API ImGuiID GetID(int int_id); @@ -649,7 +647,6 @@ namespace ImGui // - Note that all functions taking format strings in the API may be passed ("%s", text) or ("%.*s", text_len, text): which will automatically bypass the formatter. // FIXME-IMSTR: Functions taking format should use ImStrv. It will however break the IM_FMTARGS() macros. IMGUI_API void TextUnformatted(ImStrv text); // raw text without formatting. Practically equivalent to 'Text("%s", text)' but doesn't require null terminated string if 'text_end' is specified. - inline void TextUnformatted(const char* text, const char* text_end) { TextUnformatted(ImStrv(text, text_end)); } IMGUI_API void Text(const char* fmt, ...) IM_FMTARGS(1); // formatted text IMGUI_API void TextV(const char* fmt, va_list args) IM_FMTLIST(1); IMGUI_API void TextColored(const ImVec4& col, const char* fmt, ...) IM_FMTARGS(2); // shortcut for PushStyleColor(ImGuiCol_Text, col); Text(fmt, ...); PopStyleColor(); @@ -1087,7 +1084,6 @@ namespace ImGui // Text Utilities IMGUI_API ImVec2 CalcTextSize(ImStrv text, bool hide_text_after_double_hash = false, float wrap_width = -1.0f); - inline ImVec2 CalcTextSize(const char* text, const char* text_end, bool hide_text_after_double_hash = false, float wrap_width = -1.0f) { return CalcTextSize(ImStrv(text, text_end), hide_text_after_double_hash, wrap_width); } // Color Utilities IMGUI_API ImVec4 ColorConvertU32ToFloat4(ImU32 in); @@ -2760,11 +2756,13 @@ struct ImGuiInputTextCallbackData IMGUI_API ImGuiInputTextCallbackData(); IMGUI_API void DeleteChars(int pos, int bytes_count); IMGUI_API void InsertChars(int pos, ImStrv text); - inline void InsertChars(int pos, const char* text, const char* text_end) { InsertChars(pos, ImStrv(text, text_end)); } void SelectAll() { SelectionStart = 0; SelectionEnd = BufTextLen; } void SetSelection(int s, int e) { IM_ASSERT(s >= 0 && s <= BufTextLen); IM_ASSERT(e >= 0 && e <= BufTextLen); SelectionStart = s; CursorPos = SelectionEnd = e; } void ClearSelection() { SelectionStart = SelectionEnd = BufTextLen; } bool HasSelection() const { return SelectionStart != SelectionEnd; } +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + inline void InsertChars(int pos, const char* text, const char* text_end) { InsertChars(pos, ImStrv(text, text_end)); } +#endif }; // Resizing callback data to apply custom constraint. As enabled by SetNextWindowSizeConstraints(). Callback is called during the next Begin(). @@ -2824,6 +2822,7 @@ struct ImGuiOnceUponAFrame struct ImGuiTextFilterItem; struct ImGuiTextFilter { + // Functions IMGUI_API ImGuiTextFilter(ImStrv default_filter = ""); IMGUI_API bool PassFilter(ImStrv label) const; IMGUI_API void Build(); // Update internal data when filter changes @@ -2862,9 +2861,11 @@ struct ImGuiTextBuffer void reserve(int capacity) { Buf.reserve(capacity); } const char* c_str() const { return Buf.Data ? Buf.Data : EmptyString; } IMGUI_API void append(ImStrv str); - inline void append(const char* str, const char* str_end) { append(ImStrv(str, str_end)); } IMGUI_API void appendf(const char* fmt, ...) IM_FMTARGS(2); IMGUI_API void appendfv(const char* fmt, va_list args) IM_FMTLIST(2); +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + inline void append(const char* str, const char* str_end) { append(ImStrv(str, str_end)); } +#endif }; // [Internal] Key+Value for ImGuiStorage @@ -3498,9 +3499,7 @@ struct ImDrawList IMGUI_API void AddEllipse(const ImVec2& center, const ImVec2& radius, ImU32 col, float rot = 0.0f, int num_segments = 0, float thickness = 1.0f, ImDrawFlags flags = 0); IMGUI_API void AddEllipseFilled(const ImVec2& center, const ImVec2& radius, ImU32 col, float rot = 0.0f, int num_segments = 0); IMGUI_API void AddText(const ImVec2& pos, ImU32 col, ImStrv text); - inline void AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end) { AddText(NULL, 0.0f, pos, col, ImStrv(text_begin, text_end)); } IMGUI_API void AddText(ImFont* font, float font_size, const ImVec2& pos, ImU32 col, ImStrv text, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL); - inline void AddText(ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL) { AddText(font, font_size, pos, col, ImStrv(text_begin, text_end), wrap_width, cpu_fine_clip_rect); } IMGUI_API void AddBezierCubic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments = 0, ImDrawFlags flags = 0); // Cubic Bezier (4 control points) IMGUI_API void AddBezierQuadratic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col, float thickness, int num_segments = 0, ImDrawFlags flags = 0); // Quadratic Bezier (3 control points) @@ -3511,6 +3510,11 @@ struct ImDrawList IMGUI_API void AddConvexPolyFilled(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags = 0); IMGUI_API void AddConcavePolyFilled(const ImVec2* points, int num_points, ImU32 col); +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + inline void AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end) { AddText(NULL, 0.0f, pos, col, ImStrv(text_begin, text_end)); } + inline void AddText(ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL) { AddText(font, font_size, pos, col, ImStrv(text_begin, text_end), wrap_width, cpu_fine_clip_rect); } +#endif + // Image primitives // - Read FAQ to understand what ImTextureID/ImTextureRef are. // - "p_min" and "p_max" represent the upper-left and lower-right corners of the rectangle. @@ -3801,9 +3805,12 @@ struct ImFontGlyphRangesBuilder inline void SetBit(size_t n) { int off = (int)(n >> 5); ImU32 mask = 1u << (n & 31); UsedChars[off] |= mask; } // Set bit n in the array inline void AddChar(ImWchar c) { SetBit(c); } // Add character IMGUI_API void AddText(ImStrv text); // Add string (each character of the UTF-8 string are added) - inline void AddText(const char* text, const char* text_end = NULL) { AddText(ImStrv(text, text_end)); } IMGUI_API void AddRanges(const ImWchar* ranges); // Add ranges, e.g. builder.AddRanges(ImFontAtlas::GetGlyphRangesDefault()) to force add all of ASCII/Latin+Ext IMGUI_API void BuildRanges(ImVector* out_ranges); // Output new ranges + +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + inline void AddText(const char* text, const char* text_end = NULL) { AddText(ImStrv(text, text_end)); } +#endif }; // An opaque identifier to a rectangle in the atlas. -1 when invalid. @@ -4087,16 +4094,17 @@ struct ImFont // 'max_width' stops rendering after a certain width (could be turned into a 2d size). FLT_MAX to disable. // 'wrap_width' enable automatic word-wrapping across multiple lines to fit into given width. 0.0f to disable. IMGUI_API ImFontBaked* GetFontBaked(float font_size, float density = -1.0f); // Get or create baked data for given size + IMGUI_API ImVec2 CalcTextSizeA(float size, float max_width, float wrap_width, ImStrv text, const char** remaining = NULL); // utf8 + IMGUI_API const char* CalcWordWrapPosition(float scale, ImStrv text, float wrap_width); IMGUI_API void RenderChar(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, ImWchar c, const ImVec4* cpu_fine_clip = NULL); IMGUI_API void RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, const ImVec4& clip_rect, ImStrv text, float wrap_width = 0.0f, ImDrawTextFlags flags = 0); inline void RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width = 0.0f, ImDrawTextFlags flags = 0) { RenderText(draw_list, size, pos, col, clip_rect, ImStrv(text_begin, text_end), wrap_width, flags); } - IMGUI_API ImVec2 CalcTextSizeA(float size, float max_width, float wrap_width, ImStrv text, const char** remaining = NULL); // utf8 - IMGUI_API const char* CalcWordWrapPosition(float scale, ImStrv text, float wrap_width); #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - inline ImVec2 CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end, const char** remaining = NULL) { return CalcTextSizeA(size, max_width, wrap_width, ImStrv(text_begin, text_end), remaining); } - inline const char* CalcWordWrapPosition(float size, const char* text, const char* text_end, float wrap_width) { return CalcWordWrapPosition(size, ImStrv(text, text_end), wrap_width); } - inline const char* CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) { return CalcWordWrapPosition(LegacySize * scale, ImStrv(text, text_end), wrap_width); } // Obsoleted old name in 1.92.0. Note how `scale` was to `size`. + inline ImVec2 CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end, const char** remaining = NULL) { return CalcTextSizeA(size, max_width, wrap_width, ImStrv(text_begin, text_end), remaining); } + inline const char* CalcWordWrapPosition(float size, const char* text, const char* text_end, float wrap_width) { return CalcWordWrapPosition(size, ImStrv(text, text_end), wrap_width); } + inline const char* CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) { return CalcWordWrapPosition(LegacySize * scale, ImStrv(text, text_end), wrap_width); } // Obsoleted old name in 1.92.0. Note how `scale` was to `size`. + inline void RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width = 0.0f, bool cpu_fine_clip = false) { RenderText(draw_list, size, pos, col, clip_rect, ImStrv(text_begin, text_end), wrap_width, cpu_fine_clip); } #endif // [Internal] Don't use! @@ -4261,6 +4269,11 @@ struct ImGuiPlatformImeData #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS namespace ImGui { + // OBSOLETED in 1.XX (string_view branch) + inline void PushID(const char* str_id_begin, const char* str_id_end){ PushID(ImStrv(str_id_begin, str_id_end)); } + inline ImGuiID GetID(const char* str_id_begin, const char* str_id_end) { return GetID(ImStrv(str_id_begin, str_id_end)); } + inline void TextUnformatted(const char* text, const char* text_end) { TextUnformatted(ImStrv(text, text_end)); } + inline ImVec2 CalcTextSize(const char* text, const char* text_end, bool hide_text_after_double_hash = false, float wrap_width = -1.0f) { return CalcTextSize(ImStrv(text, text_end), hide_text_after_double_hash, wrap_width); } // OBSOLETED in 1.92.9 (from July 2026) IMGUI_API void SetColorEditOptions(ImGuiColorEditFlags flags); // set current options for if you want to select a default format, picker type, etc. User will be able to change those settings, unless you pass the _NoOptions flag to your calls. // OBSOLETED in 1.92.0 (from June 2025) @@ -4281,8 +4294,8 @@ namespace ImGui //inline void PushTabStop(bool tab_stop) { PushItemFlag(ImGuiItemFlags_NoTabStop, !tab_stop); } //inline void PopTabStop() { PopItemFlag(); } // OBSOLETED in 1.90.0 (from September 2023) - //IMGUI_API bool Combo(const char* label, int* current_item, bool (*old_callback)(void* user_data, int idx, const char** out_text), void* user_data, int items_count, int popup_max_height_in_items = -1); // Getter signature changed. See 2023/09/15 and 2026/02/27 commits. - //IMGUI_API bool ListBox(const char* label, int* current_item, bool (*old_callback)(void* user_data, int idx, const char** out_text), void* user_data, int items_count, int height_in_items = -1); // Getter signature changed. See 2023/09/15 and 2026/02/27 commits. + //IMGUI_API bool Combo(ImStrv label, int* current_item, bool (*old_callback)(void* user_data, int idx, const char** out_text), void* user_data, int items_count, int popup_max_height_in_items = -1); // Getter signature changed. See 2023/09/15 and 2026/02/27 commits. + //IMGUI_API bool ListBox(ImStrv label, int* current_item, bool (*old_callback)(void* user_data, int idx, const char** out_text), void* user_data, int items_count, int height_in_items = -1); // Getter signature changed. See 2023/09/15 and 2026/02/27 commits. //inline bool BeginChild(const char* str_id, const ImVec2& size_arg, bool borders, ImGuiWindowFlags window_flags) { return BeginChild(str_id, size_arg, borders ? ImGuiChildFlags_Borders : ImGuiChildFlags_None, window_flags); } // Unnecessary as true == ImGuiChildFlags_Borders //inline bool BeginChild(ImGuiID id, const ImVec2& size_arg, bool borders, ImGuiWindowFlags window_flags) { return BeginChild(id, size_arg, borders ? ImGuiChildFlags_Borders : ImGuiChildFlags_None, window_flags); } // Unnecessary as true == ImGuiChildFlags_Borders //inline bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags flags = 0) { return BeginChild(id, size, ImGuiChildFlags_FrameStyle, flags); } diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 84f61e426..dbed7b510 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -4475,7 +4475,7 @@ ImFont* ImFontAtlas::AddFontFromFileTTF(ImStrv filename, float size_pixels, cons { if (font_cfg_template == NULL || (font_cfg_template->Flags & ImFontFlags_NoLoadError) == 0) { - IMGUI_DEBUG_LOG("While loading '%s'\n", filename); + IMGUI_DEBUG_LOG("While loading '%.*s'\n", filename.length(), filename.Begin); IM_ASSERT_USER_ERROR(0, "Could not load font file!"); } return NULL; @@ -7371,7 +7371,7 @@ begin: } else { - s = line_end ? line_end + 1 : text.End; + s = line_end ? line_end + 1 : text_end; } y += line_height; } diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 4fda9eef9..acbdcf859 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1748,8 +1748,8 @@ void ImGui::TableSetupColumn(ImStrv label, ImGuiTableColumnFlags flags, float in { char zero_terminator = 0; name_offset = (ImS16)table->ColumnsNames.size(); - table->ColumnsNames.append(label.Begin, label.End); - table->ColumnsNames.append(&zero_terminator, &zero_terminator + 1); + table->ColumnsNames.append(label); + table->ColumnsNames.append(ImStrv(&zero_terminator, &zero_terminator + 1)); } const ImGuiID column_id = label ? ImHashStr(label) : 0; @@ -3339,8 +3339,8 @@ void ImGui::TableHeader(ImStrv label) if (!label) label = ""; ImGuiID id = window->GetID(label); - ImStrv label_for_display(label.Begin, FindRenderedTextEnd(label)); - ImVec2 label_size = CalcTextSize(label_for_display, false); + const ImStrv label_for_display(label.Begin, FindRenderedTextEnd(label)); + const ImVec2 label_size = CalcTextSize(label_for_display, false); ImVec2 label_pos = window->DC.CursorPos; // If we already got a row height, there's use that. diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 1718e3e07..701592b02 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -210,7 +210,7 @@ void ImGui::TextEx(ImStrv text, ImGuiTextFlags flags) if (!line_end) line_end = text_end; if ((flags & ImGuiTextFlags_NoWidthForLargeClippedText) == 0) - text_size.x = ImMax(text_size.x, CalcTextSize(line, line_end).x); + text_size.x = ImMax(text_size.x, CalcTextSize(ImStrv(line, line_end)).x); line = line_end + 1; lines_skipped++; } @@ -230,7 +230,7 @@ void ImGui::TextEx(ImStrv text, ImGuiTextFlags flags) const char* line_end = (const char*)ImMemchr(line, '\n', text_end - line); if (!line_end) line_end = text_end; - text_size.x = ImMax(text_size.x, CalcTextSize(line, line_end).x); + text_size.x = ImMax(text_size.x, CalcTextSize(ImStrv(line, line_end)).x); RenderText(pos, ImStrv(line, line_end), false); line = line_end + 1; line_rect.Min.y += line_height; @@ -246,7 +246,7 @@ void ImGui::TextEx(ImStrv text, ImGuiTextFlags flags) if (!line_end) line_end = text_end; if ((flags & ImGuiTextFlags_NoWidthForLargeClippedText) == 0) - text_size.x = ImMax(text_size.x, CalcTextSize(line, line_end).x); + text_size.x = ImMax(text_size.x, CalcTextSize(ImStrv(line, line_end)).x); line = line_end + 1; lines_skipped++; } @@ -10862,9 +10862,9 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, ImStrv label, bool* p_open, ImGui } else { + char zero_c = 0; tab->NameOffset = (ImS32)tab_bar->TabsNames.size(); tab_bar->TabsNames.append(label_for_display); - char zero_c = 0; tab_bar->TabsNames.append(ImStrv(&zero_c, &zero_c + 1)); } From 84971a499327dbc499a5b10dd9405b6e852033a4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 25 May 2021 14:08:20 +0200 Subject: [PATCH 05/15] ImStrv: standardized code doing format copy, optimized ImStrStr --- imgui.cpp | 21 +++++++-------- imgui_widgets.cpp | 69 ++++++++++++++++++++++++++++++++--------------- 2 files changed, 57 insertions(+), 33 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 27891609f..3bcb3c9f3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2397,22 +2397,19 @@ const char* ImStristr(const char* haystack, const char* haystack_end, const char return NULL; } -// FIXME-IMSTR: probably unneeded. const char* ImStrstr(ImStrv haystack, ImStrv needle) { const char un0 = (char)*needle.Begin; - while ((!haystack.End && *haystack.Begin) || (haystack.End && haystack.Begin < haystack.End)) + const char* p = haystack.Begin; + const size_t needle_len_m1 = needle.length() - 1; + while (true) { - if (*haystack.Begin == un0) - { - const char* b = needle.Begin + 1; - for (const char* a = haystack.Begin + 1; b < needle.End; a++, b++) - if (*a != *b) - break; - if (b == needle.End) - return haystack.Begin; - } - haystack.Begin++; + p = (const char*)memchr(p, un0, haystack.End - p); + if (p == NULL || (size_t)(haystack.End - p) - 1u < needle_len_m1) + return NULL; + if (needle_len_m1 == 0 || memcmp(p + 1, needle.Begin + 1, needle_len_m1) == 0) + return p; + p += 1; } return NULL; } diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 701592b02..ae306d802 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -2768,14 +2768,20 @@ bool ImGui::DragScalar(ImStrv label, ImGuiDataType data_type, void* p_data, floa return false; // FIXME-IMSTR - char format_0[64]; // format may not end with \0 - const char* format = format_0; - IM_ASSERT(format_p.End - format_p.Begin < IM_ARRAYSIZE(format_0)); - ImStrncpy(format_0, format_p, IM_ARRAYSIZE(format_0)); - - // Default format string when passing NULL + const char* format; + char format_buf[64]; if (!format_p) + { + // Default format string when passing NULL format = DataTypeGetInfo(data_type)->PrintFmt; + } + else + { + // Copy format string (format may not be zero-terminated) + format = format_buf; + IM_ASSERT(format_p.End - format_p.Begin < IM_ARRAYSIZE(format_buf)); + ImStrncpy(format_buf, format_p, IM_ARRAYSIZE(format_buf)); + } const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.ItemFlags); bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id); @@ -3392,13 +3398,20 @@ bool ImGui::SliderScalar(ImStrv label, ImGuiDataType data_type, void* p_data, co return false; // FIXME-IMSTR - char format_0[64]; // format may not end with \0 - const char* format = format_0; - IM_ASSERT(format_p.End - format_p.Begin < IM_ARRAYSIZE(format_0)); - - // Default format string when passing NULL + const char* format; + char format_buf[64]; if (!format_p) + { + // Default format string when passing NULL format = DataTypeGetInfo(data_type)->PrintFmt; + } + else + { + // Copy format string (format may not be zero-terminated) + format = format_buf; + IM_ASSERT(format_p.End - format_p.Begin < IM_ARRAYSIZE(format_buf)); + ImStrncpy(format_buf, format_p, IM_ARRAYSIZE(format_buf)); + } const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.ItemFlags); bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id); @@ -3579,13 +3592,20 @@ bool ImGui::VSliderScalar(ImStrv label, const ImVec2& size, ImGuiDataType data_t return false; // FIXME-IMSTR - char format_0[64]; // format may not end with \0 - const char* format = format_0; - IM_ASSERT(format_p.End - format_p.Begin < IM_ARRAYSIZE(format_0)); - - // Default format string when passing NULL + const char* format; + char format_buf[64]; if (!format_p) + { + // Default format string when passing NULL format = DataTypeGetInfo(data_type)->PrintFmt; + } + else + { + // Copy format string (format may not be zero-terminated) + format = format_buf; + IM_ASSERT(format_p.End - format_p.Begin < IM_ARRAYSIZE(format_buf)); + ImStrncpy(format_buf, format_p, IM_ARRAYSIZE(format_buf)); + } const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.ItemFlags); const bool clicked = hovered && IsMouseClicked(0, ImGuiInputFlags_None, id); @@ -3891,13 +3911,20 @@ bool ImGui::InputScalar(ImStrv label, ImGuiDataType data_type, void* p_data, con //IM_ASSERT((flags & ImGuiInputTextFlags_EnterReturnsTrue) == 0); // Not supported by InputScalar(). Please open an issue if you this would be useful to you. Otherwise use IsItemDeactivatedAfterEdit()! // FIXME-IMSTR - char format_0[64]; // format may not end with \0 - const char* format = format_0; - IM_ASSERT(format_p.End - format_p.Begin < IM_ARRAYSIZE(format_0)); - ImStrncpy(format_0, format_p, IM_ARRAYSIZE(format_0)); - + const char* format; + char format_buf[64]; if (!format_p) + { + // Default format string when passing NULL format = DataTypeGetInfo(data_type)->PrintFmt; + } + else + { + // Copy format string (format may not be zero-terminated) + format = format_buf; + IM_ASSERT(format_p.End - format_p.Begin < IM_ARRAYSIZE(format_buf)); + ImStrncpy(format_buf, format_p, IM_ARRAYSIZE(format_buf)); + } void* p_data_default = (g.NextItemData.HasFlags & ImGuiNextItemDataFlags_HasRefVal) ? &g.NextItemData.RefVal : &g.DataTypeZeroValue; From 4d477b5084a208df339edf928a6efd8b613432be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=92=80=E5=A2=83=E7=9F=B3?= Date: Mon, 22 Aug 2022 11:05:58 +0200 Subject: [PATCH 06/15] ImStrv: enhanced VS debugger .natvis support. build fixes. (5333, 5906) --- imgui.cpp | 6 +++--- misc/debuggers/imgui.natvis | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 3bcb3c9f3..767153cb9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -18381,7 +18381,7 @@ void ImGui::ShowDebugLogWindow(bool* p_open) // Display line, search for 0xXXXXXXXX identifiers and call DebugLocateItemOnHover() when hovered. void ImGui::DebugTextUnformattedWithLocateItem(const char* line_begin, const char* line_end) { - TextUnformatted(line_begin, line_end); + TextUnformatted(ImStrv(line_begin, line_end)); if (!IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) return; ImGuiContext& g = *GImGui; @@ -18391,8 +18391,8 @@ void ImGui::DebugTextUnformattedWithLocateItem(const char* line_begin, const cha ImGuiID id = 0; if (p[0] != '0' || (p[1] != 'x' && p[1] != 'X') || sscanf(p + 2, "%X", &id) != 1 || ImCharIsXdigitA(p[10])) continue; - ImVec2 p0 = CalcTextSize(line_begin, p); - ImVec2 p1 = CalcTextSize(p, p + 10); + ImVec2 p0 = CalcTextSize(ImStrv(line_begin, p)); + ImVec2 p1 = CalcTextSize(ImStrv(p, p + 10)); g.LastItemData.Rect = ImRect(text_rect.Min + ImVec2(p0.x, 0.0f), text_rect.Min + ImVec2(p0.x + p1.x, p1.y)); if (IsMouseHoveringRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, true)) DebugLocateItemOnHover(id); diff --git a/misc/debuggers/imgui.natvis b/misc/debuggers/imgui.natvis index 7d0c9dd1a..8dbc7eacf 100644 --- a/misc/debuggers/imgui.natvis +++ b/misc/debuggers/imgui.natvis @@ -53,7 +53,8 @@ More information at: https://docs.microsoft.com/en-us/visualstudio/debugger/crea - {Begin,[End-Begin]s} ({End-Begin,d}) + {Begin,[End-Begin]s8} ({End-Begin,d}) + Begin,[End-Begin]s8 From 09f7ec1ba599846f3577c32177a7b2bab24f3e02 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 25 Aug 2022 12:54:07 +0200 Subject: [PATCH 07/15] ImStrv: backtracked for now on supporting ImStrv for format strings. It's widely incomplete and slow, requires a printf function taking non-zero-terminated format string to work. Might do it eventually but it's much less a problem than labels. Format string are more frequently inlined in code and tend to be small, so existing solutions at call site can work better for now. --- imgui.h | 67 ++++++++++++------------ imgui_widgets.cpp | 129 ++++++++++++++-------------------------------- 2 files changed, 73 insertions(+), 123 deletions(-) diff --git a/imgui.h b/imgui.h index c5be3af37..3f30a8b0c 100644 --- a/imgui.h +++ b/imgui.h @@ -645,7 +645,6 @@ namespace ImGui // Widgets: Text // - Note that all functions taking format strings in the API may be passed ("%s", text) or ("%.*s", text_len, text): which will automatically bypass the formatter. - // FIXME-IMSTR: Functions taking format should use ImStrv. It will however break the IM_FMTARGS() macros. IMGUI_API void TextUnformatted(ImStrv text); // raw text without formatting. Practically equivalent to 'Text("%s", text)' but doesn't require null terminated string if 'text_end' is specified. IMGUI_API void Text(const char* fmt, ...) IM_FMTARGS(1); // formatted text IMGUI_API void TextV(const char* fmt, va_list args) IM_FMTLIST(1); @@ -709,18 +708,18 @@ namespace ImGui // - We use the same sets of flags for DragXXX() and SliderXXX() functions as the features are the same and it makes it easier to swap them. // - Legacy: Pre-1.78 there are DragXXX() function signatures that take a final `float power=1.0f' argument instead of the `ImGuiSliderFlags flags=0' argument. // If you get a warning converting a float to ImGuiSliderFlags, read https://github.com/ocornut/imgui/issues/3361 - IMGUI_API bool DragFloat(ImStrv label, float* v, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, ImStrv format = "%.3f", ImGuiSliderFlags flags = 0); // If v_min >= v_max we have no bound - IMGUI_API bool DragFloat2(ImStrv label, float v[2], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, ImStrv format = "%.3f", ImGuiSliderFlags flags = 0); - IMGUI_API bool DragFloat3(ImStrv label, float v[3], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, ImStrv format = "%.3f", ImGuiSliderFlags flags = 0); - IMGUI_API bool DragFloat4(ImStrv label, float v[4], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, ImStrv format = "%.3f", ImGuiSliderFlags flags = 0); - IMGUI_API bool DragFloatRange2(ImStrv label, float* v_current_min, float* v_current_max, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, ImStrv format = "%.3f", ImStrv format_max = ImStrv(), ImGuiSliderFlags flags = 0); - IMGUI_API bool DragInt(ImStrv label, int* v, float v_speed = 1.0f, int v_min = 0, int v_max = 0, ImStrv format = "%d", ImGuiSliderFlags flags = 0); // If v_min >= v_max we have no bound - IMGUI_API bool DragInt2(ImStrv label, int v[2], float v_speed = 1.0f, int v_min = 0, int v_max = 0, ImStrv format = "%d", ImGuiSliderFlags flags = 0); - IMGUI_API bool DragInt3(ImStrv label, int v[3], float v_speed = 1.0f, int v_min = 0, int v_max = 0, ImStrv format = "%d", ImGuiSliderFlags flags = 0); - IMGUI_API bool DragInt4(ImStrv label, int v[4], float v_speed = 1.0f, int v_min = 0, int v_max = 0, ImStrv format = "%d", ImGuiSliderFlags flags = 0); - IMGUI_API bool DragIntRange2(ImStrv label, int* v_current_min, int* v_current_max, float v_speed = 1.0f, int v_min = 0, int v_max = 0, ImStrv format = "%d", ImStrv format_max = ImStrv(), ImGuiSliderFlags flags = 0); - IMGUI_API bool DragScalar(ImStrv label, ImGuiDataType data_type, void* p_data, float v_speed = 1.0f, const void* p_min = NULL, const void* p_max = NULL, ImStrv format = ImStrv(), ImGuiSliderFlags flags = 0); - IMGUI_API bool DragScalarN(ImStrv label, ImGuiDataType data_type, void* p_data, int components, float v_speed = 1.0f, const void* p_min = NULL, const void* p_max = NULL, ImStrv format = ImStrv(), ImGuiSliderFlags flags = 0); + IMGUI_API bool DragFloat(ImStrv label, float* v, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", ImGuiSliderFlags flags = 0); // If v_min >= v_max we have no bound + IMGUI_API bool DragFloat2(ImStrv label, float v[2], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", ImGuiSliderFlags flags = 0); + IMGUI_API bool DragFloat3(ImStrv label, float v[3], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", ImGuiSliderFlags flags = 0); + IMGUI_API bool DragFloat4(ImStrv label, float v[4], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", ImGuiSliderFlags flags = 0); + IMGUI_API bool DragFloatRange2(ImStrv label, float* v_current_min, float* v_current_max, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", const char* format_max = NULL, ImGuiSliderFlags flags = 0); + IMGUI_API bool DragInt(ImStrv label, int* v, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", ImGuiSliderFlags flags = 0); // If v_min >= v_max we have no bound + IMGUI_API bool DragInt2(ImStrv label, int v[2], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", ImGuiSliderFlags flags = 0); + IMGUI_API bool DragInt3(ImStrv label, int v[3], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", ImGuiSliderFlags flags = 0); + IMGUI_API bool DragInt4(ImStrv label, int v[4], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", ImGuiSliderFlags flags = 0); + IMGUI_API bool DragIntRange2(ImStrv label, int* v_current_min, int* v_current_max, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", const char* format_max = NULL, ImGuiSliderFlags flags = 0); + IMGUI_API bool DragScalar(ImStrv label, ImGuiDataType data_type, void* p_data, float v_speed = 1.0f, const void* p_min = NULL, const void* p_max = NULL, const char* format = NULL, ImGuiSliderFlags flags = 0); + IMGUI_API bool DragScalarN(ImStrv label, ImGuiDataType data_type, void* p_data, int components, float v_speed = 1.0f, const void* p_min = NULL, const void* p_max = NULL, const char* format = NULL, ImGuiSliderFlags flags = 0); // Widgets: Regular Sliders // - Ctrl+Click on any slider to turn them into an input box. Manually input values aren't clamped by default and can go off-bounds. Use ImGuiSliderFlags_AlwaysClamp to always clamp. @@ -728,20 +727,20 @@ namespace ImGui // - Format string may also be set to NULL or use the default format ("%f" or "%d"). // - Legacy: Pre-1.78 there are SliderXXX() function signatures that take a final `float power=1.0f' argument instead of the `ImGuiSliderFlags flags=0' argument. // If you get a warning converting a float to ImGuiSliderFlags, read https://github.com/ocornut/imgui/issues/3361 - IMGUI_API bool SliderFloat(ImStrv label, float* v, float v_min, float v_max, ImStrv format = "%.3f", ImGuiSliderFlags flags = 0); // adjust format to decorate the value with a prefix or a suffix for in-slider labels or unit display. - IMGUI_API bool SliderFloat2(ImStrv label, float v[2], float v_min, float v_max, ImStrv format = "%.3f", ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderFloat3(ImStrv label, float v[3], float v_min, float v_max, ImStrv format = "%.3f", ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderFloat4(ImStrv label, float v[4], float v_min, float v_max, ImStrv format = "%.3f", ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderAngle(ImStrv label, float* v_rad, float v_degrees_min = -360.0f, float v_degrees_max = +360.0f, ImStrv format = "%.0f deg", ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderInt(ImStrv label, int* v, int v_min, int v_max, ImStrv format = "%d", ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderInt2(ImStrv label, int v[2], int v_min, int v_max, ImStrv format = "%d", ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderInt3(ImStrv label, int v[3], int v_min, int v_max, ImStrv format = "%d", ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderInt4(ImStrv label, int v[4], int v_min, int v_max, ImStrv format = "%d", ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderScalar(ImStrv label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, ImStrv format = ImStrv(), ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderScalarN(ImStrv label, ImGuiDataType data_type, void* p_data, int components, const void* p_min, const void* p_max, ImStrv format = ImStrv(), ImGuiSliderFlags flags = 0); - IMGUI_API bool VSliderFloat(ImStrv label, const ImVec2& size, float* v, float v_min, float v_max, ImStrv format = "%.3f", ImGuiSliderFlags flags = 0); - IMGUI_API bool VSliderInt(ImStrv label, const ImVec2& size, int* v, int v_min, int v_max, ImStrv format = "%d", ImGuiSliderFlags flags = 0); - IMGUI_API bool VSliderScalar(ImStrv label, const ImVec2& size, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, ImStrv format = ImStrv(), ImGuiSliderFlags flags = 0); + IMGUI_API bool SliderFloat(ImStrv label, float* v, float v_min, float v_max, const char* format = "%.3f", ImGuiSliderFlags flags = 0); // adjust format to decorate the value with a prefix or a suffix for in-slider labels or unit display. + IMGUI_API bool SliderFloat2(ImStrv label, float v[2], float v_min, float v_max, const char* format = "%.3f", ImGuiSliderFlags flags = 0); + IMGUI_API bool SliderFloat3(ImStrv label, float v[3], float v_min, float v_max, const char* format = "%.3f", ImGuiSliderFlags flags = 0); + IMGUI_API bool SliderFloat4(ImStrv label, float v[4], float v_min, float v_max, const char* format = "%.3f", ImGuiSliderFlags flags = 0); + IMGUI_API bool SliderAngle(ImStrv label, float* v_rad, float v_degrees_min = -360.0f, float v_degrees_max = +360.0f, const char* format = "%.0f deg", ImGuiSliderFlags flags = 0); + IMGUI_API bool SliderInt(ImStrv label, int* v, int v_min, int v_max, const char* format = "%d", ImGuiSliderFlags flags = 0); + IMGUI_API bool SliderInt2(ImStrv label, int v[2], int v_min, int v_max, const char* format = "%d", ImGuiSliderFlags flags = 0); + IMGUI_API bool SliderInt3(ImStrv label, int v[3], int v_min, int v_max, const char* format = "%d", ImGuiSliderFlags flags = 0); + IMGUI_API bool SliderInt4(ImStrv label, int v[4], int v_min, int v_max, const char* format = "%d", ImGuiSliderFlags flags = 0); + IMGUI_API bool SliderScalar(ImStrv label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format = NULL, ImGuiSliderFlags flags = 0); + IMGUI_API bool SliderScalarN(ImStrv label, ImGuiDataType data_type, void* p_data, int components, const void* p_min, const void* p_max, const char* format = NULL, ImGuiSliderFlags flags = 0); + IMGUI_API bool VSliderFloat(ImStrv label, const ImVec2& size, float* v, float v_min, float v_max, const char* format = "%.3f", ImGuiSliderFlags flags = 0); + IMGUI_API bool VSliderInt(ImStrv label, const ImVec2& size, int* v, int v_min, int v_max, const char* format = "%d", ImGuiSliderFlags flags = 0); + IMGUI_API bool VSliderScalar(ImStrv label, const ImVec2& size, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format = NULL, ImGuiSliderFlags flags = 0); // Widgets: Input with Keyboard // - If you want to use InputText() with std::string or any custom dynamic string type, use the wrapper in misc/cpp/imgui_stdlib.h/.cpp! @@ -750,17 +749,17 @@ namespace ImGui IMGUI_API bool InputText(ImStrv label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); IMGUI_API bool InputTextMultiline(ImStrv label, char* buf, size_t buf_size, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); IMGUI_API bool InputTextWithHint(ImStrv label, ImStrv hint, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); - IMGUI_API bool InputFloat(ImStrv label, float* v, float step = 0.0f, float step_fast = 0.0f, ImStrv format = "%.3f", ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputFloat2(ImStrv label, float v[2], ImStrv format = "%.3f", ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputFloat3(ImStrv label, float v[3], ImStrv format = "%.3f", ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputFloat4(ImStrv label, float v[4], ImStrv format = "%.3f", ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputFloat(ImStrv label, float* v, float step = 0.0f, float step_fast = 0.0f, const char* format = "%.3f", ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputFloat2(ImStrv label, float v[2], const char* format = "%.3f", ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputFloat3(ImStrv label, float v[3], const char* format = "%.3f", ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputFloat4(ImStrv label, float v[4], const char* format = "%.3f", ImGuiInputTextFlags flags = 0); IMGUI_API bool InputInt(ImStrv label, int* v, int step = 1, int step_fast = 100, ImGuiInputTextFlags flags = 0); IMGUI_API bool InputInt2(ImStrv label, int v[2], ImGuiInputTextFlags flags = 0); IMGUI_API bool InputInt3(ImStrv label, int v[3], ImGuiInputTextFlags flags = 0); IMGUI_API bool InputInt4(ImStrv label, int v[4], ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputDouble(ImStrv label, double* v, double step = 0.0, double step_fast = 0.0, ImStrv format = "%.6f", ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputScalar(ImStrv label, ImGuiDataType data_type, void* p_data, const void* p_step = NULL, const void* p_step_fast = NULL, ImStrv format = ImStrv(), ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputScalarN(ImStrv label, ImGuiDataType data_type, void* p_data, int components, const void* p_step = NULL, const void* p_step_fast = NULL, ImStrv format = ImStrv(), ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputDouble(ImStrv label, double* v, double step = 0.0, double step_fast = 0.0, const char* format = "%.6f", ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputScalar(ImStrv label, ImGuiDataType data_type, void* p_data, const void* p_step = NULL, const void* p_step_fast = NULL, const char* format = NULL, ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputScalarN(ImStrv label, ImGuiDataType data_type, void* p_data, int components, const void* p_step = NULL, const void* p_step_fast = NULL, const char* format = NULL, ImGuiInputTextFlags flags = 0); // Widgets: Color Editor/Picker (tip: the ColorEdit* functions have a little color square that can be left-clicked to open a picker, and right-clicked to open an option menu.) // - Note that in C++ a 'float v[X]' function argument is the _same_ as 'float* v', the array syntax is just a way to document the number of elements that are expected to be accessible. diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index ae306d802..100497560 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -2745,7 +2745,7 @@ static bool TempInputIsClampEnabled(ImGuiSliderFlags flags, ImGuiDataType data_t // Note: p_data, p_min and p_max are _pointers_ to a memory address holding the data. For a Drag widget, p_min and p_max are optional. // Read code of e.g. DragFloat(), DragInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly. -bool ImGui::DragScalar(ImStrv label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min, const void* p_max, ImStrv format_p, ImGuiSliderFlags flags) +bool ImGui::DragScalar(ImStrv label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -2767,21 +2767,9 @@ bool ImGui::DragScalar(ImStrv label, ImGuiDataType data_type, void* p_data, floa if (!ItemAdd(total_bb, id, &frame_bb, temp_input_allowed ? ImGuiItemFlags_Inputable : 0)) return false; - // FIXME-IMSTR - const char* format; - char format_buf[64]; - if (!format_p) - { - // Default format string when passing NULL + // Default format string when passing NULL + if (format == NULL) format = DataTypeGetInfo(data_type)->PrintFmt; - } - else - { - // Copy format string (format may not be zero-terminated) - format = format_buf; - IM_ASSERT(format_p.End - format_p.Begin < IM_ARRAYSIZE(format_buf)); - ImStrncpy(format_buf, format_p, IM_ARRAYSIZE(format_buf)); - } const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.ItemFlags); bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id); @@ -2857,7 +2845,7 @@ bool ImGui::DragScalar(ImStrv label, ImGuiDataType data_type, void* p_data, floa return value_changed; } -bool ImGui::DragScalarN(ImStrv label, ImGuiDataType data_type, void* p_data, int components, float v_speed, const void* p_min, const void* p_max, ImStrv format, ImGuiSliderFlags flags) +bool ImGui::DragScalarN(ImStrv label, ImGuiDataType data_type, void* p_data, int components, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -2894,28 +2882,28 @@ bool ImGui::DragScalarN(ImStrv label, ImGuiDataType data_type, void* p_data, int return value_changed; } -bool ImGui::DragFloat(ImStrv label, float* v, float v_speed, float v_min, float v_max, ImStrv format, ImGuiSliderFlags flags) +bool ImGui::DragFloat(ImStrv label, float* v, float v_speed, float v_min, float v_max, const char* format, ImGuiSliderFlags flags) { return DragScalar(label, ImGuiDataType_Float, v, v_speed, &v_min, &v_max, format, flags); } -bool ImGui::DragFloat2(ImStrv label, float v[2], float v_speed, float v_min, float v_max, ImStrv format, ImGuiSliderFlags flags) +bool ImGui::DragFloat2(ImStrv label, float v[2], float v_speed, float v_min, float v_max, const char* format, ImGuiSliderFlags flags) { return DragScalarN(label, ImGuiDataType_Float, v, 2, v_speed, &v_min, &v_max, format, flags); } -bool ImGui::DragFloat3(ImStrv label, float v[3], float v_speed, float v_min, float v_max, ImStrv format, ImGuiSliderFlags flags) +bool ImGui::DragFloat3(ImStrv label, float v[3], float v_speed, float v_min, float v_max, const char* format, ImGuiSliderFlags flags) { return DragScalarN(label, ImGuiDataType_Float, v, 3, v_speed, &v_min, &v_max, format, flags); } -bool ImGui::DragFloat4(ImStrv label, float v[4], float v_speed, float v_min, float v_max, ImStrv format, ImGuiSliderFlags flags) +bool ImGui::DragFloat4(ImStrv label, float v[4], float v_speed, float v_min, float v_max, const char* format, ImGuiSliderFlags flags) { return DragScalarN(label, ImGuiDataType_Float, v, 4, v_speed, &v_min, &v_max, format, flags); } // NB: You likely want to specify the ImGuiSliderFlags_AlwaysClamp when using this. -bool ImGui::DragFloatRange2(ImStrv label, float* v_current_min, float* v_current_max, float v_speed, float v_min, float v_max, ImStrv format, ImStrv format_max, ImGuiSliderFlags flags) +bool ImGui::DragFloatRange2(ImStrv label, float* v_current_min, float* v_current_max, float v_speed, float v_min, float v_max, const char* format, const char* format_max, ImGuiSliderFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -2949,28 +2937,28 @@ bool ImGui::DragFloatRange2(ImStrv label, float* v_current_min, float* v_current } // NB: v_speed is float to allow adjusting the drag speed with more precision -bool ImGui::DragInt(ImStrv label, int* v, float v_speed, int v_min, int v_max, ImStrv format, ImGuiSliderFlags flags) +bool ImGui::DragInt(ImStrv label, int* v, float v_speed, int v_min, int v_max, const char* format, ImGuiSliderFlags flags) { return DragScalar(label, ImGuiDataType_S32, v, v_speed, &v_min, &v_max, format, flags); } -bool ImGui::DragInt2(ImStrv label, int v[2], float v_speed, int v_min, int v_max, ImStrv format, ImGuiSliderFlags flags) +bool ImGui::DragInt2(ImStrv label, int v[2], float v_speed, int v_min, int v_max, const char* format, ImGuiSliderFlags flags) { return DragScalarN(label, ImGuiDataType_S32, v, 2, v_speed, &v_min, &v_max, format, flags); } -bool ImGui::DragInt3(ImStrv label, int v[3], float v_speed, int v_min, int v_max, ImStrv format, ImGuiSliderFlags flags) +bool ImGui::DragInt3(ImStrv label, int v[3], float v_speed, int v_min, int v_max, const char* format, ImGuiSliderFlags flags) { return DragScalarN(label, ImGuiDataType_S32, v, 3, v_speed, &v_min, &v_max, format, flags); } -bool ImGui::DragInt4(ImStrv label, int v[4], float v_speed, int v_min, int v_max, ImStrv format, ImGuiSliderFlags flags) +bool ImGui::DragInt4(ImStrv label, int v[4], float v_speed, int v_min, int v_max, const char* format, ImGuiSliderFlags flags) { return DragScalarN(label, ImGuiDataType_S32, v, 4, v_speed, &v_min, &v_max, format, flags); } // NB: You likely want to specify the ImGuiSliderFlags_AlwaysClamp when using this. -bool ImGui::DragIntRange2(ImStrv label, int* v_current_min, int* v_current_max, float v_speed, int v_min, int v_max, ImStrv format, ImStrv format_max, ImGuiSliderFlags flags) +bool ImGui::DragIntRange2(ImStrv label, int* v_current_min, int* v_current_max, float v_speed, int v_min, int v_max, const char* format, const char* format_max, ImGuiSliderFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -3375,7 +3363,7 @@ bool ImGui::SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type // Note: p_data, p_min and p_max are _pointers_ to a memory address holding the data. For a slider, they are all required. // Read code of e.g. SliderFloat(), SliderInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly. -bool ImGui::SliderScalar(ImStrv label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, ImStrv format_p, ImGuiSliderFlags flags) +bool ImGui::SliderScalar(ImStrv label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -3397,21 +3385,9 @@ bool ImGui::SliderScalar(ImStrv label, ImGuiDataType data_type, void* p_data, co if (!ItemAdd(total_bb, id, &frame_bb, temp_input_allowed ? ImGuiItemFlags_Inputable : 0)) return false; - // FIXME-IMSTR - const char* format; - char format_buf[64]; - if (!format_p) - { - // Default format string when passing NULL + // Default format string when passing NULL + if (format == NULL) format = DataTypeGetInfo(data_type)->PrintFmt; - } - else - { - // Copy format string (format may not be zero-terminated) - format = format_buf; - IM_ASSERT(format_p.End - format_p.Begin < IM_ARRAYSIZE(format_buf)); - ImStrncpy(format_buf, format_p, IM_ARRAYSIZE(format_buf)); - } const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.ItemFlags); bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id); @@ -3484,7 +3460,7 @@ bool ImGui::SliderScalar(ImStrv label, ImGuiDataType data_type, void* p_data, co } // Add multiple sliders on 1 line for compact edition of multiple components -bool ImGui::SliderScalarN(ImStrv label, ImGuiDataType data_type, void* v, int components, const void* v_min, const void* v_max, ImStrv format, ImGuiSliderFlags flags) +bool ImGui::SliderScalarN(ImStrv label, ImGuiDataType data_type, void* v, int components, const void* v_min, const void* v_max, const char* format, ImGuiSliderFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -3521,27 +3497,27 @@ bool ImGui::SliderScalarN(ImStrv label, ImGuiDataType data_type, void* v, int co return value_changed; } -bool ImGui::SliderFloat(ImStrv label, float* v, float v_min, float v_max, ImStrv format, ImGuiSliderFlags flags) +bool ImGui::SliderFloat(ImStrv label, float* v, float v_min, float v_max, const char* format, ImGuiSliderFlags flags) { return SliderScalar(label, ImGuiDataType_Float, v, &v_min, &v_max, format, flags); } -bool ImGui::SliderFloat2(ImStrv label, float v[2], float v_min, float v_max, ImStrv format, ImGuiSliderFlags flags) +bool ImGui::SliderFloat2(ImStrv label, float v[2], float v_min, float v_max, const char* format, ImGuiSliderFlags flags) { return SliderScalarN(label, ImGuiDataType_Float, v, 2, &v_min, &v_max, format, flags); } -bool ImGui::SliderFloat3(ImStrv label, float v[3], float v_min, float v_max, ImStrv format, ImGuiSliderFlags flags) +bool ImGui::SliderFloat3(ImStrv label, float v[3], float v_min, float v_max, const char* format, ImGuiSliderFlags flags) { return SliderScalarN(label, ImGuiDataType_Float, v, 3, &v_min, &v_max, format, flags); } -bool ImGui::SliderFloat4(ImStrv label, float v[4], float v_min, float v_max, ImStrv format, ImGuiSliderFlags flags) +bool ImGui::SliderFloat4(ImStrv label, float v[4], float v_min, float v_max, const char* format, ImGuiSliderFlags flags) { return SliderScalarN(label, ImGuiDataType_Float, v, 4, &v_min, &v_max, format, flags); } -bool ImGui::SliderAngle(ImStrv label, float* v_rad, float v_degrees_min, float v_degrees_max, ImStrv format, ImGuiSliderFlags flags) +bool ImGui::SliderAngle(ImStrv label, float* v_rad, float v_degrees_min, float v_degrees_max, const char* format, ImGuiSliderFlags flags) { if (!format) format = "%.0f deg"; @@ -3552,27 +3528,27 @@ bool ImGui::SliderAngle(ImStrv label, float* v_rad, float v_degrees_min, float v return value_changed; } -bool ImGui::SliderInt(ImStrv label, int* v, int v_min, int v_max, ImStrv format, ImGuiSliderFlags flags) +bool ImGui::SliderInt(ImStrv label, int* v, int v_min, int v_max, const char* format, ImGuiSliderFlags flags) { return SliderScalar(label, ImGuiDataType_S32, v, &v_min, &v_max, format, flags); } -bool ImGui::SliderInt2(ImStrv label, int v[2], int v_min, int v_max, ImStrv format, ImGuiSliderFlags flags) +bool ImGui::SliderInt2(ImStrv label, int v[2], int v_min, int v_max, const char* format, ImGuiSliderFlags flags) { return SliderScalarN(label, ImGuiDataType_S32, v, 2, &v_min, &v_max, format, flags); } -bool ImGui::SliderInt3(ImStrv label, int v[3], int v_min, int v_max, ImStrv format, ImGuiSliderFlags flags) +bool ImGui::SliderInt3(ImStrv label, int v[3], int v_min, int v_max, const char* format, ImGuiSliderFlags flags) { return SliderScalarN(label, ImGuiDataType_S32, v, 3, &v_min, &v_max, format, flags); } -bool ImGui::SliderInt4(ImStrv label, int v[4], int v_min, int v_max, ImStrv format, ImGuiSliderFlags flags) +bool ImGui::SliderInt4(ImStrv label, int v[4], int v_min, int v_max, const char* format, ImGuiSliderFlags flags) { return SliderScalarN(label, ImGuiDataType_S32, v, 4, &v_min, &v_max, format, flags); } -bool ImGui::VSliderScalar(ImStrv label, const ImVec2& size, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, ImStrv format_p, ImGuiSliderFlags flags) +bool ImGui::VSliderScalar(ImStrv label, const ImVec2& size, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -3591,21 +3567,9 @@ bool ImGui::VSliderScalar(ImStrv label, const ImVec2& size, ImGuiDataType data_t if (!ItemAdd(frame_bb, id)) return false; - // FIXME-IMSTR - const char* format; - char format_buf[64]; - if (!format_p) - { - // Default format string when passing NULL + // Default format string when passing NULL + if (format == NULL) format = DataTypeGetInfo(data_type)->PrintFmt; - } - else - { - // Copy format string (format may not be zero-terminated) - format = format_buf; - IM_ASSERT(format_p.End - format_p.Begin < IM_ARRAYSIZE(format_buf)); - ImStrncpy(format_buf, format_p, IM_ARRAYSIZE(format_buf)); - } const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.ItemFlags); const bool clicked = hovered && IsMouseClicked(0, ImGuiInputFlags_None, id); @@ -3652,12 +3616,12 @@ bool ImGui::VSliderScalar(ImStrv label, const ImVec2& size, ImGuiDataType data_t return value_changed; } -bool ImGui::VSliderFloat(ImStrv label, const ImVec2& size, float* v, float v_min, float v_max, ImStrv format, ImGuiSliderFlags flags) +bool ImGui::VSliderFloat(ImStrv label, const ImVec2& size, float* v, float v_min, float v_max, const char* format, ImGuiSliderFlags flags) { return VSliderScalar(label, size, ImGuiDataType_Float, v, &v_min, &v_max, format, flags); } -bool ImGui::VSliderInt(ImStrv label, const ImVec2& size, int* v, int v_min, int v_max, ImStrv format, ImGuiSliderFlags flags) +bool ImGui::VSliderInt(ImStrv label, const ImVec2& size, int* v, int v_min, int v_max, const char* format, ImGuiSliderFlags flags) { return VSliderScalar(label, size, ImGuiDataType_S32, v, &v_min, &v_max, format, flags); } @@ -3900,7 +3864,7 @@ void ImGui::SetNextItemRefVal(ImGuiDataType data_type, void* p_data) // Note: p_data, p_step, p_step_fast are _pointers_ to a memory address holding the data. For an Input widget, p_step and p_step_fast are optional. // Read code of e.g. InputFloat(), InputInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly. -bool ImGui::InputScalar(ImStrv label, ImGuiDataType data_type, void* p_data, const void* p_step, const void* p_step_fast, ImStrv format_p, ImGuiInputTextFlags flags) +bool ImGui::InputScalar(ImStrv label, ImGuiDataType data_type, void* p_data, const void* p_step, const void* p_step_fast, const char* format, ImGuiInputTextFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -3910,21 +3874,8 @@ bool ImGui::InputScalar(ImStrv label, ImGuiDataType data_type, void* p_data, con ImGuiStyle& style = g.Style; //IM_ASSERT((flags & ImGuiInputTextFlags_EnterReturnsTrue) == 0); // Not supported by InputScalar(). Please open an issue if you this would be useful to you. Otherwise use IsItemDeactivatedAfterEdit()! - // FIXME-IMSTR - const char* format; - char format_buf[64]; - if (!format_p) - { - // Default format string when passing NULL + if (format == NULL) format = DataTypeGetInfo(data_type)->PrintFmt; - } - else - { - // Copy format string (format may not be zero-terminated) - format = format_buf; - IM_ASSERT(format_p.End - format_p.Begin < IM_ARRAYSIZE(format_buf)); - ImStrncpy(format_buf, format_p, IM_ARRAYSIZE(format_buf)); - } void* p_data_default = (g.NextItemData.HasFlags & ImGuiNextItemDataFlags_HasRefVal) ? &g.NextItemData.RefVal : &g.DataTypeZeroValue; @@ -4024,7 +3975,7 @@ bool ImGui::InputScalar(ImStrv label, ImGuiDataType data_type, void* p_data, con return value_changed; } -bool ImGui::InputScalarN(ImStrv label, ImGuiDataType data_type, void* p_data, int components, const void* p_step, const void* p_step_fast, ImStrv format, ImGuiInputTextFlags flags) +bool ImGui::InputScalarN(ImStrv label, ImGuiDataType data_type, void* p_data, int components, const void* p_step, const void* p_step_fast, const char* format, ImGuiInputTextFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -4059,22 +4010,22 @@ bool ImGui::InputScalarN(ImStrv label, ImGuiDataType data_type, void* p_data, in return value_changed; } -bool ImGui::InputFloat(ImStrv label, float* v, float step, float step_fast, ImStrv format, ImGuiInputTextFlags flags) +bool ImGui::InputFloat(ImStrv label, float* v, float step, float step_fast, const char* format, ImGuiInputTextFlags flags) { return InputScalar(label, ImGuiDataType_Float, (void*)v, (void*)(step > 0.0f ? &step : NULL), (void*)(step_fast > 0.0f ? &step_fast : NULL), format, flags); } -bool ImGui::InputFloat2(ImStrv label, float v[2], ImStrv format, ImGuiInputTextFlags flags) +bool ImGui::InputFloat2(ImStrv label, float v[2], const char* format, ImGuiInputTextFlags flags) { return InputScalarN(label, ImGuiDataType_Float, v, 2, NULL, NULL, format, flags); } -bool ImGui::InputFloat3(ImStrv label, float v[3], ImStrv format, ImGuiInputTextFlags flags) +bool ImGui::InputFloat3(ImStrv label, float v[3], const char* format, ImGuiInputTextFlags flags) { return InputScalarN(label, ImGuiDataType_Float, v, 3, NULL, NULL, format, flags); } -bool ImGui::InputFloat4(ImStrv label, float v[4], ImStrv format, ImGuiInputTextFlags flags) +bool ImGui::InputFloat4(ImStrv label, float v[4], const char* format, ImGuiInputTextFlags flags) { return InputScalarN(label, ImGuiDataType_Float, v, 4, NULL, NULL, format, flags); } @@ -4101,7 +4052,7 @@ bool ImGui::InputInt4(ImStrv label, int v[4], ImGuiInputTextFlags flags) return InputScalarN(label, ImGuiDataType_S32, v, 4, NULL, NULL, "%d", flags); } -bool ImGui::InputDouble(ImStrv label, double* v, double step, double step_fast, ImStrv format, ImGuiInputTextFlags flags) +bool ImGui::InputDouble(ImStrv label, double* v, double step, double step_fast, const char* format, ImGuiInputTextFlags flags) { return InputScalar(label, ImGuiDataType_Double, (void*)v, (void*)(step > 0.0 ? &step : NULL), (void*)(step_fast > 0.0 ? &step_fast : NULL), format, flags); } From b57179a0468f160c7a6026514bb117b6eaeaa5e1 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 29 Sep 2022 22:51:33 +0200 Subject: [PATCH 08/15] ImStrv: add needed disambiguishing functions for const char* now being ambiguous. (5079) amended for gcc/clang warnings amended to facilitate merge with docking --- imgui.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/imgui.h b/imgui.h index 3f30a8b0c..f9154aebc 100644 --- a/imgui.h +++ b/imgui.h @@ -155,6 +155,7 @@ Index of this file: #pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx' #pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast #pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe +#pragma clang diagnostic ignored "-Wformat-nonliteral" // warning: format string is not a string literal // passing non-literal to vsnformat(). yes, user passing incorrect format strings can crash the code. #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" // warning: zero as null pointer constant #pragma clang diagnostic ignored "-Wreserved-identifier" // warning: identifier '_Xxx' is reserved because it starts with '_' followed by a capital letter #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // warning: 'xxx' is an unsafe pointer used for buffer access @@ -164,6 +165,7 @@ Index of this file: #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wfloat-equal" // warning: comparing floating-point with '==' or '!=' is unsafe #pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead +#pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format string not a string literal #endif //----------------------------------------------------------------------------- @@ -1194,6 +1196,23 @@ namespace ImGui } // namespace ImGui +namespace ImGui +{ + // FIXME-IMSTR + // Functions which could accept both 'const char*' and 'const void*' now have an ambiguity between 'ImStrv' and 'const void*' when passed literals. + // Binding generators would likely need to ignore those. + // See https://github.com/ocornut/imgui/issues/5079 +IM_MSVC_RUNTIME_CHECKS_OFF + inline void PushID(const char* str_id) { PushID(ImStrv(str_id)); } + inline ImGuiID GetID(const char* str_id) { return GetID(ImStrv(str_id)); } + inline IM_FMTARGS(2) bool TreeNode(const char* str_id, const char* fmt, ...) { va_list args; va_start(args, fmt); bool ret = TreeNodeV(ImStrv(str_id), fmt, args); va_end(args); return ret; } + inline IM_FMTLIST(2) bool TreeNodeV(const char* str_id, const char* fmt, va_list args) { return TreeNodeV(ImStrv(str_id), fmt, args); } + inline IM_FMTARGS(3) bool TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) { va_list args; va_start(args, fmt); bool ret = TreeNodeExV(ImStrv(str_id), flags, fmt, args); va_end(args); return ret; } + inline IM_FMTLIST(3) bool TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) { return TreeNodeEx(ImStrv(str_id), flags, fmt, args); } + inline void TreePush(const char* str_id) { TreePush(ImStrv(str_id)); } +IM_MSVC_RUNTIME_CHECKS_RESTORE +} + //----------------------------------------------------------------------------- // [SECTION] Flags & Enumerations //----------------------------------------------------------------------------- From 81c9a72e9fae745f5d2186e2a87a231f8f1b5747 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 3 Apr 2024 09:58:36 +0900 Subject: [PATCH 09/15] ImStrv: convert Combo()/ListBox() to use ImStrv in their getters. Didn't convert Combo() "const char* items_separated_by_zeros" as this doesn't translate well when used via a ImStrv constructor, may actually aim to obsolete. Fixed for shadowing local variable warning on 2025/06/25. --- imgui.h | 8 +++-- imgui_demo.cpp | 2 +- imgui_widgets.cpp | 89 ++++++++++++++++++++++++++++++++++------------- 3 files changed, 72 insertions(+), 27 deletions(-) diff --git a/imgui.h b/imgui.h index f9154aebc..ec823b469 100644 --- a/imgui.h +++ b/imgui.h @@ -695,8 +695,9 @@ namespace ImGui IMGUI_API bool BeginCombo(ImStrv label, ImStrv preview_value, ImGuiComboFlags flags = 0); IMGUI_API void EndCombo(); // only call EndCombo() if BeginCombo() returns true! IMGUI_API bool Combo(ImStrv label, int* current_item, const char* const items[], int items_count, int popup_max_height_in_items = -1); + IMGUI_API bool Combo(ImStrv label, int* current_item, ImStrv const items[], int items_count, int popup_max_height_in_items = -1); + IMGUI_API bool Combo(ImStrv label, int* current_item, ImStrv (*getter)(void* user_data, int idx), void* user_data, int items_count, int popup_max_height_in_items = -1); IMGUI_API bool Combo(ImStrv label, int* current_item, const char* items_separated_by_zeros, int popup_max_height_in_items = -1); // Separate items with \0 within a string, end item-list with \0\0. e.g. "One\0Two\0Three\0" - IMGUI_API bool Combo(ImStrv label, int* current_item, const char* (*getter)(void* user_data, int idx), void* user_data, int items_count, int popup_max_height_in_items = -1); // Widgets: Drag Sliders // - Ctrl+Click on any drag box to turn them into an input box. Manually input values aren't clamped by default and can go off-bounds. Use ImGuiSliderFlags_AlwaysClamp to always clamp. @@ -822,7 +823,8 @@ namespace ImGui IMGUI_API bool BeginListBox(ImStrv label, const ImVec2& size = ImVec2(0, 0)); // open a framed scrolling region IMGUI_API void EndListBox(); // only call EndListBox() if BeginListBox() returned true! IMGUI_API bool ListBox(ImStrv label, int* current_item, const char* const items[], int items_count, int height_in_items = -1); - IMGUI_API bool ListBox(ImStrv label, int* current_item, const char* (*getter)(void* user_data, int idx), void* user_data, int items_count, int height_in_items = -1); + IMGUI_API bool ListBox(ImStrv label, int* current_item, ImStrv const items[], int items_count, int height_in_items = -1); + IMGUI_API bool ListBox(ImStrv label, int* current_item, ImStrv (*getter)(void* user_data, int idx), void* user_data, int items_count, int height_in_items = -1); // Widgets: Data Plotting // - Consider using ImPlot (https://github.com/epezent/implot) which is much better! @@ -4292,6 +4294,8 @@ namespace ImGui inline ImGuiID GetID(const char* str_id_begin, const char* str_id_end) { return GetID(ImStrv(str_id_begin, str_id_end)); } inline void TextUnformatted(const char* text, const char* text_end) { TextUnformatted(ImStrv(text, text_end)); } inline ImVec2 CalcTextSize(const char* text, const char* text_end, bool hide_text_after_double_hash = false, float wrap_width = -1.0f) { return CalcTextSize(ImStrv(text, text_end), hide_text_after_double_hash, wrap_width); } + IMGUI_API bool Combo(ImStrv label, int* current_item, const char* (*getter)(void* user_data, int idx), void* user_data, int items_count, int popup_max_height_in_items = -1); + IMGUI_API bool ListBox(ImStrv label, int* current_item, const char* (*getter)(void* user_data, int idx), void* user_data, int items_count, int height_in_items = -1); // OBSOLETED in 1.92.9 (from July 2026) IMGUI_API void SetColorEditOptions(ImGuiColorEditFlags flags); // set current options for if you want to select a default format, picker type, etc. User will be able to change those settings, unless you pass the _NoOptions flag to your calls. // OBSOLETED in 1.92.0 (from June 2025) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 504cc5d62..b4b2761c0 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1487,7 +1487,7 @@ static void DemoWindowWidgetsComboBoxes() // Simplified one-liner Combo() using an accessor function static int item_current_4 = 0; - ImGui::Combo("combo 5 (function)", &item_current_4, [](void* data, int n) { return ((const char**)data)[n]; }, items, IM_COUNTOF(items)); + ImGui::Combo("combo 5 (function)", &item_current_4, [](void* data, int n) { return ImStrv(((const char**)data)[n]); }, items, IM_COUNTOF(items)); ImGui::TreePop(); } diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 100497560..7330b5330 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -2156,15 +2156,21 @@ void ImGui::EndComboPreview() preview_data->WithinPreview = false; } -// Getter for the old Combo() API: const char*[] -static const char* Items_ArrayGetter(void* data, int idx) +// Getter for the old Combo()/ListBox() API: const char*[] +static ImStrv Items_CharArrayGetter(void* data, int idx) { const char* const* items = (const char* const*)data; return items[idx]; } +static ImStrv Items_StrvArrayGetter(void* data, int idx) +{ + ImStrv const* items = (ImStrv const*)data; + return items[idx]; +} + // Getter for the old Combo() API: "item1\0item2\0item3\0" -static const char* Items_SingleStringGetter(void* data, int idx) +static ImStrv Items_SingleStringGetter(void* data, int idx) { const char* items_separated_by_zeros = (const char*)data; int items_count = 0; @@ -2172,24 +2178,23 @@ static const char* Items_SingleStringGetter(void* data, int idx) while (*p) { if (idx == items_count) - break; + return p; p += ImStrlen(p) + 1; items_count++; } - return *p ? p : NULL; + return NULL; } // Old API, prefer using BeginCombo() nowadays if you can. -bool ImGui::Combo(ImStrv label, int* current_item, const char* (*getter)(void* user_data, int idx), void* user_data, int items_count, int popup_max_height_in_items) +bool ImGui::Combo(ImStrv label, int* current_item, ImStrv (*getter)(void* user_data, int idx), void* user_data, int items_count, int popup_max_height_in_items) { ImGuiContext& g = *GImGui; // Call the getter to obtain the preview string which is a parameter to BeginCombo() - const char* preview_value = NULL; - if ((g.NextItemData.ItemFlagsSet | g.CurrentItemFlags) & ImGuiItemFlags_MixedValue) - preview_value = ""; - else if (*current_item >= 0 && *current_item < items_count) - preview_value = getter(user_data, *current_item); + ImStrv preview_value = NULL; + if (((g.NextItemData.ItemFlagsSet | g.CurrentItemFlags) & ImGuiItemFlags_MixedValue) == 0) + if (*current_item >= 0 && *current_item < items_count) + preview_value = getter(user_data, *current_item); // The old Combo() API exposed "popup_max_height_in_items". The new more general BeginCombo() API doesn't have/need it, but we emulate it here. if (popup_max_height_in_items != -1 && !(g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasSizeConstraint)) @@ -2206,8 +2211,8 @@ bool ImGui::Combo(ImStrv label, int* current_item, const char* (*getter)(void* u while (clipper.Step()) for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) { - const char* item_text = getter(user_data, i); - if (item_text == NULL) + ImStrv item_text = getter(user_data, i); + if (!item_text) item_text = "*Unknown item*"; PushID(i); @@ -2230,24 +2235,46 @@ bool ImGui::Combo(ImStrv label, int* current_item, const char* (*getter)(void* u } // Combo box helper allowing to pass an array of strings. -bool ImGui::Combo(ImStrv label, int* current_item, const char* const items[], int items_count, int height_in_items) +bool ImGui::Combo(ImStrv label, int* current_item, ImStrv const items[], int items_count, int height_in_items) { - const bool value_changed = Combo(label, current_item, Items_ArrayGetter, (void*)items, items_count, height_in_items); - return value_changed; + return Combo(label, current_item, Items_StrvArrayGetter, (void*)items, items_count, height_in_items); } +// We cannot easily obsolete the 'const char* []' version as this would be stored on user side.. +bool ImGui::Combo(ImStrv label, int* current_item, const char* const items[], int items_count, int height_in_items) +{ + return Combo(label, current_item, Items_CharArrayGetter, (void*)items, items_count, height_in_items); +} + +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS +struct GetterProxyData { void* UserData; const char* (*UserGetter)(void* user_data, int idx); }; +static ImStrv ConstCharToStrvProxy(void* user_data, int idx) +{ + GetterProxyData* p_proxy_data = (GetterProxyData*)user_data; + return ImStrv(p_proxy_data->UserGetter(p_proxy_data->UserData, idx)); +} +bool ImGui::Combo(ImStrv label, int* current_item, const char* (*getter)(void* user_data, int idx), void* user_data, int items_count, int popup_max_height_in_items) +{ + // Convert 'const char*' getter to ImStrv version via a proxy. Cumbersome but no way out. + GetterProxyData proxy_data = { user_data, getter }; + return Combo(label, current_item, ConstCharToStrvProxy, &proxy_data, items_count, popup_max_height_in_items); +} +#endif + // Combo box helper allowing to pass all items in a single string literal holding multiple zero-terminated items "item1\0item2\0" +// We don't support an ImStrv version of this, because passing the typical "hello\0world" to a ImStrv constructor wouldn't yield the expected result. +// FIXME-OPT: Avoid computing count, or at least only when combo is open +// FIXME-OPT: The dual pass is stupid, at least could build an index on first pass. bool ImGui::Combo(ImStrv label, int* current_item, const char* items_separated_by_zeros, int height_in_items) { int items_count = 0; - const char* p = items_separated_by_zeros; // FIXME-OPT: Avoid computing this, or at least only when combo is open + const char* p = items_separated_by_zeros; while (*p) { p += ImStrlen(p) + 1; items_count++; } - bool value_changed = Combo(label, current_item, Items_SingleStringGetter, (void*)items_separated_by_zeros, items_count, height_in_items); - return value_changed; + return Combo(label, current_item, Items_SingleStringGetter, (void*)items_separated_by_zeros, items_count, height_in_items); } //------------------------------------------------------------------------- @@ -8996,15 +9023,20 @@ void ImGui::EndListBox() EndGroup(); // This is only required to be able to do IsItemXXX query on the whole ListBox including label } +bool ImGui::ListBox(ImStrv label, int* current_item, ImStrv const items[], int items_count, int height_items) +{ + return ListBox(label, current_item, Items_StrvArrayGetter, (void*)items, items_count, height_items); +} + +// We cannot easily obsolete the 'const char* []' version as this would be stored on user side.. bool ImGui::ListBox(ImStrv label, int* current_item, const char* const items[], int items_count, int height_items) { - const bool value_changed = ListBox(label, current_item, Items_ArrayGetter, (void*)items, items_count, height_items); - return value_changed; + return ListBox(label, current_item, Items_CharArrayGetter, (void*)items, items_count, height_items); } // This is merely a helper around BeginListBox(), EndListBox(). // Considering using those directly to submit custom data or store selection differently. -bool ImGui::ListBox(ImStrv label, int* current_item, const char* (*getter)(void* user_data, int idx), void* user_data, int items_count, int height_in_items) +bool ImGui::ListBox(ImStrv label, int* current_item, ImStrv (*getter)(void* user_data, int idx), void* user_data, int items_count, int height_in_items) { ImGuiContext& g = *GImGui; @@ -9026,8 +9058,8 @@ bool ImGui::ListBox(ImStrv label, int* current_item, const char* (*getter)(void* while (clipper.Step()) for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) { - const char* item_text = getter(user_data, i); - if (item_text == NULL) + ImStrv item_text = getter(user_data, i); + if (!item_text) item_text = "*Unknown item*"; PushID(i); @@ -9049,6 +9081,15 @@ bool ImGui::ListBox(ImStrv label, int* current_item, const char* (*getter)(void* return value_changed; } +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS +bool ImGui::ListBox(ImStrv label, int* current_item, const char* (*getter)(void* user_data, int idx), void* user_data, int items_count, int height_in_items) +{ + // Convert 'const char*' getter to ImStrv version via a proxy. Cumbersome but no way out. + GetterProxyData proxy_data = { user_data, getter }; + return ListBox(label, current_item, ConstCharToStrvProxy, &proxy_data, items_count, height_in_items); +} +#endif + //------------------------------------------------------------------------- // [SECTION] Widgets: PlotLines, PlotHistogram //------------------------------------------------------------------------- From 71ce91097a07d8226f91af88b970ed9185c9e2dd Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 3 Apr 2024 10:02:32 +0900 Subject: [PATCH 10/15] ImStrv: Combo(), ListBox(): seems better to not introduce the ImStrv [] versions? As 1) user is unlikely to store that on their end. 2) nowadays with lambdas isn't an easy user-side conversion. Then we limit explosion of an already messy API. --- imgui.h | 2 -- imgui_widgets.cpp | 17 +---------------- 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/imgui.h b/imgui.h index ec823b469..9732f1f9a 100644 --- a/imgui.h +++ b/imgui.h @@ -695,7 +695,6 @@ namespace ImGui IMGUI_API bool BeginCombo(ImStrv label, ImStrv preview_value, ImGuiComboFlags flags = 0); IMGUI_API void EndCombo(); // only call EndCombo() if BeginCombo() returns true! IMGUI_API bool Combo(ImStrv label, int* current_item, const char* const items[], int items_count, int popup_max_height_in_items = -1); - IMGUI_API bool Combo(ImStrv label, int* current_item, ImStrv const items[], int items_count, int popup_max_height_in_items = -1); IMGUI_API bool Combo(ImStrv label, int* current_item, ImStrv (*getter)(void* user_data, int idx), void* user_data, int items_count, int popup_max_height_in_items = -1); IMGUI_API bool Combo(ImStrv label, int* current_item, const char* items_separated_by_zeros, int popup_max_height_in_items = -1); // Separate items with \0 within a string, end item-list with \0\0. e.g. "One\0Two\0Three\0" @@ -823,7 +822,6 @@ namespace ImGui IMGUI_API bool BeginListBox(ImStrv label, const ImVec2& size = ImVec2(0, 0)); // open a framed scrolling region IMGUI_API void EndListBox(); // only call EndListBox() if BeginListBox() returned true! IMGUI_API bool ListBox(ImStrv label, int* current_item, const char* const items[], int items_count, int height_in_items = -1); - IMGUI_API bool ListBox(ImStrv label, int* current_item, ImStrv const items[], int items_count, int height_in_items = -1); IMGUI_API bool ListBox(ImStrv label, int* current_item, ImStrv (*getter)(void* user_data, int idx), void* user_data, int items_count, int height_in_items = -1); // Widgets: Data Plotting diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 7330b5330..5b36c523f 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -2163,12 +2163,6 @@ static ImStrv Items_CharArrayGetter(void* data, int idx) return items[idx]; } -static ImStrv Items_StrvArrayGetter(void* data, int idx) -{ - ImStrv const* items = (ImStrv const*)data; - return items[idx]; -} - // Getter for the old Combo() API: "item1\0item2\0item3\0" static ImStrv Items_SingleStringGetter(void* data, int idx) { @@ -2235,11 +2229,6 @@ bool ImGui::Combo(ImStrv label, int* current_item, ImStrv (*getter)(void* user_d } // Combo box helper allowing to pass an array of strings. -bool ImGui::Combo(ImStrv label, int* current_item, ImStrv const items[], int items_count, int height_in_items) -{ - return Combo(label, current_item, Items_StrvArrayGetter, (void*)items, items_count, height_in_items); -} - // We cannot easily obsolete the 'const char* []' version as this would be stored on user side.. bool ImGui::Combo(ImStrv label, int* current_item, const char* const items[], int items_count, int height_in_items) { @@ -9023,11 +9012,7 @@ void ImGui::EndListBox() EndGroup(); // This is only required to be able to do IsItemXXX query on the whole ListBox including label } -bool ImGui::ListBox(ImStrv label, int* current_item, ImStrv const items[], int items_count, int height_items) -{ - return ListBox(label, current_item, Items_StrvArrayGetter, (void*)items, items_count, height_items); -} - +// List box helper allowing to pass an array of strings. // We cannot easily obsolete the 'const char* []' version as this would be stored on user side.. bool ImGui::ListBox(ImStrv label, int* current_item, const char* const items[], int items_count, int height_items) { From 0bf9a6ac49bf4115cb5b76f377d90290ec820bf9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 3 May 2024 16:24:52 +0200 Subject: [PATCH 11/15] ImStrv: allow constructing from two null pointers. --- imgui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index 9732f1f9a..8e2ac40d5 100644 --- a/imgui.h +++ b/imgui.h @@ -338,7 +338,7 @@ struct ImStrv const char* End; ImStrv() { Begin = End = NULL; } ImStrv(const char* b) { Begin = b; End = b ? b + strlen(b) : NULL; } - ImStrv(const char* b, const char* e){ Begin = b; End = e ? e : b + strlen(b); } + ImStrv(const char* b, const char* e){ Begin = b; End = e ? e : b ? b + strlen(b) : NULL; } inline size_t length() const { return (size_t)(End - Begin); } inline bool empty() const { return Begin == End; } // == "" or == NULL inline operator bool() const { return Begin != NULL; } // return true when valid ("" is valid, NULL construction is not) From e3854498faebb17131dcaf85d81f618093dc1f68 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 2 Jul 2024 18:50:28 +0200 Subject: [PATCH 12/15] ImStrv: made length() returns an int as it simplify the most common case (of passing %.*s to printf) --- imgui.cpp | 44 ++++++++++++++++++++++---------------------- imgui.h | 4 ++-- imgui_draw.cpp | 4 ++-- imgui_widgets.cpp | 20 ++++++++++---------- 4 files changed, 36 insertions(+), 36 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 767153cb9..38554a2cf 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2263,11 +2263,11 @@ ImVec2 ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, int ImStrcmp(ImStrv str1, ImStrv str2) { - size_t str1_len = str1.length(); - size_t str2_len = str2.length(); + int str1_len = str1.length(); + int str2_len = str2.length(); if (str1_len != str2_len) - return (int)str1_len - (int)str2_len; - return memcmp(str1.Begin, str2.Begin, str1_len); + return str1_len - str2_len; + return memcmp(str1.Begin, str2.Begin, (size_t)str1_len); } // Consider using _stricmp/_strnicmp under Windows or strcasecmp/strncasecmp. We don't actually use either ImStricmp/ImStrnicmp in the codebase any more. @@ -2298,7 +2298,7 @@ void ImStrncpy(char* dst, ImStrv src, size_t count) { // Even though src does not necessarily include \0 terminator it is ok to include it. ImStrncpy above does not // actually include that in a copy operation and inserts zero terminator manually. - ImStrncpy(dst, src.Begin, ImMin(count, src.length() + 1)); + ImStrncpy(dst, src.Begin, ImMin(count, (size_t)src.length() + 1)); } char* ImStrdup(const char* str) @@ -2310,7 +2310,7 @@ char* ImStrdup(const char* str) char* ImStrdup(ImStrv str) { - size_t len = str.length(); + size_t len = (size_t)str.length(); void* buf = IM_ALLOC(len + 1); *((char*)buf + len) = 0; // str may not contain \0, it must be inserted manually. if (len > 0) @@ -2321,7 +2321,7 @@ char* ImStrdup(ImStrv str) char* ImStrdupcpy(char* dst, size_t* p_dst_size, ImStrv src) { size_t dst_buf_size = p_dst_size ? *p_dst_size : ImStrlen(dst) + 1; - size_t src_size = src.length() + 1; + size_t src_size = (size_t)src.length() + 1; if (dst_buf_size < src_size) { IM_FREE(dst); @@ -2401,7 +2401,7 @@ const char* ImStrstr(ImStrv haystack, ImStrv needle) { const char un0 = (char)*needle.Begin; const char* p = haystack.Begin; - const size_t needle_len_m1 = needle.length() - 1; + const size_t needle_len_m1 = (size_t)needle.length() - 1; while (true) { p = (const char*)memchr(p, un0, haystack.End - p); @@ -2628,7 +2628,7 @@ ImGuiID ImHashStr(ImStrv str, ImGuiID seed) #endif if (str.End != NULL) { - size_t data_size = str.length(); + size_t data_size = (size_t)str.length(); while (data_size-- != 0) { unsigned char c = *data++; @@ -2689,8 +2689,8 @@ ImFileHandle ImFileOpen(ImStrv filename, ImStrv mode) #if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && (defined(__MINGW32__) || (!defined(__CYGWIN__) && !defined(__GNUC__))) // We need a fopen() wrapper because MSVC/Windows fopen doesn't handle UTF-8 filenames. // Previously we used ImTextCountCharsFromUtf8/ImTextStrFromUtf8 here but we now need to support ImWchar16 and ImWchar32! - const int filename_wsize = ::MultiByteToWideChar(CP_UTF8, 0, filename.Begin, (int)filename.length() + 1, NULL, 0); - const int mode_wsize = ::MultiByteToWideChar(CP_UTF8, 0, mode.Begin, (int)mode.length() + 1, NULL, 0); + const int filename_wsize = ::MultiByteToWideChar(CP_UTF8, 0, filename.Begin, filename.length() + 1, NULL, 0); + const int mode_wsize = ::MultiByteToWideChar(CP_UTF8, 0, mode.Begin, mode.length() + 1, NULL, 0); // Use stack buffer if possible, otherwise heap buffer. Sizes include zero terminator. // We don't rely on current ImGuiContext as this is implied to be a helper function which doesn't depend on it (see #7314). @@ -2700,8 +2700,8 @@ ImFileHandle ImFileOpen(ImStrv filename, ImStrv mode) local_temp_heap.resize(filename_wsize + mode_wsize); wchar_t* filename_wbuf = local_temp_heap.Data ? local_temp_heap.Data : local_temp_stack; wchar_t* mode_wbuf = filename_wbuf + filename_wsize; - ::MultiByteToWideChar(CP_UTF8, 0, filename.Begin, (int)filename.length(), filename_wbuf, filename_wsize); - ::MultiByteToWideChar(CP_UTF8, 0, mode.Begin, (int)mode.length(), mode_wbuf, mode_wsize); + ::MultiByteToWideChar(CP_UTF8, 0, filename.Begin, filename.length(), filename_wbuf, filename_wsize); + ::MultiByteToWideChar(CP_UTF8, 0, mode.Begin, mode.length(), mode_wbuf, mode_wsize); filename_wbuf[filename_wsize - 1] = mode_wbuf[mode_wsize - 1] = 0; return ::_wfopen(filename_wbuf, mode_wbuf); #else @@ -3344,7 +3344,7 @@ char ImGuiTextBuffer::EmptyString[1] = { 0 }; void ImGuiTextBuffer::append(ImStrv str) { - int len = (int)str.length(); + const int len = str.length(); if (len == 0) return; @@ -4799,7 +4799,7 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* ctx, ImStrv name) : DrawListInst(NULL) memset((void*)this, 0, sizeof(*this)); Ctx = ctx; Name = ImStrdup(name); - NameBufLen = (int)name.length() + 1; + NameBufLen = name.length() + 1; ID = ImHashStr(name); IDStack.push_back(ID); MoveId = GetID("#MOVE"); @@ -5368,7 +5368,7 @@ void ImGui::SetClipboardText(ImStrv text) ImGuiContext& g = *GImGui; if (g.PlatformIO.Platform_SetClipboardTextFn != NULL) { - int len = (int)text.length(); + int len = text.length(); char* text_p = (char*)IM_ALLOC(len + 1); if (len > 0) memcpy(text_p, text.Begin, len); @@ -6749,10 +6749,10 @@ bool ImGui::BeginChildEx(ImStrv name, ImGuiID id, const ImVec2& size_arg, ImGuiC // e.g. "ParentName###ParentIdentifier/ChildName###ChildIdentifier" would get hashed incorrectly by ImHashStr(), trailing _%08X somehow fixes it. ImStrv temp_window_name; /*if (name && parent_window->IDStack.back() == parent_window->ID) - ImFormatStringToTempBuffer(&temp_window_name, "%s/%.*s", parent_window->Name, (int)name.length(), name.Begin); // May omit ID if in root of ID stack + ImFormatStringToTempBuffer(&temp_window_name, "%s/%.*s", parent_window->Name, name.length(), name.Begin); // May omit ID if in root of ID stack else*/ if (name) - ImFormatStringToTempBuffer(&temp_window_name, "%s/%.*s_%08X", parent_window->Name, (int)name.length(), name.Begin, id); + ImFormatStringToTempBuffer(&temp_window_name, "%s/%.*s_%08X", parent_window->Name, name.length(), name.Begin, id); else ImFormatStringToTempBuffer(&temp_window_name, "%s/%08X", parent_window->Name, id); @@ -12832,7 +12832,7 @@ bool ImGui::BeginPopupMenuEx(ImGuiID id, ImStrv label, ImGuiWindowFlags extra_wi char name[128]; IM_ASSERT(extra_window_flags & ImGuiWindowFlags_ChildMenu); - ImFormatString(name, IM_COUNTOF(name), "%.*s###Menu_%02d", (int)label.length(), label.Begin, g.BeginMenuDepth); // Recycle windows based on depth + ImFormatString(name, IM_COUNTOF(name), "%.*s###Menu_%02d", label.length(), label.Begin, g.BeginMenuDepth); // Recycle windows based on depth bool is_open = Begin(name, NULL, extra_window_flags | ImGuiWindowFlags_Popup); if (!is_open) // NB: Begin can return false when the popup is completely clipped (e.g. zero size display) EndPopup(); @@ -15948,7 +15948,7 @@ void ImGui::LoadIniSettingsFromMemory(ImStrv ini_data) // For user convenience, we allow passing a non zero-terminated string (hence the ini_size parameter). // For our convenience and to make the code simpler, we'll also write zero-terminators within the buffer. So let's create a writable copy.. - const int ini_size = (int)ini_data.length(); + const int ini_size = ini_data.length(); g.SettingsIniData.Buf.resize((int)ini_size + 1); char* const buf = g.SettingsIniData.Buf.Data; char* const buf_end = buf + ini_size; @@ -16051,7 +16051,7 @@ ImGuiWindowSettings* ImGui::CreateNewWindowSettings(ImStrv name) // Preserve the full string when ConfigDebugVerboseIniSettings is set to make .ini inspection easier. if (g.IO.ConfigDebugIniSettings == false) name.Begin = ImHashSkipUncontributingPrefix(name); - const size_t name_len = name.length(); + const size_t name_len = (size_t)name.length(); if (name_len == 0) { IM_ASSERT(false && "Name must not be empty."); @@ -16717,7 +16717,7 @@ void ImGui::DebugRenderKeyboardPreview(ImDrawList* draw_list) // Helper tool to diagnose between text encoding issues and font loading issues. Pass your UTF-8 string and verify that there are correct. void ImGui::DebugTextEncoding(ImStrv str) { - Text("Text: \"%.*s\"", (int)str.length(), str.Begin); + Text("Text: \"%.*s\"", str.length(), str.Begin); if (!BeginTable("##DebugTextEncoding", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable)) return; TableSetupColumn("Offset"); diff --git a/imgui.h b/imgui.h index 8e2ac40d5..0bfe70466 100644 --- a/imgui.h +++ b/imgui.h @@ -339,7 +339,7 @@ struct ImStrv ImStrv() { Begin = End = NULL; } ImStrv(const char* b) { Begin = b; End = b ? b + strlen(b) : NULL; } ImStrv(const char* b, const char* e){ Begin = b; End = e ? e : b ? b + strlen(b) : NULL; } - inline size_t length() const { return (size_t)(End - Begin); } + inline int length() const { return (int)(End - Begin); } inline bool empty() const { return Begin == End; } // == "" or == NULL inline operator bool() const { return Begin != NULL; } // return true when valid ("" is valid, NULL construction is not) #ifdef IM_STRV_CLASS_EXTRA @@ -2810,7 +2810,7 @@ struct ImGuiPayload ImGuiPayload() { Clear(); } void Clear() { SourceId = SourceParentId = 0; Data = NULL; DataSize = 0; memset(DataType, 0, sizeof(DataType)); DataFrameCount = -1; Preview = Delivery = false; } - bool IsDataType(ImStrv type) const { size_t len = type.length(); return DataFrameCount != -1 && memcmp(DataType, type.Begin, len) == 0 && DataType[len] == 0; } + bool IsDataType(ImStrv type) const { size_t len = (size_t)type.length(); return DataFrameCount != -1 && memcmp(DataType, type.Begin, len) == 0 && DataType[len] == 0; } bool IsPreview() const { return Preview; } bool IsDelivery() const { return Delivery; } }; diff --git a/imgui_draw.cpp b/imgui_draw.cpp index dbed7b510..c8ecd5d15 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -4487,7 +4487,7 @@ ImFont* ImFontAtlas::AddFontFromFileTTF(ImStrv filename, float size_pixels, cons const char* p; for (p = filename.End; p > filename.Begin && p[-1] != '/' && p[-1] != '\\'; p--) {} filename.Begin = p; - ImFormatString(font_cfg.Name, IM_COUNTOF(font_cfg.Name), "%.*s", (int)filename.length(), filename.Begin); + ImFormatString(font_cfg.Name, IM_COUNTOF(font_cfg.Name), "%.*s", filename.length(), filename.Begin); } return AddFontFromMemoryTTF(data, (int)data_size, size_pixels, &font_cfg, glyph_ranges); } @@ -4521,7 +4521,7 @@ ImFont* ImFontAtlas::AddFontFromMemoryCompressedTTF(const void* compressed_ttf_d ImFont* ImFontAtlas::AddFontFromMemoryCompressedBase85TTF(ImStrv compressed_ttf_data_base85, float size_pixels, const ImFontConfig* font_cfg, const ImWchar* glyph_ranges) { - int compressed_ttf_size = (((int)compressed_ttf_data_base85.length() + 4) / 5) * 4; + int compressed_ttf_size = ((compressed_ttf_data_base85.length() + 4) / 5) * 4; void* compressed_ttf = IM_ALLOC((size_t)compressed_ttf_size); Decode85(compressed_ttf_data_base85, (unsigned char*)compressed_ttf); ImFont* font = AddFontFromMemoryCompressedTTF(compressed_ttf, compressed_ttf_size, size_pixels, font_cfg, glyph_ranges); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 5b36c523f..3ee30efa3 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1576,10 +1576,10 @@ bool ImGui::TextLinkOpenURL(ImStrv label, ImStrv url) if (pressed && g.PlatformIO.Platform_OpenInShellFn != NULL) { ImStrv url_zt; - ImFormatStringToTempBuffer(&url_zt, "%.*s", (int)url.length(), url.Begin); + ImFormatStringToTempBuffer(&url_zt, "%.*s", url.length(), url.Begin); g.PlatformIO.Platform_OpenInShellFn(&g, url_zt.Begin); } - SetItemTooltip(LocalizeGetMsg(ImGuiLocKey_OpenLink_s), (int)url.length(), url.Begin); // It is more reassuring for user to _always_ display URL when it is the same as the label. + SetItemTooltip(LocalizeGetMsg(ImGuiLocKey_OpenLink_s), url.length(), url.Begin); // It is more reassuring for user to _always_ display URL when it is the same as the label. if (BeginPopupContextItem()) { if (MenuItem(LocalizeGetMsg(ImGuiLocKey_CopyLink))) @@ -4476,7 +4476,7 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, ImStrv new_text) IM_ASSERT(obj->ID != 0 && g.ActiveId == obj->ID); const bool is_resizable = (Flags & ImGuiInputTextFlags_CallbackResize) != 0; const bool is_readonly = (Flags & ImGuiInputTextFlags_ReadOnly) != 0; - int new_text_len = (int)new_text.length(); + int new_text_len = new_text.length(); // We support partial insertion (with a mod in stb_textedit.h) const int avail = BufSize - 1 - BufTextLen; @@ -5355,7 +5355,7 @@ bool ImGui::InputTextEx(ImStrv label, ImStrv hint, char* buf, int buf_size, cons if (ImStrv clipboard = GetClipboardText()) { // Filter pasted buffer - const int clipboard_len = (int)clipboard.length(); + const int clipboard_len = clipboard.length(); ImVector clipboard_filtered; clipboard_filtered.reserve(clipboard_len + 1); for (const char* s = clipboard.Begin; *s != 0; ) @@ -9252,17 +9252,17 @@ void ImGui::PlotHistogram(ImStrv label, float (*values_getter)(void* data, int i void ImGui::Value(ImStrv prefix, bool b) { - Text("%.*s: %s", (int)prefix.length(), prefix.Begin, (b ? "true" : "false")); + Text("%.*s: %s", prefix.length(), prefix.Begin, (b ? "true" : "false")); } void ImGui::Value(ImStrv prefix, int v) { - Text("%.*s: %d", (int)prefix.length(), prefix.Begin, v); + Text("%.*s: %d", prefix.length(), prefix.Begin, v); } void ImGui::Value(ImStrv prefix, unsigned int v) { - Text("%.*s: %d", (int)prefix.length(), prefix.Begin, v); + Text("%.*s: %d", prefix.length(), prefix.Begin, v); } void ImGui::Value(ImStrv prefix, float v, ImStrv float_format) @@ -9270,12 +9270,12 @@ void ImGui::Value(ImStrv prefix, float v, ImStrv float_format) if (float_format) { char fmt[64]; - ImFormatString(fmt, IM_COUNTOF(fmt), "%%.*s: %.*s", (int)float_format.length(), float_format.Begin); - Text(fmt, (int)prefix.length(), prefix.Begin, v); + ImFormatString(fmt, IM_COUNTOF(fmt), "%%.*s: %.*s", float_format.length(), float_format.Begin); + Text(fmt, prefix.length(), prefix.Begin, v); } else { - Text("%.*s: %.3f", (int)prefix.length(), prefix.Begin, v); + Text("%.*s: %.3f", prefix.length(), prefix.Begin, v); } } From b8274df9c98cbf5b789d63cac9206f4ca753f2ad Mon Sep 17 00:00:00 2001 From: David Mentler Date: Wed, 1 Oct 2025 20:45:42 +0200 Subject: [PATCH 13/15] ImStrv: Added ImStrv formatter for LLDB (e.g. Xcode) --- misc/debuggers/imgui_lldb.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/misc/debuggers/imgui_lldb.py b/misc/debuggers/imgui_lldb.py index 7d3c6bfcb..790669add 100644 --- a/misc/debuggers/imgui_lldb.py +++ b/misc/debuggers/imgui_lldb.py @@ -91,6 +91,35 @@ class ImRectSummary(object): return f"Min=({minX}, {minY}) Max=({maxX}, {maxY}) Size=({maxX - minX}, {maxY - minY})" +class ImStrvSummary(object): + def __init__(self, valobj, internal_dict): + self.valobj = valobj + + def update(self): + pass + + def get_summary(self): + begin = self.valobj.GetChildMemberWithName("Begin").GetValueAsUnsigned() + end = self.valobj.GetChildMemberWithName("End").GetValueAsUnsigned() + + if begin == 0: + return "" + + if end < begin: + return "" + + error = lldb.SBError() + data = self.valobj.GetProcess().ReadMemory(begin, end - begin, error) + + if not error.Success(): + return "" + + # Turn the byte sequence into utf-8, escape non-printables + data = data.decode("utf-8", errors="backslashreplace") + data = repr(data)[1:-1] + + return f'"{data}"' + def get_active_enum_flags(valobj): flag_set = set() @@ -187,3 +216,4 @@ def __lldb_init_module(debugger, internal_dict): add_summary("^ImVec4$", "x=${var.x} y=${var.y} z=${var.z} w=${var.w}") add_summary("^ImRect$", ImRectSummary) add_summary("^ImGuiWindow$", ImGuiWindowSummary) + add_summary("^ImStrv", ImStrvSummary) From 3626e2df2b70902e138f2f2c0679c5f80a16d235 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 24 Jun 2026 16:14:54 +0200 Subject: [PATCH 14/15] ImStrv: detect and fixed misuses of CalcTextSize() old signature. (9321) --- imgui.cpp | 2 +- imgui.h | 4 ++++ imgui_tables.cpp | 4 ++-- imgui_widgets.cpp | 7 +++---- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 38554a2cf..3fb73cc00 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -17646,7 +17646,7 @@ bool ImGui::DebugBreakButton(const char* label, const char* description_of_locat ImGuiContext& g = *GImGui; const ImGuiID id = window->GetID(label); - const ImVec2 label_size = CalcTextSize(label, NULL, true); + const ImVec2 label_size = CalcTextSize(label, true); ImVec2 pos = window->DC.CursorPos + ImVec2(0.0f, window->DC.CurrLineTextBaseOffset); ImVec2 size = ImVec2(label_size.x + g.Style.FramePadding.x * 2.0f, label_size.y); diff --git a/imgui.h b/imgui.h index 0bfe70466..18996b459 100644 --- a/imgui.h +++ b/imgui.h @@ -1211,6 +1211,10 @@ IM_MSVC_RUNTIME_CHECKS_OFF inline IM_FMTLIST(3) bool TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) { return TreeNodeEx(ImStrv(str_id), flags, fmt, args); } inline void TreePush(const char* str_id) { TreePush(ImStrv(str_id)); } IM_MSVC_RUNTIME_CHECKS_RESTORE + + // Detect misuses (#9321) + // FIXME-IMSTR: Validate that syntax is ok for our minimum target. + ImVec2 CalcTextSize(ImStrv, const char*, bool hide_text_after_double_hash = false, float wrap_width = -1.0f) = delete; } //----------------------------------------------------------------------------- diff --git a/imgui_tables.cpp b/imgui_tables.cpp index acbdcf859..8d449136c 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -3270,7 +3270,7 @@ float ImGui::TableGetHeaderAngledMaxLabelWidth() for (int column_n = 0; column_n < table->ColumnsCount; column_n++) if (IM_BITARRAY_TESTBIT(table->EnabledMaskByIndex, column_n)) if (table->Columns[column_n].Flags & ImGuiTableColumnFlags_AngledHeader) - width = ImMax(width, CalcTextSize(TableGetColumnName(table, column_n), NULL, true).x); + width = ImMax(width, CalcTextSize(TableGetColumnName(table, column_n), true).x); return width + g.Style.CellPadding.y * 2.0f; // Swap padding } @@ -3682,7 +3682,7 @@ static bool MenuItemForColumnReorder(ImStrv label, bool selected, bool enabled) ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - ImVec2 label_size = CalcTextSize(label, NULL, true); + ImVec2 label_size = CalcTextSize(label, true); ImGuiMenuColumns* offsets = &window->DC.MenuColumns; float checkmark_w = IM_TRUNC(g.FontSize * 1.20f); float min_w = offsets->DeclColumns(0.0f, label_size.x, 0.0f, checkmark_w); // Feedback for next frame diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 3ee30efa3..01fb1756b 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1522,7 +1522,6 @@ bool ImGui::TextLink(ImStrv label) ImGuiContext& g = *GImGui; const ImGuiID id = window->GetID(label); - const ImStrv label_for_display(label.Begin, FindRenderedTextEnd(label)); ImVec2 pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset); ImVec2 size = CalcTextSize(label_for_display, false); @@ -5740,14 +5739,14 @@ bool ImGui::InputTextEx(ImStrv label, ImStrv hint, char* buf, int buf_size, cons float rect_width = 0.0f; if (line_selected_begin < line_selected_end) - rect_width += CalcTextSize(line_selected_begin, line_selected_end).x; + rect_width += CalcTextSize(ImStrv(line_selected_begin, line_selected_end)).x; if (text_selected_begin <= p_eol && text_selected_end > p_eol && !p_eol_is_wrap) rect_width += bg_eol_width; // So we can see selected empty lines if (rect_width == 0.0f) continue; ImRect rect; - rect.Min.x = draw_pos.x - draw_scroll.x + CalcTextSize(p, line_selected_begin).x; + rect.Min.x = draw_pos.x - draw_scroll.x + CalcTextSize(ImStrv(p, line_selected_begin)).x; rect.Min.y = draw_pos.y - draw_scroll.y + line_n * g.FontSize; rect.Max.x = rect.Min.x + rect_width; rect.Max.y = rect.Min.y + bg_offy_dn + g.FontSize; @@ -5760,7 +5759,7 @@ bool ImGui::InputTextEx(ImStrv label, ImStrv hint, char* buf, int buf_size, cons // Find render position for right alignment (single-line only) if (g.ActiveId != id && (flags & ImGuiInputTextFlags_ElideLeft) && !render_cursor && !render_selection) - draw_pos.x = ImMin(draw_pos.x, frame_bb.Max.x - CalcTextSize(buf_display, NULL).x - style.FramePadding.x); + draw_pos.x = ImMin(draw_pos.x, frame_bb.Max.x - CalcTextSize(buf_display).x - style.FramePadding.x); //draw_scroll.x = state->Scroll.x; // Preserve scroll when inactive? // Render text From 657f560510242a2dc8a424d2766cd63b54314c25 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 9 Sep 2026 21:23:46 +0200 Subject: [PATCH 15/15] ImStrv: marked with IM_NODEBUGSTEP. Reduce cognitive/debug-stepping load. --- imgui.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/imgui.h b/imgui.h index 18996b459..2e5d6a9da 100644 --- a/imgui.h +++ b/imgui.h @@ -336,12 +336,12 @@ struct ImStrv { const char* Begin; const char* End; - ImStrv() { Begin = End = NULL; } - ImStrv(const char* b) { Begin = b; End = b ? b + strlen(b) : NULL; } - ImStrv(const char* b, const char* e){ Begin = b; End = e ? e : b ? b + strlen(b) : NULL; } - inline int length() const { return (int)(End - Begin); } - inline bool empty() const { return Begin == End; } // == "" or == NULL - inline operator bool() const { return Begin != NULL; } // return true when valid ("" is valid, NULL construction is not) + IM_NODEBUGSTEP inline ImStrv() { Begin = End = NULL; } + IM_NODEBUGSTEP inline ImStrv(const char* b) { Begin = b; End = b ? b + strlen(b) : NULL; } + IM_NODEBUGSTEP inline ImStrv(const char* b, const char* e){ Begin = b; End = e ? e : b ? b + strlen(b) : NULL; } + IM_NODEBUGSTEP inline int length() const { return (int)(End - Begin); } + IM_NODEBUGSTEP inline bool empty() const { return Begin == End; } // == "" or == NULL + IM_NODEBUGSTEP inline operator bool() const { return Begin != NULL; } // return true when valid ("" is valid, NULL construction is not) #ifdef IM_STRV_CLASS_EXTRA IM_STRV_CLASS_EXTRA // Define additional constructor in imconfig.h to convert your string types (e.g. std::string, std::string_view) to ImStrV. #endif