Refactor: Moved Text functions from imgui.cpp to imgui_widgets.cpp (#2036)
diff --git a/imgui.cpp b/imgui.cpp
index e2a4c4d..1025951 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -7871,177 +7871,6 @@
     return window->DC.StateStorage;
 }
 
-void ImGui::TextV(const char* fmt, va_list args)
-{
-    ImGuiWindow* window = GetCurrentWindow();
-    if (window->SkipItems)
-        return;
-
-    ImGuiContext& g = *GImGui;
-    const char* text_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
-    TextUnformatted(g.TempBuffer, text_end);
-}
-
-void ImGui::Text(const char* fmt, ...)
-{
-    va_list args;
-    va_start(args, fmt);
-    TextV(fmt, args);
-    va_end(args);
-}
-
-void ImGui::TextColoredV(const ImVec4& col, const char* fmt, va_list args)
-{
-    PushStyleColor(ImGuiCol_Text, col);
-    TextV(fmt, args);
-    PopStyleColor();
-}
-
-void ImGui::TextColored(const ImVec4& col, const char* fmt, ...)
-{
-    va_list args;
-    va_start(args, fmt);
-    TextColoredV(col, fmt, args);
-    va_end(args);
-}
-
-void ImGui::TextDisabledV(const char* fmt, va_list args)
-{
-    PushStyleColor(ImGuiCol_Text, GImGui->Style.Colors[ImGuiCol_TextDisabled]);
-    TextV(fmt, args);
-    PopStyleColor();
-}
-
-void ImGui::TextDisabled(const char* fmt, ...)
-{
-    va_list args;
-    va_start(args, fmt);
-    TextDisabledV(fmt, args);
-    va_end(args);
-}
-
-void ImGui::TextWrappedV(const char* fmt, va_list args)
-{
-    bool need_wrap = (GImGui->CurrentWindow->DC.TextWrapPos < 0.0f);    // Keep existing wrap position is one ia already set
-    if (need_wrap) PushTextWrapPos(0.0f);
-    TextV(fmt, args);
-    if (need_wrap) PopTextWrapPos();
-}
-
-void ImGui::TextWrapped(const char* fmt, ...)
-{
-    va_list args;
-    va_start(args, fmt);
-    TextWrappedV(fmt, args);
-    va_end(args);
-}
-
-void ImGui::TextUnformatted(const char* text, const char* text_end)
-{
-    ImGuiWindow* window = GetCurrentWindow();
-    if (window->SkipItems)
-        return;
-
-    ImGuiContext& g = *GImGui;
-    IM_ASSERT(text != NULL);
-    const char* text_begin = text;
-    if (text_end == NULL)
-        text_end = text + strlen(text); // FIXME-OPT
-
-    const ImVec2 text_pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrentLineTextBaseOffset);
-    const float wrap_pos_x = window->DC.TextWrapPos;
-    const bool wrap_enabled = wrap_pos_x >= 0.0f;
-    if (text_end - text > 2000 && !wrap_enabled)
-    {
-        // Long text!
-        // Perform manual coarse clipping to optimize for long multi-line text
-        // From this point we will only compute the width of lines that are visible. Optimization only available when word-wrapping is disabled.
-        // We also don't vertically center the text within the line full height, which is unlikely to matter because we are likely the biggest and only item on the line.
-        const char* line = text;
-        const float line_height = GetTextLineHeight();
-        const ImRect clip_rect = window->ClipRect;
-        ImVec2 text_size(0,0);
-
-        if (text_pos.y <= clip_rect.Max.y)
-        {
-            ImVec2 pos = text_pos;
-
-            // Lines to skip (can't skip when logging text)
-            if (!g.LogEnabled)
-            {
-                int lines_skippable = (int)((clip_rect.Min.y - text_pos.y) / line_height);
-                if (lines_skippable > 0)
-                {
-                    int lines_skipped = 0;
-                    while (line < text_end && lines_skipped < lines_skippable)
-                    {
-                        const char* line_end = strchr(line, '\n');
-                        if (!line_end)
-                            line_end = text_end;
-                        line = line_end + 1;
-                        lines_skipped++;
-                    }
-                    pos.y += lines_skipped * line_height;
-                }
-            }
-
-            // Lines to render
-            if (line < text_end)
-            {
-                ImRect line_rect(pos, pos + ImVec2(FLT_MAX, line_height));
-                while (line < text_end)
-                {
-                    const char* line_end = strchr(line, '\n');
-                    if (IsClippedEx(line_rect, 0, false))
-                        break;
-
-                    const ImVec2 line_size = CalcTextSize(line, line_end, false);
-                    text_size.x = ImMax(text_size.x, line_size.x);
-                    RenderText(pos, line, line_end, false);
-                    if (!line_end)
-                        line_end = text_end;
-                    line = line_end + 1;
-                    line_rect.Min.y += line_height;
-                    line_rect.Max.y += line_height;
-                    pos.y += line_height;
-                }
-
-                // Count remaining lines
-                int lines_skipped = 0;
-                while (line < text_end)
-                {
-                    const char* line_end = strchr(line, '\n');
-                    if (!line_end)
-                        line_end = text_end;
-                    line = line_end + 1;
-                    lines_skipped++;
-                }
-                pos.y += lines_skipped * line_height;
-            }
-
-            text_size.y += (pos - text_pos).y;
-        }
-
-        ImRect bb(text_pos, text_pos + text_size);
-        ItemSize(bb);
-        ItemAdd(bb, 0);
-    }
-    else
-    {
-        const float wrap_width = wrap_enabled ? CalcWrapWidthForPos(window->DC.CursorPos, wrap_pos_x) : 0.0f;
-        const ImVec2 text_size = CalcTextSize(text_begin, text_end, false, wrap_width);
-
-        // Account of baseline offset
-        ImRect bb(text_pos, text_pos + text_size);
-        ItemSize(text_size);
-        if (!ItemAdd(bb, 0))
-            return;
-
-        // Render (we don't hide text after ## in this end-user function)
-        RenderTextWrapped(bb.Min, text_begin, text_end, wrap_width);
-    }
-}
-
 void ImGui::AlignTextToFramePadding()
 {
     ImGuiWindow* window = GetCurrentWindow();
@@ -8053,40 +7882,6 @@
     window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.CurrentLineTextBaseOffset, g.Style.FramePadding.y);
 }
 
