From patchwork Sun Jul 5 21:04:01 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Palka X-Patchwork-Id: 7523 Received: (qmail 66176 invoked by alias); 5 Jul 2015 21:04:22 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 66090 invoked by uid 89); 5 Jul 2015 21:04:21 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.3 required=5.0 tests=AWL, BAYES_50, KAM_LAZY_DOMAIN_SECURITY, RCVD_IN_DNSWL_LOW autolearn=no version=3.3.2 X-HELO: mail-qg0-f45.google.com Received: from mail-qg0-f45.google.com (HELO mail-qg0-f45.google.com) (209.85.192.45) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Sun, 05 Jul 2015 21:04:19 +0000 Received: by qget71 with SMTP id t71so61858311qge.2 for ; Sun, 05 Jul 2015 14:04:17 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=ikEqMHrCl85Dw0bxtN3scOhV14gY6S18J71md0QyhGM=; b=f20qfIA9deGib3yTVhAbjdj9mOCSjTHgLlt7mf66wwOozqdzYsewPBh/Rp3pKrkPxb cBz5sCqGl8HMRvyxvcwmNZWz+Xd67gGQbDOj3ge4LIXaX2B7rwPxKJDgfWNeDNDMfXKL +cObhtE9Bd7RKnur012PGCR2zuyo6kwLVNxTsfewvSc1sbAY6M/p2YTFxz7mEeCB52zo dHveGlMvO4pJ97nFFmwyqAL/XBgAO/fGVYkI9AT7D5ag/J8KFneJbuT5HoXfWsJYbaie XgC7GUVvdHM+h/uxJ3WOXHxeyZSAqHa/DYTghZGYzIoABJopQDTEIe+rb76gH14XDI5n qnHA== X-Gm-Message-State: ALoCoQndoLHQ861IRPe1K/FuPD/C/+agwb/kixfhUJlB/+KDCqIB9zcwkfnyY9a49P9fF1Jo+7Wa X-Received: by 10.140.234.1 with SMTP id f1mr68598137qhc.48.1436130257192; Sun, 05 Jul 2015 14:04:17 -0700 (PDT) Received: from localhost.localdomain (ool-4353acd8.dyn.optonline.net. [67.83.172.216]) by mx.google.com with ESMTPSA id 131sm8181073qhf.14.2015.07.05.14.04.16 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 05 Jul 2015 14:04:16 -0700 (PDT) From: Patrick Palka To: gdb-patches@sourceware.org Cc: Patrick Palka Subject: [PATCH 5/5] tui: maintain a scrollback buffer and dump it upon exit (PR tui/14584) Date: Sun, 5 Jul 2015 17:04:01 -0400 Message-Id: <1436130241-21443-5-git-send-email-patrick@parcs.ath.cx> In-Reply-To: <1436130241-21443-1-git-send-email-patrick@parcs.ath.cx> References: <1436130177-21362-1-git-send-email-patrick@parcs.ath.cx> <1436130241-21443-1-git-send-email-patrick@parcs.ath.cx> 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. */