From 69dcbe9b3081ee51d1468b1b7777b8b930bfba6c Mon Sep 17 00:00:00 2001
From: Erik Abair <erik.abair@gmail.com>
Date: Fri, 3 Jun 2022 23:11:12 -0700
Subject: [PATCH] ui: Make monitor text selectable

---
 ui/xemu-monitor.c |  4 ++--
 ui/xui/monitor.cc | 27 ++++++++++++++++++++++++++-
 2 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/ui/xemu-monitor.c b/ui/xemu-monitor.c
index a16003cae3..4018d9e397 100644
--- a/ui/xemu-monitor.c
+++ b/ui/xemu-monitor.c
@@ -35,8 +35,8 @@
 #define TYPE_CHARDEV_XEMU_MONITOR "chardev-xemu-monitor"
 
 static Chardev *mon_chr;
-static char mon_buffer[8*4096];
-static const size_t mon_buffer_size = 8*4096;
+static char mon_buffer[12*4096];
+static const size_t mon_buffer_size = sizeof(mon_buffer);
 static size_t offset;
 
 static void char_xemu_class_init(ObjectClass *oc, void *data);
diff --git a/ui/xui/monitor.cc b/ui/xui/monitor.cc
index 4566425330..d2f7039f91 100644
--- a/ui/xui/monitor.cc
+++ b/ui/xui/monitor.cc
@@ -53,7 +53,32 @@ void MonitorWindow::Draw()
 
         ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4,1)); // Tighten spacing
         ImGui::PushFont(g_font_mgr.m_fixed_width_font);
-        ImGui::TextUnformatted(xemu_get_monitor_buffer());
+
+        // FIXME: Replace scroll to bottom hack when https://github.com/ocornut/imgui/issues/1972 is resolved.
+        // ImGui does not provide any mechanism to adjust scrolling in an InputTextMultiline and does not
+        // provide any other widget that allows for selectable text.
+        char *buffer = xemu_get_monitor_buffer();
+        size_t buffer_len = strlen(buffer);
+        // Calculating the precise size will cause an unnecessary vertical scrollbar in the InputTextMultiline.
+        int num_newlines = 2;
+        const char *start = buffer;
+        while (start) {
+            start = strchr(start, '\n');
+            if (start) {
+                ++num_newlines;
+                ++start;
+            }
+        }
+        float input_height = fmax(ImGui::GetWindowHeight(),
+                                  g_font_mgr.m_fixed_width_font->FontSize * num_newlines);
+
+        ImGui::PushID("#MonitorOutput");
+        ImGui::InputTextMultiline("",
+                                  buffer,
+                                  buffer_len,
+                                  ImVec2(-1.0f, input_height),
+                                  ImGuiInputTextFlags_ReadOnly|ImGuiInputTextFlags_NoUndoRedo);
+        ImGui::PopID();
         ImGui::PopFont();
 
         if (ScrollToBottom || (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY())) {