Rewrite tui_puts
authorTom Tromey <tom@tromey.com>
Mon, 28 Sep 2020 02:30:30 +0000 (20:30 -0600)
committerTom Tromey <tom@tromey.com>
Mon, 28 Sep 2020 02:30:33 +0000 (20:30 -0600)
This rewrites tui_puts.  It now writes as many bytes as possible in a
call to waddnstr, letting curses handle multi-byte sequences properly.

Note that tui_puts_internal remains.  It is needed to handle computing
the start line of the readline prompt, which is difficult to do
properly in the case where redisplaying can also cause the command
window to scroll.  This might be possible to implement by reverting to
single "character" output, by using mbsrtowcs for its side effects to
find character boundaries in the input.  I have not attempted this.

gdb/ChangeLog
2020-09-27  Tom Tromey  <tom@tromey.com>

PR tui/25342:
* tui/tui-io.c (tui_puts): Rewrite.  Move earlier.

gdb/ChangeLog
gdb/tui/tui-io.c

index fc016aeb3456ae4dfeb5b93f6664905ff3659369..7a73f9a047f9a204c6973fb0b486c1e47b066e64 100644 (file)
@@ -1,3 +1,8 @@
+2020-09-27  Tom Tromey  <tom@tromey.com>
+
+       PR tui/25342:
+       * tui/tui-io.c (tui_puts): Rewrite.  Move earlier.
+
 2020-09-27  Tom Tromey  <tom@tromey.com>
 
        PR tui/25342:
index 7698d7903f19cfd1f70fb60d728a0c8268320f6c..1a2764e21967adcd48e360501f61af2daf8295b4 100644 (file)
@@ -435,6 +435,69 @@ tui_write (const char *buf, size_t length)
   tui_puts (copy.c_str ());
 }
 
+/* Print a string in the curses command window.  The output is
+   buffered.  It is up to the caller to refresh the screen if
+   necessary.  */
+
+void
+tui_puts (const char *string, WINDOW *w)
+{
+  if (w == nullptr)
+    w = TUI_CMD_WIN->handle.get ();
+
+  while (true)
+    {
+      const char *next = strpbrk (string, "\n\1\2\033\t");
+
+      /* Print the plain text prefix.  */
+      size_t n_chars = next == nullptr ? strlen (string) : next - string;
+      if (n_chars > 0)
+       waddnstr (w, string, n_chars);
+
+      /* We finished.  */
+      if (next == nullptr)
+       break;
+
+      char c = *next;
+      switch (c)
+       {
+       case '\1':
+       case '\2':
+         /* Ignore these, they are readline escape-marking
+            sequences.  */
+         ++next;
+         break;
+
+       case '\n':
+       case '\t':
+         do_tui_putc (w, c);
+         ++next;
+         break;
+
+       case '\033':
+         {
+           size_t bytes_read = apply_ansi_escape (w, next);
+           if (bytes_read > 0)
+             next += bytes_read;
+           else
+             {
+               /* Just drop the escape.  */
+               ++next;
+             }
+         }
+         break;
+
+       default:
+         gdb_assert_not_reached ("missing case in tui_puts");
+       }
+
+      string = next;
+    }
+
+  if (TUI_CMD_WIN != nullptr && w == TUI_CMD_WIN->handle.get ())
+    update_cmdwin_start_line ();
+}
+
 static void
 tui_puts_internal (WINDOW *w, const char *string, int *height)
 {
@@ -480,18 +543,6 @@ tui_puts_internal (WINDOW *w, const char *string, int *height)
     wrefresh (w);
 }
 
-/* Print a string in the curses command window.  The output is
-   buffered.  It is up to the caller to refresh the screen if
-   necessary.  */
-
-void
-tui_puts (const char *string, WINDOW *w)
-{
-  if (w == nullptr)
-    w = TUI_CMD_WIN->handle.get ();
-  tui_puts_internal (w, string, nullptr);
-}
-
 /* Readline callback.
    Redisplay the command line with its prompt after readline has
    changed the edited text.  */
This page took 0.03406 seconds and 4 git commands to generate.