Бранимир Караџић 4 недель назад
Родитель
Сommit
3fdf319b8b

+ 82 - 63
3rdparty/dear-imgui/imgui.cpp

@@ -394,6 +394,15 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures:
  When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files.
  You can read releases logs https://github.com/ocornut/imgui/releases for more details.
 
+ - 2025/12/23 (1.92.6) - Fonts:AddFontDefault() now automatically selects an embedded font between the new scalable AddFontDefaultVector() and the classic pixel-clean AddFontDefaultBitmap().
+                         The default selection is based on (style.FontSizeBase * FontScaleMain * FontScaleDpi) reaching a small threshold. Prefer calling either based on your own logic. You can call AddFontDefaultBitmap() to ensure legacy behavior.
+ - 2025/12/23 (1.92.6) - Fonts: removed ImFontConfig::PixelSnapV added in 1.92 which turns out is unnecessary (and misdocumented). Post-rescale GlyphOffset is always rounded.
+ - 2025/12/17 (1.92.6) - Renamed helper macro IM_ARRAYSIZE() -> IM_COUNTOF(). Kept redirection/legacy name for now.
+ - 2025/12/11 (1.92.6) - Hashing: handling of "###" operator to reset to seed within a string identifier doesn't include the "###" characters in the output hash anymore.
+                         - Before: GetID("Hello###World") == GetID("###World") != GetID("World");
+                         - Now:    GetID("Hello###World") == GetID("###World") == GetID("World");
+                         - This has the property of facilitating concatenating and manipulating identifiers using "###", and will allow fixing other dangling issues.
+                         - This will invalidate hashes (stored in .ini data) for Tables and Windows that are using the "###" operators. (#713, #1698)
  - 2025/11/24 (1.92.6) - Fonts: Fixed handling of `ImFontConfig::FontDataOwnedByAtlas = false` which did erroneously make a copy of the font data, essentially defeating the purpose of this flag and wasting memory.
                          (trivia: undetected since July 2015, this is perhaps the oldest bug in Dear ImGui history, albeit for a rarely used feature, see #9086)
                          HOWEVER, fixing this bug is likely to surface bugs in user code using `FontDataOwnedByAtlas = false`.
@@ -1260,7 +1269,7 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures:
 #define IMGUI_DEBUG_NAV_RECTS       0   // Display the reference navigation rectangle for each window
 
 // Default font size if unspecified in both style.FontSizeBase and AddFontXXX() calls.
-static const float FONT_DEFAULT_SIZE = 20.0f;
+static const float FONT_DEFAULT_SIZE_BASE = 20.0f;
 
 // When using Ctrl+Tab (or Gamepad Square+L/R) we delay the visual a little in order to reduce visual noise doing a fast switch.
 static const float NAV_WINDOWING_HIGHLIGHT_DELAY            = 0.20f;    // Time before the highlight and screen dimming starts fading in
@@ -1540,7 +1549,7 @@ ImGuiIO::ImGuiIO()
 {
     // Most fields are initialized with zero
     memset(this, 0, sizeof(*this));
-    IM_STATIC_ASSERT(IM_ARRAYSIZE(ImGuiIO::MouseDown) == ImGuiMouseButton_COUNT && IM_ARRAYSIZE(ImGuiIO::MouseClicked) == ImGuiMouseButton_COUNT);
+    IM_STATIC_ASSERT(IM_COUNTOF(ImGuiIO::MouseDown) == ImGuiMouseButton_COUNT && IM_COUNTOF(ImGuiIO::MouseClicked) == ImGuiMouseButton_COUNT);
 
     // Settings
     ConfigFlags = ImGuiConfigFlags_None;
@@ -1612,8 +1621,8 @@ ImGuiIO::ImGuiIO()
     MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
     MousePosPrev = ImVec2(-FLT_MAX, -FLT_MAX);
     MouseSource = ImGuiMouseSource_Mouse;
-    for (int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++) MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f;
-    for (int i = 0; i < IM_ARRAYSIZE(KeysData); i++) { KeysData[i].DownDuration = KeysData[i].DownDurationPrev = -1.0f; }
+    for (int i = 0; i < IM_COUNTOF(MouseDownDuration); i++) MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f;
+    for (int i = 0; i < IM_COUNTOF(KeysData); i++) { KeysData[i].DownDuration = KeysData[i].DownDurationPrev = -1.0f; }
     AppAcceptingEvents = true;
 }
 
@@ -1721,7 +1730,7 @@ void ImGuiIO::ClearInputMouse()
         key_data->DownDurationPrev = -1.0f;
     }
     MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
-    for (int n = 0; n < IM_ARRAYSIZE(MouseDown); n++)
+    for (int n = 0; n < IM_COUNTOF(MouseDown); n++)
     {
         MouseDown[n] = false;
         MouseDownDuration[n] = MouseDownDurationPrev[n] = -1.0f;
@@ -2450,7 +2459,7 @@ ImFileHandle ImFileOpen(const char* filename, const char* mode)
     // We don't rely on current ImGuiContext as this is implied to be a helper function which doesn't depend on it (see #7314).
     wchar_t local_temp_stack[FILENAME_MAX];
     ImVector<wchar_t> local_temp_heap;
-    if (filename_wsize + mode_wsize > IM_ARRAYSIZE(local_temp_stack))
+    if (filename_wsize + mode_wsize > IM_COUNTOF(local_temp_stack))
         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;
@@ -2965,7 +2974,7 @@ ImGuiTextFilter::ImGuiTextFilter(const char* default_filter) //-V1077
     CountGrep = 0;
     if (default_filter)
     {
-        ImStrncpy(InputBuf, default_filter, IM_ARRAYSIZE(InputBuf));
+        ImStrncpy(InputBuf, default_filter, IM_COUNTOF(InputBuf));
         Build();
     }
 }
@@ -2974,7 +2983,7 @@ bool ImGuiTextFilter::Draw(const char* label, float width)
 {
     if (width != 0.0f)
         ImGui::SetNextItemWidth(width);
-    bool value_changed = ImGui::InputText(label, InputBuf, IM_ARRAYSIZE(InputBuf));
+    bool value_changed = ImGui::InputText(label, InputBuf, IM_COUNTOF(InputBuf));
     if (value_changed)
         Build();
     return value_changed;
@@ -3598,7 +3607,7 @@ static const ImGuiStyleVarInfo GStyleVarsInfo[] =
 const ImGuiStyleVarInfo* ImGui::GetStyleVarInfo(ImGuiStyleVar idx)
 {
     IM_ASSERT(idx >= 0 && idx < ImGuiStyleVar_COUNT);
-    IM_STATIC_ASSERT(IM_ARRAYSIZE(GStyleVarsInfo) == ImGuiStyleVar_COUNT);
+    IM_STATIC_ASSERT(IM_COUNTOF(GStyleVarsInfo) == ImGuiStyleVar_COUNT);
     return &GStyleVarsInfo[idx];
 }
 
@@ -4339,7 +4348,7 @@ void ImGui::Initialize()
     TableSettingsAddSettingsHandler();
 
     // Setup default localization table
-    LocalizeRegisterEntries(GLocalizationEntriesEnUS, IM_ARRAYSIZE(GLocalizationEntriesEnUS));
+    LocalizeRegisterEntries(GLocalizationEntriesEnUS, IM_COUNTOF(GLocalizationEntriesEnUS));
 
     // Setup default ImGuiPlatformIO clipboard/IME handlers.
     g.PlatformIO.Platform_GetClipboardTextFn = Platform_GetClipboardTextFn_DefaultImpl;    // Platform dependent default implementations
@@ -4472,7 +4481,7 @@ void ImGui::Shutdown()
 // (A) Will be visible in debugger, (B) Will be included in all IMGUI_DEBUG_LOG() calls, (C) Should be <= 15 characters long.
 void ImGui::SetContextName(ImGuiContext* ctx, const char* name)
 {
-    ImStrncpy(ctx->ContextName, name, IM_ARRAYSIZE(ctx->ContextName));
+    ImStrncpy(ctx->ContextName, name, IM_COUNTOF(ctx->ContextName));
 }
 
 // No specific ordering/dependency support, will see as needed
@@ -5043,7 +5052,7 @@ void ImGui::DebugAllocHook(ImGuiDebugAllocInfo* info, int frame_count, void* ptr
     IM_UNUSED(ptr);
     if (entry->FrameCount != frame_count)
     {
-        info->LastEntriesIdx = (info->LastEntriesIdx + 1) % IM_ARRAYSIZE(info->LastEntriesBuf);
+        info->LastEntriesIdx = (info->LastEntriesIdx + 1) % IM_COUNTOF(info->LastEntriesBuf);
         entry = &info->LastEntriesBuf[info->LastEntriesIdx];
         entry->FrameCount = frame_count;
         entry->AllocCount = entry->FreeCount = 0;
@@ -5128,7 +5137,7 @@ static ImDrawList* GetViewportBgFgDrawList(ImGuiViewportP* viewport, size_t draw
 {
     // Create the draw list on demand, because they are not frequently used for all viewports
     ImGuiContext& g = *GImGui;
-    IM_ASSERT(drawlist_no < IM_ARRAYSIZE(viewport->BgFgDrawLists));
+    IM_ASSERT(drawlist_no < IM_COUNTOF(viewport->BgFgDrawLists));
     ImDrawList* draw_list = viewport->BgFgDrawLists[drawlist_no];
     if (draw_list == NULL)
     {
@@ -5351,7 +5360,7 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags(const ImVec2& mouse_pos)
     const bool has_open_modal = (modal_window != NULL);
     int mouse_earliest_down = -1;
     bool mouse_any_down = false;
-    for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++)
+    for (int i = 0; i < IM_COUNTOF(io.MouseDown); i++)
     {
         if (io.MouseClicked[i])
         {
@@ -5454,8 +5463,8 @@ void ImGui::NewFrame()
     // Calculate frame-rate for the user, as a purely luxurious feature
     g.FramerateSecPerFrameAccum += g.IO.DeltaTime - g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx];
     g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx] = g.IO.DeltaTime;
-    g.FramerateSecPerFrameIdx = (g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(g.FramerateSecPerFrame);
-    g.FramerateSecPerFrameCount = ImMin(g.FramerateSecPerFrameCount + 1, IM_ARRAYSIZE(g.FramerateSecPerFrame));
+    g.FramerateSecPerFrameIdx = (g.FramerateSecPerFrameIdx + 1) % IM_COUNTOF(g.FramerateSecPerFrame);
+    g.FramerateSecPerFrameCount = ImMin(g.FramerateSecPerFrameCount + 1, IM_COUNTOF(g.FramerateSecPerFrame));
     g.IO.Framerate = (g.FramerateSecPerFrameAccum > 0.0f) ? (1.0f / (g.FramerateSecPerFrameAccum / (float)g.FramerateSecPerFrameCount)) : FLT_MAX;
 
     // Process input queue (trickle as many events as possible), turn events into writes to IO structure
@@ -5764,10 +5773,10 @@ static void FlattenDrawDataIntoSingleLayer(ImDrawDataBuilder* builder)
 {
     int n = builder->Layers[0]->Size;
     int full_size = n;
-    for (int i = 1; i < IM_ARRAYSIZE(builder->Layers); i++)
+    for (int i = 1; i < IM_COUNTOF(builder->Layers); i++)
         full_size += builder->Layers[i]->Size;
     builder->Layers[0]->resize(full_size);
-    for (int layer_n = 1; layer_n < IM_ARRAYSIZE(builder->Layers); layer_n++)
+    for (int layer_n = 1; layer_n < IM_COUNTOF(builder->Layers); layer_n++)
     {
         ImVector<ImDrawList*>* layer = builder->Layers[layer_n];
         if (layer->empty())
@@ -6043,7 +6052,7 @@ void ImGui::Render()
         if (IsWindowActiveAndVisible(window) && (window->Flags & ImGuiWindowFlags_ChildWindow) == 0 && window != windows_to_render_top_most[0] && window != windows_to_render_top_most[1])
             AddRootWindowToDrawData(window);
     }
-    for (int n = 0; n < IM_ARRAYSIZE(windows_to_render_top_most); n++)
+    for (int n = 0; n < IM_COUNTOF(windows_to_render_top_most); n++)
         if (windows_to_render_top_most[n] && IsWindowActiveAndVisible(windows_to_render_top_most[n])) // NavWindowingTarget is always temporarily displayed as the top-most window
             AddRootWindowToDrawData(windows_to_render_top_most[n]);
 
@@ -6325,6 +6334,12 @@ ImVec2 ImGui::GetItemRectSize()
     return g.LastItemData.Rect.GetSize();
 }
 
+ImGuiItemFlags ImGui::GetItemFlags()
+{
+    ImGuiContext& g = *GImGui;
+    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'.
 // 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)
@@ -8259,12 +8274,13 @@ void ImGui::EndDisabledOverrideReenable()
     g.Style.Alpha = g.CurrentWindowStack.back().DisabledOverrideReenableAlphaBackup;
 }
 
-void ImGui::PushTextWrapPos(float wrap_pos_x)
+// ATTENTION THIS IS IN LEGACY LOCAL SPACE.
+void ImGui::PushTextWrapPos(float wrap_local_pos_x)
 {
     ImGuiContext& g = *GImGui;
     ImGuiWindow* window = g.CurrentWindow;
     window->DC.TextWrapPosStack.push_back(window->DC.TextWrapPos);
-    window->DC.TextWrapPos = wrap_pos_x;
+    window->DC.TextWrapPos = wrap_local_pos_x;
 }
 
 void ImGui::PopTextWrapPos()
@@ -8891,7 +8907,7 @@ void ImGui::UpdateFontsNewFrame()
     // Apply default font size the first time
     ImFont* font = ImGui::GetDefaultFont();
     if (g.Style.FontSizeBase <= 0.0f)
-        g.Style.FontSizeBase = (font->LegacySize > 0.0f ? font->LegacySize : FONT_DEFAULT_SIZE);
+        g.Style.FontSizeBase = (font->LegacySize > 0.0f ? font->LegacySize : FONT_DEFAULT_SIZE_BASE);
 
     // Set initial font
     g.Font = font;
@@ -9371,7 +9387,7 @@ static const char* const GKeyNames[] =
     "MouseLeft", "MouseRight", "MouseMiddle", "MouseX1", "MouseX2", "MouseWheelX", "MouseWheelY",
     "ModCtrl", "ModShift", "ModAlt", "ModSuper", // ReservedForModXXX are showing the ModXXX names.
 };
-IM_STATIC_ASSERT(ImGuiKey_NamedKey_COUNT == IM_ARRAYSIZE(GKeyNames));
+IM_STATIC_ASSERT(ImGuiKey_NamedKey_COUNT == IM_COUNTOF(GKeyNames));
 
 const char* ImGui::GetKeyName(ImGuiKey key)
 {
@@ -9395,7 +9411,7 @@ const char* ImGui::GetKeyChordName(ImGuiKeyChord key_chord)
     const ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
     if (IsLRModKey(key))
         key_chord &= ~GetModForLRModKey(key); // Return "Ctrl+LeftShift" instead of "Ctrl+Shift+LeftShift"
-    ImFormatString(g.TempKeychordName, IM_ARRAYSIZE(g.TempKeychordName), "%s%s%s%s%s",
+    ImFormatString(g.TempKeychordName, IM_COUNTOF(g.TempKeychordName), "%s%s%s%s%s",
         (key_chord & ImGuiMod_Ctrl) ? "Ctrl+" : "",
         (key_chord & ImGuiMod_Shift) ? "Shift+" : "",
         (key_chord & ImGuiMod_Alt) ? "Alt+" : "",
@@ -9803,14 +9819,14 @@ bool ImGui::IsKeyReleased(ImGuiKey key, ImGuiID owner_id)
 bool ImGui::IsMouseDown(ImGuiMouseButton button)
 {
     ImGuiContext& g = *GImGui;
-    IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
+    IM_ASSERT(button >= 0 && button < IM_COUNTOF(g.IO.MouseDown));
     return g.IO.MouseDown[button] && TestKeyOwner(MouseButtonToKey(button), ImGuiKeyOwner_Any); // should be same as IsKeyDown(MouseButtonToKey(button), ImGuiKeyOwner_Any), but this allows legacy code hijacking the io.Mousedown[] array.
 }
 
 bool ImGui::IsMouseDown(ImGuiMouseButton button, ImGuiID owner_id)
 {
     ImGuiContext& g = *GImGui;
-    IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
+    IM_ASSERT(button >= 0 && button < IM_COUNTOF(g.IO.MouseDown));
     return g.IO.MouseDown[button] && TestKeyOwner(MouseButtonToKey(button), owner_id); // Should be same as IsKeyDown(MouseButtonToKey(button), owner_id), but this allows legacy code hijacking the io.Mousedown[] array.
 }
 
@@ -9822,7 +9838,7 @@ bool ImGui::IsMouseClicked(ImGuiMouseButton button, bool repeat)
 bool ImGui::IsMouseClicked(ImGuiMouseButton button, ImGuiInputFlags flags, ImGuiID owner_id)
 {
     ImGuiContext& g = *GImGui;
-    IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
+    IM_ASSERT(button >= 0 && button < IM_COUNTOF(g.IO.MouseDown));
     if (!g.IO.MouseDown[button]) // In theory this should already be encoded as (DownDuration < 0.0f), but testing this facilitates eating mechanism (until we finish work on key ownership)
         return false;
     const float t = g.IO.MouseDownDuration[button];
@@ -9844,14 +9860,14 @@ bool ImGui::IsMouseClicked(ImGuiMouseButton button, ImGuiInputFlags flags, ImGui
 bool ImGui::IsMouseReleased(ImGuiMouseButton button)
 {
     ImGuiContext& g = *GImGui;
-    IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
+    IM_ASSERT(button >= 0 && button < IM_COUNTOF(g.IO.MouseDown));
     return g.IO.MouseReleased[button] && TestKeyOwner(MouseButtonToKey(button), ImGuiKeyOwner_Any); // Should be same as IsKeyReleased(MouseButtonToKey(button), ImGuiKeyOwner_Any)
 }
 
 bool ImGui::IsMouseReleased(ImGuiMouseButton button, ImGuiID owner_id)
 {
     ImGuiContext& g = *GImGui;
-    IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
+    IM_ASSERT(button >= 0 && button < IM_COUNTOF(g.IO.MouseDown));
     return g.IO.MouseReleased[button] && TestKeyOwner(MouseButtonToKey(button), owner_id); // Should be same as IsKeyReleased(MouseButtonToKey(button), owner_id)
 }
 
@@ -9861,7 +9877,7 @@ bool ImGui::IsMouseReleased(ImGuiMouseButton button, ImGuiID owner_id)
 bool ImGui::IsMouseReleasedWithDelay(ImGuiMouseButton button, float delay)
 {
     ImGuiContext& g = *GImGui;
-    IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
+    IM_ASSERT(button >= 0 && button < IM_COUNTOF(g.IO.MouseDown));
     const float time_since_release = (float)(g.Time - g.IO.MouseReleasedTime[button]);
     return !IsMouseDown(button) && (time_since_release - g.IO.DeltaTime < delay) && (time_since_release >= delay);
 }
@@ -9869,21 +9885,21 @@ bool ImGui::IsMouseReleasedWithDelay(ImGuiMouseButton button, float delay)
 bool ImGui::IsMouseDoubleClicked(ImGuiMouseButton button)
 {
     ImGuiContext& g = *GImGui;
-    IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
+    IM_ASSERT(button >= 0 && button < IM_COUNTOF(g.IO.MouseDown));
     return g.IO.MouseClickedCount[button] == 2 && TestKeyOwner(MouseButtonToKey(button), ImGuiKeyOwner_Any);
 }
 
 bool ImGui::IsMouseDoubleClicked(ImGuiMouseButton button, ImGuiID owner_id)
 {
     ImGuiContext& g = *GImGui;
-    IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
+    IM_ASSERT(button >= 0 && button < IM_COUNTOF(g.IO.MouseDown));
     return g.IO.MouseClickedCount[button] == 2 && TestKeyOwner(MouseButtonToKey(button), owner_id);
 }
 
 int ImGui::GetMouseClickedCount(ImGuiMouseButton button)
 {
     ImGuiContext& g = *GImGui;
-    IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
+    IM_ASSERT(button >= 0 && button < IM_COUNTOF(g.IO.MouseDown));
     return g.IO.MouseClickedCount[button];
 }
 
@@ -9910,7 +9926,7 @@ bool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool c
 bool ImGui::IsMouseDragPastThreshold(ImGuiMouseButton button, float lock_threshold)
 {
     ImGuiContext& g = *GImGui;
-    IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
+    IM_ASSERT(button >= 0 && button < IM_COUNTOF(g.IO.MouseDown));
     if (lock_threshold < 0.0f)
         lock_threshold = g.IO.MouseDragThreshold;
     return g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold;
@@ -9919,7 +9935,7 @@ bool ImGui::IsMouseDragPastThreshold(ImGuiMouseButton button, float lock_thresho
 bool ImGui::IsMouseDragging(ImGuiMouseButton button, float lock_threshold)
 {
     ImGuiContext& g = *GImGui;
-    IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
+    IM_ASSERT(button >= 0 && button < IM_COUNTOF(g.IO.MouseDown));
     if (!g.IO.MouseDown[button])
         return false;
     return IsMouseDragPastThreshold(button, lock_threshold);
@@ -9966,7 +9982,7 @@ bool ImGui::IsMousePosValid(const ImVec2* mouse_pos)
 bool ImGui::IsAnyMouseDown()
 {
     ImGuiContext& g = *GImGui;
-    for (int n = 0; n < IM_ARRAYSIZE(g.IO.MouseDown); n++)
+    for (int n = 0; n < IM_COUNTOF(g.IO.MouseDown); n++)
         if (g.IO.MouseDown[n])
             return true;
     return false;
@@ -9978,7 +9994,7 @@ bool ImGui::IsAnyMouseDown()
 ImVec2 ImGui::GetMouseDragDelta(ImGuiMouseButton button, float lock_threshold)
 {
     ImGuiContext& g = *GImGui;
-    IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
+    IM_ASSERT(button >= 0 && button < IM_COUNTOF(g.IO.MouseDown));
     if (lock_threshold < 0.0f)
         lock_threshold = g.IO.MouseDragThreshold;
     if (g.IO.MouseDown[button] || g.IO.MouseReleased[button])
@@ -9991,7 +10007,7 @@ ImVec2 ImGui::GetMouseDragDelta(ImGuiMouseButton button, float lock_threshold)
 void ImGui::ResetMouseDragDelta(ImGuiMouseButton button)
 {
     ImGuiContext& g = *GImGui;
-    IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
+    IM_ASSERT(button >= 0 && button < IM_COUNTOF(g.IO.MouseDown));
     // NB: We don't need to reset g.IO.MouseDragMaxDistanceSqr
     g.IO.MouseClickedPos[button] = g.IO.MousePos;
 }
@@ -10134,7 +10150,7 @@ static void ImGui::UpdateMouseInputs()
     if (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f)
         g.NavHighlightItemUnderNav = false;
 
-    for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++)
+    for (int i = 0; i < IM_COUNTOF(io.MouseDown); i++)
     {
         io.MouseClicked[i] = io.MouseDown[i] && io.MouseDownDuration[i] < 0.0f;
         io.MouseClickedCount[i] = 0; // Will be filled below
@@ -10341,7 +10357,7 @@ void ImGui::SetNextFrameWantCaptureMouse(bool want_capture_mouse)
 static const char* GetInputSourceName(ImGuiInputSource source)
 {
     const char* input_source_names[] = { "None", "Mouse", "Keyboard", "Gamepad" };
-    IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT);
+    IM_ASSERT(IM_COUNTOF(input_source_names) == ImGuiInputSource_COUNT);
     if (source < 0 || source >= ImGuiInputSource_COUNT)
         return "Unknown";
     return input_source_names[source];
@@ -10349,7 +10365,7 @@ static const char* GetInputSourceName(ImGuiInputSource source)
 static const char* GetMouseSourceName(ImGuiMouseSource source)
 {
     const char* mouse_source_names[] = { "Mouse", "TouchScreen", "Pen" };
-    IM_ASSERT(IM_ARRAYSIZE(mouse_source_names) == ImGuiMouseSource_COUNT);
+    IM_ASSERT(IM_COUNTOF(mouse_source_names) == ImGuiMouseSource_COUNT);
     if (source < 0 || source >= ImGuiMouseSource_COUNT)
         return "Unknown";
     return mouse_source_names[source];
@@ -11983,7 +11999,7 @@ bool ImGui::BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags ext
 
     const char* window_name_template = is_dragdrop_tooltip ? "##Tooltip_DragDrop_%02d" : "##Tooltip_%02d";
     char window_name[32];
-    ImFormatString(window_name, IM_ARRAYSIZE(window_name), window_name_template, g.TooltipOverrideCount);
+    ImFormatString(window_name, IM_COUNTOF(window_name), window_name_template, g.TooltipOverrideCount);
     ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize;
     Begin(window_name, NULL, flags | extra_window_flags);
     // 2023-03-09: Added bool return value to the API, but currently always returning true.
@@ -12339,7 +12355,7 @@ bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_window_flags)
 
     char name[20];
     IM_ASSERT((extra_window_flags & ImGuiWindowFlags_ChildMenu) == 0); // Use BeginPopupMenuEx()
-    ImFormatString(name, IM_ARRAYSIZE(name), "##Popup_%08x", id); // No recycling, so we can close/open during the same frame
+    ImFormatString(name, IM_COUNTOF(name), "##Popup_%08x", id); // No recycling, so we can close/open during the same frame
 
     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)
@@ -12359,7 +12375,7 @@ bool ImGui::BeginPopupMenuEx(ImGuiID id, const char* label, ImGuiWindowFlags ext
 
     char name[128];
     IM_ASSERT(extra_window_flags & ImGuiWindowFlags_ChildMenu);
-    ImFormatString(name, IM_ARRAYSIZE(name), "%s###Menu_%02d", label, g.BeginMenuDepth); // Recycle windows based on depth
+    ImFormatString(name, IM_COUNTOF(name), "%s###Menu_%02d", label, 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();
@@ -13107,7 +13123,7 @@ static bool ImGui::NavScoreItem(ImGuiNavItemData* result, const ImRect& nav_bb)
     {
         if (quadrant == move_dir)
         {
-            ImFormatString(buf, IM_ARRAYSIZE(buf), "%.0f/%.0f", dist_box, dist_center);
+            ImFormatString(buf, IM_COUNTOF(buf), "%.0f/%.0f", dist_box, dist_center);
             ImDrawList* draw_list = GetForegroundDrawList(window);
             draw_list->AddRectFilled(cand.Min, cand.Max, IM_COL32(255, 0, 0, 80));
             draw_list->AddRectFilled(cand.Min, cand.Min + CalcTextSize(buf), IM_COL32(255, 0, 0, 200));
@@ -13118,7 +13134,7 @@ static bool ImGui::NavScoreItem(ImGuiNavItemData* result, const ImRect& nav_bb)
     const bool debug_tty = (g.IO.KeyCtrl && IsKeyPressed(ImGuiKey_Space));
     if (debug_hovering || debug_tty)
     {
-        ImFormatString(buf, IM_ARRAYSIZE(buf),
+        ImFormatString(buf, IM_COUNTOF(buf),
             "d-box    (%7.3f,%7.3f) -> %7.3f\nd-center (%7.3f,%7.3f) -> %7.3f\nd-axial  (%7.3f,%7.3f) -> %7.3f\nnav %c, quadrant %c",
             dbx, dby, dist_box, dcx, dcy, dist_center, dax, day, dist_axial, "-WENS"[move_dir+1], "-WENS"[quadrant+1]);
         if (debug_hovering)
@@ -14787,7 +14803,7 @@ bool ImGui::SetDragDropPayload(const char* type, const void* data, size_t data_s
         cond = ImGuiCond_Always;
 
     IM_ASSERT(type != NULL);
-    IM_ASSERT(ImStrlen(type) < IM_ARRAYSIZE(payload.DataType) && "Payload type can be at most 32 characters long");
+    IM_ASSERT(ImStrlen(type) < 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()
@@ -14795,7 +14811,7 @@ bool ImGui::SetDragDropPayload(const char* type, const void* data, size_t data_s
     if (cond == ImGuiCond_Always || payload.DataFrameCount == -1)
     {
         // Copy payload
-        ImStrncpy(payload.DataType, type, IM_ARRAYSIZE(payload.DataType));
+        ImStrncpy(payload.DataType, type, IM_COUNTOF(payload.DataType));
         g.DragDropPayloadBufHeap.resize(0);
         if (data_size > sizeof(g.DragDropPayloadBufLocal))
         {
@@ -16066,7 +16082,7 @@ void ImGui::DebugRenderKeyboardPreview(ImDrawList* draw_list)
     if (!IsItemVisible())
         return;
     draw_list->PushClipRect(board_min, board_max, true);
-    for (int n = 0; n < IM_ARRAYSIZE(keys_to_display); n++)
+    for (int n = 0; n < IM_COUNTOF(keys_to_display); n++)
     {
         const KeyLayoutData* key_data = &keys_to_display[n];
         ImVec2 key_min = ImVec2(start_pos.x + key_data->Col * key_step.x + key_data->Row * key_row_offset, start_pos.y + key_data->Row * key_step.y);
@@ -16355,7 +16371,7 @@ void ImGui::DebugNodeTexture(ImTextureData* tex, int int_id, const ImFontAtlasRe
 
         char texref_desc[30];
         Text("Status = %s (%d), Format = %s (%d), UseColors = %d", ImTextureDataGetStatusName(tex->Status), tex->Status, ImTextureDataGetFormatName(tex->Format), tex->Format, tex->UseColors);
-        Text("TexRef = %s, BackendUserData = %p", FormatTextureRefForDebugDisplay(texref_desc, IM_ARRAYSIZE(texref_desc), tex->GetTexRef()), tex->BackendUserData);
+        Text("TexRef = %s, BackendUserData = %p", FormatTextureRefForDebugDisplay(texref_desc, IM_COUNTOF(texref_desc), tex->GetTexRef()), tex->BackendUserData);
         TreePop();
     }
     PopID();
@@ -16510,7 +16526,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
                         for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
                         {
                             ImRect r = Funcs::GetTableRect(table, rect_n, column_n);
-                            ImFormatString(buf, IM_ARRAYSIZE(buf), "(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) Col %d %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), column_n, trt_rects_names[rect_n]);
+                            ImFormatString(buf, IM_COUNTOF(buf), "(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) Col %d %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), column_n, trt_rects_names[rect_n]);
                             Selectable(buf);
                             if (IsItemHovered())
                                 GetForegroundDrawList(table->OuterWindow)->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f);
@@ -16519,7 +16535,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
                     else
                     {
                         ImRect r = Funcs::GetTableRect(table, rect_n, -1);
-                        ImFormatString(buf, IM_ARRAYSIZE(buf), "(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), trt_rects_names[rect_n]);
+                        ImFormatString(buf, IM_COUNTOF(buf), "(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), trt_rects_names[rect_n]);
                         Selectable(buf);
                         if (IsItemHovered())
                             GetForegroundDrawList(table->OuterWindow)->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f);
@@ -16543,7 +16559,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
         {
             static char buf[64] = "";
             SetNextItemWidth(-FLT_MIN);
-            InputText("##DebugTextEncodingBuf", buf, IM_ARRAYSIZE(buf));
+            InputText("##DebugTextEncodingBuf", buf, IM_COUNTOF(buf));
             if (buf[0] != 0)
                 DebugTextEncoding(buf);
         }
@@ -16737,7 +16753,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
         Text("%d current allocations", info->TotalAllocCount - info->TotalFreeCount);
         if (SmallButton("GC now")) { g.GcCompactAll = true; }
         Text("Recent frames with allocations:");
-        int buf_size = IM_ARRAYSIZE(info->LastEntriesBuf);
+        int buf_size = IM_COUNTOF(info->LastEntriesBuf);
         for (int n = buf_size - 1; n >= 0; n--)
         {
             ImGuiDebugAllocEntry* entry = &info->LastEntriesBuf[(info->LastEntriesIdx - n + buf_size) % buf_size];
@@ -16774,7 +16790,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
             else
                 Text("Mouse pos: <INVALID>");
             Text("Mouse delta: (%g, %g)", io.MouseDelta.x, io.MouseDelta.y);
-            int count = IM_ARRAYSIZE(io.MouseDown);
+            int count = IM_COUNTOF(io.MouseDown);
             Text("Mouse down:");     for (int i = 0; i < count; i++) if (IsMouseDown(i)) { SameLine(); Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); }
             Text("Mouse clicked:");  for (int i = 0; i < count; i++) if (IsMouseClicked(i)) { SameLine(); Text("b%d (%d)", i, io.MouseClickedCount[i]); }
             Text("Mouse released:"); for (int i = 0; i < count; i++) if (IsMouseReleased(i)) { SameLine(); Text("b%d", i); }
@@ -16905,7 +16921,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
             if (cfg->ShowWindowsBeginOrder && !(window->Flags & ImGuiWindowFlags_ChildWindow))
             {
                 char buf[32];
-                ImFormatString(buf, IM_ARRAYSIZE(buf), "%d", window->BeginOrderWithinContext);
+                ImFormatString(buf, IM_COUNTOF(buf), "%d", window->BeginOrderWithinContext);
                 float font_size = GetFontSize();
                 draw_list->AddRectFilled(window->Pos, window->Pos + ImVec2(font_size, font_size), IM_COL32(200, 100, 100, 255));
                 draw_list->AddText(window->Pos, IM_COL32(255, 255, 255, 255), buf);
@@ -17056,9 +17072,9 @@ void ImGui::DebugNodeDrawList(ImGuiWindow* window, ImGuiViewportP* viewport, con
         }
 
         char texid_desc[30];
-        FormatTextureRefForDebugDisplay(texid_desc, IM_ARRAYSIZE(texid_desc), pcmd->TexRef);
+        FormatTextureRefForDebugDisplay(texid_desc, IM_COUNTOF(texid_desc), pcmd->TexRef);
         char buf[300];
-        ImFormatString(buf, IM_ARRAYSIZE(buf), "DrawCmd:%5d tris, Tex %s, ClipRect (%4.0f,%4.0f)-(%4.0f,%4.0f)",
+        ImFormatString(buf, IM_COUNTOF(buf), "DrawCmd:%5d tris, Tex %s, ClipRect (%4.0f,%4.0f)-(%4.0f,%4.0f)",
             pcmd->ElemCount / 3, texid_desc, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w);
         bool pcmd_node_open = TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "%s", buf);
         if (IsItemHovered() && (cfg->ShowDrawCmdMesh || cfg->ShowDrawCmdBoundingBoxes) && fg_draw_list)
@@ -17080,7 +17096,7 @@ void ImGui::DebugNodeDrawList(ImGuiWindow* window, ImGuiViewportP* viewport, con
         }
 
         // Display vertex information summary. Hover to get all triangles drawn in wire-frame
-        ImFormatString(buf, IM_ARRAYSIZE(buf), "Mesh: ElemCount: %d, VtxOffset: +%d, IdxOffset: +%d, Area: ~%0.f px", pcmd->ElemCount, pcmd->VtxOffset, pcmd->IdxOffset, total_area);
+        ImFormatString(buf, IM_COUNTOF(buf), "Mesh: ElemCount: %d, VtxOffset: +%d, IdxOffset: +%d, Area: ~%0.f px", pcmd->ElemCount, pcmd->VtxOffset, pcmd->IdxOffset, total_area);
         Selectable(buf);
         if (IsItemHovered() && fg_draw_list)
             DebugNodeDrawCmdShowMeshAndBoundingBox(fg_draw_list, draw_list, pcmd, true, false);
@@ -17091,7 +17107,7 @@ void ImGui::DebugNodeDrawList(ImGuiWindow* window, ImGuiViewportP* viewport, con
         while (clipper.Step())
             for (int prim = clipper.DisplayStart, idx_i = pcmd->IdxOffset + clipper.DisplayStart * 3; prim < clipper.DisplayEnd; prim++)
             {
-                char* buf_p = buf, * buf_end = buf + IM_ARRAYSIZE(buf);
+                char* buf_p = buf, * buf_end = buf + IM_COUNTOF(buf);
                 ImVec2 triangle[3];
                 for (int n = 0; n < 3; n++, idx_i++)
                 {
@@ -17224,6 +17240,9 @@ void ImGui::DebugNodeFont(ImFont* font)
         {
             const ImFontLoader* loader = src->FontLoader ? src->FontLoader : atlas->FontLoader;
             Text("Loader: '%s'", loader->Name ? loader->Name : "N/A");
+
+            //if (DragFloat("ExtraSizeScale", &src->ExtraSizeScale, 0.01f, 0.10f, 2.0f))
+            //    ImFontAtlasFontRebuildOutput(atlas, font);
 #ifdef IMGUI_ENABLE_FREETYPE
             if (loader->Name != NULL && strcmp(loader->Name, "FreeType") == 0)
             {
@@ -17396,7 +17415,7 @@ void ImGui::DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label)
     // Standalone tab bars (not associated to docking/windows functionality) currently hold no discernible strings.
     char buf[256];
     char* p = buf;
-    const char* buf_end = buf + IM_ARRAYSIZE(buf);
+    const char* buf_end = buf + IM_COUNTOF(buf);
     const bool is_active = (tab_bar->PrevFrameVisible >= GetFrameCount() - 2);
     p += ImFormatString(p, buf_end - p, "%s 0x%08X (%d tabs)%s  {", label, tab_bar->ID, tab_bar->Tabs.Size, is_active ? "" : " *Inactive*");
     for (int tab_n = 0; tab_n < ImMin(tab_bar->Tabs.Size, 3); tab_n++)
@@ -17554,7 +17573,7 @@ void ImGui::DebugNodeWindowsListByBeginStackParent(ImGuiWindow** windows, int wi
         if (window->ParentWindowInBeginStack != parent_in_begin_stack)
             continue;
         char buf[20];
-        ImFormatString(buf, IM_ARRAYSIZE(buf), "[%04d] Window", window->BeginOrderWithinContext);
+        ImFormatString(buf, IM_COUNTOF(buf), "[%04d] Window", window->BeginOrderWithinContext);
         //BulletText("[%04d] Window '%s'", window->BeginOrderWithinContext, window->Name);
         DebugNodeWindow(window, buf);
         TreePush(buf);
@@ -17988,7 +18007,7 @@ static const char* DebugItemPathQuery_GetResultAsPath(ImGuiDebugItemPathQuery* q
     for (int stack_n = 0; stack_n < query->Results.Size; stack_n++)
     {
         char level_desc[256];
-        DebugItemPathQuery_FormatLevelInfo(query, stack_n, false, level_desc, IM_ARRAYSIZE(level_desc));
+        DebugItemPathQuery_FormatLevelInfo(query, stack_n, false, level_desc, IM_COUNTOF(level_desc));
         buf->append(stack_n == 0 ? "//" : "/");
         for (const char* p = level_desc; *p != 0; )
         {

+ 17 - 8
3rdparty/dear-imgui/imgui.h

@@ -30,7 +30,7 @@
 // Library Version
 // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
 #define IMGUI_VERSION       "1.92.6 WIP"
-#define IMGUI_VERSION_NUM   19255
+#define IMGUI_VERSION_NUM   19258
 #define IMGUI_HAS_TABLE             // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000
 #define IMGUI_HAS_TEXTURES          // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198
 
@@ -95,7 +95,7 @@ Index of this file:
 #include <assert.h>
 #define IM_ASSERT(_EXPR)            assert(_EXPR)                               // You can override the default assert handler by editing imconfig.h
 #endif
-#define IM_ARRAYSIZE(_ARR)          ((int)(sizeof(_ARR) / sizeof(*(_ARR))))     // Size of a static C-style array. Don't use on pointers!
+#define IM_COUNTOF(_ARR)            ((int)(sizeof(_ARR) / sizeof(*(_ARR))))     // Size of a static C-style array. Don't use on pointers!
 #define IM_UNUSED(_VAR)             ((void)(_VAR))                              // Used to silence "unused variable warnings". Often useful as asserts may be stripped out from final builds.
 #define IM_STRINGIFY_HELPER(_EXPR)  #_EXPR
 #define IM_STRINGIFY(_EXPR)         IM_STRINGIFY_HELPER(_EXPR)                  // Preprocessor idiom to stringify e.g. an integer or a macro.
@@ -1017,6 +1017,7 @@ namespace ImGui
     IMGUI_API ImVec2        GetItemRectMin();                                                   // get upper-left bounding rectangle of the last item (screen space)
     IMGUI_API ImVec2        GetItemRectMax();                                                   // get lower-right bounding rectangle of the last item (screen space)
     IMGUI_API ImVec2        GetItemRectSize();                                                  // get size of last item
+    IMGUI_API ImGuiItemFlags GetItemFlags();                                                    // get generic flags of last item
 
     // Viewports
     // - Currently represents the Platform Window created by the application which is hosting our Dear ImGui windows.
@@ -1218,7 +1219,7 @@ enum ImGuiChildFlags_
 };
 
 // Flags for ImGui::PushItemFlag()
-// (Those are shared by all items)
+// (Those are shared by all submitted items)
 enum ImGuiItemFlags_
 {
     ImGuiItemFlags_None                     = 0,        // (Default)
@@ -1228,6 +1229,7 @@ enum ImGuiItemFlags_
     ImGuiItemFlags_ButtonRepeat             = 1 << 3,   // false    // Any button-like behavior will have repeat mode enabled (based on io.KeyRepeatDelay and io.KeyRepeatRate values). Note that you can also call IsItemActive() after any button to tell if it is being held.
     ImGuiItemFlags_AutoClosePopups          = 1 << 4,   // true     // MenuItem()/Selectable() automatically close their parent popup window.
     ImGuiItemFlags_AllowDuplicateId         = 1 << 5,   // false    // Allow submitting an item with the same identifier as an item already submitted this frame without triggering a warning tooltip if io.ConfigDebugHighlightIdConflicts is set.
+    ImGuiItemFlags_Disabled                 = 1 << 6,   // false    // [Internal] Disable interactions. DOES NOT affect visuals. This is used by BeginDisabled()/EndDisabled() and only provided here so you can read back via GetItemFlags(). 
 };
 
 // Flags for ImGui::InputText()
@@ -3525,12 +3527,11 @@ struct ImFontConfig
 
     // Options
     bool            MergeMode;              // false    // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). You may want to use GlyphOffset.y when merge font of different heights.
-    bool            PixelSnapH;             // false    // Align every glyph AdvanceX to pixel boundaries. Useful e.g. if you are merging a non-pixel aligned font with the default font. If enabled, you can set OversampleH/V to 1.
-    bool            PixelSnapV;             // true     // Align Scaled GlyphOffset.y to pixel boundaries.
+    bool            PixelSnapH;             // false    // Align every glyph AdvanceX to pixel boundaries. Prevents fractional font size from working correctly! Useful e.g. if you are merging a non-pixel aligned font with the default font. If enabled, you can set OversampleH/V to 1.
     ImS8            OversampleH;            // 0 (2)    // Rasterize at higher quality for sub-pixel positioning. 0 == auto == 1 or 2 depending on size. Note the difference between 2 and 3 is minimal. You can reduce this to 1 for large glyphs save memory. Read https://github.com/nothings/stb/blob/master/tests/oversample/README.md for details.
     ImS8            OversampleV;            // 0 (1)    // Rasterize at higher quality for sub-pixel positioning. 0 == auto == 1. This is not really useful as we don't use sub-pixel positions on the Y axis.
     ImWchar         EllipsisChar;           // 0        // Explicitly specify Unicode codepoint of ellipsis character. When fonts are being merged first specified ellipsis will be used.
-    float           SizePixels;             //          // Size in pixels for rasterizer (more or less maps to the resulting font height).
+    float           SizePixels;             //          // Output size in pixels for rasterizer (more or less maps to the resulting font height).
     const ImWchar*  GlyphRanges;            // NULL     // *LEGACY* THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE. Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list).
     const ImWchar*  GlyphExcludeRanges;     // NULL     // Pointer to a small user-provided list of Unicode ranges (2 value per range, values are inclusive, zero-terminated list). This is very close to GlyphRanges[] but designed to exclude ranges from a font source, when merging fonts with overlapping glyphs. Use "Input Glyphs Overlap Detection Tool" to find about your overlapping ranges.
     //ImVec2        GlyphExtraSpacing;      // 0, 0     // (REMOVED AT IT SEEMS LARGELY OBSOLETE. PLEASE REPORT IF YOU WERE USING THIS). Extra spacing (in pixels) between glyphs when rendered: essentially add to glyph->AdvanceX. Only X axis is supported for now.
@@ -3540,9 +3541,10 @@ struct ImFontConfig
     float           GlyphExtraAdvanceX;     // 0        // Extra spacing (in pixels) between glyphs. Please contact us if you are using this. // FIXME-NEWATLAS: Intentionally unscaled
     ImU32           FontNo;                 // 0        // Index of font within TTF/OTF file
     unsigned int    FontLoaderFlags;        // 0        // Settings for custom font builder. THIS IS BUILDER IMPLEMENTATION DEPENDENT. Leave as zero if unsure.
-    //unsigned int  FontBuilderFlags;       // --       // [Renamed in 1.92] Ue FontLoaderFlags.
+    //unsigned int  FontBuilderFlags;       // --       // [Renamed in 1.92] Use FontLoaderFlags.
     float           RasterizerMultiply;     // 1.0f     // Linearly brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable. This is a silly thing we may remove in the future.
     float           RasterizerDensity;      // 1.0f     // [LEGACY: this only makes sense when ImGuiBackendFlags_RendererHasTextures is not supported] DPI scale multiplier for rasterization. Not altering other font metrics: makes it easy to swap between e.g. a 100% and a 400% fonts for a zooming display, or handle Retina screen. IMPORTANT: If you change this it is expected that you increase/decrease font scale roughly to the inverse of this, otherwise quality may look lowered.
+    float           ExtraSizeScale;         // 1.0f     // Extra rasterizer scale over SizePixels.
 
     // [Internal]
     ImFontFlags     Flags;                  // Font flags (don't use just yet, will be exposed in upcoming 1.92.X updates)
@@ -3550,6 +3552,9 @@ struct ImFontConfig
     const ImFontLoader* FontLoader;         // Custom font backend for this source (default source is the one stored in ImFontAtlas)
     void*           FontLoaderData;         // Font loader opaque storage (per font config)
 
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+    bool            PixelSnapV;             // true    // [Obsoleted in 1.91.6] Align Scaled GlyphOffset.y to pixel boundaries.
+#endif
     IMGUI_API ImFontConfig();
 };
 
@@ -3635,7 +3640,9 @@ struct ImFontAtlas
     IMGUI_API ImFontAtlas();
     IMGUI_API ~ImFontAtlas();
     IMGUI_API ImFont*           AddFont(const ImFontConfig* font_cfg);
-    IMGUI_API ImFont*           AddFontDefault(const ImFontConfig* font_cfg = NULL);
+    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.
@@ -4151,6 +4158,8 @@ typedef ImFontAtlasRect ImFontAtlasCustomRect;
 
 #endif // #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
 
+#define IM_ARRAYSIZE                IM_COUNTOF                  // RENAMED IN 1.92.6: IM_ARRAYSIZE -> IM_COUNTOF
+
 // RENAMED IMGUI_DISABLE_METRICS_WINDOW > IMGUI_DISABLE_DEBUG_TOOLS in 1.88 (from June 2022)
 #ifdef IMGUI_DISABLE_METRICS_WINDOW
 #error IMGUI_DISABLE_METRICS_WINDOW was renamed to IMGUI_DISABLE_DEBUG_TOOLS, please use new name.

+ 106 - 106
3rdparty/dear-imgui/imgui_demo.cpp

@@ -764,7 +764,7 @@ static const ExampleMemberInfo ExampleTreeNodeMemberInfos[]
 static ExampleTreeNode* ExampleTree_CreateNode(const char* name, int uid, ExampleTreeNode* parent)
 {
     ExampleTreeNode* node = IM_NEW(ExampleTreeNode);
-    snprintf(node->Name, IM_ARRAYSIZE(node->Name), "%s", name);
+    snprintf(node->Name, IM_COUNTOF(node->Name), "%s", name);
     node->UID = uid;
     node->Parent = parent;
     node->IndexInParent = parent ? (unsigned short)parent->Childs.Size : 0;
@@ -790,19 +790,19 @@ static ExampleTreeNode* ExampleTree_CreateDemoTree()
     int uid = 0;
     ExampleTreeNode* node_L0 = ExampleTree_CreateNode("<ROOT>", ++uid, NULL);
     const int root_items_multiplier = 2;
-    for (int idx_L0 = 0; idx_L0 < IM_ARRAYSIZE(root_names) * root_items_multiplier; idx_L0++)
+    for (int idx_L0 = 0; idx_L0 < IM_COUNTOF(root_names) * root_items_multiplier; idx_L0++)
     {
-        snprintf(name_buf, IM_ARRAYSIZE(name_buf), "%s %d", root_names[idx_L0 / root_items_multiplier], idx_L0 % root_items_multiplier);
+        snprintf(name_buf, IM_COUNTOF(name_buf), "%s %d", root_names[idx_L0 / root_items_multiplier], idx_L0 % root_items_multiplier);
         ExampleTreeNode* node_L1 = ExampleTree_CreateNode(name_buf, ++uid, node_L0);
         const int number_of_childs = (int)strlen(node_L1->Name);
         for (int idx_L1 = 0; idx_L1 < number_of_childs; idx_L1++)
         {
-            snprintf(name_buf, IM_ARRAYSIZE(name_buf), "Child %d", idx_L1);
+            snprintf(name_buf, IM_COUNTOF(name_buf), "Child %d", idx_L1);
             ExampleTreeNode* node_L2 = ExampleTree_CreateNode(name_buf, ++uid, node_L1);
             node_L2->HasData = true;
             if (idx_L1 == 0)
             {
-                snprintf(name_buf, IM_ARRAYSIZE(name_buf), "Sub-child %d", 0);
+                snprintf(name_buf, IM_COUNTOF(name_buf), "Sub-child %d", 0);
                 ExampleTreeNode* node_L3 = ExampleTree_CreateNode(name_buf, ++uid, node_L2);
                 node_L3->HasData = true;
             }
@@ -892,7 +892,7 @@ static void DemoWindowWidgetsBasic()
             // - Otherwise, see the 'Dear ImGui Demo->Widgets->Text Input->Resize Callback' for using ImGuiInputTextFlags_CallbackResize.
             IMGUI_DEMO_MARKER("Widgets/Basic/InputText");
             static char str0[128] = "Hello, world!";
-            ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0));
+            ImGui::InputText("input text", str0, IM_COUNTOF(str0));
             ImGui::SameLine(); HelpMarker(
                 "USER:\n"
                 "Hold Shift or use mouse to select text.\n"
@@ -907,7 +907,7 @@ static void DemoWindowWidgetsBasic()
                 "in imgui_demo.cpp).");
 
             static char str1[128] = "";
-            ImGui::InputTextWithHint("input text (w/ hint)", "enter text here", str1, IM_ARRAYSIZE(str1));
+            ImGui::InputTextWithHint("input text (w/ hint)", "enter text here", str1, IM_COUNTOF(str1));
 
             IMGUI_DEMO_MARKER("Widgets/Basic/InputInt, InputFloat");
             static int i0 = 123;
@@ -998,7 +998,7 @@ static void DemoWindowWidgetsBasic()
             IMGUI_DEMO_MARKER("Widgets/Basic/Combo");
             const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIIIIII", "JJJJ", "KKKKKKK" };
             static int item_current = 0;
-            ImGui::Combo("combo", &item_current, items, IM_ARRAYSIZE(items));
+            ImGui::Combo("combo", &item_current, items, IM_COUNTOF(items));
             ImGui::SameLine(); HelpMarker(
                 "Using the simplified one-liner Combo API here.\n"
                 "Refer to the \"Combo\" section below for an explanation of how to use the more flexible and general BeginCombo/EndCombo API.");
@@ -1010,7 +1010,7 @@ static void DemoWindowWidgetsBasic()
             IMGUI_DEMO_MARKER("Widgets/Basic/ListBox");
             const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" };
             static int item_current = 1;
-            ImGui::ListBox("listbox", &item_current, items, IM_ARRAYSIZE(items), 4);
+            ImGui::ListBox("listbox", &item_current, items, IM_COUNTOF(items), 4);
             ImGui::SameLine(); HelpMarker(
                 "Using the simplified one-liner ListBox API here.\n"
                 "Refer to the \"List boxes\" section below for an explanation of how to use the more flexible and general BeginListBox/EndListBox API.");
@@ -1133,7 +1133,7 @@ static void DemoWindowWidgetsColorAndPickers()
         static ImVec4 saved_palette[32] = {};
         if (saved_palette_init)
         {
-            for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)
+            for (int n = 0; n < IM_COUNTOF(saved_palette); n++)
             {
                 ImGui::ColorConvertHSVtoRGB(n / 31.0f, 0.8f, 0.8f,
                     saved_palette[n].x, saved_palette[n].y, saved_palette[n].z);
@@ -1166,7 +1166,7 @@ static void DemoWindowWidgetsColorAndPickers()
                 color = backup_color;
             ImGui::Separator();
             ImGui::Text("Palette");
-            for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)
+            for (int n = 0; n < IM_COUNTOF(saved_palette); n++)
             {
                 ImGui::PushID(n);
                 if ((n % 8) != 0)
@@ -1319,7 +1319,7 @@ static void DemoWindowWidgetsComboBoxes()
         const char* combo_preview_value = items[item_selected_idx];
         if (ImGui::BeginCombo("combo 1", combo_preview_value, flags))
         {
-            for (int n = 0; n < IM_ARRAYSIZE(items); n++)
+            for (int n = 0; n < IM_COUNTOF(items); n++)
             {
                 const bool is_selected = (item_selected_idx == n);
                 if (ImGui::Selectable(items[n], is_selected))
@@ -1345,7 +1345,7 @@ static void DemoWindowWidgetsComboBoxes()
             ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_F);
             filter.Draw("##Filter", -FLT_MIN);
 
-            for (int n = 0; n < IM_ARRAYSIZE(items); n++)
+            for (int n = 0; n < IM_COUNTOF(items); n++)
             {
                 const bool is_selected = (item_selected_idx == n);
                 if (filter.PassFilter(items[n]))
@@ -1367,11 +1367,11 @@ static void DemoWindowWidgetsComboBoxes()
         // Simplified one-liner Combo() using an array of const char*
         // This is not very useful (may obsolete): prefer using BeginCombo()/EndCombo() for full control.
         static int item_current_3 = -1; // If the selection isn't within 0..count, Combo won't display a preview
-        ImGui::Combo("combo 4 (array)", &item_current_3, items, IM_ARRAYSIZE(items));
+        ImGui::Combo("combo 4 (array)", &item_current_3, items, IM_COUNTOF(items));
 
         // 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_ARRAYSIZE(items));
+        ImGui::Combo("combo 5 (function)", &item_current_4, [](void* data, int n) { return ((const char**)data)[n]; }, items, IM_COUNTOF(items));
 
         ImGui::TreePop();
     }
@@ -1570,7 +1570,7 @@ static void DemoWindowWidgetsDragAndDrop()
                 "Brianna", "Barry", "Bernard",
                 "Bibi", "Blaine", "Bryn"
             };
-            for (int n = 0; n < IM_ARRAYSIZE(names); n++)
+            for (int n = 0; n < IM_COUNTOF(names); n++)
             {
                 ImGui::PushID(n);
                 if ((n % 3) != 0)
@@ -1632,7 +1632,7 @@ static void DemoWindowWidgetsDragAndDrop()
                 "We don't use the drag and drop api at all here! "
                 "Instead we query when the item is held but not hovered, and order items accordingly.");
             static const char* item_names[] = { "Item One", "Item Two", "Item Three", "Item Four", "Item Five" };
-            for (int n = 0; n < IM_ARRAYSIZE(item_names); n++)
+            for (int n = 0; n < IM_COUNTOF(item_names); n++)
             {
                 const char* item = item_names[n];
                 ImGui::Selectable(item);
@@ -1640,7 +1640,7 @@ static void DemoWindowWidgetsDragAndDrop()
                 if (ImGui::IsItemActive() && !ImGui::IsItemHovered())
                 {
                     int n_next = n + (ImGui::GetMouseDragDelta(0).y < 0.f ? -1 : 1);
-                    if (n_next >= 0 && n_next < IM_ARRAYSIZE(item_names))
+                    if (n_next >= 0 && n_next < IM_COUNTOF(item_names))
                     {
                         item_names[n] = item_names[n_next];
                         item_names[n_next] = item;
@@ -1880,7 +1880,7 @@ static void DemoWindowWidgetsListBoxes()
 
         if (ImGui::BeginListBox("listbox 1"))
         {
-            for (int n = 0; n < IM_ARRAYSIZE(items); n++)
+            for (int n = 0; n < IM_COUNTOF(items); n++)
             {
                 const bool is_selected = (item_selected_idx == n);
                 if (ImGui::Selectable(items[n], is_selected))
@@ -1901,7 +1901,7 @@ static void DemoWindowWidgetsListBoxes()
         ImGui::Text("Full-width:");
         if (ImGui::BeginListBox("##listbox 2", ImVec2(-FLT_MIN, 5 * ImGui::GetTextLineHeightWithSpacing())))
         {
-            for (int n = 0; n < IM_ARRAYSIZE(items); n++)
+            for (int n = 0; n < IM_COUNTOF(items); n++)
             {
                 bool is_selected = (item_selected_idx == n);
                 ImGuiSelectableFlags flags = (item_highlighted_idx == n) ? ImGuiSelectableFlags_Highlight : 0;
@@ -1987,8 +1987,8 @@ static void DemoWindowWidgetsPlotting()
 
         // Plot as lines and plot as histogram
         static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
-        ImGui::PlotLines("Frame Times", arr, IM_ARRAYSIZE(arr));
-        ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0, 80.0f));
+        ImGui::PlotLines("Frame Times", arr, IM_COUNTOF(arr));
+        ImGui::PlotHistogram("Histogram", arr, IM_COUNTOF(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0, 80.0f));
         //ImGui::SameLine(); HelpMarker("Consider using ImPlot instead!");
 
         // Fill an array of contiguous float values to plot
@@ -2003,7 +2003,7 @@ static void DemoWindowWidgetsPlotting()
         {
             static float phase = 0.0f;
             values[values_offset] = cosf(phase);
-            values_offset = (values_offset + 1) % IM_ARRAYSIZE(values);
+            values_offset = (values_offset + 1) % IM_COUNTOF(values);
             phase += 0.10f * values_offset;
             refresh_time += 1.0f / 60.0f;
         }
@@ -2012,12 +2012,12 @@ static void DemoWindowWidgetsPlotting()
         // (in this example, we will display an average value)
         {
             float average = 0.0f;
-            for (int n = 0; n < IM_ARRAYSIZE(values); n++)
+            for (int n = 0; n < IM_COUNTOF(values); n++)
                 average += values[n];
-            average /= (float)IM_ARRAYSIZE(values);
+            average /= (float)IM_COUNTOF(values);
             char overlay[32];
             sprintf(overlay, "avg %f", average);
-            ImGui::PlotLines("Lines", values, IM_ARRAYSIZE(values), values_offset, overlay, -1.0f, 1.0f, ImVec2(0, 80.0f));
+            ImGui::PlotLines("Lines", values, IM_COUNTOF(values), values_offset, overlay, -1.0f, 1.0f, ImVec2(0, 80.0f));
         }
 
         // Use functions to generate output
@@ -2096,7 +2096,7 @@ static void DemoWindowWidgetsQueryingStatuses()
         };
         static int item_type = 4;
         static bool item_disabled = false;
-        ImGui::Combo("Item Type", &item_type, item_names, IM_ARRAYSIZE(item_names), IM_ARRAYSIZE(item_names));
+        ImGui::Combo("Item Type", &item_type, item_names, IM_COUNTOF(item_names), IM_COUNTOF(item_names));
         ImGui::SameLine();
         HelpMarker("Testing how various types of items are interacting with the IsItemXXX functions. Note that the bool return value of most ImGui function is generally equivalent to calling ImGui::IsItemHovered().");
         ImGui::Checkbox("Item Disabled", &item_disabled);
@@ -2113,8 +2113,8 @@ static void DemoWindowWidgetsQueryingStatuses()
         if (item_type == 2) { ImGui::PushItemFlag(ImGuiItemFlags_ButtonRepeat, true); ret = ImGui::Button("ITEM: Button"); ImGui::PopItemFlag(); } // Testing button (with repeater)
         if (item_type == 3) { ret = ImGui::Checkbox("ITEM: Checkbox", &b); }                            // Testing checkbox
         if (item_type == 4) { ret = ImGui::SliderFloat("ITEM: SliderFloat", &col4f[0], 0.0f, 1.0f); }   // Testing basic item
-        if (item_type == 5) { ret = ImGui::InputText("ITEM: InputText", &str[0], IM_ARRAYSIZE(str)); }  // Testing input text (which handles tabbing)
-        if (item_type == 6) { ret = ImGui::InputTextMultiline("ITEM: InputTextMultiline", &str[0], IM_ARRAYSIZE(str)); } // Testing input text (which uses a child window)
+        if (item_type == 5) { ret = ImGui::InputText("ITEM: InputText", &str[0], IM_COUNTOF(str)); }  // Testing input text (which handles tabbing)
+        if (item_type == 6) { ret = ImGui::InputTextMultiline("ITEM: InputTextMultiline", &str[0], IM_COUNTOF(str)); } // Testing input text (which uses a child window)
         if (item_type == 7) { ret = ImGui::InputFloat("ITEM: InputFloat", col4f, 1.0f); }               // Testing +/- buttons on scalar input
         if (item_type == 8) { ret = ImGui::InputFloat3("ITEM: InputFloat3", col4f); }                   // Testing multi-component items (IsItemXXX flags are reported merged)
         if (item_type == 9) { ret = ImGui::ColorEdit4("ITEM: ColorEdit4", col4f); }                     // Testing multi-component items (IsItemXXX flags are reported merged)
@@ -2122,8 +2122,8 @@ static void DemoWindowWidgetsQueryingStatuses()
         if (item_type == 11) { ret = ImGui::MenuItem("ITEM: MenuItem"); }                                // Testing menu item (they use ImGuiButtonFlags_PressedOnRelease button policy)
         if (item_type == 12) { ret = ImGui::TreeNode("ITEM: TreeNode"); if (ret) ImGui::TreePop(); }     // Testing tree node
         if (item_type == 13) { ret = ImGui::TreeNodeEx("ITEM: TreeNode w/ ImGuiTreeNodeFlags_OpenOnDoubleClick", ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_NoTreePushOnOpen); } // Testing tree node with ImGuiButtonFlags_PressedOnDoubleClick button policy.
-        if (item_type == 14) { const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::Combo("ITEM: Combo", &current, items, IM_ARRAYSIZE(items)); }
-        if (item_type == 15) { const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", &current, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); }
+        if (item_type == 14) { const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::Combo("ITEM: Combo", &current, items, IM_COUNTOF(items)); }
+        if (item_type == 15) { const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", &current, items, IM_COUNTOF(items), IM_COUNTOF(items)); }
 
         bool hovered_delay_none = ImGui::IsItemHovered();
         bool hovered_delay_stationary = ImGui::IsItemHovered(ImGuiHoveredFlags_Stationary);
@@ -2190,7 +2190,7 @@ static void DemoWindowWidgetsQueryingStatuses()
             ImGui::EndDisabled();
 
         char buf[1] = "";
-        ImGui::InputText("unused", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_ReadOnly);
+        ImGui::InputText("unused", buf, IM_COUNTOF(buf), ImGuiInputTextFlags_ReadOnly);
         ImGui::SameLine();
         HelpMarker("This widget is only here to be able to tab-out of the widgets above and see e.g. Deactivated() status.");
 
@@ -2726,7 +2726,7 @@ static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_d
                 for (int n = 0; n < ITEMS_COUNT; n++)
                 {
                     char label[64];
-                    sprintf(label, "Object %05d: %s", n, ExampleNames[n % IM_ARRAYSIZE(ExampleNames)]);
+                    sprintf(label, "Object %05d: %s", n, ExampleNames[n % IM_COUNTOF(ExampleNames)]);
                     bool item_is_selected = selection.Contains((ImGuiID)n);
                     ImGui::SetNextItemSelectionUserData(n);
                     ImGui::Selectable(label, item_is_selected);
@@ -2766,7 +2766,7 @@ static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_d
                     for (int n = clipper.DisplayStart; n < clipper.DisplayEnd; n++)
                     {
                         char label[64];
-                        sprintf(label, "Object %05d: %s", n, ExampleNames[n % IM_ARRAYSIZE(ExampleNames)]);
+                        sprintf(label, "Object %05d: %s", n, ExampleNames[n % IM_COUNTOF(ExampleNames)]);
                         bool item_is_selected = selection.Contains((ImGuiID)n);
                         ImGui::SetNextItemSelectionUserData(n);
                         ImGui::Selectable(label, item_is_selected);
@@ -2828,7 +2828,7 @@ static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_d
                 {
                     const ImGuiID item_id = items[n];
                     char label[64];
-                    sprintf(label, "Object %05u: %s", item_id, ExampleNames[item_id % IM_ARRAYSIZE(ExampleNames)]);
+                    sprintf(label, "Object %05u: %s", item_id, ExampleNames[item_id % IM_COUNTOF(ExampleNames)]);
 
                     bool item_is_selected = selection.Contains(item_id);
                     ImGui::SetNextItemSelectionUserData(n);
@@ -2854,7 +2854,7 @@ static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_d
             // Init default state
             static ExampleDualListBox dlb;
             if (dlb.Items[0].Size == 0 && dlb.Items[1].Size == 0)
-                for (int item_id = 0; item_id < IM_ARRAYSIZE(ExampleNames); item_id++)
+                for (int item_id = 0; item_id < IM_COUNTOF(ExampleNames); item_id++)
                     dlb.Items[0].push_back((ImGuiID)item_id);
 
             // Show
@@ -2894,7 +2894,7 @@ static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_d
                         ImGui::TableNextColumn();
                         ImGui::PushID(n);
                         char label[64];
-                        sprintf(label, "Object %05d: %s", n, ExampleNames[n % IM_ARRAYSIZE(ExampleNames)]);
+                        sprintf(label, "Object %05d: %s", n, ExampleNames[n % IM_COUNTOF(ExampleNames)]);
                         bool item_is_selected = selection.Contains((ImGuiID)n);
                         ImGui::SetNextItemSelectionUserData(n);
                         ImGui::Selectable(label, item_is_selected, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowOverlap);
@@ -2928,7 +2928,7 @@ static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_d
 
             if (ImGui::BeginChild("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_Borders | ImGuiChildFlags_ResizeY))
             {
-                ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, -1, IM_ARRAYSIZE(items));
+                ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, -1, IM_COUNTOF(items));
                 ImGuiSelectionExternalStorage storage_wrapper;
                 storage_wrapper.UserData = (void*)items;
                 storage_wrapper.AdapterSetItemSelected = [](ImGuiSelectionExternalStorage* self, int n, bool selected) { bool* array = (bool*)self->UserData; array[n] = selected; };
@@ -2979,7 +2979,7 @@ static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_d
                 for (int n = 0; n < ITEMS_COUNT; n++)
                 {
                     char label[64];
-                    sprintf(label, "Object %05d: %s", n, ExampleNames[n % IM_ARRAYSIZE(ExampleNames)]);
+                    sprintf(label, "Object %05d: %s", n, ExampleNames[n % IM_COUNTOF(ExampleNames)]);
                     bool item_is_selected = selection->Contains((ImGuiID)n);
                     ImGui::SetNextItemSelectionUserData(n);
                     ImGui::Selectable(label, item_is_selected);
@@ -3268,7 +3268,7 @@ static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_d
                             ImGui::TableNextColumn();
 
                         const int item_id = items[n];
-                        const char* item_category = ExampleNames[item_id % IM_ARRAYSIZE(ExampleNames)];
+                        const char* item_category = ExampleNames[item_id % IM_COUNTOF(ExampleNames)];
                         char label[64];
                         sprintf(label, "Object %05d: %s", item_id, item_category);
 
@@ -3330,7 +3330,7 @@ static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_d
                             const int* payload_items = (int*)payload->Data;
                             const int payload_count = (int)payload->DataSize / (int)sizeof(int);
                             if (payload_count == 1)
-                                ImGui::Text("Object %05d: %s", payload_items[0], ExampleNames[payload_items[0] % IM_ARRAYSIZE(ExampleNames)]);
+                                ImGui::Text("Object %05d: %s", payload_items[0], ExampleNames[payload_items[0] % IM_COUNTOF(ExampleNames)]);
                             else
                                 ImGui::Text("Dragging %d objects", payload_count);
 
@@ -3456,7 +3456,7 @@ static void DemoWindowWidgetsTabs()
             ImGui::Text("Opened:");
             const char* names[4] = { "Artichoke", "Beetroot", "Celery", "Daikon" };
             static bool opened[4] = { true, true, true, true }; // Persistent user state
-            for (int n = 0; n < IM_ARRAYSIZE(opened); n++)
+            for (int n = 0; n < IM_COUNTOF(opened); n++)
             {
                 ImGui::SameLine();
                 ImGui::Checkbox(names[n], &opened[n]);
@@ -3466,7 +3466,7 @@ static void DemoWindowWidgetsTabs()
             // the underlying bool will be set to false when the tab is closed.
             if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
             {
-                for (int n = 0; n < IM_ARRAYSIZE(opened); n++)
+                for (int n = 0; n < IM_COUNTOF(opened); n++)
                     if (opened[n] && ImGui::BeginTabItem(names[n], &opened[n], ImGuiTabItemFlags_None))
                     {
                         ImGui::Text("This is the %s tab!", names[n]);
@@ -3525,7 +3525,7 @@ static void DemoWindowWidgetsTabs()
                 {
                     bool open = true;
                     char name[16];
-                    snprintf(name, IM_ARRAYSIZE(name), "%04d", active_tabs[n]);
+                    snprintf(name, IM_COUNTOF(name), "%04d", active_tabs[n]);
                     if (ImGui::BeginTabItem(name, &open, ImGuiTabItemFlags_None))
                     {
                         ImGui::Text("This is the %s tab!", name);
@@ -3659,7 +3659,7 @@ static void DemoWindowWidgetsText()
             ImGui::Text("Kanjis: \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (nihongo)");
             static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e";
             //static char buf[32] = u8"NIHONGO"; // <- this is how you would write it with C++11, using real kanjis
-            ImGui::InputText("UTF-8 input", buf, IM_ARRAYSIZE(buf));
+            ImGui::InputText("UTF-8 input", buf, IM_COUNTOF(buf));
             ImGui::TreePop();
         }
         ImGui::TreePop();
@@ -3686,7 +3686,7 @@ static void DemoWindowWidgetsTextFilter()
             "  \"-xxx\"     hide lines containing \"xxx\"");
         filter.Draw();
         const char* lines[] = { "aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world" };
-        for (int i = 0; i < IM_ARRAYSIZE(lines); i++)
+        for (int i = 0; i < IM_COUNTOF(lines); i++)
             if (filter.PassFilter(lines[i]))
                 ImGui::BulletText("%s", lines[i]);
         ImGui::TreePop();
@@ -3731,7 +3731,7 @@ static void DemoWindowWidgetsTextInput()
             ImGui::CheckboxFlags("ImGuiInputTextFlags_AllowTabInput", &flags, ImGuiInputTextFlags_AllowTabInput);
             ImGui::SameLine(); HelpMarker("When _AllowTabInput is set, passing through the widget with Tabbing doesn't automatically activate it, in order to also cycling through subsequent widgets.");
             ImGui::CheckboxFlags("ImGuiInputTextFlags_CtrlEnterForNewLine", &flags, ImGuiInputTextFlags_CtrlEnterForNewLine);
-            ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16), flags);
+            ImGui::InputTextMultiline("##source", text, IM_COUNTOF(text), ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16), flags);
             ImGui::TreePop();
         }
 
@@ -3757,13 +3757,13 @@ static void DemoWindowWidgetsTextInput()
                 }
             };
 
-            static char buf1[32] = ""; ImGui::InputText("default", buf1, IM_ARRAYSIZE(buf1));
-            static char buf2[32] = ""; ImGui::InputText("decimal", buf2, IM_ARRAYSIZE(buf2), ImGuiInputTextFlags_CharsDecimal);
-            static char buf3[32] = ""; ImGui::InputText("hexadecimal", buf3, IM_ARRAYSIZE(buf3), ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase);
-            static char buf4[32] = ""; ImGui::InputText("uppercase", buf4, IM_ARRAYSIZE(buf4), ImGuiInputTextFlags_CharsUppercase);
-            static char buf5[32] = ""; ImGui::InputText("no blank", buf5, IM_ARRAYSIZE(buf5), ImGuiInputTextFlags_CharsNoBlank);
-            static char buf6[32] = ""; ImGui::InputText("casing swap", buf6, IM_ARRAYSIZE(buf6), ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterCasingSwap); // Use CharFilter callback to replace characters.
-            static char buf7[32] = ""; ImGui::InputText("\"imgui\"", buf7, IM_ARRAYSIZE(buf7), ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters); // Use CharFilter callback to disable some characters.
+            static char buf1[32] = ""; ImGui::InputText("default", buf1, IM_COUNTOF(buf1));
+            static char buf2[32] = ""; ImGui::InputText("decimal", buf2, IM_COUNTOF(buf2), ImGuiInputTextFlags_CharsDecimal);
+            static char buf3[32] = ""; ImGui::InputText("hexadecimal", buf3, IM_COUNTOF(buf3), ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase);
+            static char buf4[32] = ""; ImGui::InputText("uppercase", buf4, IM_COUNTOF(buf4), ImGuiInputTextFlags_CharsUppercase);
+            static char buf5[32] = ""; ImGui::InputText("no blank", buf5, IM_COUNTOF(buf5), ImGuiInputTextFlags_CharsNoBlank);
+            static char buf6[32] = ""; ImGui::InputText("casing swap", buf6, IM_COUNTOF(buf6), ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterCasingSwap); // Use CharFilter callback to replace characters.
+            static char buf7[32] = ""; ImGui::InputText("\"imgui\"", buf7, IM_COUNTOF(buf7), ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters); // Use CharFilter callback to disable some characters.
             ImGui::TreePop();
         }
 
@@ -3771,10 +3771,10 @@ static void DemoWindowWidgetsTextInput()
         if (ImGui::TreeNode("Password Input"))
         {
             static char password[64] = "password123";
-            ImGui::InputText("password", password, IM_ARRAYSIZE(password), ImGuiInputTextFlags_Password);
+            ImGui::InputText("password", password, IM_COUNTOF(password), ImGuiInputTextFlags_Password);
             ImGui::SameLine(); HelpMarker("Display all characters as '*'.\nDisable clipboard cut and copy.\nDisable logging.\n");
-            ImGui::InputTextWithHint("password (w/ hint)", "<password>", password, IM_ARRAYSIZE(password), ImGuiInputTextFlags_Password);
-            ImGui::InputText("password (clear)", password, IM_ARRAYSIZE(password));
+            ImGui::InputTextWithHint("password (w/ hint)", "<password>", password, IM_COUNTOF(password), ImGuiInputTextFlags_Password);
+            ImGui::InputText("password (clear)", password, IM_COUNTOF(password));
             ImGui::TreePop();
         }
 
@@ -3819,20 +3819,20 @@ static void DemoWindowWidgetsTextInput()
                 }
             };
             static char buf1[64];
-            ImGui::InputText("Completion", buf1, IM_ARRAYSIZE(buf1), ImGuiInputTextFlags_CallbackCompletion, Funcs::MyCallback);
+            ImGui::InputText("Completion", buf1, IM_COUNTOF(buf1), ImGuiInputTextFlags_CallbackCompletion, Funcs::MyCallback);
             ImGui::SameLine(); HelpMarker(
                 "Here we append \"..\" each time Tab is pressed. "
                 "See 'Examples>Console' for a more meaningful demonstration of using this callback.");
 
             static char buf2[64];
-            ImGui::InputText("History", buf2, IM_ARRAYSIZE(buf2), ImGuiInputTextFlags_CallbackHistory, Funcs::MyCallback);
+            ImGui::InputText("History", buf2, IM_COUNTOF(buf2), ImGuiInputTextFlags_CallbackHistory, Funcs::MyCallback);
             ImGui::SameLine(); HelpMarker(
                 "Here we replace and select text each time Up/Down are pressed. "
                 "See 'Examples>Console' for a more meaningful demonstration of using this callback.");
 
             static char buf3[64];
             static int edit_count = 0;
-            ImGui::InputText("Edit", buf3, IM_ARRAYSIZE(buf3), ImGuiInputTextFlags_CallbackEdit, Funcs::MyCallback, (void*)&edit_count);
+            ImGui::InputText("Edit", buf3, IM_COUNTOF(buf3), ImGuiInputTextFlags_CallbackEdit, Funcs::MyCallback, (void*)&edit_count);
             ImGui::SameLine(); HelpMarker(
                 "Here we toggle the casing of the first character on every edit + count edits.");
             ImGui::SameLine(); ImGui::Text("(%d)", edit_count);
@@ -3892,7 +3892,7 @@ static void DemoWindowWidgetsTextInput()
             static char buf1[128] = "/path/to/some/folder/with/long/filename.cpp";
             static ImGuiInputTextFlags flags = ImGuiInputTextFlags_ElideLeft;
             ImGui::CheckboxFlags("ImGuiInputTextFlags_ElideLeft", &flags, ImGuiInputTextFlags_ElideLeft);
-            ImGui::InputText("Path", buf1, IM_ARRAYSIZE(buf1), flags);
+            ImGui::InputText("Path", buf1, IM_COUNTOF(buf1), flags);
             ImGui::TreePop();
         }
 
@@ -3904,7 +3904,7 @@ static void DemoWindowWidgetsTextInput()
             ImGui::CheckboxFlags("ImGuiInputTextFlags_EscapeClearsAll", &flags, ImGuiInputTextFlags_EscapeClearsAll);
             ImGui::CheckboxFlags("ImGuiInputTextFlags_ReadOnly", &flags, ImGuiInputTextFlags_ReadOnly);
             ImGui::CheckboxFlags("ImGuiInputTextFlags_NoUndoRedo", &flags, ImGuiInputTextFlags_NoUndoRedo);
-            ImGui::InputText("Hello", buf1, IM_ARRAYSIZE(buf1), flags);
+            ImGui::InputText("Hello", buf1, IM_COUNTOF(buf1), flags);
             ImGui::TreePop();
         }
 
@@ -3946,7 +3946,7 @@ static void DemoWindowWidgetsTooltips()
         {
             ImGui::Text("I am a fancy tooltip");
             static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
-            ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr));
+            ImGui::PlotLines("Curve", arr, IM_COUNTOF(arr));
             ImGui::Text("Sin(time) = %f", sinf((float)ImGui::GetTime()));
             ImGui::EndTooltip();
         }
@@ -4585,7 +4585,7 @@ static void DemoWindowLayout()
         ImGui::PushItemWidth(ImGui::CalcTextSize("AAAAAAA").x);
         const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD" };
         static int item = -1;
-        ImGui::Combo("Combo", &item, items, IM_ARRAYSIZE(items)); ImGui::SameLine();
+        ImGui::Combo("Combo", &item, items, IM_COUNTOF(items)); ImGui::SameLine();
         ImGui::SliderFloat("X", &f0, 0.0f, 5.0f); ImGui::SameLine();
         ImGui::SliderFloat("Y", &f1, 0.0f, 5.0f); ImGui::SameLine();
         ImGui::SliderFloat("Z", &f2, 0.0f, 5.0f);
@@ -4596,7 +4596,7 @@ static void DemoWindowLayout()
         {
             if (i > 0) ImGui::SameLine();
             ImGui::PushID(i);
-            ImGui::ListBox("", &selection[i], items, IM_ARRAYSIZE(items));
+            ImGui::ListBox("", &selection[i], items, IM_COUNTOF(items));
             ImGui::PopID();
             //ImGui::SetItemTooltip("ListBox %d hovered", i);
         }
@@ -4656,7 +4656,7 @@ static void DemoWindowLayout()
         // Capture the group size and create widgets using the same size
         ImVec2 size = ImGui::GetItemRectSize();
         const float values[5] = { 0.5f, 0.20f, 0.80f, 0.60f, 0.25f };
-        ImGui::PlotHistogram("##values", values, IM_ARRAYSIZE(values), 0, NULL, 0.0f, 1.0f, size);
+        ImGui::PlotHistogram("##values", values, IM_COUNTOF(values), 0, NULL, 0.0f, 1.0f, size);
 
         ImGui::Button("ACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x) * 0.5f, size.y));
         ImGui::SameLine();
@@ -5240,7 +5240,7 @@ static void DemoWindowPopups()
         if (ImGui::BeginPopup("my_select_popup"))
         {
             ImGui::SeparatorText("Aquarium");
-            for (int i = 0; i < IM_ARRAYSIZE(names); i++)
+            for (int i = 0; i < IM_COUNTOF(names); i++)
                 if (ImGui::Selectable(names[i]))
                     selected_fish = i;
             ImGui::EndPopup();
@@ -5251,7 +5251,7 @@ static void DemoWindowPopups()
             ImGui::OpenPopup("my_toggle_popup");
         if (ImGui::BeginPopup("my_toggle_popup"))
         {
-            for (int i = 0; i < IM_ARRAYSIZE(names); i++)
+            for (int i = 0; i < IM_COUNTOF(names); i++)
                 ImGui::MenuItem(names[i], "", &toggles[i]);
             if (ImGui::BeginMenu("Sub-menu"))
             {
@@ -5267,7 +5267,7 @@ static void DemoWindowPopups()
                 ImGui::OpenPopup("another popup");
             if (ImGui::BeginPopup("another popup"))
             {
-                for (int i = 0; i < IM_ARRAYSIZE(names); i++)
+                for (int i = 0; i < IM_COUNTOF(names); i++)
                     ImGui::MenuItem(names[i], "", &toggles[i]);
                 if (ImGui::BeginMenu("Sub-menu"))
                 {
@@ -5389,7 +5389,7 @@ static void DemoWindowPopups()
             if (ImGui::BeginPopupContextItem())
             {
                 ImGui::Text("Edit name:");
-                ImGui::InputText("##edit", name, IM_ARRAYSIZE(name));
+                ImGui::InputText("##edit", name, IM_COUNTOF(name));
                 if (ImGui::Button("Close"))
                     ImGui::CloseCurrentPopup();
                 ImGui::EndPopup();
@@ -5594,13 +5594,13 @@ static void EditTableSizingFlags(ImGuiTableFlags* p_flags)
         { ImGuiTableFlags_SizingStretchSame,  "ImGuiTableFlags_SizingStretchSame",  "Columns default to _WidthStretch with same weights." }
     };
     int idx;
-    for (idx = 0; idx < IM_ARRAYSIZE(policies); idx++)
+    for (idx = 0; idx < IM_COUNTOF(policies); idx++)
         if (policies[idx].Value == (*p_flags & ImGuiTableFlags_SizingMask_))
             break;
-    const char* preview_text = (idx < IM_ARRAYSIZE(policies)) ? policies[idx].Name + (idx > 0 ? strlen("ImGuiTableFlags") : 0) : "";
+    const char* preview_text = (idx < IM_COUNTOF(policies)) ? policies[idx].Name + (idx > 0 ? strlen("ImGuiTableFlags") : 0) : "";
     if (ImGui::BeginCombo("Sizing Policy", preview_text))
     {
-        for (int n = 0; n < IM_ARRAYSIZE(policies); n++)
+        for (int n = 0; n < IM_COUNTOF(policies); n++)
             if (ImGui::Selectable(policies[n].Name, idx == n))
                 *p_flags = (*p_flags & ~ImGuiTableFlags_SizingMask_) | policies[n].Value;
         ImGui::EndCombo();
@@ -5610,7 +5610,7 @@ static void EditTableSizingFlags(ImGuiTableFlags* p_flags)
     if (ImGui::BeginItemTooltip())
     {
         ImGui::PushTextWrapPos(ImGui::GetFontSize() * 50.0f);
-        for (int m = 0; m < IM_ARRAYSIZE(policies); m++)
+        for (int m = 0; m < IM_COUNTOF(policies); m++)
         {
             ImGui::Separator();
             ImGui::Text("%s:", policies[m].Name);
@@ -6108,7 +6108,7 @@ static void DemoWindowTables()
                     strcpy(text_bufs[cell], "edit me");
                 ImGui::SetNextItemWidth(-FLT_MIN);
                 ImGui::PushID(cell);
-                ImGui::InputText("##cell", text_bufs[cell], IM_ARRAYSIZE(text_bufs[cell]));
+                ImGui::InputText("##cell", text_bufs[cell], IM_COUNTOF(text_bufs[cell]));
                 ImGui::PopID();
             }
             if (!show_widget_frame_bg)
@@ -6221,7 +6221,7 @@ static void DemoWindowTables()
                 case CT_ShowWidth:  ImGui::Text("W: %.1f", ImGui::GetContentRegionAvail().x); break;
                 case CT_Button:     ImGui::Button(label); break;
                 case CT_FillButton: ImGui::Button(label, ImVec2(-FLT_MIN, 0.0f)); break;
-                case CT_InputText:  ImGui::SetNextItemWidth(-FLT_MIN); ImGui::InputText("##", text_buf, IM_ARRAYSIZE(text_buf)); break;
+                case CT_InputText:  ImGui::SetNextItemWidth(-FLT_MIN); ImGui::InputText("##", text_buf, IM_COUNTOF(text_buf)); break;
                 }
                 ImGui::PopID();
             }
@@ -6940,7 +6940,7 @@ static void DemoWindowTables()
     if (ImGui::TreeNode("Angled headers"))
     {
         const char* column_names[] = { "Track", "cabasa", "ride", "smash", "tom-hi", "tom-mid", "tom-low", "hihat-o", "hihat-c", "snare-s", "snare-c", "clap", "rim", "kick" };
-        const int columns_count = IM_ARRAYSIZE(column_names);
+        const int columns_count = IM_COUNTOF(column_names);
         const int rows_count = 12;
 
         static ImGuiTableFlags table_flags = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersInnerH | ImGuiTableFlags_Hideable | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_HighlightHoveredColumn;
@@ -7169,7 +7169,7 @@ static void DemoWindowTables()
             items.resize(50, MyItem());
             for (int n = 0; n < items.Size; n++)
             {
-                const int template_n = n % IM_ARRAYSIZE(template_items_names);
+                const int template_n = n % IM_COUNTOF(template_items_names);
                 MyItem& item = items[n];
                 item.ID = n;
                 item.Name = template_items_names[template_n];
@@ -7260,7 +7260,7 @@ static void DemoWindowTables()
         const char* contents_type_names[] = { "Text", "Button", "SmallButton", "FillButton", "Selectable", "Selectable (span row)" };
         static int freeze_cols = 1;
         static int freeze_rows = 1;
-        static int items_count = IM_ARRAYSIZE(template_items_names) * 2;
+        static int items_count = IM_COUNTOF(template_items_names) * 2;
         static ImVec2 outer_size_value = ImVec2(0.0f, TEXT_BASE_HEIGHT * 12);
         static float row_min_height = 0.0f; // Auto
         static float inner_width_with_scroll = 0.0f; // Auto-extend
@@ -7378,7 +7378,7 @@ static void DemoWindowTables()
                 ImGui::SameLine(); HelpMarker("Specify height of the Selectable item.");
 
                 ImGui::DragInt("items_count", &items_count, 0.1f, 0, 9999);
-                ImGui::Combo("items_type (first column)", &contents_type, contents_type_names, IM_ARRAYSIZE(contents_type_names));
+                ImGui::Combo("items_type (first column)", &contents_type, contents_type_names, IM_COUNTOF(contents_type_names));
                 //filter.Draw("filter");
                 ImGui::TreePop();
             }
@@ -7398,7 +7398,7 @@ static void DemoWindowTables()
             items.resize(items_count, MyItem());
             for (int n = 0; n < items_count; n++)
             {
-                const int template_n = n % IM_ARRAYSIZE(template_items_names);
+                const int template_n = n % IM_COUNTOF(template_items_names);
                 MyItem& item = items[n];
                 item.ID = n;
                 item.Name = template_items_names[template_n];
@@ -7800,10 +7800,10 @@ static void DemoWindowInputs()
                 ImGui::Text("Mouse pos: <INVALID>");
             ImGui::Text("Mouse delta: (%g, %g)", io.MouseDelta.x, io.MouseDelta.y);
             ImGui::Text("Mouse down:");
-            for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDown(i)) { ImGui::SameLine(); ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); }
+            for (int i = 0; i < IM_COUNTOF(io.MouseDown); i++) if (ImGui::IsMouseDown(i)) { ImGui::SameLine(); ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); }
             ImGui::Text("Mouse wheel: %.1f", io.MouseWheel);
             ImGui::Text("Mouse clicked count:");
-            for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (io.MouseClickedCount[i] > 0) { ImGui::SameLine(); ImGui::Text("b%d: %d", i, io.MouseClickedCount[i]); }
+            for (int i = 0; i < IM_COUNTOF(io.MouseDown); i++) if (io.MouseClickedCount[i] > 0) { ImGui::SameLine(); ImGui::Text("b%d: %d", i, io.MouseClickedCount[i]); }
 
             // We iterate both legacy native range and named ImGuiKey ranges. This is a little unusual/odd but this allows
             // displaying the data for old/new backends.
@@ -7926,7 +7926,7 @@ static void DemoWindowInputs()
             // (Commented because the owner-aware version of Shortcut() is still in imgui_internal.h)
             //char str[16] = "Press Ctrl+A";
             //ImGui::Spacing();
-            //ImGui::InputText("InputTextB", str, IM_ARRAYSIZE(str), ImGuiInputTextFlags_ReadOnly);
+            //ImGui::InputText("InputTextB", str, IM_COUNTOF(str), ImGuiInputTextFlags_ReadOnly);
             //ImGuiID item_id = ImGui::GetItemID();
             //ImGui::SameLine(); HelpMarker("Internal widgets always use _RouteFocused");
             //ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags, item_id) ? "PRESSED" : "...");
@@ -7951,7 +7951,7 @@ static void DemoWindowInputs()
                 ImGui::Text("(in PopupF)");
                 ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags) ? "PRESSED" : "...");
                 // (Commented because the owner-aware version of Shortcut() is still in imgui_internal.h)
-                //ImGui::InputText("InputTextG", str, IM_ARRAYSIZE(str), ImGuiInputTextFlags_ReadOnly);
+                //ImGui::InputText("InputTextG", str, IM_COUNTOF(str), ImGuiInputTextFlags_ReadOnly);
                 //ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags, ImGui::GetItemID()) ? "PRESSED" : "...");
                 ImGui::EndPopup();
             }
@@ -7966,7 +7966,7 @@ static void DemoWindowInputs()
         if (ImGui::TreeNode("Mouse Cursors"))
         {
             const char* mouse_cursors_names[] = { "Arrow", "TextInput", "ResizeAll", "ResizeNS", "ResizeEW", "ResizeNESW", "ResizeNWSE", "Hand", "Wait", "Progress", "NotAllowed" };
-            IM_ASSERT(IM_ARRAYSIZE(mouse_cursors_names) == ImGuiMouseCursor_COUNT);
+            IM_ASSERT(IM_COUNTOF(mouse_cursors_names) == ImGuiMouseCursor_COUNT);
 
             ImGuiMouseCursor current = ImGui::GetMouseCursor();
             const char* cursor_name = (current >= ImGuiMouseCursor_Arrow) && (current < ImGuiMouseCursor_COUNT) ? mouse_cursors_names[current] : "N/A";
@@ -7996,14 +7996,14 @@ static void DemoWindowInputs()
         {
             ImGui::Text("Use Tab/Shift+Tab to cycle through keyboard editable fields.");
             static char buf[32] = "hello";
-            ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
-            ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
-            ImGui::InputText("3", buf, IM_ARRAYSIZE(buf));
+            ImGui::InputText("1", buf, IM_COUNTOF(buf));
+            ImGui::InputText("2", buf, IM_COUNTOF(buf));
+            ImGui::InputText("3", buf, IM_COUNTOF(buf));
             ImGui::PushItemFlag(ImGuiItemFlags_NoTabStop, true);
-            ImGui::InputText("4 (tab skip)", buf, IM_ARRAYSIZE(buf));
+            ImGui::InputText("4 (tab skip)", buf, IM_COUNTOF(buf));
             ImGui::SameLine(); HelpMarker("Item won't be cycled through when using TAB or Shift+Tab.");
             ImGui::PopItemFlag();
-            ImGui::InputText("5", buf, IM_ARRAYSIZE(buf));
+            ImGui::InputText("5", buf, IM_COUNTOF(buf));
             ImGui::TreePop();
         }
 
@@ -8017,16 +8017,16 @@ static void DemoWindowInputs()
             static char buf[128] = "click on a button to set focus";
 
             if (focus_1) ImGui::SetKeyboardFocusHere();
-            ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
+            ImGui::InputText("1", buf, IM_COUNTOF(buf));
             if (ImGui::IsItemActive()) has_focus = 1;
 
             if (focus_2) ImGui::SetKeyboardFocusHere();
-            ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
+            ImGui::InputText("2", buf, IM_COUNTOF(buf));
             if (ImGui::IsItemActive()) has_focus = 2;
 
             ImGui::PushItemFlag(ImGuiItemFlags_NoTabStop, true);
             if (focus_3) ImGui::SetKeyboardFocusHere();
-            ImGui::InputText("3 (tab skip)", buf, IM_ARRAYSIZE(buf));
+            ImGui::InputText("3 (tab skip)", buf, IM_COUNTOF(buf));
             if (ImGui::IsItemActive()) has_focus = 3;
             ImGui::SameLine(); HelpMarker("Item won't be cycled through when using TAB or Shift+Tab.");
             ImGui::PopItemFlag();
@@ -8284,9 +8284,9 @@ bool ImGui::ShowStyleSelector(const char* label)
     static int style_idx = -1;
     const char* style_names[] = { "Dark", "Light", "Classic" };
     bool ret = false;
-    if (ImGui::BeginCombo(label, (style_idx >= 0 && style_idx < IM_ARRAYSIZE(style_names)) ? style_names[style_idx] : ""))
+    if (ImGui::BeginCombo(label, (style_idx >= 0 && style_idx < IM_COUNTOF(style_names)) ? style_names[style_idx] : ""))
     {
-        for (int n = 0; n < IM_ARRAYSIZE(style_names); n++)
+        for (int n = 0; n < IM_COUNTOF(style_names); n++)
         {
             if (ImGui::Selectable(style_names[n], style_idx == n, ImGuiSelectableFlags_SelectOnNav))
             {
@@ -8861,8 +8861,8 @@ struct ExampleAppConsole
         char buf[1024];
         va_list args;
         va_start(args, fmt);
-        vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
-        buf[IM_ARRAYSIZE(buf)-1] = 0;
+        vsnprintf(buf, IM_COUNTOF(buf), fmt, args);
+        buf[IM_COUNTOF(buf)-1] = 0;
         va_end(args);
         Items.push_back(Strdup(buf));
     }
@@ -8990,7 +8990,7 @@ struct ExampleAppConsole
         // Command-line
         bool reclaim_focus = false;
         ImGuiInputTextFlags input_text_flags = ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_EscapeClearsAll | ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory;
-        if (ImGui::InputText("Input", InputBuf, IM_ARRAYSIZE(InputBuf), input_text_flags, &TextEditCallbackStub, (void*)this))
+        if (ImGui::InputText("Input", InputBuf, IM_COUNTOF(InputBuf), input_text_flags, &TextEditCallbackStub, (void*)this))
         {
             char* s = InputBuf;
             Strtrim(s);
@@ -9314,8 +9314,8 @@ static void ShowExampleAppLog(bool* p_open)
         const char* words[] = { "Bumfuzzled", "Cattywampus", "Snickersnee", "Abibliophobia", "Absquatulate", "Nincompoop", "Pauciloquent" };
         for (int n = 0; n < 5; n++)
         {
-            const char* category = categories[counter % IM_ARRAYSIZE(categories)];
-            const char* word = words[counter % IM_ARRAYSIZE(words)];
+            const char* category = categories[counter % IM_COUNTOF(categories)];
+            const char* word = words[counter % IM_COUNTOF(words)];
             log.AddLog("[%05d] [%s] Hello, current time is %.1f, here's a word: '%s'\n",
                 ImGui::GetFrameCount(), category, ImGui::GetTime(), word);
             counter++;
@@ -9416,7 +9416,7 @@ struct ExampleAppPropertyEditor
             ImGui::SetNextItemWidth(-FLT_MIN);
             ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_F, ImGuiInputFlags_Tooltip);
             ImGui::PushItemFlag(ImGuiItemFlags_NoNavDefaultFocus, true);
-            if (ImGui::InputTextWithHint("##Filter", "incl,-excl", Filter.InputBuf, IM_ARRAYSIZE(Filter.InputBuf), ImGuiInputTextFlags_EscapeClearsAll))
+            if (ImGui::InputTextWithHint("##Filter", "incl,-excl", Filter.InputBuf, IM_COUNTOF(Filter.InputBuf), ImGuiInputTextFlags_EscapeClearsAll))
                 Filter.Build();
             ImGui::PopItemFlag();
 
@@ -9722,7 +9722,7 @@ static void ShowExampleAppConstrainedResize(bool* p_open)
             if (ImGui::Button("Set 500x500")) { ImGui::SetWindowSize(ImVec2(500, 500)); } ImGui::SameLine();
             if (ImGui::Button("Set 800x200")) { ImGui::SetWindowSize(ImVec2(800, 200)); }
             ImGui::SetNextItemWidth(ImGui::GetFontSize() * 20);
-            ImGui::Combo("Constraint", &type, test_desc, IM_ARRAYSIZE(test_desc));
+            ImGui::Combo("Constraint", &type, test_desc, IM_COUNTOF(test_desc));
             ImGui::SetNextItemWidth(ImGui::GetFontSize() * 20);
             ImGui::DragInt("Lines", &display_lines, 0.2f, 1, 100);
             ImGui::Checkbox("Auto-resize", &auto_resize);
@@ -9964,7 +9964,7 @@ static void ShowExampleAppCustomRendering(bool* p_open)
                 draw_list->AddTriangle(ImVec2(x+sz*0.5f,y), ImVec2(x+sz, y+sz-0.5f), ImVec2(x, y+sz-0.5f), col, th);x += sz + spacing;  // Triangle
                 //draw_list->AddTriangle(ImVec2(x+sz*0.2f,y), ImVec2(x, y+sz-0.5f), ImVec2(x+sz*0.4f, y+sz-0.5f), col, th);x+= sz*0.4f + spacing; // Thin triangle
                 PathConcaveShape(draw_list, x, y, sz); draw_list->PathStroke(col, ImDrawFlags_Closed, th);          x += sz + spacing;  // Concave Shape
-                //draw_list->AddPolyline(concave_shape, IM_ARRAYSIZE(concave_shape), col, ImDrawFlags_Closed, th);
+                //draw_list->AddPolyline(concave_shape, IM_COUNTOF(concave_shape), col, ImDrawFlags_Closed, th);
                 draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y), col, th);                                       x += sz + spacing;  // Horizontal line (note: drawing a filled rectangle will be faster!)
                 draw_list->AddLine(ImVec2(x, y), ImVec2(x, y + sz), col, th);                                       x += spacing;       // Vertical line (note: drawing a filled rectangle will be faster!)
                 draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y + sz), col, th);                                  x += sz + spacing;  // Diagonal line
@@ -10414,7 +10414,7 @@ void ShowExampleAppDocuments(bool* p_open)
         if (ImGui::BeginPopup("Rename"))
         {
             ImGui::SetNextItemWidth(ImGui::GetFontSize() * 30);
-            if (ImGui::InputText("###Name", app.RenamingDoc->Name, IM_ARRAYSIZE(app.RenamingDoc->Name), ImGuiInputTextFlags_EnterReturnsTrue))
+            if (ImGui::InputText("###Name", app.RenamingDoc->Name, IM_COUNTOF(app.RenamingDoc->Name), ImGuiInputTextFlags_EnterReturnsTrue))
             {
                 ImGui::CloseCurrentPopup();
                 app.RenamingDoc = NULL;
@@ -10812,7 +10812,7 @@ struct ExampleAssetsBrowser
                             draw_list->AddRectFilled(box_min, box_max, icon_bg_color); // Background color
                             if (ShowTypeOverlay && item_data->Type != 0)
                             {
-                                ImU32 type_col = icon_type_overlay_colors[item_data->Type % IM_ARRAYSIZE(icon_type_overlay_colors)];
+                                ImU32 type_col = icon_type_overlay_colors[item_data->Type % IM_COUNTOF(icon_type_overlay_colors)];
                                 draw_list->AddRectFilled(ImVec2(box_max.x - 2 - icon_type_overlay_size.x, box_min.y + 2), ImVec2(box_max.x - 2, box_min.y + 2 + icon_type_overlay_size.y), type_col);
                             }
                             if (display_label)

+ 505 - 62
3rdparty/dear-imgui/imgui_draw.cpp

@@ -17,10 +17,11 @@ Index of this file:
 // [SECTION] ImFontAtlas: backend for stb_truetype
 // [SECTION] ImFontAtlas: glyph ranges helpers
 // [SECTION] ImFontGlyphRangesBuilder
-// [SECTION] ImFont
+// [SECTION] ImFontBaked, ImFont
 // [SECTION] ImGui Internal Render Helpers
 // [SECTION] Decompression code
 // [SECTION] Default font data (ProggyClean.ttf)
+// [SECTION] Default font data (ProggyVector-minimal.ttf)
 
 */
 
@@ -391,9 +392,9 @@ ImDrawListSharedData::ImDrawListSharedData()
 {
     memset(this, 0, sizeof(*this));
     InitialFringeScale = 1.0f;
-    for (int i = 0; i < IM_ARRAYSIZE(ArcFastVtx); i++)
+    for (int i = 0; i < IM_COUNTOF(ArcFastVtx); i++)
     {
-        const float a = ((float)i * 2 * IM_PI) / (float)IM_ARRAYSIZE(ArcFastVtx);
+        const float a = ((float)i * 2 * IM_PI) / (float)IM_COUNTOF(ArcFastVtx);
         ArcFastVtx[i] = ImVec2(ImCos(a), ImSin(a));
     }
     ArcFastRadiusCutoff = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC_R(IM_DRAWLIST_ARCFAST_SAMPLE_MAX, CircleSegmentMaxError);
@@ -411,7 +412,7 @@ void ImDrawListSharedData::SetCircleTessellationMaxError(float max_error)
 
     IM_ASSERT(max_error > 0.0f);
     CircleSegmentMaxError = max_error;
-    for (int i = 0; i < IM_ARRAYSIZE(CircleSegmentCounts); i++)
+    for (int i = 0; i < IM_COUNTOF(CircleSegmentCounts); i++)
     {
         const float radius = (float)i;
         CircleSegmentCounts[i] = (ImU8)((i > 0) ? IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, CircleSegmentMaxError) : IM_DRAWLIST_ARCFAST_SAMPLE_MAX);
@@ -646,7 +647,7 @@ int ImDrawList::_CalcCircleAutoSegmentCount(float radius) const
 {
     // Automatic segment count
     const int radius_idx = (int)(radius + 0.999999f); // ceil to never reduce accuracy
-    if (radius_idx >= 0 && radius_idx < IM_ARRAYSIZE(_Data->CircleSegmentCounts))
+    if (radius_idx >= 0 && radius_idx < IM_COUNTOF(_Data->CircleSegmentCounts))
         return _Data->CircleSegmentCounts[radius_idx]; // Use cached value
     else
         return IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, _Data->CircleSegmentMaxError);
@@ -2418,6 +2419,7 @@ ImFontConfig::ImFontConfig()
     FontDataOwnedByAtlas = true;
     OversampleH = 0; // Auto == 1 or 2 depending on size
     OversampleV = 0; // Auto == 1
+    ExtraSizeScale = 1.0f;
     GlyphMaxAdvanceX = FLT_MAX;
     RasterizerMultiply = 1.0f;
     RasterizerDensity = 1.0f;
@@ -2516,6 +2518,8 @@ void ImTextureData::DestroyPixels()
 //-----------------------------------------------------------------------------
 // - ImFontAtlas::AddFont()
 // - ImFontAtlas::AddFontDefault()
+// - ImFontAtlas::AddFontDefaultBitmap()
+// - ImFontAtlas::AddFontDefaultVector()
 // - ImFontAtlas::AddFontFromFileTTF()
 // - ImFontAtlas::AddFontFromMemoryTTF()
 // - ImFontAtlas::AddFontFromMemoryCompressedTTF()
@@ -3043,7 +3047,7 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg_in)
     }
     else
     {
-        IM_ASSERT(Fonts.Size > 0 && "Cannot use MergeMode for the first font"); // When using MergeMode make sure that a font has already been added before. You can use ImGui::GetIO().Fonts->AddFontDefault() to add the default imgui font.
+        IM_ASSERT(Fonts.Size > 0 && "Cannot use MergeMode for the first font"); // When using MergeMode make sure that a font has already been added before.
         font = font_cfg_in->DstFont ? font_cfg_in->DstFont : Fonts.back();
     }
 
@@ -3105,12 +3109,30 @@ static void         Decode85(const unsigned char* src, unsigned char* dst)
     }
 }
 #ifndef IMGUI_DISABLE_DEFAULT_FONT
-static const char* GetDefaultCompressedFontDataTTF(int* out_size);
+static const char* GetDefaultCompressedFontDataProggyClean(int* out_size);
+static const char* GetDefaultCompressedFontDataProggyVector(int* out_size);
 #endif
 
-// Load embedded ProggyClean.ttf at size 13, disable oversampling
-// If you want a similar font which may be better scaled, consider using ProggyVector from the same author!
-ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg_template)
+// This duplicates some of the logic in UpdateFontsNewFrame() which is a bit chicken-and-eggy/tricky to extract due to variety of codepaths and possible initialization ordering.
+static float GetExpectedContextFontSize(ImGuiContext* ctx)
+{
+    return ((ctx->Style.FontSizeBase > 0.0f) ? ctx->Style.FontSizeBase : 13.0f) * ctx->Style.FontScaleMain * ctx->Style.FontScaleDpi;
+}
+
+// Legacy function with heuristic to select Pixel or Vector font.
+// The selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold at the time of adding the default font.
+// Prefer calling AddFontDefaultVector() or AddFontDefaultBitmap() based on your own logic.
+ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg)
+{
+    if (OwnerContext == NULL || GetExpectedContextFontSize(OwnerContext) >= 16.0f)
+        return AddFontDefaultVector(font_cfg);
+    else
+        return AddFontDefaultBitmap(font_cfg);
+}
+
+// Load embedded ProggyClean.ttf. Default size 13, disable oversampling.
+// If you want a similar font which may be better scaled, consider using AddFontDefaultVector().
+ImFont* ImFontAtlas::AddFontDefaultBitmap(const ImFontConfig* font_cfg_template)
 {
 #ifndef IMGUI_DISABLE_DEFAULT_FONT
     ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();
@@ -3120,17 +3142,40 @@ ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg_template)
         font_cfg.PixelSnapH = true;
     }
     if (font_cfg.SizePixels <= 0.0f)
-        font_cfg.SizePixels = 13.0f * 1.0f;
+        font_cfg.SizePixels = 13.0f; // This only serves (1) as a reference for GlyphOffset.y setting and (2) as a default for pre-1.92 backend.
     if (font_cfg.Name[0] == '\0')
-        ImFormatString(font_cfg.Name, IM_ARRAYSIZE(font_cfg.Name), "ProggyClean.ttf");
+        ImFormatString(font_cfg.Name, IM_COUNTOF(font_cfg.Name), "ProggyClean.ttf");
     font_cfg.EllipsisChar = (ImWchar)0x0085;
-    font_cfg.GlyphOffset.y += 1.0f * IM_TRUNC(font_cfg.SizePixels / 13.0f);  // Add +1 offset per 13 units
+    font_cfg.GlyphOffset.y += 1.0f * (font_cfg.SizePixels / 13.0f); // Add +1 offset per 13 units
 
     int ttf_compressed_size = 0;
-    const char* ttf_compressed = GetDefaultCompressedFontDataTTF(&ttf_compressed_size);
+    const char* ttf_compressed = GetDefaultCompressedFontDataProggyClean(&ttf_compressed_size);
     return AddFontFromMemoryCompressedTTF(ttf_compressed, ttf_compressed_size, font_cfg.SizePixels, &font_cfg);
 #else
-    IM_ASSERT(0 && "AddFontDefault() disabled in this build.");
+    IM_ASSERT(0 && "Function is disabled in this build.");
+    IM_UNUSED(font_cfg_template);
+    return NULL;
+#endif // #ifndef IMGUI_DISABLE_DEFAULT_FONT
+}
+
+// Load a minimal version of ProggyVector, designed to match our good old ProggyClean, but nicely scalable.
+// (See misc/fonts/ProggyVector-ExtractScript.txt for details)
+ImFont* ImFontAtlas::AddFontDefaultVector(const ImFontConfig* font_cfg_template)
+{
+#ifndef IMGUI_DISABLE_DEFAULT_FONT
+    ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();
+    if (font_cfg.SizePixels <= 0.0f)
+        font_cfg.SizePixels = 16.0f;
+    if (font_cfg.Name[0] == '\0')
+        ImFormatString(font_cfg.Name, IM_COUNTOF(font_cfg.Name), "ProggyVector.ttf");
+    font_cfg.ExtraSizeScale = 1.140f; // Match ProggyClean
+    font_cfg.GlyphOffset.y += -0.5f * (font_cfg.SizePixels / 13.0f); // Closer match ProggyClean + avoid descenders going too high (with current code).
+
+    int ttf_compressed_size = 0;
+    const char* ttf_compressed = GetDefaultCompressedFontDataProggyVector(&ttf_compressed_size);
+    return AddFontFromMemoryCompressedTTF(ttf_compressed, ttf_compressed_size, font_cfg.SizePixels, &font_cfg);
+#else
+    IM_ASSERT(0 && "Function is disabled in this build.");
     IM_UNUSED(font_cfg_template);
     return NULL;
 #endif // #ifndef IMGUI_DISABLE_DEFAULT_FONT
@@ -3156,7 +3201,7 @@ ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels,
         // Store a short copy of filename into 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_ARRAYSIZE(font_cfg.Name), "%s", p);
+        ImFormatString(font_cfg.Name, IM_COUNTOF(font_cfg.Name), "%s", p);
     }
     return AddFontFromMemoryTTF(data, (int)data_size, size_pixels, &font_cfg, glyph_ranges);
 }
@@ -3392,6 +3437,7 @@ void ImFontAtlasBuildMain(ImFontAtlas* atlas)
 
 void ImFontAtlasBuildGetOversampleFactors(ImFontConfig* src, ImFontBaked* baked, int* out_oversample_h, int* out_oversample_v)
 {
+    // (Only used by stb_truetype builder)
     // Automatically disable horizontal oversampling over size 36
     const float raster_size = baked->Size * baked->RasterizerDensity * src->RasterizerDensity;
     *out_oversample_h = (src->OversampleH != 0) ? src->OversampleH : (raster_size > 36.0f || src->PixelSnapH) ? 1 : 2;
@@ -3606,6 +3652,12 @@ void ImFontAtlasFontDestroyOutput(ImFontAtlas* atlas, ImFont* font)
     }
 }
 
+void ImFontAtlasFontRebuildOutput(ImFontAtlas* atlas, ImFont* font)
+{
+    ImFontAtlasFontDestroyOutput(atlas, font);
+    ImFontAtlasFontInitOutput(atlas, font);
+}
+
 //-----------------------------------------------------------------------------------------------------------------------------
 
 bool ImFontAtlasFontSourceInit(ImFontAtlas* atlas, ImFontConfig* src)
@@ -4005,7 +4057,7 @@ static void ImFontAtlasDebugWriteTexToDisk(ImTextureData* tex, const char* descr
 {
     ImGuiContext& g = *GImGui;
     char buf[128];
-    ImFormatString(buf, IM_ARRAYSIZE(buf), "[%05d] Texture #%03d - %s.png", g.FrameCount, tex->UniqueID, description);
+    ImFormatString(buf, IM_COUNTOF(buf), "[%05d] Texture #%03d - %s.png", g.FrameCount, tex->UniqueID, description);
     stbi_write_png(buf, tex->Width, tex->Height, tex->BytesPerPixel, tex->Pixels, tex->GetPitch()); // tex->BytesPerPixel is technically not component, but ok for the formats we support.
 }
 #endif
@@ -4234,6 +4286,10 @@ void ImFontAtlasBuildInit(ImFontAtlas* atlas)
     ImFontAtlasUpdateDrawListsSharedData(atlas);
 
     //atlas->TexIsBuilt = true;
+
+    // Lazily initialize char/text classifier
+    // FIXME: This could be practically anywhere, and should eventually be parameters to CalcTextSize/word-wrapping code, but there's no obvious spot now.
+    ImTextInitClassifiers();
 }
 
 // Destroy builder and all cached glyphs. Do not destroy actual fonts.
@@ -4601,6 +4657,7 @@ static bool ImGui_ImplStbTrueType_FontSrcInit(ImFontAtlas* atlas, ImFontConfig*
     bd_font_data->ScaleFactor = stbtt_ScaleForPixelHeight(&bd_font_data->FontInfo, 1.0f);
     if (src->MergeMode && src->SizePixels != 0.0f && ref_size != 0.0f)
         bd_font_data->ScaleFactor *= src->SizePixels / ref_size; // FIXME-NEWATLAS: Should tidy up that a bit
+    bd_font_data->ScaleFactor *= src->ExtraSizeScale;
 
     return true;
 }
@@ -4708,12 +4765,8 @@ static bool ImGui_ImplStbTrueType_FontBakedLoadGlyph(ImFontAtlas* atlas, ImFontC
 
         const float ref_size = baked->OwnerFont->Sources[0]->SizePixels;
         const float offsets_scale = (ref_size != 0.0f) ? (baked->Size / ref_size) : 1.0f;
-        float font_off_x = (src->GlyphOffset.x * offsets_scale);
-        float font_off_y = (src->GlyphOffset.y * offsets_scale);
-        if (src->PixelSnapH) // Snap scaled offset. This is to mitigate backward compatibility issues for GlyphOffset, but a better design would be welcome.
-            font_off_x = IM_ROUND(font_off_x);
-        if (src->PixelSnapV)
-            font_off_y = IM_ROUND(font_off_y);
+        float font_off_x = ImFloor(src->GlyphOffset.x * offsets_scale + 0.5f); // Snap scaled offset.
+        float font_off_y = ImFloor(src->GlyphOffset.y * offsets_scale + 0.5f);
         font_off_x += sub_x;
         font_off_y += sub_y + IM_ROUND(baked->Ascent);
         float recip_h = 1.0f / (oversample_h * rasterizer_density);
@@ -4885,11 +4938,11 @@ const ImWchar*  ImFontAtlas::GetGlyphRangesChineseSimplifiedCommon()
         0xFF00, 0xFFEF, // Half-width characters
         0xFFFD, 0xFFFD  // Invalid
     };
-    static ImWchar full_ranges[IM_ARRAYSIZE(base_ranges) + IM_ARRAYSIZE(accumulative_offsets_from_0x4E00) * 2 + 1] = { 0 };
+    static ImWchar full_ranges[IM_COUNTOF(base_ranges) + IM_COUNTOF(accumulative_offsets_from_0x4E00) * 2 + 1] = { 0 };
     if (!full_ranges[0])
     {
         memcpy(full_ranges, base_ranges, sizeof(base_ranges));
-        UnpackAccumulativeOffsetsIntoRanges(0x4E00, accumulative_offsets_from_0x4E00, IM_ARRAYSIZE(accumulative_offsets_from_0x4E00), full_ranges + IM_ARRAYSIZE(base_ranges));
+        UnpackAccumulativeOffsetsIntoRanges(0x4E00, accumulative_offsets_from_0x4E00, IM_COUNTOF(accumulative_offsets_from_0x4E00), full_ranges + IM_COUNTOF(base_ranges));
     }
     return &full_ranges[0];
 }
@@ -4975,11 +5028,11 @@ const ImWchar*  ImFontAtlas::GetGlyphRangesJapanese()
         0xFF00, 0xFFEF, // Half-width characters
         0xFFFD, 0xFFFD  // Invalid
     };
-    static ImWchar full_ranges[IM_ARRAYSIZE(base_ranges) + IM_ARRAYSIZE(accumulative_offsets_from_0x4E00)*2 + 1] = { 0 };
+    static ImWchar full_ranges[IM_COUNTOF(base_ranges) + IM_COUNTOF(accumulative_offsets_from_0x4E00)*2 + 1] = { 0 };
     if (!full_ranges[0])
     {
         memcpy(full_ranges, base_ranges, sizeof(base_ranges));
-        UnpackAccumulativeOffsetsIntoRanges(0x4E00, accumulative_offsets_from_0x4E00, IM_ARRAYSIZE(accumulative_offsets_from_0x4E00), full_ranges + IM_ARRAYSIZE(base_ranges));
+        UnpackAccumulativeOffsetsIntoRanges(0x4E00, accumulative_offsets_from_0x4E00, IM_COUNTOF(accumulative_offsets_from_0x4E00), full_ranges + IM_COUNTOF(base_ranges));
     }
     return &full_ranges[0];
 }
@@ -5068,7 +5121,7 @@ void ImFontGlyphRangesBuilder::BuildRanges(ImVector<ImWchar>* out_ranges)
 }
 
 //-----------------------------------------------------------------------------
-// [SECTION] ImFont
+// [SECTION] ImFontBaked, ImFont
 //-----------------------------------------------------------------------------
 
 ImFontBaked::ImFontBaked()
@@ -5371,17 +5424,64 @@ const char* ImTextCalcWordWrapNextLineStart(const char* text, const char* text_e
     return text;
 }
 
+void ImTextClassifierClear(ImU32* bits, unsigned int codepoint_min, unsigned int codepoint_end, ImWcharClass char_class)
+{
+    for (unsigned int c = codepoint_min; c < codepoint_end; c++)
+        ImTextClassifierSetCharClass(bits, codepoint_min, codepoint_end, char_class, c);
+}
+
+void ImTextClassifierSetCharClass(ImU32* bits, unsigned int codepoint_min, unsigned int codepoint_end, ImWcharClass char_class, unsigned int c)
+{
+    IM_ASSERT(c >= codepoint_min && c < codepoint_end);
+    IM_UNUSED(codepoint_end);
+    c -= codepoint_min;
+    const ImU32 shift = (c & 15) << 1;
+    bits[c >> 4] = (bits[c >> 4] & ~(0x03 << shift)) | (char_class << shift);
+}
+
+void ImTextClassifierSetCharClassFromStr(ImU32* bits, unsigned int codepoint_min, unsigned int codepoint_end, ImWcharClass char_class, const char* s)
+{
+    const char* s_end = s + strlen(s);
+    while (*s)
+    {
+        unsigned int c;
+        s += ImTextCharFromUtf8(&c, s, s_end);
+        ImTextClassifierSetCharClass(bits, codepoint_min, codepoint_end, char_class, c);
+    }
+}
+
+#define ImTextClassifierGet(_BITS, _CHAR_OFFSET)    ((_BITS[(_CHAR_OFFSET) >> 4] >> (((_CHAR_OFFSET) & 15) << 1)) & 0x03)
+
+// 2-bit per character
+static ImU32 g_CharClassifierIsSeparator_0000_007f[128 / 16] = {};
+static ImU32 g_CharClassifierIsSeparator_3000_300f[ 16 / 16] = {};
+
+void ImTextInitClassifiers()
+{
+    if (ImTextClassifierGet(g_CharClassifierIsSeparator_0000_007f, ',') != 0)
+        return;
+
+    // List of hardcoded separators: .,;!?'"
+    // Making this dynamic given known ranges is trivial BUT requires us to standardize where you pass them as parameters. (#3002, #8503)
+    ImTextClassifierClear(g_CharClassifierIsSeparator_0000_007f, 0, 128, ImWcharClass_Other);
+    ImTextClassifierSetCharClassFromStr(g_CharClassifierIsSeparator_0000_007f, 0, 128, ImWcharClass_Blank, " \t");
+    ImTextClassifierSetCharClassFromStr(g_CharClassifierIsSeparator_0000_007f, 0, 128, ImWcharClass_Punct, ".,;!?\"");
+
+    ImTextClassifierClear(g_CharClassifierIsSeparator_3000_300f, 0x3000, 0x300F, ImWcharClass_Other);
+    ImTextClassifierSetCharClass(g_CharClassifierIsSeparator_3000_300f, 0x3000, 0x300F, ImWcharClass_Blank, 0x3000);
+    ImTextClassifierSetCharClass(g_CharClassifierIsSeparator_3000_300f, 0x3000, 0x300F, ImWcharClass_Punct, 0x3001);
+    ImTextClassifierSetCharClass(g_CharClassifierIsSeparator_3000_300f, 0x3000, 0x300F, ImWcharClass_Punct, 0x3002);
+}
+
 // 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.
-// FIXME: Much possible improvements (don't cut things like "word !", "word!!!" but cut within "word,,,,", more sensible support for punctuations, support for Unicode punctuations, etc.)
+// 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)
 {
     // For references, possible wrap point marked with ^
     //  "aaa bbb, ccc,ddd. eee   fff. ggg!"
     //      ^    ^    ^   ^   ^__    ^    ^
 
-    // List of hardcoded separators: .,;!?'"
-
     // Skip extra blanks after a line returns (that includes not counting them in width computation)
     // e.g. "Hello    world" --> "Hello" "World"
 
@@ -5392,16 +5492,20 @@ const char* ImFontCalcWordWrapPositionEx(ImFont* font, float size, const char* t
     const float scale = size / baked->Size;
 
     float line_width = 0.0f;
-    float word_width = 0.0f;
     float blank_width = 0.0f;
     wrap_width /= scale; // We work with unscaled widths to avoid scaling every characters
 
-    const char* word_end = text;
-    const char* prev_word_end = NULL;
-    bool inside_word = true;
-
     const char* s = text;
     IM_ASSERT(text_end != NULL);
+
+    int prev_type = ImWcharClass_Other;
+    const bool keep_blanks = (flags & ImDrawTextFlags_WrapKeepBlanks) != 0;
+
+    // Find next wrapping point
+    //const char* span_begin = s;
+    const char* span_end = s;
+    float span_width = 0.0f;
+
     while (s < text_end)
     {
         unsigned int c = (unsigned int)*s;
@@ -5417,7 +5521,7 @@ const char* ImFontCalcWordWrapPositionEx(ImFont* font, float size, const char* t
                 return s; // Direct return, skip "Wrap_width is too small to fit anything" path.
             if (c == '\r')
             {
-                s = next_s;
+                s = next_s; // Fast-skip
                 continue;
             }
         }
@@ -5427,46 +5531,56 @@ const char* ImFontCalcWordWrapPositionEx(ImFont* font, float size, const char* t
         if (char_width < 0.0f)
             char_width = BuildLoadGlyphGetAdvanceOrFallback(baked, c);
 
-        if (ImCharIsBlankW(c))
+        // Classify current character
+        int curr_type;
+        if (c < 128)
+            curr_type = ImTextClassifierGet(g_CharClassifierIsSeparator_0000_007f, c);
+        else if (c >= 0x3000 && c < 0x3010)
+            curr_type = ImTextClassifierGet(g_CharClassifierIsSeparator_3000_300f, c & 15); //-V578
+        else
+            curr_type = ImWcharClass_Other;
+
+        if (curr_type == ImWcharClass_Blank)
         {
-            if (inside_word)
+            // End span: 'A ' or '. '
+            if (prev_type != ImWcharClass_Blank && !keep_blanks)
             {
-                line_width += blank_width;
-                blank_width = 0.0f;
-                word_end = s;
+                span_end = s;
+                line_width += span_width;
+                span_width = 0.0f;
             }
             blank_width += char_width;
-            inside_word = false;
         }
         else
         {
-            word_width += char_width;
-            if (inside_word)
+            // End span: '.X' unless X is a digit
+            if (prev_type == ImWcharClass_Punct && curr_type != ImWcharClass_Punct && !(c >= '0' && c <= '9')) // FIXME: Digit checks might be removed if allow custom separators (#8503)
             {
-                word_end = next_s;
+                span_end = s;
+                line_width += span_width + blank_width;
+                span_width = blank_width = 0.0f;
             }
-            else
+            // End span: 'A ' or '. '
+            else if (prev_type == ImWcharClass_Blank && keep_blanks)
             {
-                prev_word_end = word_end;
-                line_width += word_width + blank_width;
-                if ((flags & ImDrawTextFlags_WrapKeepBlanks) && line_width <= wrap_width)
-                    prev_word_end = s;
-                word_width = blank_width = 0.0f;
+                span_end = s;
+                line_width += span_width + blank_width;
+                span_width = blank_width = 0.0f;
             }
-
-            // Allow wrapping after punctuation.
-            inside_word = (c != '.' && c != ',' && c != ';' && c != '!' && c != '?' && c != '\"' && c != 0x3001 && c != 0x3002);
+            span_width += char_width;
         }
 
-        // We ignore blank width at the end of the line (they can be skipped)
-        if (line_width + word_width > wrap_width)
+        if (span_width + blank_width + line_width > wrap_width)
         {
-            // Words that cannot possibly fit within an entire line will be cut anywhere.
-            if (word_width < wrap_width)
-                s = prev_word_end ? prev_word_end : word_end;
-            break;
+            if (span_width + blank_width > wrap_width)
+                break;
+            // FIXME: Narrow wrapping e.g. "A quick brown" -> "Quic|k br|own", would require knowing if span is going to be longer than wrap_width.
+            //if (span_width > wrap_width && !is_blank && !was_blank)
+            //    return s;
+            return span_end;
         }
 
+        prev_type = curr_type;
         s = next_s;
     }
 
@@ -6336,11 +6450,340 @@ static const unsigned char proggy_clean_ttf_compressed_data[9583] =
     239,32,57,141,239,32,57,141,239,32,57,141,239,32,57,141,239,32,57,141,239,35,57,102,0,0,5,250,72,249,98,247,
 };
 
-static const char* GetDefaultCompressedFontDataTTF(int* out_size)
+static const char* GetDefaultCompressedFontDataProggyClean(int* out_size)
 {
     *out_size = proggy_clean_ttf_compressed_size;
     return (const char*)proggy_clean_ttf_compressed_data;
 }
+
+//-----------------------------------------------------------------------------
+// [SECTION] Default font data (ProggyVector-minimal.ttf)
+//-----------------------------------------------------------------------------
+// Based on ProggyVector.ttf, Copyright (c) 2019,2023 Tristan Grimmer / Copyright (c) 2018 Source Foundry Authors / Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved.
+// MIT license + public domain, see licenses at https://github.com/bluescan/proggyfonts/tree/master/ProggyVector
+//-----------------------------------------------------------------------------
+// See misc/fonts/ProggyVector-ExtractScript.txt for FontForge script to create this from ProggyVector.ttf
+//-----------------------------------------------------------------------------
+
+// File: 'ProggyVector-minimal.ttf' (23952 bytes)
+// Exported using binary_to_compressed_c.exe -u8 "ProggyVector-minimal.ttf" proggy_vector_minimal_ttf
+static const unsigned int proggy_vector_minimal_ttf_compressed_size = 18519;
+static const unsigned char proggy_vector_minimal_ttf_compressed_data[18519] =
+{
+    87,188,0,0,0,0,0,0,0,0,93,144,0,4,0,0,55,0,1,0,0,0,14,0,128,0,3,0,96,70,70,84,77,165,245,48,76,0,0,93,116,130,21,38,28,71,68,69,70,0,37,130,9,34,0,93,92,130,5,44,24,79,83,47,50,135,
+    98,111,82,0,0,1,104,130,15,44,96,99,109,97,112,10,236,8,177,0,0,3,88,130,19,44,82,99,118,116,32,0,34,2,136,0,0,4,172,130,31,38,4,103,97,115,112,255,255,130,89,34,0,93,84,130,15,56,
+    8,103,108,121,102,169,208,238,39,0,0,6,56,0,0,84,32,104,101,97,100,39,214,168,186,130,27,32,236,130,3,33,54,104,130,16,35,6,225,0,231,130,75,32,36,130,15,40,36,104,109,116,120,37,72,
+    32,85,130,15,32,200,130,3,40,142,108,111,99,97,26,185,47,212,130,95,32,176,130,15,40,136,109,97,120,112,0,201,0,151,130,11,32,72,130,47,43,32,110,97,109,101,10,160,159,163,0,0,90,131,
+    143,44,68,112,111,115,116,153,185,200,234,0,0,91,156,130,35,32,184,132,235,45,1,0,0,96,193,239,192,95,15,60,245,0,11,4,130,54,37,0,0,225,81,71,241,131,8,43,228,205,29,41,255,247,255,
+    2,2,162,3,161,130,15,34,8,0,2,130,5,131,2,32,1,130,225,38,182,254,184,0,143,2,102,130,31,34,196,2,162,132,73,131,25,135,3,32,4,132,17,37,195,0,104,0,5,0,134,49,131,6,132,3,32,46,132,
+    5,36,2,2,102,1,144,131,29,39,2,138,2,188,0,47,0,140,131,7,40,255,92,1,224,0,49,1,2,0,131,0,32,9,132,57,143,61,43,0,66,105,114,100,0,64,0,32,32,172,3,132,131,47,3,182,1,72,32,63,0,255,
+    223,253,0,0,2,14,3,182,130,48,38,32,0,1,2,102,0,34,130,9,32,0,130,7,132,3,35,0,237,0,169,130,147,46,91,0,19,0,29,1,10,0,168,0,205,0,46,0,41,130,5,32,83,130,25,44,65,0,67,0,132,0,76,
+    0,75,0,40,0,72,130,11,40,70,0,66,0,63,0,239,0,209,130,33,52,45,0,44,0,81,255,251,0,18,0,79,0,70,0,69,0,94,0,117,0,51,130,7,34,100,0,61,130,5,34,108,0,38,130,21,36,58,0,86,0,58,130,
+    57,42,70,0,24,0,60,0,29,0,2,0,9,130,47,50,55,0,148,0,62,0,154,0,61,255,247,0,167,0,68,0,96,0,82,130,51,34,62,0,66,130,105,40,97,0,166,0,118,0,113,0,141,130,97,32,97,130,71,32,95,130,
+    3,40,129,0,106,0,128,0,84,0,50,130,183,32,38,130,85,38,101,0,92,1,6,0,102,130,147,36,0,0,232,0,105,130,17,34,102,0,18,130,187,34,99,0,160,130,33,38,135,0,40,0,44,0,178,130,9,34,159,
+    0,150,130,9,52,161,0,163,0,238,0,83,0,53,0,227,0,198,0,172,0,122,0,116,0,13,132,1,32,96,130,139,32,18,136,3,32,0,130,71,33,98,0,133,1,33,100,0,133,1,32,4,132,195,32,58,130,195,131,
+    3,36,75,0,4,0,74,134,1,32,18,130,33,32,94,130,187,32,68,136,3,32,20,130,197,32,62,130,215,131,3,34,109,0,134,132,1,33,69,0,131,195,32,69,130,195,131,3,34,44,0,24,130,15,32,97,132,3,
+    36,52,0,95,0,52,130,123,130,166,33,0,3,130,4,131,3,34,28,0,1,130,9,36,0,0,76,0,3,132,9,32,28,130,111,32,48,130,17,46,8,0,8,0,2,0,0,0,126,0,255,32,172,255,255,130,9,34,32,0,160,131,
+    9,37,255,227,255,194,224,22,132,43,130,20,131,2,34,1,6,0,136,14,35,1,2,0,0,132,55,130,6,136,2,8,152,1,0,0,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,
+    30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,
+    90,91,92,93,94,95,96,97,0,134,135,137,139,147,152,158,163,162,164,166,165,167,169,171,170,172,173,175,174,176,177,179,181,180,182,184,183,188,187,189,190,0,114,100,101,105,0,120,161,
+    112,107,0,118,106,0,136,154,0,115,0,0,103,119,132,161,39,108,124,0,168,186,129,99,110,131,12,38,109,125,0,98,130,133,151,131,10,131,3,37,185,0,193,0,0,194,131,9,33,0,121,130,5,47,132,
+    140,131,141,138,143,144,145,142,149,150,0,148,156,157,155,130,18,32,113,130,3,32,122,130,3,130,2,34,34,2,136,130,5,33,42,0,133,1,8,186,80,0,100,0,170,1,22,1,132,2,2,2,16,2,36,2,56,
+    2,104,2,124,2,166,2,182,2,208,2,226,3,26,3,52,3,132,3,214,3,246,4,46,4,126,4,150,4,238,5,66,5,120,5,194,5,224,5,244,6,14,6,84,6,224,7,12,7,80,7,122,7,162,7,184,7,208,8,0,8,24,8,46,
+    8,76,8,116,8,132,8,170,8,202,8,254,9,42,9,98,9,160,9,248,10,10,10,66,10,98,10,152,10,208,10,246,11,20,11,38,11,68,11,86,11,116,11,128,11,152,11,234,12,52,12,100,12,180,12,238,13,16,
+    13,108,13,148,13,194,13,236,14,18,14,38,14,96,14,128,14,176,14,222,15,18,15,60,15,122,15,152,15,190,15,224,16,18,16,76,16,146,16,178,16,240,16,254,17,68,17,122,130,1,8,225,158,17,228,
+    18,12,18,88,18,142,18,162,19,32,19,66,19,176,19,246,20,40,20,56,20,68,20,192,20,206,21,8,21,34,21,80,21,160,21,184,21,232,22,4,22,32,22,62,22,88,22,146,22,198,23,4,23,80,23,196,24,
+    40,24,96,24,146,24,208,25,46,25,116,25,188,25,228,26,48,26,84,26,114,26,156,26,212,26,244,27,16,27,52,27,100,27,154,27,244,28,46,28,98,28,162,29,10,29,82,29,144,30,0,30,68,30,134,30,
+    210,31,38,31,84,31,122,31,212,32,68,32,176,33,36,33,182,34,50,34,188,35,44,35,128,35,206,36,24,36,104,36,192,36,238,37,20,37,64,37,118,37,216,38,38,38,104,38,160,38,222,39,60,39,134,
+    39,174,39,250,40,50,40,100,40,158,40,226,41,42,41,92,41,178,42,16,0,2,0,34,0,0,1,50,2,170,0,3,0,7,0,46,177,1,0,47,60,178,7,4,0,237,50,177,6,5,220,60,178,3,2,130,10,34,0,177,3,131,22,
+    32,5,131,22,39,178,7,6,1,252,60,178,1,131,23,53,51,17,33,17,39,51,17,35,34,1,16,238,204,204,2,170,253,86,34,2,102,0,130,83,8,71,237,255,255,1,126,2,228,0,14,0,20,0,0,37,50,23,22,20,
+    14,1,35,34,39,38,53,52,55,54,19,3,35,3,53,51,1,53,50,17,6,33,25,15,32,19,21,21,19,85,15,80,18,113,140,42,13,47,30,9,19,19,24,41,19,19,1,221,254,160,1,96,123,0,131,75,38,169,1,185,1,
+    191,2,189,132,159,34,0,1,17,131,115,39,51,17,1,104,87,254,234,87,130,25,35,4,254,252,1,130,3,61,0,2,0,1,0,5,2,102,2,183,0,5,0,46,0,0,19,51,54,55,35,6,15,1,35,62,1,55,35,53,130,12,130,
+    14,38,53,51,55,51,14,1,7,134,5,33,21,35,131,11,34,21,35,7,131,34,51,229,123,31,11,123,11,50,52,80,10,32,10,129,149,7,13,14,7,133,152,132,12,32,123,132,5,40,121,140,8,26,8,125,144,53,
+    79,130,30,51,1,10,112,46,46,178,195,37,121,37,71,30,49,49,29,73,194,37,120,37,131,3,36,73,29,98,30,71,131,22,32,0,130,169,8,40,91,255,237,2,41,2,210,0,8,0,18,0,72,0,0,1,21,54,55,54,
+    53,52,39,38,39,53,6,7,6,29,1,6,23,22,19,46,1,39,38,35,38,131,18,39,22,23,30,1,23,22,23,53,130,12,8,166,52,55,54,55,53,51,21,20,30,4,23,21,39,38,47,2,34,39,21,22,23,22,21,20,7,6,7,21,
+    1,102,56,26,31,31,32,132,62,25,8,2,26,30,44,1,1,1,3,7,12,25,79,59,21,30,13,23,16,36,46,82,53,50,53,61,71,82,56,19,21,20,20,11,22,35,25,33,16,8,8,98,43,54,58,63,74,1,54,205,10,20,37,
+    49,39,29,21,91,194,5,62,20,6,10,25,34,24,254,84,10,37,11,1,1,5,13,23,85,12,15,5,9,6,13,2,217,11,45,42,144,45,50,6,57,57,3,10,3,5,4,6,3,81,10,14,7,8,2,1,202,16,43,46,71,72,50,49,4,58,
+    0,5,0,19,0,17,2,84,2,172,130,9,38,22,0,38,0,55,0,71,130,219,37,0,7,35,18,19,3,130,166,33,51,50,133,228,38,35,34,7,6,20,23,6,65,239,7,33,51,50,131,193,33,1,22,131,30,32,52,130,239,40,
+    38,34,14,2,21,20,55,20,7,140,33,8,124,2,40,254,177,58,96,234,160,60,13,34,7,11,24,20,20,20,19,21,52,17,5,165,43,54,52,46,38,39,36,61,55,41,40,254,24,13,34,27,20,20,5,10,27,12,27,23,
+    20,10,204,68,33,25,67,41,39,67,30,26,68,42,40,2,172,253,200,98,1,140,1,14,253,205,28,10,1,18,20,19,32,18,19,38,11,27,77,38,37,38,53,57,36,36,37,40,51,54,1,162,18,18,20,38,11,23,11,
+    4,8,18,22,14,27,28,75,37,17,37,35,56,73,40,16,38,36,0,130,0,63,3,0,29,255,243,2,98,2,209,0,11,0,37,0,85,0,0,19,62,1,53,52,35,34,6,7,6,23,22,3,20,23,132,223,45,63,1,54,55,62,2,55,38,
+    39,38,47,1,38,39,130,26,43,55,38,53,54,55,54,51,50,30,1,29,1,130,208,41,7,30,3,23,54,61,1,54,38,59,132,13,34,22,23,34,131,227,37,6,43,1,34,39,38,130,22,8,147,237,30,57,71,34,40,3,14,
+    38,19,102,53,29,57,18,15,53,41,12,5,6,7,4,3,2,26,20,34,19,67,17,27,47,26,22,50,86,2,75,42,52,35,78,35,34,24,59,33,53,40,46,26,38,1,2,1,81,20,19,36,36,49,43,47,5,10,40,81,104,8,100,
+    73,70,13,1,221,18,49,44,61,35,14,53,35,17,254,239,71,49,27,13,4,23,6,3,3,4,5,1,1,34,26,41,26,86,21,36,36,33,38,163,66,66,99,37,23,23,60,24,38,41,45,31,41,42,69,53,57,33,46,91,26,6,
+    24,108,52,51,38,45,63,1,52,64,63,64,85,20,127,130,250,52,0,1,1,10,1,186,1,102,2,191,0,3,0,0,1,17,51,17,1,10,92,130,16,34,5,254,251,130,14,41,0,168,255,174,1,141,3,7,0,7,130,12,55,6,
+    16,23,35,38,16,55,1,141,132,132,80,149,149,3,7,217,254,88,216,224,1,157,220,130,26,39,0,205,255,179,1,178,3,12,132,39,8,48,22,16,7,35,54,16,39,1,29,149,149,80,132,132,3,12,220,254,
+    96,221,216,1,175,210,0,0,1,0,46,0,90,2,57,2,100,0,27,0,0,19,39,54,55,22,23,53,51,21,55,131,7,8,64,7,23,22,23,7,46,1,39,21,35,53,7,39,54,219,173,19,25,129,43,87,88,55,33,14,30,176,88,
+    54,33,44,33,109,33,87,174,42,99,1,100,96,28,40,70,24,186,186,48,30,17,20,49,96,48,30,19,68,18,59,18,196,196,92,67,56,132,203,48,0,41,0,100,2,61,2,85,0,11,0,0,37,53,35,53,51,130,94,
+    49,51,21,35,21,1,8,223,223,84,225,225,100,208,80,209,209,80,208,130,135,44,205,255,85,1,125,0,141,0,25,0,0,23,38,130,136,45,54,55,34,38,39,38,53,52,55,54,51,50,23,22,65,207,5,8,44,
+    6,241,6,30,59,17,7,7,20,29,5,4,43,13,15,32,19,22,3,13,91,17,171,8,42,51,37,15,18,29,13,13,15,49,18,4,19,20,31,6,15,17,92,86,16,130,83,40,83,1,52,2,23,1,133,0,5,130,219,46,53,33,21,
+    22,21,83,1,195,1,1,52,81,40,25,16,130,156,38,1,0,237,255,255,1,126,130,115,35,13,0,0,4,139,109,8,34,20,1,85,47,25,11,21,44,13,16,30,20,22,1,9,10,19,33,48,18,5,20,20,63,0,0,1,0,65,255,
+    208,2,41,2,230,131,83,8,37,23,0,55,51,0,7,65,1,38,99,95,254,217,98,48,2,81,197,253,176,198,0,0,3,0,67,255,243,2,38,2,203,0,7,0,18,0,32,130,247,51,50,17,52,39,6,7,22,19,38,35,34,7,6,
+    21,20,23,54,55,5,16,67,111,6,32,16,131,221,8,57,1,56,148,8,104,149,35,185,33,78,93,35,21,8,63,63,1,1,137,45,60,120,60,61,241,121,60,61,72,1,34,48,46,130,182,72,1,232,72,111,77,102,
+    49,46,79,78,54,254,240,68,23,92,91,180,1,109,92,88,130,198,130,147,39,132,0,0,1,254,2,189,0,130,199,8,34,51,53,51,17,6,7,38,53,54,55,51,17,51,21,132,144,32,111,1,107,35,94,142,82,2,
+    0,25,89,82,33,80,26,253,149,82,133,51,44,76,0,0,2,30,2,202,0,54,0,0,1,34,130,48,33,62,1,131,137,36,21,20,14,1,7,130,2,49,6,15,1,14,5,7,33,21,33,53,52,62,4,63,1,62,3,55,69,50,5,8,102,
+    46,1,35,1,27,70,132,1,96,93,23,100,67,65,30,12,8,20,49,10,30,34,18,9,14,20,19,20,28,17,1,100,254,46,27,33,39,42,40,12,22,17,14,9,18,11,47,9,5,37,16,53,15,2,123,73,58,29,51,14,55,52,
+    89,49,62,15,12,30,49,11,33,34,16,7,18,16,18,22,27,17,82,63,17,26,34,38,43,40,13,22,19,12,12,20,13,61,40,19,24,52,33,15,19,130,211,44,75,255,243,2,34,2,203,0,56,0,0,19,54,131,154,69,
+    120,6,69,128,6,37,43,1,38,39,46,1,69,175,5,33,22,51,68,234,6,34,43,1,53,68,245,11,8,161,7,97,120,73,74,64,58,26,16,6,31,97,93,37,22,69,67,127,25,12,14,54,35,14,23,31,65,23,62,45,131,
+    34,10,44,44,67,86,77,107,30,10,36,33,72,51,88,25,26,2,172,31,29,26,56,34,29,46,17,78,24,23,68,36,51,101,55,55,1,1,4,10,3,5,11,95,30,5,15,77,25,32,65,34,36,78,63,20,27,54,28,29,21,7,
+    10,0,2,0,40,0,0,2,64,2,189,0,6,0,17,0,0,55,51,17,14,3,39,1,51,17,51,21,35,21,35,53,33,136,242,61,108,39,24,106,1,26,135,119,119,90,254,185,245,1,114,87,170,61,38,6,1,180,254,56,78,
+    167,167,0,0,0,1,0,72,130,227,32,23,130,63,32,36,135,227,36,21,20,7,14,1,132,218,34,2,39,53,136,214,8,69,39,38,34,7,17,33,21,33,196,47,35,120,69,68,109,50,80,22,36,12,14,69,41,20,10,
+    88,96,129,37,11,9,15,17,53,170,66,1,135,254,214,1,194,14,65,64,109,141,62,25,11,1,1,5,12,7,3,97,46,90,30,29,48,22,36,15,47,35,1,96,79,130,175,38,67,255,246,2,38,2,191,130,173,32,54,
+    130,175,136,95,66,149,6,38,22,39,54,51,50,23,22,70,9,6,67,123,7,39,54,59,1,30,2,23,21,38,130,149,8,91,35,6,7,6,214,34,68,101,25,9,53,30,51,69,34,37,21,8,46,51,117,105,57,60,61,56,117,
+    130,58,49,9,3,89,89,104,9,19,7,25,32,30,17,8,60,44,19,9,9,73,69,51,108,43,92,30,39,99,42,22,43,46,75,59,36,12,249,97,63,62,226,63,60,85,71,113,38,43,192,83,87,1,4,9,4,3,88,32,1,2,71,
+    71,0,130,0,8,62,1,0,70,0,0,2,28,2,189,0,9,0,0,9,1,35,18,55,54,55,33,53,33,2,28,254,244,105,120,101,22,17,254,155,1,214,2,150,253,106,1,39,232,54,41,79,0,0,3,0,66,255,243,2,39,2,203,
+    0,14,0,28,0,58,130,209,33,20,23,132,211,34,52,39,38,131,210,34,55,50,53,134,9,32,21,130,24,34,37,20,7,66,58,6,36,35,34,38,53,52,130,91,33,38,39,68,96,6,130,244,8,95,167,82,26,33,65,
+    40,37,37,37,68,69,35,37,141,125,32,30,63,93,24,8,72,23,1,0,121,78,29,31,16,58,170,113,128,39,24,75,43,23,32,9,14,60,61,208,61,61,198,100,28,10,36,37,128,37,35,35,35,145,115,60,28,30,
+    67,22,28,85,24,7,126,135,26,17,46,46,75,49,38,115,104,97,73,49,47,16,11,26,32,25,38,35,76,50,49,49,51,130,222,39,0,2,0,63,255,249,2,35,130,175,38,13,0,53,0,0,19,20,66,171,11,40,18,
+    38,39,53,22,23,30,1,54,130,152,36,6,7,14,1,34,133,156,130,14,66,251,10,8,97,6,7,38,163,134,68,34,37,79,29,23,78,30,34,59,32,72,36,31,19,36,61,35,100,18,18,19,39,63,81,40,86,30,15,23,
+    11,61,139,130,59,34,12,15,23,42,93,47,63,36,1,219,164,43,43,78,118,36,11,41,42,253,206,1,17,78,15,6,1,2,1,18,50,198,36,15,30,16,15,33,90,44,42,71,67,19,97,89,49,65,73,62,114,65,133,
+    46,22,4,2,133,167,45,239,0,111,1,129,2,66,0,15,0,32,0,0,1,72,26,14,34,3,22,21,130,17,132,159,32,52,130,172,40,54,50,1,129,22,20,23,39,20,130,0,57,23,55,21,5,45,44,22,19,48,13,26,11,
+    6,5,10,29,13,31,1,251,33,18,20,20,16,35,130,5,49,42,13,254,236,17,56,24,20,19,5,9,28,13,31,13,25,12,5,130,108,36,2,0,209,255,197,132,107,38,31,0,47,0,0,23,54,130,81,35,34,38,39,38,
+    132,89,69,248,10,37,7,6,7,46,3,19,142,137,60,209,42,14,18,15,19,29,5,4,5,9,29,13,15,31,20,22,3,3,4,21,29,51,29,6,9,8,8,171,139,147,62,9,36,19,24,42,29,13,13,31,12,26,12,5,20,20,31,
+    6,12,18,29,12,54,34,58,18,7,13,11,12,2,11,138,162,130,146,8,57,0,1,0,41,0,116,2,57,2,75,0,14,0,0,45,1,53,36,55,21,14,2,7,30,2,31,1,2,57,253,240,1,140,132,91,126,156,52,28,74,115,78,
+    130,116,196,78,148,49,86,33,44,55,19,9,26,41,27,45,132,207,38,45,0,205,2,61,1,245,75,31,5,36,55,53,33,21,37,130,3,44,45,2,16,253,240,2,16,205,81,81,216,80,80,133,99,58,44,0,114,2,60,
+    2,73,0,11,0,0,1,37,53,4,23,21,5,53,62,1,55,54,1,213,254,87,130,98,60,253,240,28,73,58,195,1,93,151,85,148,49,78,196,86,9,26,21,68,0,2,0,81,255,255,2,33,2,223,130,151,130,107,75,199,
+    14,61,3,39,62,1,51,50,22,29,1,6,15,1,14,1,29,1,35,53,54,55,62,2,53,54,39,38,43,1,34,6,75,223,12,56,124,72,33,130,78,106,117,2,85,32,29,44,96,2,87,17,48,45,1,25,38,73,9,37,94,75,243,
+    12,56,156,46,52,85,86,73,4,77,60,22,21,44,30,55,54,72,61,13,34,45,25,41,20,29,57,131,191,44,2,255,251,255,225,2,162,2,224,0,16,0,95,130,193,36,35,38,7,6,7,74,116,10,46,19,22,23,14,
+    1,7,6,35,34,39,38,39,46,1,53,65,206,8,33,21,20,130,39,42,6,35,17,38,35,53,6,7,6,46,1,68,101,6,8,203,54,30,1,31,1,22,23,51,22,55,54,61,1,54,39,46,2,34,6,7,14,2,29,1,20,23,22,23,62,1,
+    1,111,10,10,17,53,6,6,22,32,37,38,29,29,62,17,236,3,50,12,49,40,78,96,83,79,104,75,45,18,27,56,132,64,54,196,88,31,8,14,39,14,19,56,18,20,38,30,69,46,33,53,83,43,60,26,43,17,7,14,9,
+    12,34,12,11,5,2,38,18,71,53,42,37,32,84,77,27,82,82,122,81,117,1,229,1,8,27,94,64,32,32,35,33,60,91,29,8,254,167,3,59,10,43,19,37,25,32,109,63,104,50,98,64,142,54,26,98,37,60,18,26,
+    47,15,7,254,242,1,45,34,16,14,6,27,29,62,86,119,66,37,2,22,10,4,14,9,13,2,23,10,6,7,25,36,16,33,7,2,11,31,113,93,47,12,115,100,87,3,1,41,0,0,2,0,18,130,4,45,86,2,189,0,10,0,23,0,0,
+    19,51,46,3,39,130,202,8,61,1,15,1,35,54,19,51,22,18,30,1,23,35,39,202,213,13,39,30,18,7,13,19,37,30,32,54,105,41,188,123,28,83,63,39,15,104,56,1,3,44,132,98,62,23,43,67,125,100,100,
+    183,124,2,65,85,254,254,192,120,46,183,0,130,0,38,3,0,79,255,255,2,58,132,87,45,21,0,44,0,0,55,51,50,55,54,52,38,39,38,70,243,10,42,43,1,3,17,51,50,23,22,23,20,7,71,197,5,68,240,7,
+    8,88,175,149,124,26,10,20,20,40,80,149,127,104,23,8,33,32,82,115,96,207,112,64,60,2,6,13,21,6,12,30,17,84,26,41,66,69,129,78,67,24,67,51,16,32,78,60,21,28,57,21,24,253,144,2,189,46,
+    46,86,39,15,30,26,7,13,10,7,22,38,47,76,94,50,49,0,1,0,70,255,243,2,25,2,203,0,25,0,0,37,6,76,84,10,39,21,38,35,34,7,6,21,16,131,151,8,41,55,2,25,76,90,147,76,78,139,71,91,88,78,79,
+    87,98,49,49,197,58,68,20,19,25,38,95,96,171,232,90,44,39,97,58,71,74,142,254,225,34,10,15,130,218,39,0,2,0,69,0,0,2,44,130,219,34,12,0,23,134,217,34,53,52,39,132,219,133,208,8,32,21,
+    16,7,6,35,170,86,153,32,13,50,25,23,41,62,83,101,189,172,63,63,172,55,71,78,142,54,78,157,56,30,11,18,131,173,39,85,87,179,254,250,66,22,0,130,163,32,94,130,79,32,35,130,79,38,11,0,
+    0,51,17,33,21,135,1,49,94,1,196,254,161,1,53,254,203,1,96,2,189,79,208,80,254,80,130,43,32,117,130,43,36,41,2,190,0,12,131,43,34,50,54,51,131,44,53,51,21,35,17,117,28,75,60,1,17,254,
+    174,246,246,2,189,1,76,222,76,254,184,131,171,34,1,0,51,130,255,32,40,130,255,32,31,135,255,74,164,8,32,21,130,177,65,3,8,8,53,53,35,53,51,2,40,86,116,71,56,61,36,75,80,81,139,96,79,
+    25,38,43,58,109,47,49,194,60,45,134,230,57,70,24,29,45,94,170,175,94,97,50,98,25,19,26,71,71,146,254,226,30,189,78,0,130,143,32,69,130,143,32,36,135,187,79,93,5,55,35,17,33,17,69,101,
+    1,20,102,102,254,236,2,189,254,225,1,31,253,67,1,78,254,178,130,144,34,1,0,100,130,47,32,3,134,47,37,53,51,17,35,53,33,130,188,47,51,21,100,157,157,1,159,157,157,80,2,30,79,79,253,
+    226,68,115,6,36,61,255,247,1,222,130,43,32,17,131,187,33,7,6,66,58,7,131,52,61,17,20,1,169,38,51,29,63,183,185,80,23,28,191,1,36,41,38,7,5,77,30,36,95,1,137,79,254,40,132,134,151,32,
+    100,130,59,53,24,0,0,51,17,51,17,62,3,55,51,6,7,30,2,23,35,46,3,39,6,7,130,159,51,38,116,86,55,20,119,194,97,126,102,52,19,122,29,90,66,42,16,58,19,130,173,52,200,38,115,85,54,20,191,
+    95,173,143,72,27,43,129,96,60,23,57,20,254,238,130,79,32,108,130,183,32,57,130,79,32,5,133,79,41,33,21,108,101,1,104,2,189,253,147,134,171,32,38,130,31,32,68,130,31,50,20,0,0,1,3,35,
+    39,46,2,39,17,35,17,51,22,23,62,2,55,130,229,8,40,1,236,145,77,21,13,39,54,17,88,135,90,45,18,86,24,8,136,88,2,102,254,142,56,32,101,137,44,253,154,2,189,229,115,45,218,59,22,253,67,
+    0,72,87,8,32,35,133,247,37,51,17,51,30,3,23,130,192,8,38,35,46,1,39,38,39,17,70,128,31,92,69,43,17,97,128,31,93,34,72,22,2,189,69,210,156,98,38,2,59,253,67,70,210,78,164,49,253,197,
+    130,63,48,2,0,58,255,247,2,46,2,198,0,13,0,29,0,0,18,16,72,101,5,46,16,39,38,35,34,7,19,34,17,16,55,54,50,22,23,130,1,8,58,21,16,7,6,164,34,33,77,78,33,34,34,35,76,75,35,110,250,141,
+    47,93,54,24,48,32,61,141,50,1,242,254,216,68,65,65,64,1,48,64,67,67,253,193,1,103,1,15,66,23,11,11,22,46,94,176,254,239,65,21,130,102,39,0,2,0,86,0,0,2,46,130,167,41,12,0,26,0,0,19,
+    51,50,55,54,79,194,5,67,216,8,8,51,22,20,7,6,43,1,17,187,117,56,33,11,10,39,39,40,78,109,101,218,125,65,35,10,19,16,49,189,117,1,104,21,7,7,37,61,60,37,34,253,144,2,189,53,30,28,49,
+    101,39,119,254,230,130,87,36,58,255,159,2,104,130,191,42,23,0,32,0,0,37,30,1,23,21,35,130,251,35,6,34,39,38,137,188,54,16,1,6,16,22,50,54,16,38,34,1,248,26,56,30,64,62,23,24,53,145,
+    47,140,135,193,52,254,152,34,68,153,68,69,151,92,29,66,35,59,70,27,27,35,22,66,1,14,136,195,43,254,171,1,125,68,254,217,134,130,1,47,131,130,111,32,72,130,199,32,50,130,199,34,9,0,
+    40,134,199,34,52,39,38,135,196,44,21,20,6,7,6,7,30,4,31,1,35,46,2,130,134,32,35,130,25,8,43,17,173,111,82,33,36,38,36,79,109,101,219,123,54,66,23,24,34,56,16,19,6,13,35,28,48,107,54,
+    45,16,6,16,13,59,12,24,37,1,119,31,30,124,32,32,131,220,55,52,60,88,45,60,26,32,28,29,34,13,24,66,54,90,105,91,31,11,31,26,1,254,216,68,159,6,36,37,2,203,0,58,74,225,11,130,102,73,
+    237,8,43,51,50,23,30,2,23,21,38,47,1,38,34,130,136,36,6,21,20,23,22,130,1,33,30,1,76,96,5,8,108,34,39,46,1,39,79,110,102,118,33,11,29,27,75,14,7,62,40,58,24,47,103,63,79,37,54,16,45,
+    26,13,39,21,32,43,87,28,58,21,11,6,8,14,32,69,13,13,39,189,146,48,90,27,57,75,27,130,67,72,23,28,52,27,27,17,3,1,9,16,25,24,43,77,118,57,33,9,4,11,9,4,96,23,7,12,13,7,17,45,21,20,32,
+    12,19,13,28,13,3,3,8,38,165,153,40,13,3,5,24,10,0,130,175,43,24,0,0,2,81,2,189,0,7,0,0,33,67,189,6,44,1,2,234,2,57,234,2,110,79,79,253,146,0,131,35,36,60,255,243,2,43,130,35,37,34,
+    0,0,5,35,34,132,204,130,164,37,38,53,17,51,17,20,71,116,6,33,55,54,132,13,131,208,60,1,82,29,49,59,10,9,42,12,30,18,4,16,103,21,11,38,75,54,24,56,10,2,101,11,17,34,61,13,130,119,60,
+    19,11,25,41,12,48,105,1,176,253,250,43,34,11,32,11,27,52,20,205,1,67,254,80,105,35,58,30,48,132,111,32,29,130,147,32,76,130,111,32,15,130,124,36,2,3,35,38,2,130,114,8,44,51,30,3,23,
+    19,2,76,111,107,123,27,80,30,48,33,98,12,31,49,67,22,181,2,189,254,162,254,161,85,1,2,96,155,107,40,106,168,226,75,2,103,0,1,0,2,130,63,32,102,130,63,32,30,130,63,40,3,35,47,1,38,47,
+    1,14,2,130,154,34,35,2,3,132,70,8,72,51,18,23,22,23,18,55,2,102,109,99,40,25,10,8,15,4,10,16,12,41,15,98,44,66,86,10,28,21,14,5,86,112,39,14,26,8,58,19,2,189,253,67,244,157,59,51,85,
+    22,59,99,75,254,87,1,9,1,180,68,206,153,96,37,2,48,254,255,88,173,43,1,165,140,130,107,32,9,130,107,32,95,130,107,32,31,132,107,36,19,54,55,46,1,132,173,8,83,1,23,19,51,6,7,14,1,7,
+    22,23,30,1,23,35,38,39,46,1,1,59,197,109,174,46,30,17,40,31,64,83,108,39,100,44,167,109,28,41,45,95,14,47,113,22,42,15,108,12,16,32,101,1,46,254,210,1,2,68,46,23,56,43,88,119,57,143,
+    64,1,8,40,61,68,138,22,75,173,36,64,24,20,26,52,167,130,98,71,223,8,32,19,130,12,33,19,51,130,95,36,6,7,17,35,17,131,94,8,45,39,51,22,23,22,1,52,181,109,29,88,33,51,39,101,29,44,78,
+    72,16,108,44,47,64,1,136,1,53,46,143,52,82,63,254,197,1,59,47,71,126,117,25,76,79,107,0,130,62,33,0,55,130,187,32,49,130,187,8,47,16,0,0,51,53,54,18,54,55,33,53,33,21,14,3,7,33,21,
+    55,109,180,65,25,254,144,1,229,26,67,106,144,47,1,144,73,156,1,6,95,36,79,71,36,95,150,202,67,80,131,59,44,148,255,166,1,205,3,24,0,7,0,0,23,17,69,243,5,43,148,1,57,220,220,90,3,114,
+    74,253,35,75,132,95,8,52,62,255,210,2,40,2,233,0,13,0,0,19,22,23,18,31,1,35,39,46,1,47,1,38,39,158,31,43,212,41,67,96,60,34,62,25,50,121,42,2,233,62,85,254,84,82,134,120,68,124,51,
+    102,244,80,31,6,36,154,255,167,1,210,134,95,70,87,5,44,17,154,220,220,1,56,89,75,2,220,74,252,143,132,95,36,61,1,177,2,43,130,191,32,14,130,144,39,7,35,19,51,30,1,23,22,65,106,6,59,
+    52,136,111,203,88,25,74,28,58,18,111,8,12,24,75,2,112,191,1,12,32,99,36,77,24,13,16,32,130,252,45,1,255,247,255,167,2,114,255,243,0,3,0,0,7,130,245,49,9,2,123,89,76,76,0,1,0,167,2,
+    51,1,169,3,2,0,10,130,83,33,35,38,65,202,6,8,33,22,1,169,112,33,39,64,10,111,9,26,20,48,2,51,46,56,92,13,13,36,29,67,0,0,2,0,68,255,243,2,19,2,27,130,227,32,57,78,1,9,38,61,1,35,34,
+    7,6,5,72,159,8,49,55,54,59,1,53,52,39,38,43,1,34,7,53,51,50,62,1,50,130,168,32,22,82,86,5,8,94,35,34,39,54,52,38,160,70,21,27,78,44,38,116,96,42,24,1,31,48,144,84,50,53,35,38,54,59,
+    77,107,36,37,61,88,34,40,40,19,32,40,50,24,59,27,76,14,8,1,31,10,42,2,2,158,73,20,7,57,50,81,18,39,22,133,83,44,45,81,67,39,40,13,17,13,68,25,27,2,73,1,1,3,9,15,40,66,36,76,250,24,
+    21,1,30,14,15,131,163,32,96,130,163,52,44,2,246,0,25,0,47,0,0,19,20,23,22,50,55,54,55,62,2,55,54,130,147,36,46,1,34,6,7,132,1,79,126,5,68,133,5,32,7,131,186,8,86,6,7,35,17,51,193,70,
+    28,69,19,32,18,28,16,4,2,1,43,26,51,46,37,14,30,10,20,4,6,5,48,107,86,52,57,15,3,47,23,43,40,61,106,48,5,4,83,92,1,7,134,50,20,5,8,21,31,54,35,17,17,16,114,47,29,13,10,10,21,22,41,
+    25,46,168,80,52,54,121,24,24,110,78,38,27,24,80,44,23,130,136,35,0,1,0,82,130,147,36,3,2,27,0,30,73,199,14,36,22,23,21,38,39,69,25,9,8,57,51,50,55,2,3,72,91,128,73,69,123,62,87,54,
+    24,50,33,41,24,45,76,27,47,35,41,76,40,67,91,62,27,40,76,72,128,167,74,35,7,16,17,91,32,9,17,7,12,40,53,91,123,53,28,58,0,2,0,61,130,95,43,9,2,245,0,28,0,51,0,0,55,30,1,130,72,130,
+    243,36,1,55,54,52,39,130,95,35,39,38,35,34,130,245,36,14,2,21,20,5,130,234,132,17,32,52,78,236,7,8,37,17,51,17,35,38,200,24,48,22,42,20,37,11,16,6,2,1,1,2,2,3,12,35,80,45,26,29,9,17,
+    6,3,1,14,50,101,62,63,17,130,252,8,60,30,29,57,102,75,48,16,11,92,83,2,101,29,13,15,26,29,35,49,17,17,32,17,17,17,30,26,80,20,22,22,37,52,34,16,114,82,80,37,16,54,122,25,88,100,37,
+    73,45,15,20,1,42,253,11,19,0,0,0,2,0,62,130,159,32,44,130,255,38,10,0,36,0,0,19,33,132,149,131,147,32,1,87,7,12,35,29,1,33,21,80,85,6,8,67,55,162,1,47,14,21,60,20,26,69,46,40,1,110,
+    96,100,129,74,74,116,60,83,170,50,15,254,114,46,46,90,72,76,23,24,1,54,37,42,54,18,5,46,38,254,157,40,72,74,126,164,79,37,148,46,46,56,3,83,48,50,33,10,11,0,0,1,0,66,130,120,44,40,
+    2,224,0,22,0,0,51,17,35,53,51,53,131,242,34,59,1,21,131,119,8,35,29,1,51,21,35,17,231,165,165,22,21,43,99,136,140,50,19,19,169,169,1,143,78,71,43,84,21,40,73,19,17,62,88,78,254,113,
+    130,62,37,0,76,255,3,2,23,130,183,37,18,0,63,0,0,19,134,155,32,53,131,190,33,46,1,80,245,5,49,23,52,38,53,51,6,29,1,6,20,14,3,35,7,53,51,54,55,131,1,34,53,6,7,132,217,34,39,46,3,77,
+    142,5,8,106,168,83,26,33,98,27,8,9,15,13,28,47,27,60,38,38,125,105,55,1,83,1,1,1,17,62,60,45,222,102,53,36,66,34,33,1,32,29,48,40,70,42,20,17,29,32,10,6,48,24,43,42,1,13,147,41,12,
+    113,37,33,77,27,50,16,31,13,50,50,173,67,13,29,10,34,45,95,93,193,113,99,66,37,2,78,1,1,2,46,46,60,77,38,9,15,24,13,15,28,72,48,48,24,110,74,37,26,24,131,251,32,97,130,188,35,13,2,
+    245,0,130,12,42,19,54,59,1,50,23,22,21,17,35,17,81,160,6,33,7,6,131,12,8,38,51,189,50,106,10,68,38,64,92,57,20,26,73,38,19,7,4,92,92,1,207,80,32,57,127,254,185,1,71,105,23,9,52,26,
+    47,20,21,254,214,130,68,35,0,2,0,166,130,84,51,129,2,219,0,21,0,33,0,0,33,35,53,54,61,1,35,53,51,21,20,130,248,34,22,29,1,130,2,41,20,6,17,20,43,1,34,61,1,52,130,109,38,21,1,128,92,
+    1,127,218,130,222,63,1,15,71,16,16,71,15,114,28,120,187,77,64,16,35,37,126,11,23,40,16,18,66,16,37,2,103,14,14,81,14,14,130,166,37,0,118,255,4,1,187,130,91,43,15,0,27,0,0,23,53,51,
+    50,54,53,17,130,92,41,17,20,6,7,6,35,19,50,29,1,134,88,63,51,118,143,46,44,144,236,22,23,45,80,149,14,14,73,14,14,252,80,80,58,1,227,77,253,208,46,96,25,51,3,215,131,79,32,81,130,81,
+    130,170,33,0,113,130,88,34,84,2,218,130,175,8,61,0,1,7,21,35,17,51,17,62,1,55,54,55,51,6,7,30,3,23,35,38,1,20,68,95,95,29,89,33,40,51,111,158,62,31,94,69,44,17,113,186,1,15,60,211,
+    2,218,254,90,27,80,30,37,44,141,57,40,121,89,56,22,245,131,75,32,141,130,4,36,119,2,190,0,8,130,7,55,7,17,35,17,52,39,35,53,1,119,2,92,1,139,2,190,192,254,2,2,9,40,63,78,130,26,41,
+    0,41,0,0,2,69,2,27,0,38,130,12,33,54,51,65,114,13,32,21,130,55,76,176,7,130,10,8,72,51,20,6,21,54,55,50,1,71,46,85,66,29,28,84,15,12,39,38,25,16,84,3,9,17,30,55,14,15,84,77,1,33,89,
+    60,1,217,66,47,50,137,254,207,1,45,114,26,26,29,26,111,254,211,1,96,69,16,30,28,26,112,254,211,2,14,8,29,9,57,2,0,1,0,65,231,5,40,27,0,18,0,0,1,52,35,34,65,217,6,33,22,23,130,127,130,
+    114,61,1,177,107,100,28,9,92,83,7,2,51,114,171,92,1,71,137,95,31,40,254,214,2,14,49,30,92,212,254,185,130,174,37,0,69,255,243,2,36,130,179,34,15,0,28,66,223,13,131,75,35,19,34,39,38,
+    88,17,6,8,51,16,6,166,81,27,34,67,39,37,82,26,35,69,36,37,143,179,46,15,15,46,178,117,61,62,122,1,7,146,44,14,54,53,97,149,41,13,52,51,254,136,157,51,134,51,159,71,70,254,243,142,0,
+    131,95,36,95,255,3,2,42,130,95,32,10,131,95,34,37,50,16,132,162,36,20,23,22,23,34,76,96,6,65,40,5,46,20,7,6,1,82,132,132,101,28,9,79,25,34,105,46,131,177,8,32,48,103,99,60,57,127,39,
+    59,1,151,117,37,49,147,43,14,72,80,254,192,3,11,41,26,80,74,73,129,196,62,18,0,2,130,187,40,4,2,15,2,26,0,14,0,32,85,95,15,39,20,1,54,55,51,17,35,17,68,93,10,8,33,190,34,65,66,34,35,
+    78,25,32,65,34,35,1,24,7,2,83,92,47,105,136,53,25,127,40,50,101,111,54,54,51,99,151,39,130,191,47,199,1,40,38,28,252,248,1,62,81,130,61,74,206,63,19,130,195,34,1,0,129,130,200,32,25,
+    130,195,44,25,0,0,1,38,43,1,34,6,7,6,29,1,130,195,8,53,21,35,17,51,22,20,6,21,54,59,1,22,23,2,25,56,84,39,10,63,21,45,1,1,92,90,1,2,56,127,5,82,49,1,155,48,24,21,45,43,42,30,48,146,
+    60,2,14,6,18,24,23,84,2,38,130,82,35,0,1,0,106,70,15,6,39,39,0,0,1,34,21,20,23,75,15,9,86,136,10,33,46,1,84,150,5,8,72,55,54,50,23,21,38,1,67,121,25,28,109,12,139,59,59,183,108,108,
+    80,57,36,35,29,27,67,10,9,29,66,40,36,55,54,185,83,80,1,211,78,37,17,17,19,2,26,116,78,45,45,32,90,51,24,21,40,36,19,19,13,2,2,6,12,36,34,60,76,41,40,31,84,43,133,123,41,128,255,254,
+    1,230,2,174,0,17,0,74,223,5,36,53,17,51,21,51,130,204,130,210,59,59,1,1,230,169,103,43,43,92,221,221,24,22,60,160,2,39,41,94,2,2,160,79,254,237,59,18,18,130,60,51,1,0,84,255,242,2,
+    20,2,13,0,24,0,0,37,6,43,1,38,35,34,130,61,8,61,17,20,51,54,55,54,53,54,53,51,20,22,29,1,35,1,190,37,123,9,4,5,184,91,124,73,30,34,3,92,1,86,57,71,1,213,1,69,254,187,139,8,36,40,57,
+    240,83,63,194,72,196,0,0,1,0,50,0,0,2,54,2,14,131,135,40,1,3,35,46,3,39,51,23,22,130,1,8,40,62,1,63,1,2,54,198,119,25,72,55,34,13,95,50,30,22,46,15,26,57,30,50,2,14,253,242,64,194,
+    143,91,34,135,81,60,125,40,68,157,81,135,131,67,130,148,33,2,104,130,67,32,27,130,12,43,3,35,2,38,39,51,30,2,23,19,51,23,130,5,131,71,32,51,130,87,8,58,1,39,1,52,89,88,89,33,9,91,22,
+    49,16,6,72,102,25,16,22,14,5,11,31,12,31,91,131,88,11,32,12,1,33,254,223,1,100,136,34,93,220,70,27,1,4,80,48,71,44,17,50,151,56,153,253,242,35,107,39,130,93,130,167,32,38,130,167,32,
+    67,130,99,39,35,0,0,51,54,55,46,2,130,99,46,3,23,62,1,55,51,14,3,7,30,1,23,35,39,38,130,1,33,7,6,130,1,57,38,140,80,61,92,34,14,103,18,55,40,26,9,109,29,10,103,24,74,55,34,14,25,169,
+    27,107,130,198,33,45,17,132,4,58,171,103,79,113,44,16,23,70,52,33,12,139,39,12,31,92,69,43,17,30,211,33,65,38,29,58,21,132,4,133,115,8,40,70,255,2,2,25,2,15,0,50,0,0,23,51,54,59,1,
+    50,55,54,53,54,52,39,35,34,38,61,1,52,55,53,50,54,51,17,20,23,22,59,1,17,130,241,34,54,51,21,69,131,5,130,5,8,80,20,6,35,33,38,54,119,59,45,37,102,39,17,25,1,1,189,84,100,1,17,57,18,
+    24,25,68,163,1,1,35,11,47,1,1,1,88,66,254,248,1,1,174,1,29,45,64,10,18,8,100,63,252,32,28,50,1,254,202,77,31,27,1,82,54,52,1,83,41,37,76,40,66,115,51,32,32,81,127,21,39,0,130,255,32,
+    101,130,255,32,8,130,139,32,17,130,255,33,53,54,88,38,5,32,21,131,238,8,34,6,7,33,21,101,39,60,114,109,254,203,1,150,39,59,115,60,27,21,1,65,80,46,70,134,129,68,78,46,70,136,69,33,
+    24,71,131,63,40,92,255,151,2,3,3,38,0,44,66,111,6,130,193,83,72,8,130,11,32,55,130,222,71,147,6,32,20,84,214,5,33,29,1,132,219,8,76,2,3,33,122,44,43,26,27,56,72,59,71,25,26,43,43,123,
+    33,36,68,22,21,23,26,48,46,28,23,21,24,46,56,105,34,35,109,113,70,28,23,88,21,28,72,111,109,35,35,84,14,19,71,110,74,33,40,11,10,41,33,76,115,63,19,15,0,1,1,6,255,181,1,92,3,9,0,3,
+    130,123,43,17,51,17,1,6,86,75,3,84,252,172,0,131,151,32,102,130,151,32,16,130,151,40,50,0,0,23,53,51,50,55,54,132,140,34,55,38,39,130,1,137,163,33,23,22,132,142,35,23,22,51,22,72,59,
+    8,130,167,8,99,35,102,34,72,20,22,22,31,43,28,16,37,9,6,22,20,72,34,31,124,43,42,10,6,7,33,65,16,21,28,32,96,35,23,42,42,125,105,83,16,20,70,108,74,34,42,9,6,15,31,40,26,59,97,63,20,
+    14,84,35,34,110,113,36,24,11,10,37,1,88,39,33,61,100,109,36,34,0,1,0,40,0,241,2,61,1,215,0,33,0,0,19,39,54,55,54,51,50,23,30,1,130,115,130,149,33,55,23,87,136,6,131,151,8,89,35,34,
+    7,14,1,118,78,12,21,41,76,37,19,28,41,11,57,36,56,13,5,3,77,33,36,83,39,22,33,28,51,16,19,19,38,17,7,12,1,20,18,71,36,70,11,15,41,14,76,73,22,27,17,51,59,68,12,19,37,65,10,13,33,27,
+    44,0,2,0,232,255,227,1,138,2,193,0,6,0,20,0,0,55,54,55,51,19,21,35,2,52,131,115,33,22,21,133,106,8,34,246,9,29,60,34,132,14,23,21,37,35,46,49,15,17,37,21,181,79,187,254,246,210,2,102,
+    76,21,23,46,27,66,18,5,21,0,130,71,48,105,255,109,2,18,2,161,0,8,0,43,0,0,37,17,6,7,79,220,5,34,53,38,39,89,241,5,36,54,55,53,51,21,130,197,32,21,130,16,32,39,71,127,5,32,21,130,36,
+    37,35,21,1,93,66,40,130,0,8,70,66,117,60,67,13,22,24,70,115,51,62,49,19,46,23,34,27,8,16,8,48,50,11,9,55,55,59,1,151,6,56,54,87,88,54,56,212,135,9,75,75,115,58,37,60,28,82,12,134,134,
+    8,17,8,81,26,5,8,3,254,102,1,3,1,10,28,81,4,4,23,135,0,82,115,8,43,44,2,203,0,27,0,0,19,52,51,50,23,131,115,73,231,8,8,47,21,33,21,33,53,51,53,35,53,51,187,227,62,70,9,8,50,60,103,
+    20,8,185,185,1,12,254,26,117,99,99,1,221,238,28,86,5,5,31,96,33,61,86,68,218,80,80,218,68,130,219,42,102,0,92,2,38,2,0,0,13,0,47,70,91,11,8,32,34,7,6,20,23,7,38,39,54,55,46,1,53,52,
+    55,38,39,55,23,54,50,23,55,23,22,23,7,22,20,7,22,23,6,130,27,8,86,6,34,250,32,45,46,30,31,31,30,92,30,32,11,82,10,36,80,3,22,7,30,72,12,48,82,50,90,50,83,22,14,9,83,30,31,23,61,38,
+    9,80,3,50,90,229,28,28,31,42,43,29,28,28,28,86,92,76,10,32,75,3,36,43,11,44,43,69,10,44,79,29,28,78,22,13,8,79,49,88,39,21,57,33,11,75,3,29,133,231,86,239,7,43,35,0,0,1,6,7,21,51,21,
+    35,21,35,131,216,33,53,39,130,221,79,22,8,8,80,23,19,51,7,14,1,7,51,21,1,145,5,38,201,201,101,200,200,45,155,122,19,30,68,33,11,108,44,47,64,27,181,109,50,51,53,11,126,1,130,9,62,17,
+    51,247,247,51,17,71,52,32,48,111,55,17,76,79,107,47,1,53,80,80,86,17,52,0,0,2,1,10,255,188,1,96,3,2,0,3,0,7,67,61,5,8,45,3,17,51,17,1,10,86,86,86,68,1,101,254,155,1,226,1,100,254,156,
+    0,2,0,99,255,164,2,6,2,203,0,17,0,85,0,0,19,20,23,22,23,54,53,52,39,38,130,1,33,6,7,130,1,32,5,92,10,8,37,43,1,39,46,3,39,70,224,11,35,2,53,52,55,66,44,6,35,51,31,1,22,130,58,86,216,
+    5,66,74,6,33,30,1,130,17,8,129,22,181,42,40,112,61,8,12,17,39,117,28,18,4,3,9,1,81,92,50,5,4,51,50,86,20,20,27,18,20,43,11,88,60,73,26,7,61,38,46,87,46,16,92,59,50,35,61,18,18,39,20,
+    9,13,20,53,82,60,42,13,33,7,7,18,26,59,5,5,20,92,36,33,1,98,35,37,36,53,38,48,20,13,20,15,35,58,18,25,4,5,19,77,84,48,44,32,14,25,58,39,40,2,3,4,3,12,3,77,36,43,13,15,44,36,25,25,47,
+    50,41,25,87,46,39,67,61,38,27,7,3,2,130,0,8,40,3,17,77,37,7,20,15,16,11,22,18,26,33,3,2,10,46,41,37,0,0,0,2,0,160,2,123,1,201,2,217,0,11,0,23,0,0,1,52,59,1,74,174,6,33,53,39,138,11,
+    36,1,99,16,70,16,130,2,43,195,14,72,15,15,72,14,2,204,13,13,68,135,2,33,0,3,130,71,51,58,2,104,2,126,0,27,0,51,0,75,0,0,37,50,55,21,6,34,39,91,150,5,46,51,50,23,21,46,2,43,1,34,7,6,
+    21,20,22,7,82,126,9,75,202,9,34,20,23,22,79,122,7,68,56,9,89,249,5,8,126,1,85,45,46,52,106,36,73,28,12,13,42,139,57,56,35,43,14,6,13,64,31,33,70,150,55,90,24,26,74,68,64,33,18,76,70,
+    111,56,32,137,27,5,32,9,1,105,53,92,160,96,52,35,17,91,165,99,72,45,34,8,50,35,35,42,26,219,25,49,22,11,24,68,31,82,32,103,20,51,17,6,2,34,33,64,60,68,26,63,19,5,42,37,72,42,37,116,
+    68,70,14,56,123,23,24,54,64,15,124,35,130,73,87,61,76,24,129,48,31,41,12,70,87,83,52,60,28,20,0,130,219,38,135,0,220,1,224,2,203,130,9,41,17,0,46,0,0,55,53,33,21,3,130,203,130,179,
+    33,50,55,130,173,34,61,1,21,73,162,8,80,51,5,8,122,34,7,53,54,63,1,50,23,22,29,1,35,38,146,1,78,138,104,22,8,22,22,62,22,43,18,9,53,80,96,33,9,103,33,56,79,49,27,93,71,40,60,35,132,
+    33,11,64,4,220,59,59,1,43,37,13,49,18,18,8,18,46,22,19,22,130,61,70,22,28,89,28,8,1,55,20,11,31,59,16,9,2,92,31,44,211,18,0,0,0,2,0,40,0,67,1,245,1,242,0,12,0,29,0,0,1,23,21,39,53,
+    62,3,55,21,14,1,7,22,23,21,38,39,46,1,130,15,32,1,130,148,8,49,21,6,1,94,151,235,29,86,64,40,16,29,93,255,78,72,15,20,53,118,28,28,87,32,61,26,78,1,26,126,89,196,38,24,72,54,34,13,
+    90,24,79,23,67,59,89,12,17,45,98,24,130,17,53,27,52,22,90,67,0,1,0,44,0,174,2,60,1,150,0,5,0,0,37,53,33,130,237,41,1,232,254,68,2,16,174,151,81,232,130,131,42,1,0,178,0,225,1,182,1,
+    46,0,3,65,11,5,39,178,1,4,225,77,77,0,4,66,3,8,39,10,0,37,0,61,0,85,0,86,143,5,32,53,85,200,8,41,21,20,7,6,7,30,1,23,30,5,81,241,5,35,43,1,21,39,66,12,46,8,32,246,51,45,14,23,19,18,
+    42,54,65,119,145,48,16,20,5,11,8,3,8,11,8,18,32,11,72,65,10,18,26,16,23,133,66,20,39,8,32,1,113,9,15,30,33,9,12,254,225,1,71,93,50,24,7,3,1,10,7,4,11,12,11,27,50,17,102,12,19,7,140,
+    3,66,31,40,8,40,1,0,159,2,135,1,202,2,205,0,3,0,0,1,21,33,53,1,202,254,213,2,205,70,70,0,0,0,2,0,150,1,160,1,211,2,203,0,13,0,35,130,29,80,201,5,46,35,34,7,6,20,22,50,55,22,23,30,1,
+    20,14,1,103,70,13,8,61,1,132,15,6,13,38,14,22,45,24,28,54,92,11,30,31,13,23,23,34,18,32,54,84,46,26,45,46,66,8,7,35,2,4,17,50,16,30,17,7,24,26,76,52,228,13,29,13,55,60,54,30,12,21,
+    63,39,38,72,43,44,1,5,132,115,32,44,130,120,34,60,2,38,130,143,38,15,0,0,51,53,33,21,101,69,11,47,44,2,16,254,206,222,222,84,222,222,80,80,160,155,80,155,130,2,130,152,47,0,161,2,14,
+    1,190,3,159,0,27,0,0,19,54,51,50,130,153,38,21,20,7,14,2,7,51,130,208,33,54,55,130,1,8,52,52,39,38,34,7,164,66,46,100,43,18,6,15,40,67,59,20,204,254,227,21,36,114,15,21,7,23,106,68,
+    3,132,27,48,20,32,10,35,19,51,60,54,18,54,53,20,33,100,27,29,38,12,38,34,130,142,50,0,1,0,163,2,9,1,206,3,161,0,55,0,0,1,20,7,22,23,88,146,5,36,34,47,1,38,39,131,1,32,53,94,4,10,92,
+    154,10,38,35,34,14,3,7,53,54,130,139,8,92,22,1,196,86,47,24,25,12,36,133,17,7,7,14,8,7,17,10,20,11,39,24,23,26,95,14,2,28,23,59,32,37,71,18,6,52,17,17,23,39,15,14,14,8,77,38,112,37,
+    11,3,59,65,22,8,26,25,67,22,71,1,2,1,1,4,2,4,5,56,15,3,7,56,7,13,29,18,18,51,33,10,13,42,12,4,8,2,5,6,2,57,17,60,19,130,159,40,238,2,81,1,221,3,2,0,9,130,159,34,6,7,35,132,238,53,55,
+    1,221,143,20,76,17,25,26,20,38,14,3,2,156,21,21,33,33,24,48,18,133,207,44,83,255,55,2,65,2,14,0,30,0,0,37,6,78,3,5,39,17,20,23,22,51,50,53,17,74,209,6,33,50,55,68,18,5,8,47,1,175,42,
+    181,42,83,91,18,33,66,127,93,17,6,5,8,7,23,40,23,39,14,24,60,73,72,254,252,2,215,254,186,54,30,55,158,1,51,254,106,42,8,3,10,70,20,14,24,133,95,36,53,255,164,2,3,85,35,5,43,5,17,38,
+    39,38,53,52,54,59,1,17,35,130,1,56,1,23,136,56,34,132,106,224,71,95,92,1,141,10,78,43,67,90,108,252,231,2,224,253,32,130,56,48,1,0,227,1,14,1,133,1,174,0,15,0,0,1,22,21,20,107,176,
+    9,8,35,51,50,1,110,23,35,29,17,34,23,24,50,14,17,32,1,152,23,43,26,34,12,23,22,35,54,20,6,0,1,0,198,255,71,1,148,130,65,41,17,0,0,5,50,53,52,38,39,51,130,61,8,33,7,6,43,1,34,39,53,
+    22,1,17,62,33,11,59,54,46,33,25,37,28,37,36,128,43,21,49,15,54,49,53,18,11,11,61,131,102,8,57,0,172,2,14,1,202,3,151,0,13,0,0,19,54,55,51,17,51,21,33,53,51,17,14,1,7,172,42,73,68,103,
+    254,235,103,21,70,21,3,132,6,13,254,172,53,53,1,30,4,11,4,0,3,0,122,0,220,1,239,69,79,6,32,37,68,67,5,34,39,22,51,101,144,6,106,122,9,32,39,103,204,10,8,71,21,20,138,1,82,213,20,25,
+    53,27,29,44,21,70,20,62,244,49,87,46,25,43,16,45,8,3,76,43,67,87,49,51,220,59,59,172,9,37,33,68,79,38,21,9,27,203,39,53,11,19,17,46,57,20,34,98,54,31,53,53,88,89,0,2,0,116,0,67,2,65,
+    1,242,91,143,5,34,1,23,21,130,161,41,6,7,53,62,1,55,38,39,7,38,130,230,33,23,22,130,19,8,61,3,7,53,54,1,86,235,29,86,32,59,29,28,94,29,54,97,76,72,78,59,60,78,37,15,40,64,87,28,72,
+    1,242,197,38,24,72,27,50,23,89,23,79,24,42,84,126,59,67,90,50,50,65,32,38,13,33,54,72,24,89,59,0,130,0,59,4,0,13,255,129,2,45,3,11,0,5,0,20,0,24,0,36,0,0,37,51,53,6,7,6,23,53,35,131,
+    108,44,54,55,51,21,51,21,35,21,19,5,39,37,1,65,45,8,8,65,6,7,1,27,137,9,12,68,89,194,22,67,25,34,34,80,59,59,69,253,237,13,2,19,254,11,115,68,103,254,235,103,63,49,12,195,13,16,94,
+    211,87,57,31,91,33,47,46,253,52,87,1,231,123,51,123,1,95,17,254,172,52,52,1,31,12,7,130,122,33,0,3,136,123,36,30,0,34,0,46,130,121,80,150,8,37,7,6,7,51,21,33,133,128,92,31,6,34,34,
+    7,37,143,131,59,8,63,48,82,44,43,15,29,39,83,36,205,254,226,22,72,19,54,9,6,6,19,25,23,96,60,1,37,142,143,58,247,26,30,34,47,29,22,40,36,75,34,53,52,20,66,17,50,12,9,6,32,18,33,17,
+    17,34,172,144,152,65,19,7,32,19,65,19,6,32,79,65,19,25,47,45,1,50,52,35,34,15,1,14,1,7,53,55,62,1,55,137,192,32,22,75,212,5,41,47,1,34,39,46,2,39,53,30,1,101,182,8,34,43,1,53,65,61,
+    22,8,45,135,95,90,37,17,25,7,15,8,18,21,19,11,16,35,71,42,42,49,16,21,96,47,48,85,9,8,29,8,7,13,23,14,8,18,24,7,38,27,93,14,2,6,21,82,33,65,98,20,8,56,212,113,5,7,2,5,2,56,4,5,2,2,
+    3,27,28,46,51,23,7,5,20,79,58,31,32,1,2,2,4,4,4,2,58,6,8,2,10,56,8,25,12,40,51,0,2,0,96,255,244,1,239,2,219,0,50,0,67,130,227,33,54,55,66,100,5,72,27,7,35,62,1,63,1,131,211,36,55,54,
+    61,1,52,130,3,32,51,131,210,36,7,14,2,15,1,81,137,5,33,51,19,69,25,5,33,35,34,66,247,6,8,119,50,1,82,68,89,31,31,11,33,25,35,38,87,52,56,17,22,53,6,27,8,12,5,15,4,8,1,96,12,18,43,12,
+    11,27,5,13,31,19,28,71,40,30,10,4,16,25,23,39,31,6,5,57,7,24,65,7,57,89,17,11,4,14,3,3,44,46,75,40,27,35,49,5,25,7,13,6,17,8,16,32,2,3,5,5,65,72,45,25,40,39,11,10,26,5,13,36,25,10,
+    31,22,38,2,149,9,27,13,51,14,23,29,13,13,16,56,14,1,0,0,0,3,90,175,5,39,3,101,0,10,0,23,0,31,98,145,23,39,3,46,1,39,51,30,1,23,98,153,23,39,145,22,70,22,92,19,61,19,98,161,22,36,2,
+    49,23,79,23,130,2,137,111,32,104,132,111,32,27,151,111,35,17,7,35,55,151,107,34,114,77,98,151,102,34,177,123,123,138,211,32,102,132,99,32,35,151,99,42,3,38,39,14,1,7,35,54,55,51,22,
+    152,215,43,47,48,35,15,52,16,69,85,20,94,44,62,151,116,41,50,51,33,15,53,16,102,23,51,74,138,123,32,81,132,123,32,62,153,123,40,34,7,6,29,1,35,52,55,54,94,110,5,32,22,79,205,5,43,51,
+    6,7,6,35,34,46,1,47,1,46,3,151,255,8,33,172,14,18,6,22,63,27,26,42,6,9,30,34,7,10,26,11,19,8,13,62,3,53,17,15,32,18,9,6,14,7,7,18,5,151,169,63,92,7,4,11,30,4,49,27,28,1,6,17,4,5,13,
+    9,15,19,3,73,23,8,8,3,3,7,4,4,9,4,0,4,66,11,12,34,35,0,47,151,189,32,19,86,222,6,36,59,1,50,21,7,138,11,151,177,32,19,76,76,5,38,196,15,72,14,14,72,15,151,157,35,93,14,14,67,135,2,
+    66,151,8,38,126,0,8,0,22,0,44,132,137,53,1,39,14,3,18,6,20,30,1,51,50,55,54,52,39,38,35,34,3,7,35,19,110,2,8,8,89,21,20,7,22,18,22,23,35,39,202,213,48,46,13,13,39,29,18,35,12,34,26,
+    16,33,21,22,5,20,52,29,101,54,105,214,61,14,46,77,56,42,39,61,46,120,34,14,104,56,1,3,158,156,43,43,132,97,62,2,11,26,44,31,11,21,20,45,13,44,253,115,183,2,145,35,72,38,22,70,38,39,
+    53,66,41,138,254,141,105,43,183,0,130,0,32,2,132,4,38,78,2,189,0,7,0,23,131,141,46,17,35,14,1,7,6,15,1,35,19,33,21,35,21,51,132,3,63,33,53,164,154,53,12,38,13,30,30,50,92,205,1,120,
+    169,153,153,178,254,240,1,3,1,107,45,133,50,106,108,180,2,100,83,5,32,180,131,74,45,1,0,70,255,71,2,25,2,203,0,51,0,0,1,130,202,78,63,5,131,217,43,55,21,6,7,34,6,7,22,23,22,21,20,71,
+    149,5,37,51,50,53,52,46,3,71,33,7,8,88,55,54,50,23,2,25,79,87,98,49,49,75,45,76,59,68,20,19,47,43,6,22,8,26,3,15,120,22,25,40,36,39,62,14,3,7,7,4,129,73,78,14,45,116,55,159,78,2,67,
+    58,71,74,142,175,70,42,34,10,15,97,23,9,3,1,34,7,32,19,82,11,61,15,43,14,26,8,9,9,6,8,87,96,171,89,50,152,50,25,39,132,226,43,0,98,0,0,2,39,3,104,0,11,0,19,101,29,13,68,3,7,50,98,1,
+    188,254,170,1,70,254,186,1,95,240,21,71,21,92,18,62,18,134,217,36,2,237,23,77,23,130,2,130,72,32,2,138,71,32,15,142,71,34,7,35,55,138,67,35,113,114,77,98,134,63,35,3,104,123,123,138,
+    59,32,102,130,131,32,24,142,59,67,179,9,33,31,1,138,68,32,151,67,167,7,35,95,20,33,52,134,77,33,2,233,67,152,6,36,23,39,63,0,3,134,143,32,101,130,83,33,25,0,130,234,101,247,11,32,3,
+    66,195,6,33,55,54,66,209,11,133,13,138,100,44,85,15,71,15,3,4,28,51,15,196,15,72,14,132,8,134,105,41,3,20,14,14,67,7,4,3,14,67,134,7,36,0,0,2,0,100,130,4,34,3,3,104,130,111,32,18,130,
+    195,95,33,5,43,21,35,17,51,21,3,46,1,39,51,22,23,101,128,6,38,216,21,70,22,92,47,52,101,135,7,38,2,237,23,77,23,60,63,140,63,32,15,142,63,34,7,35,55,134,60,35,77,114,77,98,135,57,65,
+    60,5,135,119,32,102,130,119,32,21,144,55,33,54,55,130,120,33,35,38,134,61,41,208,82,70,85,20,95,44,62,71,48,136,67,41,61,84,102,23,51,74,51,0,0,3,134,191,32,101,130,71,34,23,0,35,142,
+    73,67,255,22,134,87,32,58,67,238,12,136,91,32,20,67,223,11,42,2,0,4,0,0,2,39,2,189,0,19,131,93,38,55,51,50,55,62,1,55,81,133,6,47,43,1,21,51,21,35,3,17,35,53,51,17,51,50,22,21,106,
+    19,5,8,54,170,48,66,45,43,36,10,28,9,21,50,54,94,48,132,132,103,63,63,151,171,162,81,45,59,64,99,78,15,17,43,21,57,120,85,36,87,32,33,221,70,254,179,1,77,70,1,42,170,181,179,85,45,
+    21,20,130,102,33,0,70,130,4,38,35,3,102,0,16,0,60,130,201,32,17,96,135,5,41,17,51,17,35,38,39,38,39,17,19,69,134,5,33,30,1,84,192,8,48,61,1,51,6,7,6,34,39,46,4,47,1,46,1,39,46,1,80,
+    206,5,8,121,70,128,16,44,34,93,65,97,128,74,59,93,26,39,63,27,25,43,28,31,20,3,10,24,4,11,7,15,9,11,62,3,53,17,28,8,18,11,9,12,15,3,18,4,5,3,7,6,3,7,26,9,2,2,189,37,100,78,215,147,
+    2,65,253,67,167,137,215,59,253,190,3,0,44,31,27,13,11,1,3,13,1,4,13,11,19,3,72,23,7,1,2,4,3,6,7,2,10,1,4,1,3,3,27,8,6,0,0,3,0,58,255,243,2,46,3,104,0,13,0,26,0,34,83,209,11,43,35,34,
+    6,16,39,16,51,50,23,22,21,16,131,164,33,38,19,130,162,131,210,8,53,198,35,75,76,35,34,34,34,77,76,68,106,250,126,63,61,192,27,94,47,140,246,21,70,22,92,18,63,18,130,67,67,64,156,157,
+    64,66,132,254,205,152,1,109,90,94,181,254,190,36,5,22,66,2,162,67,178,8,142,115,32,30,156,115,35,1,7,35,55,148,111,36,1,129,114,77,98,150,108,34,3,29,123,71,159,5,133,219,32,102,132,
+    219,32,39,157,103,67,240,11,149,112,32,86,67,251,11,150,121,33,2,158,68,11,12,139,127,32,70,156,127,66,27,40,148,155,32,148,66,35,38,151,181,32,181,66,41,34,34,0,0,4,66,43,6,40,101,
+    0,13,0,26,0,38,0,50,156,209,32,1,67,188,22,148,192,33,1,143,67,203,12,151,167,32,201,67,218,11,8,34,0,1,0,75,0,82,2,30,2,9,0,36,0,0,37,7,39,54,63,1,54,55,46,3,39,55,30,2,23,54,55,23,
+    14,3,7,109,205,5,58,7,38,39,46,1,1,52,174,59,21,32,64,40,18,22,64,48,30,11,58,55,79,30,11,47,128,59,132,12,63,11,30,24,56,32,21,59,11,15,57,69,247,165,55,20,30,60,37,17,20,61,45,28,
+    11,55,50,76,28,11,43,122,55,132,12,43,11,28,22,53,30,20,55,11,14,53,67,0,130,0,52,3,0,4,255,223,2,88,2,221,0,18,0,33,0,72,0,0,9,1,30,2,78,109,5,51,38,53,39,38,53,38,39,52,5,54,55,38,
+    35,34,7,6,7,6,29,1,68,91,5,34,46,1,39,89,67,5,32,53,73,143,5,41,55,22,23,7,22,23,30,1,23,22,68,121,5,8,134,34,38,39,38,1,186,254,255,15,50,37,21,78,33,34,1,2,1,1,1,254,234,168,84,23,
+    91,42,19,36,13,33,2,39,44,28,10,31,10,89,24,5,1,1,4,98,63,88,116,57,70,35,15,84,14,4,13,6,2,3,16,30,92,46,68,49,42,17,41,1,231,254,167,35,33,11,67,73,148,13,23,10,37,8,7,7,6,10,251,
+    225,113,78,13,27,30,62,182,47,14,10,18,172,56,39,6,21,6,119,56,69,16,16,39,41,221,88,50,77,95,23,12,112,28,15,49,51,18,27,140,68,133,48,22,14,7,16,130,222,50,0,2,0,74,255,243,2,31,
+    3,102,0,34,0,41,0,0,5,34,39,81,86,5,33,38,39,80,141,5,37,51,50,55,62,1,53,131,11,130,223,130,227,37,14,1,3,38,39,51,130,202,8,77,1,46,67,42,39,13,34,9,19,2,2,1,101,11,33,89,85,35,11,
+    2,102,22,12,17,30,10,10,48,71,21,49,65,93,18,61,19,13,21,17,12,31,25,41,42,18,23,1,228,254,37,80,20,63,57,19,61,191,1,54,254,80,102,73,19,27,20,5,5,27,4,2,247,57,67,23,77,24,0,136,
+    135,32,104,130,135,32,40,164,135,37,19,6,7,35,54,55,156,134,37,106,56,59,76,65,33,161,133,37,3,117,61,62,83,40,65,11,12,32,46,165,131,68,77,9,32,23,156,137,32,68,75,247,10,161,143,
+    33,2,246,76,2,11,33,0,3,65,163,6,38,101,0,34,0,46,0,58,165,153,67,149,22,156,165,32,134,67,156,12,161,167,33,3,33,67,167,12,32,2,75,239,6,36,102,0,19,0,24,104,173,21,36,19,7,35,54,
+    55,104,178,18,36,148,115,76,44,54,104,183,20,37,1,175,124,58,66,0,72,191,6,42,71,2,189,0,8,0,23,0,0,37,50,86,24,5,8,48,21,7,17,51,21,51,50,23,22,21,20,7,6,43,1,21,1,62,158,60,36,75,
+    103,102,102,127,192,46,16,63,65,126,127,250,124,75,30,18,247,250,2,189,127,112,38,38,117,47,50,92,247,5,40,94,255,243,2,62,2,219,0,60,68,217,9,66,246,6,34,53,52,55,67,206,6,35,21,17,
+    35,17,130,12,130,91,39,23,6,7,6,21,20,31,2,109,115,5,67,194,9,8,110,39,229,75,60,84,26,7,22,8,26,70,84,6,1,90,30,39,4,114,91,20,7,93,119,39,105,39,116,3,116,35,11,24,10,38,22,32,45,
+    19,31,30,10,16,55,97,50,41,9,14,23,86,29,52,12,20,32,32,7,25,35,53,55,10,12,89,42,15,8,103,70,23,34,253,236,2,23,151,33,12,13,36,156,9,60,19,18,38,19,10,25,11,22,27,26,45,54,56,35,
+    14,10,41,10,2,3,7,0,0,0,3,0,68,130,179,40,48,3,18,0,13,0,66,0,77,130,183,40,20,23,22,50,54,55,54,61,1,98,167,5,33,7,53,102,237,5,32,51,104,105,8,93,181,6,41,30,1,23,35,38,53,38,39,
+    6,7,83,210,9,88,104,5,32,39,95,200,6,8,130,160,88,13,52,60,21,44,116,123,29,10,138,97,92,10,12,20,43,18,37,43,92,55,58,16,3,3,12,1,10,3,4,6,4,1,92,18,2,2,15,44,39,61,37,82,49,51,63,
+    62,122,123,76,27,32,50,73,28,11,99,9,24,39,52,17,159,84,15,2,26,25,48,89,18,58,20,1,24,50,87,4,3,5,13,4,7,30,31,44,8,8,30,80,115,14,13,22,35,40,26,10,17,14,2,42,19,9,10,30,28,23,12,
+    45,39,83,86,47,46,13,92,20,8,143,55,80,31,11,11,30,49,65,22,142,223,32,72,196,223,68,33,5,180,221,37,143,12,150,77,65,76,184,216,38,1,64,12,165,84,93,0,65,183,16,32,78,196,215,43,3,
+    7,35,55,51,30,1,23,35,38,39,38,180,221,43,26,90,69,123,73,23,77,23,69,17,28,29,185,227,40,3,116,177,33,111,33,22,36,36,138,231,39,2,250,0,13,0,66,0,103,196,231,36,55,50,53,51,20,88,
+    223,5,33,47,1,130,235,32,35,71,102,5,75,93,5,36,23,30,4,23,22,180,253,8,33,40,37,62,56,18,16,26,12,20,19,10,12,7,14,4,5,10,29,6,2,1,62,26,25,46,18,18,23,18,7,20,10,4,6,65,19,56,41,
+    223,73,94,30,8,5,8,15,10,9,130,88,49,39,14,19,61,36,35,6,13,16,6,18,7,2,5,0,0,0,4,67,195,5,41,2,217,0,13,0,66,0,78,0,90,65,37,69,69,233,22,65,27,52,35,123,15,71,15,130,2,32,196,93,
+    166,5,65,7,56,32,182,93,222,11,135,247,33,3,77,132,247,34,82,0,96,196,247,48,2,14,1,20,30,1,51,50,54,55,54,53,52,46,1,34,23,85,42,6,37,54,51,50,23,22,20,180,253,55,68,22,11,33,26,16,
+    32,33,6,5,32,28,32,115,40,59,56,40,41,82,55,58,41,39,65,7,56,8,47,1,55,20,26,45,30,11,31,12,12,15,31,31,10,162,38,38,37,54,55,74,37,35,113,0,0,3,0,20,255,243,2,88,2,27,0,14,0,26,0,
+    80,0,0,55,6,7,6,20,86,151,5,41,61,1,35,34,55,51,53,52,38,39,130,214,38,7,6,21,19,50,55,21,130,29,36,35,34,39,38,39,134,7,34,53,52,55,110,97,6,37,35,34,7,6,7,53,131,244,132,248,35,29,
+    1,35,21,86,17,5,8,132,176,51,15,8,23,22,32,67,15,10,24,42,149,164,15,4,18,33,33,16,45,108,75,52,51,42,17,23,80,40,14,8,31,58,21,32,90,39,23,112,36,46,60,24,23,49,49,60,8,8,72,63,91,
+    34,34,94,89,34,36,246,1,60,23,236,9,36,18,70,21,24,50,33,46,55,67,24,57,38,7,25,7,8,23,107,254,241,48,80,32,5,2,43,13,18,55,15,4,63,37,56,122,34,10,41,56,30,31,30,4,5,79,32,60,60,56,
+    54,145,42,17,1,6,10,123,18,9,0,1,0,82,255,71,2,3,130,223,34,56,0,0,90,23,5,103,203,9,32,55,132,170,36,23,21,38,39,38,130,189,32,21,95,10,7,82,168,7,71,203,5,8,94,34,39,53,22,1,53,63,
+    14,2,4,11,4,116,66,73,14,25,36,74,125,67,52,19,21,56,57,20,66,34,103,104,34,56,11,70,46,7,8,40,46,5,20,7,44,46,33,26,36,26,40,36,128,43,16,24,4,8,14,6,6,66,73,131,71,36,61,35,73,22,
+    8,10,91,47,8,3,14,40,149,150,40,14,1,10,34,6,7,90,25,9,3,1,48,44,51,20,90,130,5,54,0,3,0,62,255,243,2,44,3,18,0,12,0,39,0,50,0,0,19,51,54,59,1,130,152,132,154,65,121,6,34,43,1,34,119,
+    116,8,33,22,29,109,161,5,32,3,71,60,6,8,34,162,64,25,22,192,2,8,12,17,35,136,42,43,170,87,108,74,75,12,12,23,129,75,73,111,66,86,110,61,60,254,114,140,19,8,71,41,6,8,45,38,52,17,1,
+    53,1,44,20,34,19,39,42,41,254,188,54,86,32,6,2,73,73,129,161,74,42,67,68,119,42,3,150,28,3,2,38,55,80,31,11,11,31,48,65,22,0,130,0,141,155,32,47,169,155,37,19,7,35,62,3,55,161,153,
+    39,167,162,77,17,51,39,24,9,159,150,38,215,177,22,65,48,31,11,145,147,32,51,169,147,70,180,11,161,153,32,2,70,161,8,33,29,28,159,157,32,154,70,135,11,32,4,65,207,5,41,2,217,0,12,0,
+    39,0,51,0,63,169,161,86,133,23,161,173,38,147,15,71,16,16,71,15,69,53,6,159,175,32,77,69,28,11,50,2,0,109,255,252,2,34,3,6,0,14,0,27,0,0,5,35,34,38,109,250,6,37,23,22,59,1,1,38,73,
+    163,7,8,54,2,34,117,81,92,122,214,52,16,22,108,254,237,20,29,30,45,28,10,99,9,24,38,52,17,4,100,91,1,16,67,254,173,86,24,7,2,15,21,33,33,48,31,11,11,31,48,66,21,0,0,0,2,0,134,136,91,
+    130,15,142,91,37,3,7,35,62,2,55,138,87,38,50,162,78,27,81,24,9,139,80,35,192,177,34,101,65,247,5,139,75,32,25,145,167,84,8,6,34,39,6,7,138,80,43,254,100,92,31,74,92,31,70,68,22,68,
+    22,139,85,40,16,132,44,132,44,86,29,86,29,130,163,32,3,133,163,33,2,217,130,255,34,26,0,38,144,89,85,74,7,85,72,11,131,11,138,102,35,100,15,71,15,130,2,38,195,15,72,14,14,72,15,139,
+    104,32,66,70,134,12,34,0,2,0,109,235,5,46,219,0,46,0,65,0,0,1,22,23,14,1,7,22,21,72,98,6,69,82,5,43,22,59,2,50,23,46,2,39,38,39,46,1,130,205,34,39,54,55,85,93,5,32,3,112,248,11,8,123,
+    38,43,1,34,7,6,1,211,10,6,23,78,24,190,98,56,86,112,65,62,61,62,123,17,5,2,2,1,2,4,1,8,11,5,7,8,16,11,5,15,124,15,79,40,17,58,16,109,36,28,157,37,37,68,67,39,37,55,7,9,25,13,23,113,
+    30,10,2,196,30,16,7,24,7,190,186,151,72,38,69,72,123,127,67,70,1,1,2,9,13,7,10,9,17,12,5,5,38,46,25,12,18,58,18,39,28,254,99,92,49,51,51,51,89,113,68,4,2,6,109,36,0,0,0,2,110,239,6,
+    39,225,0,18,0,53,0,0,19,110,229,5,32,17,110,248,10,73,53,10,32,39,131,200,32,35,130,170,32,7,73,51,6,80,132,5,8,88,189,51,115,170,92,110,97,28,9,92,83,7,186,38,62,26,25,45,43,38,4,
+    9,11,8,4,3,7,8,17,10,7,2,63,27,25,45,34,36,7,3,19,16,3,5,1,191,92,212,254,185,1,71,137,95,30,41,254,214,2,14,49,188,72,65,33,35,38,3,9,10,5,3,2,3,18,11,44,63,35,35,28,7,4,18,9,3,3,
+    0,3,65,95,5,43,3,18,0,13,0,27,0,40,0,0,1,34,114,203,7,36,53,52,39,38,3,69,68,10,37,16,6,3,46,1,39,130,2,8,69,51,30,3,23,1,52,142,80,27,35,106,27,10,81,26,36,175,49,15,136,45,58,117,
+    61,62,122,124,20,60,28,16,28,11,100,9,24,38,52,17,1,210,203,150,41,13,116,38,50,151,39,13,254,33,158,51,67,202,56,18,71,72,254,243,140,2,110,22,65,32,16,69,52,9,141,131,32,33,157,131,
+    76,32,5,149,126,37,51,23,140,76,82,58,152,119,38,3,31,23,154,106,71,0,142,243,32,38,157,111,69,3,8,33,46,1,149,116,42,118,90,70,123,74,23,77,23,70,17,56,152,121,33,2,226,68,239,5,32,
+    72,135,123,39,2,225,0,13,0,27,0,62,158,123,75,76,9,66,22,22,149,146,32,53,66,32,31,65,153,24,32,166,66,41,25,34,0,0,4,66,43,5,33,2,217,132,187,34,39,0,51,157,189,69,155,23,149,179,
+    32,31,80,199,12,65,73,25,32,149,68,31,13,49,3,0,44,0,71,2,60,2,22,0,11,0,15,0,27,0,0,37,75,90,10,36,37,53,33,21,39,138,15,44,1,114,16,92,15,15,92,16,254,186,2,16,202,133,10,41,85,14,
+    14,87,13,13,90,80,80,170,130,8,49,15,15,0,3,0,24,255,211,2,75,2,57,0,10,0,20,0,47,130,225,36,6,7,22,23,22,98,170,6,114,7,6,37,54,3,6,7,38,39,106,2,5,38,51,50,23,54,55,22,23,68,147,
+    5,8,102,43,1,38,1,182,40,191,21,35,25,55,27,81,42,36,65,103,31,10,14,187,215,50,30,44,2,85,40,136,44,58,101,59,29,45,21,25,82,43,137,45,59,26,87,1,111,46,218,25,12,7,13,41,148,67,94,
+    44,111,34,31,74,56,212,254,182,55,32,34,2,94,67,111,202,56,18,52,33,49,18,17,93,63,115,204,55,17,7,0,0,0,2,0,97,255,243,2,13,3,5,0,24,0,34,130,229,74,83,7,83,241,8,33,54,53,130,10,
+    38,35,38,3,46,2,39,51,130,176,8,60,23,1,177,35,78,24,36,119,33,11,92,27,29,54,97,28,9,92,83,2,138,28,96,28,11,100,13,29,70,28,79,67,19,6,119,40,54,1,69,254,187,74,31,34,96,31,40,1,
+    41,253,243,23,2,61,29,106,31,11,17,36,90,130,96,139,111,32,30,154,111,67,142,6,145,108,37,37,20,143,76,41,99,150,104,36,238,21,156,55,122,140,211,32,35,154,99,32,1,79,57,7,33,6,7,146,
+    213,33,254,220,67,126,5,35,67,23,67,23,150,110,36,61,177,33,111,33,70,188,5,32,3,65,71,5,39,2,217,0,24,0,36,0,48,154,117,66,190,24,145,235,32,17,66,187,12,150,132,32,113,66,184,12,
+    44,2,0,52,255,55,2,65,3,5,0,38,0,44,130,133,44,19,51,14,3,7,14,2,15,1,14,2,7,6,131,1,48,43,1,53,51,50,55,54,55,46,1,39,38,39,51,23,30,1,65,105,6,8,89,59,164,98,55,58,25,21,8,13,14,
+    5,2,28,10,17,13,6,18,15,26,12,38,41,60,54,61,27,12,22,35,77,28,73,3,98,50,62,42,173,44,119,76,31,109,115,1,155,132,140,62,49,20,33,32,14,6,72,25,32,26,11,30,10,18,3,12,73,59,23,54,
+    85,187,65,174,7,125,152,107,2,119,47,129,42,134,0,0,0,2,0,95,130,143,40,42,2,224,0,10,0,30,0,0,107,185,5,37,23,22,51,50,16,5,99,147,8,34,35,34,39,130,141,8,58,17,35,17,51,1,68,101,
+    27,9,77,26,34,134,254,241,48,103,99,60,57,58,60,99,40,20,41,38,11,92,92,1,210,115,38,50,148,43,13,1,151,7,80,74,73,130,131,72,72,8,16,36,20,254,244,3,169,0,0,3,133,243,33,2,204,130,
+    243,34,50,0,62,133,245,35,1,7,14,9,130,248,33,7,6,145,240,32,21,67,186,9,32,7,138,11,56,1,59,164,98,55,58,12,16,25,7,5,3,4,2,4,4,7,7,22,47,13,6,40,65,83,65,2,13,32,153,65,148,12,53,
+    115,1,155,132,140,31,37,60,17,13,8,7,6,8,12,18,19,61,92,16,7,43,65,10,12,38,47,62,18,14,66,15,15,132,5,43,0,1,0,18,255,243,2,18,2,203,0,65,130,167,32,6,130,247,46,38,39,35,55,54,55,
+    51,53,38,61,1,38,52,55,53,130,2,37,35,55,51,54,55,54,111,182,10,48,7,51,6,7,35,21,20,6,29,1,22,21,51,14,1,7,35,104,231,5,48,62,1,55,2,18,65,146,91,32,63,28,87,13,7,5,58,1,130,0,8,86,
+    83,25,62,42,130,45,38,104,66,8,8,58,78,108,43,14,6,240,15,9,221,1,1,180,5,15,5,150,10,45,44,73,53,65,8,17,8,25,38,1,33,33,62,139,26,16,10,10,2,5,13,9,11,10,15,1,2,10,50,205,48,17,39,
+    97,6,7,47,110,36,48,34,16,9,2,6,4,62,2,3,10,32,10,92,52,50,36,6,102,24,5,35,0,14,0,174,130,193,32,0,132,0,34,1,0,4,134,11,32,1,130,7,32,10,134,11,32,2,130,7,32,16,134,11,36,3,0,29,
+    0,78,134,11,131,43,32,112,134,11,36,5,0,9,0,134,134,11,32,6,130,7,44,148,0,3,0,1,4,9,0,0,0,2,0,0,134,11,32,1,130,11,32,6,134,11,32,2,130,11,32,12,134,11,36,3,0,58,0,18,134,11,32,4,
+    130,23,32,108,134,11,32,5,130,21,32,114,134,11,32,6,130,23,35,144,0,46,0,143,2,39,70,0,111,0,110,0,116,0,131,7,40,114,0,103,0,101,0,32,0,50,130,36,32,48,130,7,32,58,130,3,32,46,134,
+    7,38,50,0,49,0,45,0,56,130,3,34,50,0,48,130,33,51,53,0,0,70,111,110,116,70,111,114,103,101,32,50,46,48,32,58,32,46,130,3,39,50,49,45,56,45,50,48,50,130,30,133,107,32,86,130,81,36,114,
+    0,115,0,105,132,103,32,32,130,89,40,0,86,101,114,115,105,111,110,32,136,140,33,2,0,132,0,35,255,156,0,35,130,8,32,1,130,3,141,2,32,195,132,21,32,2,130,201,58,4,0,5,0,6,0,7,0,8,0,9,
+    0,10,0,11,0,12,0,13,0,14,0,15,0,16,0,17,130,235,62,19,0,20,0,21,0,22,0,23,0,24,0,25,0,26,0,27,0,28,0,29,0,30,0,31,0,32,0,33,0,34,130,93,50,36,0,37,0,38,0,39,0,40,0,41,0,42,0,43,0,44,
+    0,45,130,145,32,47,130,209,32,49,130,211,9,38,51,0,52,0,53,0,54,0,55,0,56,0,57,0,58,0,59,0,60,0,61,0,62,0,63,0,64,0,65,0,66,0,67,0,68,0,69,0,70,0,71,0,72,0,73,0,74,0,75,0,76,0,77,0,
+    78,0,79,0,80,0,81,0,82,0,83,0,84,0,85,0,86,0,87,0,88,0,89,0,90,0,91,0,92,0,93,0,94,0,95,0,96,0,97,0,172,0,163,0,132,0,133,0,189,0,150,0,232,0,134,0,142,0,139,0,157,0,169,0,164,1,2,
+    0,138,0,218,0,131,0,147,0,242,0,243,0,141,0,151,0,136,0,195,0,222,0,241,0,158,0,170,0,245,0,244,0,246,0,162,0,173,0,201,0,199,0,174,0,98,0,99,0,144,0,100,0,203,0,101,0,200,0,202,0,
+    207,0,204,0,205,0,206,0,233,0,102,0,211,0,208,0,209,0,175,0,103,0,240,0,145,0,214,0,212,0,213,0,104,0,235,0,237,0,137,0,106,0,105,0,107,0,109,0,108,0,110,0,160,0,111,0,113,0,112,0,
+    114,0,115,0,117,0,116,0,118,0,119,0,234,0,120,0,122,0,121,0,123,0,125,0,124,0,184,0,161,0,127,0,126,0,128,0,129,0,236,0,238,0,186,1,3,7,117,110,105,48,48,97,100,131,7,45,50,48,97,99,
+    0,0,0,1,255,255,0,2,0,1,130,9,32,12,130,3,32,16,130,3,36,2,0,0,0,4,134,7,32,0,132,25,36,0,223,214,203,49,130,17,24,92,127,12,5,250,205,249,72,146,
+};
+
+static const char* GetDefaultCompressedFontDataProggyVector(int* out_size)
+{
+    *out_size = proggy_vector_minimal_ttf_compressed_size;
+    return (const char*)proggy_vector_minimal_ttf_compressed_data;
+}
+
 #endif // #ifndef IMGUI_DISABLE_DEFAULT_FONT
 
 #endif // #ifndef IMGUI_DISABLE

+ 23 - 15
3rdparty/dear-imgui/imgui_internal.h

@@ -276,8 +276,8 @@ extern IMGUI_API ImGuiContext* GImGui;  // Current implicit context pointer
 #define IM_MEMALIGN(_OFF,_ALIGN)        (((_OFF) + ((_ALIGN) - 1)) & ~((_ALIGN) - 1))           // Memory align e.g. IM_ALIGN(0,4)=0, IM_ALIGN(1,4)=4, IM_ALIGN(4,4)=4, IM_ALIGN(5,4)=8
 #define IM_F32_TO_INT8_UNBOUND(_VAL)    ((int)((_VAL) * 255.0f + ((_VAL)>=0 ? 0.5f : -0.5f)))   // Unsaturated, for display purpose
 #define IM_F32_TO_INT8_SAT(_VAL)        ((int)(ImSaturate(_VAL) * 255.0f + 0.5f))               // Saturated, always output 0..255
-#define IM_TRUNC(_VAL)                  ((float)(int)(_VAL))                                    // ImTrunc() is not inlined in MSVC debug builds
-#define IM_ROUND(_VAL)                  ((float)(int)((_VAL) + 0.5f))                           //
+#define IM_TRUNC(_VAL)                  ((float)(int)(_VAL))                                    // Positive values only! ImTrunc() is not inlined in MSVC debug builds
+#define IM_ROUND(_VAL)                  ((float)(int)((_VAL) + 0.5f))                           // Positive values only! 
 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
 #define IM_FLOOR IM_TRUNC               // [OBSOLETE] Renamed in 1.90.0 (Sept 2023)
 #endif
@@ -441,6 +441,16 @@ IMGUI_API ImVec2        ImFontCalcTextSizeEx(ImFont* font, float size, float max
 IMGUI_API const char*   ImFontCalcWordWrapPositionEx(ImFont* font, float size, const char* text, const char* text_end, float wrap_width, ImDrawTextFlags flags = 0);
 IMGUI_API const char*   ImTextCalcWordWrapNextLineStart(const char* text, const char* text_end, ImDrawTextFlags flags = 0); // trim trailing space and find beginning of next line
 
+// Character classification for word-wrapping logic
+enum ImWcharClass
+{
+    ImWcharClass_Blank, ImWcharClass_Punct, ImWcharClass_Other
+};
+IMGUI_API void          ImTextInitClassifiers();
+IMGUI_API void          ImTextClassifierClear(ImU32* bits, unsigned int codepoint_min, unsigned int codepoint_end, ImWcharClass char_class);
+IMGUI_API void          ImTextClassifierSetCharClass(ImU32* bits, unsigned int codepoint_min, unsigned int codepoint_end, ImWcharClass char_class, unsigned int c);
+IMGUI_API void          ImTextClassifierSetCharClassFromStr(ImU32* bits, unsigned int codepoint_min, unsigned int codepoint_end, ImWcharClass char_class, const char* s);
+
 // Helpers: File System
 #ifdef IMGUI_DISABLE_FILE_FUNCTIONS
 #define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS
@@ -517,7 +527,7 @@ inline ImVec2 ImTrunc(const ImVec2& v)                                  { return
 inline float  ImFloor(float f)                                          { return (float)((f >= 0 || (float)(int)f == f) ? (int)f : (int)f - 1); } // Decent replacement for floorf()
 inline ImVec2 ImFloor(const ImVec2& v)                                  { return ImVec2(ImFloor(v.x), ImFloor(v.y)); }
 inline float  ImTrunc64(float f)                                        { return (float)(ImS64)(f); }
-inline float  ImRound64(float f)                                        { return (float)(ImS64)(f + 0.5f); }
+inline float  ImRound64(float f)                                        { return (float)(ImS64)(f + 0.5f); } // FIXME: Positive values only.
 inline int    ImModPositive(int a, int b)                               { return (a + b) % b; }
 inline float  ImDot(const ImVec2& a, const ImVec2& b)                   { return a.x * b.x + a.y * b.y; }
 inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a)       { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); }
@@ -601,7 +611,6 @@ struct IMGUI_API ImRect
     void        TranslateY(float dy)                { Min.y += dy; Max.y += dy; }
     void        ClipWith(const ImRect& r)           { Min = ImMax(Min, r.Min); Max = ImMin(Max, r.Max); }                   // Simple version, may lead to an inverted rectangle, which is fine for Contains/Overlaps test but not for display.
     void        ClipWithFull(const ImRect& r)       { Min = ImClamp(Min, r.Min, r.Max); Max = ImClamp(Max, r.Min, r.Max); } // Full version, ensure both points are fully clipped.
-    void        Floor()                             { Min.x = IM_TRUNC(Min.x); Min.y = IM_TRUNC(Min.y); Max.x = IM_TRUNC(Max.x); Max.y = IM_TRUNC(Max.y); }
     bool        IsInverted() const                  { return Min.x > Max.x || Min.y > Max.y; }
     ImVec4      ToVec4() const                      { return ImVec4(Min.x, Min.y, Max.x, Max.y); }
     const ImVec4& AsVec4() const                    { return *(const ImVec4*)&Min.x; }
@@ -635,15 +644,15 @@ typedef ImU32* ImBitArrayPtr; // Name for use in structs
 template<int BITCOUNT, int OFFSET = 0>
 struct ImBitArray
 {
-    ImU32           Storage[(BITCOUNT + 31) >> 5];
+    ImU32           Data[(BITCOUNT + 31) >> 5];
     ImBitArray()                                { ClearAllBits(); }
-    void            ClearAllBits()              { memset(Storage, 0, sizeof(Storage)); }
-    void            SetAllBits()                { memset(Storage, 255, sizeof(Storage)); }
-    bool            TestBit(int n) const        { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); return IM_BITARRAY_TESTBIT(Storage, n); }
-    void            SetBit(int n)               { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); ImBitArraySetBit(Storage, n); }
-    void            ClearBit(int n)             { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); ImBitArrayClearBit(Storage, n); }
-    void            SetBitRange(int n, int n2)  { n += OFFSET; n2 += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT && n2 > n && n2 <= BITCOUNT); ImBitArraySetBitRange(Storage, n, n2); } // Works on range [n..n2)
-    bool            operator[](int n) const     { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); return IM_BITARRAY_TESTBIT(Storage, n); }
+    void            ClearAllBits()              { memset(Data, 0, sizeof(Data)); }
+    void            SetAllBits()                { memset(Data, 255, sizeof(Data)); }
+    bool            TestBit(int n) const        { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); return IM_BITARRAY_TESTBIT(Data, n); }
+    void            SetBit(int n)               { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); ImBitArraySetBit(Data, n); }
+    void            ClearBit(int n)             { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); ImBitArrayClearBit(Data, n); }
+    void            SetBitRange(int n, int n2)  { n += OFFSET; n2 += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT && n2 > n && n2 <= BITCOUNT); ImBitArraySetBitRange(Data, n, n2); } // Works on range [n..n2)
+    bool            operator[](int n) const     { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); return IM_BITARRAY_TESTBIT(Data, n); }
 };
 
 // Helper: ImBitVector
@@ -955,7 +964,6 @@ enum ImGuiDataTypePrivate_
 enum ImGuiItemFlagsPrivate_
 {
     // Controlled by user
-    ImGuiItemFlags_Disabled                 = 1 << 10, // false     // Disable interactions (DOES NOT affect visuals. DO NOT mix direct use of this with BeginDisabled(). See BeginDisabled()/EndDisabled() for full disable feature, and github #211).
     ImGuiItemFlags_ReadOnly                 = 1 << 11, // false     // [ALPHA] Allow hovering interactions but underlying value is not changed.
     ImGuiItemFlags_MixedValue               = 1 << 12, // false     // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets)
     ImGuiItemFlags_NoWindowHoverableCheck   = 1 << 13, // false     // Disable hoverable check in ItemHoverable()
@@ -1581,7 +1589,7 @@ struct ImGuiKeyRoutingTable
     ImVector<ImGuiKeyRoutingData>   EntriesNext;                    // Double-buffer to avoid reallocation (could use a shared buffer)
 
     ImGuiKeyRoutingTable()          { Clear(); }
-    void Clear()                    { for (int n = 0; n < IM_ARRAYSIZE(Index); n++) Index[n] = -1; Entries.clear(); EntriesNext.clear(); }
+    void Clear()                    { for (int n = 0; n < IM_COUNTOF(Index); n++) Index[n] = -1; Entries.clear(); EntriesNext.clear(); }
 };
 
 // This extends ImGuiKeyData but only for named keys (legacy keys don't support the new features)
@@ -3251,7 +3259,6 @@ namespace ImGui
 
     // Basic Accessors
     inline ImGuiItemStatusFlags GetItemStatusFlags() { ImGuiContext& g = *GImGui; return g.LastItemData.StatusFlags; }
-    inline ImGuiItemFlags   GetItemFlags()  { ImGuiContext& g = *GImGui; return g.LastItemData.ItemFlags; }
     inline ImGuiID          GetActiveID()   { ImGuiContext& g = *GImGui; return g.ActiveId; }
     inline ImGuiID          GetFocusID()    { ImGuiContext& g = *GImGui; return g.NavId; }
     IMGUI_API void          SetActiveID(ImGuiID id, ImGuiWindow* window);
@@ -3895,6 +3902,7 @@ IMGUI_API void              ImFontAtlasFontSourceAddToFont(ImFontAtlas* atlas, I
 IMGUI_API void              ImFontAtlasFontDestroySourceData(ImFontAtlas* atlas, ImFontConfig* src);
 IMGUI_API bool              ImFontAtlasFontInitOutput(ImFontAtlas* atlas, ImFont* font); // Using FontDestroyOutput/FontInitOutput sequence useful notably if font loader params have changed
 IMGUI_API void              ImFontAtlasFontDestroyOutput(ImFontAtlas* atlas, ImFont* font);
+IMGUI_API void              ImFontAtlasFontRebuildOutput(ImFontAtlas* atlas, ImFont* font);
 IMGUI_API void              ImFontAtlasFontDiscardBakes(ImFontAtlas* atlas, ImFont* font, int unused_frames);
 
 IMGUI_API ImGuiID           ImFontAtlasBakedGetId(ImGuiID font_id, float baked_size, float rasterizer_density);

+ 5 - 5
3rdparty/dear-imgui/imgui_tables.cpp

@@ -2624,7 +2624,7 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
     const int size_for_masks_bitarrays_one = (int)ImBitArrayGetStorageSizeInBytes(max_draw_channels);
     g.TempBuffer.reserve(size_for_masks_bitarrays_one * 5);
     memset(g.TempBuffer.Data, 0, size_for_masks_bitarrays_one * 5);
-    for (int n = 0; n < IM_ARRAYSIZE(merge_groups); n++)
+    for (int n = 0; n < IM_COUNTOF(merge_groups); n++)
         merge_groups[n].ChannelsMask = (ImBitArrayPtr)(void*)(g.TempBuffer.Data + (size_for_masks_bitarrays_one * n));
     ImBitArrayPtr remaining_mask = (ImBitArrayPtr)(void*)(g.TempBuffer.Data + (size_for_masks_bitarrays_one * 4));
 
@@ -2681,7 +2681,7 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
     // [DEBUG] Display merge groups
 #if 0
     if (g.IO.KeyShift)
-        for (int merge_group_n = 0; merge_group_n < IM_ARRAYSIZE(merge_groups); merge_group_n++)
+        for (int merge_group_n = 0; merge_group_n < IM_COUNTOF(merge_groups); merge_group_n++)
         {
             MergeGroup* merge_group = &merge_groups[merge_group_n];
             if (merge_group->ChannelsCount == 0)
@@ -2709,7 +2709,7 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
         int remaining_count = splitter->_Count - (has_freeze_v ? LEADING_DRAW_CHANNELS + 1 : LEADING_DRAW_CHANNELS);
         //ImRect host_rect = (table->InnerWindow == table->OuterWindow) ? table->InnerClipRect : table->HostClipRect;
         ImRect host_rect = table->HostClipRect;
-        for (int merge_group_n = 0; merge_group_n < IM_ARRAYSIZE(merge_groups); merge_group_n++)
+        for (int merge_group_n = 0; merge_group_n < IM_COUNTOF(merge_groups); merge_group_n++)
         {
             if (int merge_channels_count = merge_groups[merge_group_n].ChannelsCount)
             {
@@ -3202,7 +3202,7 @@ void ImGui::TableHeader(const char* label)
             sort_arrow = true;
         if (column->SortOrder > 0)
         {
-            ImFormatString(sort_order_suf, IM_ARRAYSIZE(sort_order_suf), "%d", column->SortOrder + 1);
+            ImFormatString(sort_order_suf, IM_COUNTOF(sort_order_suf), "%d", column->SortOrder + 1);
             w_sort_text = g.Style.ItemInnerSpacing.x + CalcTextSize(sort_order_suf).x;
         }
     }
@@ -4094,7 +4094,7 @@ void ImGui::DebugNodeTable(ImGuiTable* table)
         ImGuiTableColumn* column = &table->Columns[n];
         const char* name = TableGetColumnName(table, n);
         char buf[512];
-        ImFormatString(buf, IM_ARRAYSIZE(buf),
+        ImFormatString(buf, IM_COUNTOF(buf),
             "Column %d order %d '%s': offset %+.2f to %+.2f%s\n"
             "Enabled: %d, VisibleX/Y: %d/%d, RequestOutput: %d, SkipItems: %d, DrawChannels: %d,%d\n"
             "WidthGiven: %.1f, Request/Auto: %.1f/%.1f, StretchWeight: %.3f (%.1f%%)\n"

+ 26 - 26
3rdparty/dear-imgui/imgui_widgets.cpp

@@ -1452,7 +1452,7 @@ void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, const char* over
     {
         if (!overlay)
         {
-            ImFormatString(overlay_buf, IM_ARRAYSIZE(overlay_buf), "%.0f%%", fraction * 100 + 0.01f);
+            ImFormatString(overlay_buf, IM_COUNTOF(overlay_buf), "%.0f%%", fraction * 100 + 0.01f);
             overlay = overlay_buf;
         }
 
@@ -2019,7 +2019,7 @@ bool ImGui::BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags
 
     // This is essentially a specialized version of BeginPopupEx()
     char name[16];
-    ImFormatString(name, IM_ARRAYSIZE(name), "##Combo_%02d", g.BeginComboDepth); // Recycle windows based on depth
+    ImFormatString(name, IM_COUNTOF(name), "##Combo_%02d", g.BeginComboDepth); // Recycle windows based on depth
 
     // Set position given a custom constraint (peak into expected window size so we can position it)
     // FIXME: This might be easier to express with an hypothetical SetNextWindowPosConstraints() function?
@@ -2265,7 +2265,7 @@ static const ImGuiDataTypeInfo GDataTypeInfo[] =
     { sizeof(bool),             "bool", "%d",   "%d"    },  // ImGuiDataType_Bool
     { 0,                        "char*","%s",   "%s"    },  // ImGuiDataType_String
 };
-IM_STATIC_ASSERT(IM_ARRAYSIZE(GDataTypeInfo) == ImGuiDataType_COUNT);
+IM_STATIC_ASSERT(IM_COUNTOF(GDataTypeInfo) == ImGuiDataType_COUNT);
 
 const ImGuiDataTypeInfo* ImGui::DataTypeGetInfo(ImGuiDataType data_type)
 {
@@ -2374,7 +2374,7 @@ bool ImGui::DataTypeApplyFromText(const char* buf, ImGuiDataType data_type, void
     if (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double)
         format = type_info->ScanFmt;
     else
-        format = ImParseFormatSanitizeForScanning(format, format_sanitized, IM_ARRAYSIZE(format_sanitized));
+        format = ImParseFormatSanitizeForScanning(format, format_sanitized, IM_COUNTOF(format_sanitized));
 
     // Small types need a 32-bit buffer to receive the result from scanf()
     int v32 = 0;
@@ -2465,7 +2465,7 @@ static float GetMinimumStepAtDecimalPrecision(int decimal_precision)
     static const float min_steps[10] = { 1.0f, 0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f, 0.0000001f, 0.00000001f, 0.000000001f };
     if (decimal_precision < 0)
         return FLT_MIN;
-    return (decimal_precision < IM_ARRAYSIZE(min_steps)) ? min_steps[decimal_precision] : ImPow(10.0f, (float)-decimal_precision);
+    return (decimal_precision < IM_COUNTOF(min_steps)) ? min_steps[decimal_precision] : ImPow(10.0f, (float)-decimal_precision);
 }
 
 template<typename TYPE>
@@ -2479,12 +2479,12 @@ TYPE ImGui::RoundScalarWithFormatT(const char* format, ImGuiDataType data_type,
 
     // Sanitize format
     char fmt_sanitized[32];
-    ImParseFormatSanitizeForPrinting(fmt_start, fmt_sanitized, IM_ARRAYSIZE(fmt_sanitized));
+    ImParseFormatSanitizeForPrinting(fmt_start, fmt_sanitized, IM_COUNTOF(fmt_sanitized));
     fmt_start = fmt_sanitized;
 
     // Format value with our rounding, and read back
     char v_str[64];
-    ImFormatString(v_str, IM_ARRAYSIZE(v_str), fmt_start, v);
+    ImFormatString(v_str, IM_COUNTOF(v_str), fmt_start, v);
     const char* p = v_str;
     while (*p == ' ')
         p++;
@@ -2774,7 +2774,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
 
     // Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
     char value_buf[64];
-    const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_data, format);
+    const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_COUNTOF(value_buf), data_type, p_data, format);
     if (g.LogEnabled)
         LogSetNextTextDecoration("{", "}");
     RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f));
@@ -3386,7 +3386,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
 
     // Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
     char value_buf[64];
-    const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_data, format);
+    const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_COUNTOF(value_buf), data_type, p_data, format);
     if (g.LogEnabled)
         LogSetNextTextDecoration("{", "}");
     RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f));
@@ -3539,7 +3539,7 @@ bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType d
     // Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
     // For the vertical slider we allow centered text to overlap the frame padding
     char value_buf[64];
-    const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_data, format);
+    const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_COUNTOF(value_buf), data_type, p_data, format);
     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));
     if (label_size.x > 0.0f)
         RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
@@ -3739,16 +3739,16 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
     const ImGuiDataTypeInfo* type_info = DataTypeGetInfo(data_type);
     char fmt_buf[32];
     char data_buf[32];
-    format = ImParseFormatTrimDecorations(format, fmt_buf, IM_ARRAYSIZE(fmt_buf));
+    format = ImParseFormatTrimDecorations(format, fmt_buf, IM_COUNTOF(fmt_buf));
     if (format[0] == 0)
         format = type_info->PrintFmt;
-    DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, p_data, format);
+    DataTypeFormatString(data_buf, IM_COUNTOF(data_buf), data_type, p_data, format);
     ImStrTrimBlanks(data_buf);
 
     ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_LocalizeDecimalPoint;
     g.LastItemData.ItemFlags |= ImGuiItemFlags_NoMarkEdited; // Because TempInputText() uses ImGuiInputTextFlags_MergedItem it doesn't submit a new item, so we poke LastItemData.
     bool value_changed = false;
-    if (TempInputText(bb, id, label, data_buf, IM_ARRAYSIZE(data_buf), flags))
+    if (TempInputText(bb, id, label, data_buf, IM_COUNTOF(data_buf), flags))
     {
         // Backup old value
         size_t data_type_size = type_info->Size;
@@ -3801,7 +3801,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
     if ((flags & ImGuiInputTextFlags_DisplayEmptyRefVal) && DataTypeCompare(data_type, p_data, p_data_default) == 0)
         buf[0] = 0;
     else
-        DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, p_data, format);
+        DataTypeFormatString(buf, IM_COUNTOF(buf), data_type, p_data, format);
 
     // Disable the MarkItemEdited() call in InputText but keep ImGuiItemStatusFlags_Edited.
     // We call MarkItemEdited() ourselves by comparing the actual data rather than the string.
@@ -3811,7 +3811,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
     bool value_changed = false;
     if (p_step == NULL)
     {
-        if (InputText(label, buf, IM_ARRAYSIZE(buf), flags))
+        if (InputText(label, buf, IM_COUNTOF(buf), flags))
             value_changed = DataTypeApplyFromText(buf, data_type, p_data, format, (flags & ImGuiInputTextFlags_ParseEmptyRefVal) ? p_data_default : NULL);
     }
     else
@@ -3821,7 +3821,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
         BeginGroup(); // The only purpose of the group here is to allow the caller to query item data e.g. IsItemActive()
         PushID(label);
         SetNextItemWidth(ImMax(1.0f, CalcItemWidth() - (button_size + style.ItemInnerSpacing.x) * 2));
-        if (InputText("", buf, IM_ARRAYSIZE(buf), flags)) // PushId(label) + "" gives us the expected ID from outside point of view
+        if (InputText("", buf, IM_COUNTOF(buf), flags)) // PushId(label) + "" gives us the expected ID from outside point of view
             value_changed = DataTypeApplyFromText(buf, data_type, p_data, format, (flags & ImGuiInputTextFlags_ParseEmptyRefVal) ? p_data_default : NULL);
         IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Inputable);
 
@@ -5866,11 +5866,11 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
         // RGB Hexadecimal Input
         char buf[64];
         if (alpha)
-            ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X%02X", ImClamp(i[0], 0, 255), ImClamp(i[1], 0, 255), ImClamp(i[2], 0, 255), ImClamp(i[3], 0, 255));
+            ImFormatString(buf, IM_COUNTOF(buf), "#%02X%02X%02X%02X", ImClamp(i[0], 0, 255), ImClamp(i[1], 0, 255), ImClamp(i[2], 0, 255), ImClamp(i[3], 0, 255));
         else
-            ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", ImClamp(i[0], 0, 255), ImClamp(i[1], 0, 255), ImClamp(i[2], 0, 255));
+            ImFormatString(buf, IM_COUNTOF(buf), "#%02X%02X%02X", ImClamp(i[0], 0, 255), ImClamp(i[1], 0, 255), ImClamp(i[2], 0, 255));
         SetNextItemWidth(w_inputs);
-        if (InputText("##Text", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_CharsUppercase))
+        if (InputText("##Text", buf, IM_COUNTOF(buf), ImGuiInputTextFlags_CharsUppercase))
         {
             value_changed = true;
             char* p = buf;
@@ -6564,18 +6564,18 @@ void ImGui::ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags)
     {
         int cr = IM_F32_TO_INT8_SAT(col[0]), cg = IM_F32_TO_INT8_SAT(col[1]), cb = IM_F32_TO_INT8_SAT(col[2]), ca = (flags & ImGuiColorEditFlags_NoAlpha) ? 255 : IM_F32_TO_INT8_SAT(col[3]);
         char buf[64];
-        ImFormatString(buf, IM_ARRAYSIZE(buf), "(%.3ff, %.3ff, %.3ff, %.3ff)", col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]);
+        ImFormatString(buf, IM_COUNTOF(buf), "(%.3ff, %.3ff, %.3ff, %.3ff)", col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]);
         if (Selectable(buf))
             SetClipboardText(buf);
-        ImFormatString(buf, IM_ARRAYSIZE(buf), "(%d,%d,%d,%d)", cr, cg, cb, ca);
+        ImFormatString(buf, IM_COUNTOF(buf), "(%d,%d,%d,%d)", cr, cg, cb, ca);
         if (Selectable(buf))
             SetClipboardText(buf);
-        ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", cr, cg, cb);
+        ImFormatString(buf, IM_COUNTOF(buf), "#%02X%02X%02X", cr, cg, cb);
         if (Selectable(buf))
             SetClipboardText(buf);
         if (!(flags & ImGuiColorEditFlags_NoAlpha))
         {
-            ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X%02X", cr, cg, cb, ca);
+            ImFormatString(buf, IM_COUNTOF(buf), "#%02X%02X%02X%02X", cr, cg, cb, ca);
             if (Selectable(buf))
                 SetClipboardText(buf);
         }
@@ -7528,7 +7528,7 @@ ImGuiTypingSelectRequest* ImGui::GetTypingSelectRequest(ImGuiTypingSelectFlags f
     }
 
     // Append to buffer
-    const int buffer_max_len = IM_ARRAYSIZE(data->SearchBuffer) - 1;
+    const int buffer_max_len = IM_COUNTOF(data->SearchBuffer) - 1;
     int buffer_len = (int)ImStrlen(data->SearchBuffer);
     bool select_request = false;
     for (ImWchar w : g.IO.InputQueueCharacters)
@@ -8928,7 +8928,7 @@ void ImGui::Value(const char* prefix, float v, const char* float_format)
     if (float_format)
     {
         char fmt[64];
-        ImFormatString(fmt, IM_ARRAYSIZE(fmt), "%%s: %s", float_format);
+        ImFormatString(fmt, IM_COUNTOF(fmt), "%%s: %s", float_format);
         Text(fmt, prefix, v);
     }
     else
@@ -8967,7 +8967,7 @@ void ImGuiMenuColumns::CalcNextTotalWidth(bool update_offsets)
 {
     ImU16 offset = 0;
     bool want_spacing = false;
-    for (int i = 0; i < IM_ARRAYSIZE(Widths); i++)
+    for (int i = 0; i < IM_COUNTOF(Widths); i++)
     {
         ImU16 width = Widths[i];
         if (want_spacing && width > 0)