-// Add a label+text combo aligned to other label+value widgets
-void ImGui::LabelTextV(const char* label, const char* fmt, va_list args)
-{
-    ImGuiWindow* window = GetCurrentWindow();
-    if (window->SkipItems)
-        return;
-
-    ImGuiContext& g = *GImGui;
-    const ImGuiStyle& style = g.Style;
-    const float w = CalcItemWidth();
-
-    const ImVec2 label_size = CalcTextSize(label, NULL, true);
-    const ImRect value_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2));
-    const ImRect total_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w + (label_size.x > 0.0f ? style.ItemInnerSpacing.x : 0.0f), style.FramePadding.y*2) + label_size);
-    ItemSize(total_bb, style.FramePadding.y);
-    if (!ItemAdd(total_bb, 0))
-        return;
-
-    // Render
-    const char* value_text_begin = &g.TempBuffer[0];
-    const char* value_text_end = value_text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
-    RenderTextClipped(value_bb.Min, value_bb.Max, value_text_begin, value_text_end, NULL, ImVec2(0.0f,0.5f));
-    if (label_size.x > 0.0f)
-        RenderText(ImVec2(value_bb.Max.x + style.ItemInnerSpacing.x, value_bb.Min.y + style.FramePadding.y), label);
-}
-
-void ImGui::LabelText(const char* label, const char* fmt, ...)
-{
-    va_list args;
-    va_start(args, fmt);
-    LabelTextV(label, fmt, args);
-    va_end(args);
-}
-
 bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags)
 {
     ImGuiContext& g = *GImGui;
@@ -8979,39 +8774,6 @@
     SameLine(0, style.FramePadding.x*2);
 }
 
