From ede3a3b92dbd2d1b7f12e19a3314a2c15b3c2928 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 12 Oct 2018 13:29:13 +0200 Subject: [PATCH 1/3] Fixes crash introduced in previous commit 9cf94d5. --- imgui_draw.cpp | 8 ++++---- imgui_widgets.cpp | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 3faa9b011..14d924d42 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2648,9 +2648,8 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col if (y + line_height < clip_rect.y && !word_wrap_enabled) while (y + line_height < clip_rect.y && s < text_end) { - s = (const char*)memchr(s, '\n', text_end - s) + 1; - if (s == NULL) - s = text_end; + s = (const char*)memchr(s, '\n', text_end - s); + s = s ? s + 1 : text_end; y += line_height; } @@ -2662,7 +2661,8 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col float y_end = y; while (y_end < clip_rect.w && s_end < text_end) { - s_end = (const char*)memchr(s_end, '\n', text_end - s_end) + 1; + s_end = (const char*)memchr(s_end, '\n', text_end - s_end); + s = s ? s + 1 : text_end; y_end += line_height; } text_end = s_end; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index df83a1d88..4e632a95e 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -3691,7 +3691,8 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 break; if (rect_pos.y < clip_rect.y) { - p = (const ImWchar*)wmemchr((const wchar_t*)p, '\n', text_selected_end - p) + 1; + p = (const ImWchar*)wmemchr((const wchar_t*)p, '\n', text_selected_end - p); + p = p ? p + 1 : text_selected_end; } else { From 28953208d4afa588f252945a4ad6606757bc5e20 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 12 Oct 2018 13:38:52 +0200 Subject: [PATCH 2/3] Tests: Added imgui-test engine hooks (experimental). --- imgui.cpp | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 1ef7669dc..2fc76f590 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -857,13 +857,14 @@ CODE #include // intptr_t #endif +// Debug options #define IMGUI_DEBUG_NAV_SCORING 0 #define IMGUI_DEBUG_NAV_RECTS 0 // Visual Studio warnings #ifdef _MSC_VER -#pragma warning (disable: 4127) // condition expression is constant -#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen +#pragma warning (disable: 4127) // condition expression is constant +#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen #endif // Clang/GCC warnings with -Weverything @@ -949,6 +950,14 @@ static void UpdateMouseWheel(); static void UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4]); } +// Test engine hooks (imgui-test) +//#define IMGUI_ENABLE_TEST_ENGINE_HOOKS +#ifdef IMGUI_ENABLE_TEST_ENGINE_HOOKS +extern void ImGuiTestEngineHook_PreNewFrame(); +extern void ImGuiTestEngineHook_PostNewFrame(); +extern void ImGuiTestEngineHook_ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg); +#endif + //----------------------------------------------------------------------------- // [SECTION] CONTEXT AND MEMORY ALLOCATORS //----------------------------------------------------------------------------- @@ -2587,6 +2596,10 @@ void ImGui::ItemSize(const ImRect& bb, float text_offset_y) // declare their minimum size requirement to ItemSize() and then use a larger region for drawing/interaction, which is passed to ItemAdd(). bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg) { +#ifdef IMGUI_ENABLE_TEST_ENGINE_HOOKS + ImGuiTestEngineHook_ItemAdd(bb, id, nav_bb_arg); +#endif + ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; @@ -3100,6 +3113,10 @@ void ImGui::NewFrame() IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() or ImGui::SetCurrentContext()?"); ImGuiContext& g = *GImGui; +#ifdef IMGUI_ENABLE_TEST_ENGINE_HOOKS + ImGuiTestEngineHook_PreNewFrame(); +#endif + // Check user data // (We pass an error message in the assert expression to make it visible to programmers who are not using a debugger, as most assert handlers display their argument) IM_ASSERT(g.Initialized); @@ -3265,6 +3282,10 @@ void ImGui::NewFrame() // We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags. SetNextWindowSize(ImVec2(400,400), ImGuiCond_FirstUseEver); Begin("Debug##Default"); + +#ifdef IMGUI_ENABLE_TEST_ENGINE_HOOKS + ImGuiTestEngineHook_PostNewFrame(); +#endif } void ImGui::Initialize(ImGuiContext* context) From ca753829cb04ea4848dbedeb178493aca9deb672 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 12 Oct 2018 15:48:38 +0200 Subject: [PATCH 3/3] Revert using wchar_t functions (9cf94d5 + 2eaf5b0). Big mistake, wchar_t is not guaranteed to be 16-bits. --- docs/CHANGELOG.txt | 2 +- imgui.cpp | 6 ++++-- imgui_widgets.cpp | 22 +++++++++++++--------- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 0c3de1aa5..5e6a5102a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -59,7 +59,7 @@ Other Changes: introduced in 1.50 and broken in 1.60. (#1698, #894, #713). - TextUnformatted(): Fixed a case where large-text path would read bytes past the text_end marker depending on the position of new lines in the buffer (it wasn't affecting the output but still not the right thing to do!) -- InputTextMultiline(), RenderText(): Some optimization for very large text buffers, useful for non-optimized builds. +- RenderText(): Some optimization for very large text buffers, useful for non-optimized builds. - BeginMenu(): Fixed menu popup horizontal offset being off the item in the menu bar when WindowPadding=0.0f. - ArrowButton(): Fixed arrow shape being horizontally misaligned by (FramePadding.y-FramePadding.x) if they are different. - Drag and Drop: Added GetDragDropPayload() to peek directly into the payload (if any) from anywhere. (#143) diff --git a/imgui.cpp b/imgui.cpp index 2fc76f590..34dbca1fb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -850,7 +850,6 @@ CODE #include // toupper, isprint #include // vsnprintf, sscanf, printf -#include // wcslen #if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier #include // intptr_t #else @@ -1220,7 +1219,10 @@ const char* ImStrchrRange(const char* str, const char* str_end, char c) int ImStrlenW(const ImWchar* str) { - return (int)wcslen((const wchar_t*)str); + //return (int)wcslen((const wchar_t*)str); // FIXME-OPT: Could use this when wchar_t are 16-bits + int n = 0; + while (*str++) n++; + return n; } // Find end-of-line. Return pointer will point to either first \n, either str_end. diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 4e632a95e..c87393269 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -36,7 +36,6 @@ Index of this file: #include "imgui_internal.h" #include // toupper, isprint -#include // wmemchr #if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier #include // intptr_t #else @@ -3618,12 +3617,14 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 // In multi-line mode, we never exit the loop until all lines are counted, so add one extra to the searches_remaining counter. searches_remaining += is_multiline ? 1 : 0; int line_count = 0; - for (const ImWchar* s = text_begin; (s = (const ImWchar*)wcschr((const wchar_t*)s, (wchar_t)'\n')) != NULL; s++) - { - line_count++; - if (searches_result_line_number[0] == -1 && s >= searches_input_ptr[0]) { searches_result_line_number[0] = line_count; if (--searches_remaining <= 0) break; } - if (searches_result_line_number[1] == -1 && s >= searches_input_ptr[1]) { searches_result_line_number[1] = line_count; if (--searches_remaining <= 0) break; } - } + //for (const ImWchar* s = text_begin; (s = (const ImWchar*)wcschr((const wchar_t*)s, (wchar_t)'\n')) != NULL; s++) // FIXME-OPT: Could use this when wchar_t are 16-bits + for (const ImWchar* s = text_begin; *s != 0; s++) + if (*s == '\n') + { + line_count++; + if (searches_result_line_number[0] == -1 && s >= searches_input_ptr[0]) { searches_result_line_number[0] = line_count; if (--searches_remaining <= 0) break; } + if (searches_result_line_number[1] == -1 && s >= searches_input_ptr[1]) { searches_result_line_number[1] = line_count; if (--searches_remaining <= 0) break; } + } line_count++; if (searches_result_line_number[0] == -1) searches_result_line_number[0] = line_count; if (searches_result_line_number[1] == -1) searches_result_line_number[1] = line_count; @@ -3691,8 +3692,11 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 break; if (rect_pos.y < clip_rect.y) { - p = (const ImWchar*)wmemchr((const wchar_t*)p, '\n', text_selected_end - p); - p = p ? p + 1 : text_selected_end; + //p = (const ImWchar*)wmemchr((const wchar_t*)p, '\n', text_selected_end - p); // FIXME-OPT: Could use this when wchar_t are 16-bits + //p = p ? p + 1 : text_selected_end; + while (p < text_selected_end) + if (*p++ == '\n') + break; } else {