This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 5/5] tui: maintain a scrollback buffer and dump it upon exit (PR tui/14584)


It is currently impossible to scroll through the text emitted in the
TUI's command window.  If some output leaves the top of the window then it
is effectively gone forever.

This patch attempts to laterally work around this deficiency not by
implementing command-window scrolling within the TUI, but rather by
accumulating a scrollback buffer of command-window output while the TUI
is active and dumping it into the CLI when the TUI gets disabled.  So
when the user wants to scroll through the output emitted under the TUI,
with this patch the user can just temporarily switch to the CLI
(triggering the verbatim dumping of the window's contents) and then use
their terminal emulator/multiplexer to scroll/search through the output
as if it came from the CLI itself.  This gives the impression that the
TUI command-window and the CLI output are unified (although the
synchronization only goes one way).

The implementation is pretty straightforward.  Whenever a newline is
emitted in the command window, the current line gets copied from the
screen into a scrollback buffer.  (Care must be taken to account for
long, wrapped lines.  Now that start_line is always valid, this is easy
enough.)  And when the TUI is disabled, the buffer is dumped and emptied
verbatim.

Is this a good approach to addressing the lack of scrolling capabilities
in the TUI command window?  I don't see much advantage to having a
direct implementation of command-window scrolling compared to this
approach of piggybacking on the underlying terminal
emulator/multiplexer.

gdb/ChangeLog:

	* tui/tui-io.h (tui_dump_scrollback_buffer): Declare.
	* tui/tui-io.c (tui_dump_scrollback_buffer): Define.
	(tui_scrollback_buffer): Define.
	(tui_add_current_line_to_scrollback_buffer): Define.
	(tui_puts): Call it before emitting a newline.
	* tui/tui.c (tui_disable): Call tui_dump_scrollback_buffer.
---
 gdb/tui/tui-io.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/tui/tui-io.h |  5 +++++
 gdb/tui/tui.c    |  3 +++
 3 files changed, 65 insertions(+)

diff --git a/gdb/tui/tui-io.c b/gdb/tui/tui-io.c
index 9302391..c3718be 100644
--- a/gdb/tui/tui-io.c
+++ b/gdb/tui/tui-io.c
@@ -132,6 +132,11 @@ static FILE *tui_old_rl_outstream;
 static int tui_readline_pipe[2];
 #endif
 
+/* The scrollback buffer containing a line-by-line copy of all that's been
+   outputted to the command window during the current TUI session.  */
+
+static VEC (char_ptr) *tui_scrollback_buffer = NULL;
+
 /* The last gdb prompt that was registered in readline.
    This may be the main gdb prompt or a secondary prompt.  */
 static char *tui_rl_saved_prompt;
@@ -146,6 +151,55 @@ tui_putc (char c)
   tui_puts (buf);
 }
 
+/* See tui-io.h.  */
+
+void
+tui_dump_scrollback_buffer (void)
+{
+  int i;
+  for (i = 0; i < VEC_length (char_ptr, tui_scrollback_buffer); i++)
+    {
+      char *line = VEC_index (char_ptr, tui_scrollback_buffer, i);
+      fputs_unfiltered (line, gdb_stdout);
+      fputc_unfiltered ('\n', gdb_stdout);
+      xfree (line);
+    }
+
+  VEC_free (char_ptr, tui_scrollback_buffer);
+}
+
+/* Copy the current line, delimited by the screen coordinates
+   (START_LINE, 0) to (CUR_LINE, CURCH), to the scrollback buffer.  */
+
+static void
+tui_add_current_line_to_scrollback_buffer (void)
+{
+  WINDOW *w = TUI_CMD_WIN->generic.handle;
+  const int start_line = TUI_CMD_WIN->detail.command_info.start_line;
+  const int cur_line = TUI_CMD_WIN->detail.command_info.cur_line;
+  const int curch = TUI_CMD_WIN->detail.command_info.curch;
+  const int max_x = getmaxx (w);
+  int i, j, k;
+  char *line;
+
+  wmove (w, cur_line, curch);
+
+  /* Allocate enough space to hold the entire (possibly wrapped) line.  */
+  line = xcalloc ((cur_line - start_line) * max_x + curch + 2, sizeof (*line));
+
+  k = 0;
+  for (j = start_line; j < cur_line; j++)
+    for (i = 0; i < max_x; i++)
+      line[k++] = mvwinch (w, j, i);
+
+  for (i = 0; i < curch; i++)
+    line[k++] = mvwinch (w, cur_line, i);
+  line[k++] = '\0';
+
+  VEC_safe_push (char_ptr, tui_scrollback_buffer, line);
+  wmove (w, cur_line, curch);
+}
+
 /* Print the string in the curses command window.
    The output is buffered.  It is up to the caller to refresh the screen
    if necessary.  */
@@ -172,6 +226,9 @@ tui_puts (const char *string)
 
           tui_skip_line = -1;
 
+	  if (c == '\n')
+	    tui_add_current_line_to_scrollback_buffer ();
+
 	  getyx (w, prev_line, prev_col);
 
 	  /* Expand TABs, since ncurses on MS-Windows doesn't.  */
diff --git a/gdb/tui/tui-io.h b/gdb/tui/tui-io.h
index 3154eee..e61ed14 100644
--- a/gdb/tui/tui-io.h
+++ b/gdb/tui/tui-io.h
@@ -44,6 +44,11 @@ extern void tui_redisplay_readline (void);
 /* Expand TABs into spaces.  */
 extern char *tui_expand_tabs (const char *, int);
 
+/* Emit the scrollback buffer accumulated by the command window in its
+   entirety, and then clear it.  */
+
+extern void tui_dump_scrollback_buffer (void);
+
 extern struct ui_out *tui_out;
 extern struct ui_out *tui_old_uiout;
 
diff --git a/gdb/tui/tui.c b/gdb/tui/tui.c
index 838471d..69ed60b 100644
--- a/gdb/tui/tui.c
+++ b/gdb/tui/tui.c
@@ -538,6 +538,9 @@ tui_disable (void)
 
   tui_active = 0;
   tui_update_gdb_sizes ();
+
+  /* Dump the command window's scrollback buffer.  */
+  tui_dump_scrollback_buffer ();
 }
 
 /* Command wrapper for enabling tui mode.  */
-- 
2.5.0.rc0.5.g91e10c5.dirty


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]