From patchwork Wed Aug 26 01:06:13 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Palka X-Patchwork-Id: 8445 Received: (qmail 91889 invoked by alias); 26 Aug 2015 01:06:26 -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 91816 invoked by uid 89); 26 Aug 2015 01:06:26 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.5 required=5.0 tests=AWL, BAYES_00, KAM_LAZY_DOMAIN_SECURITY, RCVD_IN_DNSWL_LOW autolearn=no version=3.3.2 X-HELO: mail-qg0-f52.google.com Received: from mail-qg0-f52.google.com (HELO mail-qg0-f52.google.com) (209.85.192.52) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Wed, 26 Aug 2015 01:06:23 +0000 Received: by qgeg42 with SMTP id g42so118221925qge.1 for ; Tue, 25 Aug 2015 18:06:21 -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=srBiT//w2+MNbDByxbI9FswO0o/oq8K/r1rWrN8v2z0=; b=CeZlxAAwW8T7xCgZU2FaZdMRndn8oBF2XhvAsTBoeB7GQpH3pTaj30T5XWs9MtSJLd dd7k1qELmKIls5L0zmtEI1bAAaMXo9u+8XU2qirKu01bbs4qDHKzbvHPrxoV4UyYTZ4/ d4eKDMCMdcbPAQ5JXDuPhT6DS9tnI8tHcfYLkILexNLlDh6KqChVyIZ5TMC3M/NtKI2S VozyazXePCSAByvo686zugUHdCXpzK5sRiXlxkBUmpuutxsfola/T5S5RDXQpQICPO0/ 8dX8hMFR62ehDmTXXjWrthyZLHOK8lXwdpo5CobqT22QW1siYa8elu7zZTEG/UQKp6qu 6W5A== X-Gm-Message-State: ALoCoQnGDZB9H0PKuXiE8bY7l33AJP/N/jtN95CEWCXQr+Hx0cCLgY6WGAObUtvq73ahcDb2paSV X-Received: by 10.140.133.84 with SMTP id 81mr76195350qhf.13.1440551181214; Tue, 25 Aug 2015 18:06:21 -0700 (PDT) Received: from localhost.localdomain (ool-4353acd8.dyn.optonline.net. [67.83.172.216]) by smtp.gmail.com with ESMTPSA id f9sm7504787qhe.7.2015.08.25.18.06.20 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 25 Aug 2015 18:06:20 -0700 (PDT) From: Patrick Palka To: gdb-patches@sourceware.org Cc: Patrick Palka Subject: [PATCH 2/2] tui: maintain a scrollback buffer and dump it upon exit (PR tui/14584) Date: Tue, 25 Aug 2015 21:06:13 -0400 Message-Id: <1440551173-18266-2-git-send-email-patrick@parcs.ath.cx> In-Reply-To: <1440551173-18266-1-git-send-email-patrick@parcs.ath.cx> References: <1440551173-18266-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 and 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.) When the TUI is disabled, the buffer gets dumped and then cleared. [ 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. Though such an approach and the approach this patch takes are not mutually exclusive anyway. ] 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 | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ gdb/tui/tui-io.h | 5 +++++ gdb/tui/tui.c | 3 +++ 3 files changed, 66 insertions(+) diff --git a/gdb/tui/tui-io.c b/gdb/tui/tui-io.c index 311c96c..b3376ac 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,56 @@ 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 the current cursor position (CUR_LINE, CUR_X), 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 = getcury (w); + const int cur_x = getcurx (w); + const int max_x = getmaxx (w); + int i, j, k; + char *line; + + wmove (w, cur_line, cur_x); + + /* Allocate enough space to hold the entire (possibly wrapped) line. */ + line = xcalloc ((cur_line - start_line) * max_x + cur_x + 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 < cur_x; i++) + line[k++] = mvwinch (w, cur_line, i); + line[k++] = '\0'; + + VEC_safe_push (char_ptr, tui_scrollback_buffer, line); + wmove (w, cur_line, cur_x); +} + /* 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 +227,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. */