-// Text with a little bullet aligned to the typical tree node.
-void ImGui::BulletTextV(const char* fmt, va_list args)
-{
-    ImGuiWindow* window = GetCurrentWindow();
-    if (window->SkipItems)
-        return;
-
-    ImGuiContext& g = *GImGui;
-    const ImGuiStyle& style = g.Style;
-
-    const char* text_begin = g.TempBuffer;
-    const char* text_end = text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
-    const ImVec2 label_size = CalcTextSize(text_begin, text_end, false);
-    const float text_base_offset_y = ImMax(0.0f, window->DC.CurrentLineTextBaseOffset); // Latch before ItemSize changes it
-    const float line_height = ImMax(ImMin(window->DC.CurrentLineSize.y, g.FontSize + g.Style.FramePadding.y*2), g.FontSize);
-    const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize + (label_size.x > 0.0f ? (label_size.x + style.FramePadding.x*2) : 0.0f), ImMax(line_height, label_size.y)));  // Empty text doesn't add padding
-    ItemSize(bb);
-    if (!ItemAdd(bb, 0))
-        return;
-
-    // Render
-    RenderBullet(bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f));
-    RenderText(bb.Min+ImVec2(g.FontSize + style.FramePadding.x*2, text_base_offset_y), text_begin, text_end, false);
-}
-
-void ImGui::BulletText(const char* fmt, ...)
-{
-    va_list args;
-    va_start(args, fmt);
-    BulletTextV(fmt, args);
-    va_end(args);
-}
-
 static inline int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, const char* format)
 {
     if (data_type == ImGuiDataType_S32 || data_type == ImGuiDataType_U32)   // Signedness doesn't matter when pushing the argument
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 538b905..5ea5c3b 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -55,6 +55,243 @@
 // - BulletTextV()
 //-------------------------------------------------------------------------
 
+void ImGui::TextUnformatted(const char* text, const char* text_end)
+{
+    ImGuiWindow* window = GetCurrentWindow();
+    if (window->SkipItems)
+        return;
+
+    ImGuiContext& g = *GImGui;
+    IM_ASSERT(text != NULL);
+    const char* text_begin = text;
+    if (text_end == NULL)
+        text_end = text + strlen(text); // FIXME-OPT
+
+    const ImVec2 text_pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrentLineTextBaseOffset);
+    const float wrap_pos_x = window->DC.TextWrapPos;
+    const bool wrap_enabled = wrap_pos_x >= 0.0f;
+    if (text_end - text > 2000 && !wrap_enabled)
+    {
+        // Long text!
+        // Perform manual coarse clipping to optimize for long multi-line text
+        // From this point we will only compute the width of lines that are visible. Optimization only available when word-wrapping is disabled.
+        // We also don't vertically center the text within the line full height, which is unlikely to matter because we are likely the biggest and only item on the line.
+        const char* line = text;
+        const float line_height = GetTextLineHeight();
+        const ImRect clip_rect = window->ClipRect;
+        ImVec2 text_size(0,0);
+
+        if (text_pos.y <= clip_rect.Max.y)
+        {
+            ImVec2 pos = text_pos;
+
+            // Lines to skip (can't skip when logging text)
+            if (!g.LogEnabled)
+            {
+                int lines_skippable = (int)((clip_rect.Min.y - text_pos.y) / line_height);
+                if (lines_skippable > 0)
+                {
+                    int lines_skipped = 0;
+                    while (line < text_end && lines_skipped < lines_skippable)
+                    {
+                        const char* line_end = strchr(line, '\n');
+                        if (!line_end)
+                            line_end = text_end;
+                        line = line_end + 1;
+                        lines_skipped++;
+                    }
+                    pos.y += lines_skipped * line_height;
+                }
+            }
+
+            // Lines to render
+            if (line < text_end)
+            {
+                ImRect line_rect(pos, pos + ImVec2(FLT_MAX, line_height));
+                while (line < text_end)
+                {
+                    const char* line_end = strchr(line, '\n');
+                    if (IsClippedEx(line_rect, 0, false))
+                        break;
+
+                    const ImVec2 line_size = CalcTextSize(line, line_end, false);
+                    text_size.x = ImMax(text_size.x, line_size.x);
+                    RenderText(pos, line, line_end, false);
+                    if (!line_end)
+                        line_end = text_end;
+                    line = line_end + 1;
+                    line_rect.Min.y += line_height;
+                    line_rect.Max.y += line_height;
+                    pos.y += line_height;
+                }
+
+                // Count remaining lines
+                int lines_skipped = 0;
+                while (line < text_end)
+                {
+                    const char* line_end = strchr(line, '\n');
+                    if (!line_end)
+                        line_end = text_end;
+                    line = line_end + 1;
+                    lines_skipped++;
+                }
+                pos.y += lines_skipped * line_height;
+            }
+
+            text_size.y += (pos - text_pos).y;
+        }
+
+        ImRect bb(text_pos, text_pos + text_size);
+        ItemSize(bb);
+        ItemAdd(bb, 0);
+    }
+    else
+    {
+        const float wrap_width = wrap_enabled ? CalcWrapWidthForPos(window->DC.CursorPos, wrap_pos_x) : 0.0f;
+        const ImVec2 text_size = CalcTextSize(text_begin, text_end, false, wrap_width);
+
+        // Account of baseline offset
+        ImRect bb(text_pos, text_pos + text_size);
+        ItemSize(text_size);
+        if (!ItemAdd(bb, 0))
+            return;
+
+        // Render (we don't hide text after ## in this end-user function)
+        RenderTextWrapped(bb.Min, text_begin, text_end, wrap_width);
+    }
+}
+
+void ImGui::Text(const char* fmt, ...)
+{
+    va_list args;
+    va_start(args, fmt);
+    TextV(fmt, args);
+    va_end(args);
+}
+
+void ImGui::TextV(const char* fmt, va_list args)
+{
+    ImGuiWindow* window = GetCurrentWindow();
+    if (window->SkipItems)
+        return;
+
+    ImGuiContext& g = *GImGui;
+    const char* text_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
+    TextUnformatted(g.TempBuffer, text_end);
+}
+
+void ImGui::TextColored(const ImVec4& col, const char* fmt, ...)
+{
+    va_list args;
+    va_start(args, fmt);
+    TextColoredV(col, fmt, args);
+    va_end(args);
+}
+
+void ImGui::TextColoredV(const ImVec4& col, const char* fmt, va_list args)
+{
+    PushStyleColor(ImGuiCol_Text, col);
+    TextV(fmt, args);
+    PopStyleColor();
+}
+
+void ImGui::TextDisabled(const char* fmt, ...)
+{
+    va_list args;
+    va_start(args, fmt);
+    TextDisabledV(fmt, args);
+    va_end(args);
+}
+
+void ImGui::TextDisabledV(const char* fmt, va_list args)
+{
+    PushStyleColor(ImGuiCol_Text, GImGui->Style.Colors[ImGuiCol_TextDisabled]);
+    TextV(fmt, args);
+    PopStyleColor();
+}
+
+void ImGui::TextWrapped(const char* fmt, ...)
+{
+    va_list args;
+    va_start(args, fmt);
+    TextWrappedV(fmt, args);
+    va_end(args);
+}
+
+void ImGui::TextWrappedV(const char* fmt, va_list args)
+{
+    bool need_wrap = (GImGui->CurrentWindow->DC.TextWrapPos < 0.0f);    // Keep existing wrap position is one ia already set
+    if (need_wrap) PushTextWrapPos(0.0f);
+    TextV(fmt, args);
+    if (need_wrap) PopTextWrapPos();
+}
+
+void ImGui::LabelText(const char* label, const char* fmt, ...)
+{
+    va_list args;
+    va_start(args, fmt);
+    LabelTextV(label, fmt, args);
+    va_end(args);
+}
+
+// Add a label+text combo aligned to other label+value widgets
+void ImGui::LabelTextV(const char* label, const char* fmt, va_list args)
+{
+    ImGuiWindow* window = GetCurrentWindow();
+    if (window->SkipItems)
+        return;
+
+    ImGuiContext& g = *GImGui;
+    const ImGuiStyle& style = g.Style;
+    const float w = CalcItemWidth();
+
+    const ImVec2 label_size = CalcTextSize(label, NULL, true);
+    const ImRect value_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2));
+    const ImRect total_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w + (label_size.x > 0.0f ? style.ItemInnerSpacing.x : 0.0f), style.FramePadding.y*2) + label_size);
+    ItemSize(total_bb, style.FramePadding.y);
+    if (!ItemAdd(total_bb, 0))
+        return;
+
+    // Render
+    const char* value_text_begin = &g.TempBuffer[0];
+    const char* value_text_end = value_text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
+    RenderTextClipped(value_bb.Min, value_bb.Max, value_text_begin, value_text_end, NULL, ImVec2(0.0f,0.5f));
+    if (label_size.x > 0.0f)
+        RenderText(ImVec2(value_bb.Max.x + style.ItemInnerSpacing.x, value_bb.Min.y + style.FramePadding.y), label);
+}
+
+void ImGui::BulletText(const char* fmt, ...)
+{
+    va_list args;
+    va_start(args, fmt);
+    BulletTextV(fmt, args);
+    va_end(args);
+}
+
+// Text with a little bullet aligned to the typical tree node.
+void ImGui::BulletTextV(const char* fmt, va_list args)
+{
+    ImGuiWindow* window = GetCurrentWindow();
+    if (window->SkipItems)
+        return;
+
+    ImGuiContext& g = *GImGui;
+    const ImGuiStyle& style = g.Style;
+
+    const char* text_begin = g.TempBuffer;
+    const char* text_end = text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
+    const ImVec2 label_size = CalcTextSize(text_begin, text_end, false);
+    const float text_base_offset_y = ImMax(0.0f, window->DC.CurrentLineTextBaseOffset); // Latch before ItemSize changes it
+    const float line_height = ImMax(ImMin(window->DC.CurrentLineSize.y, g.FontSize + g.Style.FramePadding.y*2), g.FontSize);
+    const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize + (label_size.x > 0.0f ? (label_size.x + style.FramePadding.x*2) : 0.0f), ImMax(line_height, label_size.y)));  // Empty text doesn't add padding
+    ItemSize(bb);
+    if (!ItemAdd(bb, 0))
+        return;
+
+    // Render
+    RenderBullet(bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f));
+    RenderText(bb.Min+ImVec2(g.FontSize + style.FramePadding.x*2, text_base_offset_y), text_begin, text_end, false);
+}
 
 //-------------------------------------------------------------------------
 // WIDGETS: Main