public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 0/7] TUI command changes, including new winwidth command
@ 2022-01-28 15:55 Andrew Burgess
  2022-01-28 15:55 ` [PATCH 1/7] gdb/tui: add window width information to 'info win' output Andrew Burgess
                   ` (8 more replies)
  0 siblings, 9 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-01-28 15:55 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

I'm working on a patch to improve the TUI's window sizing and resizing
behaviour.  That's still a work in progress.  But, as part of that
work I needed to add support for resizing the width of a window.

Given that we have horizontal window layout support, I think it makes
sense to have this functionality whether or not I finish my bigger
window resizing work.

The highlights from this series are:

  1. Add width information to 'info win' output,

  2. Move some commands under the top-level 'tui' command, but add
     aliases so the old names still work,

  3. Add a new 'winwidth' command.


---

Andrew Burgess (7):
  gdb/tui: add window width information to 'info win' output
  gdb/doc: update docs for 'info win' and 'winheight' commands
  gdb: move some commands into the tui namespace
  gdb/tui: rename tui_layout_base::adjust_size to ::set_height
  gdb/tui: rename tui_layout_split:set_weights_from_heights
  gdb/testing/tui: add new functionality to tuiterm.exp
  gdb/tui: add new 'tui window width' command and 'winwidth' alias

 gdb/NEWS                           |  25 +++++
 gdb/doc/gdb.texinfo                |  43 ++++++---
 gdb/testsuite/gdb.tui/info-win.exp |  61 ++++++++++++
 gdb/testsuite/gdb.tui/winwidth.exp |  62 +++++++++++++
 gdb/testsuite/lib/tuiterm.exp      |  54 ++++++++++-
 gdb/tui/tui-layout.c               |  50 +++++++---
 gdb/tui/tui-layout.h               | 115 +++++++++++++++++++++--
 gdb/tui/tui-win.c                  | 143 +++++++++++++++++++++++++----
 8 files changed, 504 insertions(+), 49 deletions(-)
 create mode 100644 gdb/testsuite/gdb.tui/info-win.exp
 create mode 100644 gdb/testsuite/gdb.tui/winwidth.exp

-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCH 1/7] gdb/tui: add window width information to 'info win' output
  2022-01-28 15:55 [PATCH 0/7] TUI command changes, including new winwidth command Andrew Burgess
@ 2022-01-28 15:55 ` Andrew Burgess
  2022-01-28 17:00   ` Eli Zaretskii
  2022-02-06 13:43   ` Andrew Burgess
  2022-01-28 15:55 ` [PATCH 2/7] gdb/doc: update docs for 'info win' and 'winheight' commands Andrew Burgess
                   ` (7 subsequent siblings)
  8 siblings, 2 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-01-28 15:55 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

Now that we support horizontal window placement in the tui, it makes
sense to have 'info win' include the width, as well as the height, of
the currently visible windows.

That's what this commit does.  Example output is now:

  (gdb) info win
  Name       Lines Columns Focus
  src           12      40 (has focus)
  asm           12      41
  status         1      80
  cmd           11      80

I've added a NEWS entry, but the documentation was already suitably
vague, it just says that 'info win' displays the size of the visible
windows, so I don't think anything needs to be added there.

I've also added some tests, as far as I could find, the 'info win'
command was previously untested.
---
 gdb/NEWS                           |  4 ++
 gdb/testsuite/gdb.tui/info-win.exp | 61 ++++++++++++++++++++++++++++++
 gdb/tui/tui-win.c                  |  4 +-
 3 files changed, 68 insertions(+), 1 deletion(-)
 create mode 100644 gdb/testsuite/gdb.tui/info-win.exp

diff --git a/gdb/NEWS b/gdb/NEWS
index e1900596ca7..8da68c88def 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -102,6 +102,10 @@ show debug lin-lwp
   debug linux-nat' and 'show debug linux-nat' should be used
   instead.
 
+info win
+  This command now includes information about the width of the tui
+  windows in its output.
+
 * Python API
 
   ** New function gdb.add_history(), which takes a gdb.Value object
diff --git a/gdb/testsuite/gdb.tui/info-win.exp b/gdb/testsuite/gdb.tui/info-win.exp
new file mode 100644
index 00000000000..2607d5be493
--- /dev/null
+++ b/gdb/testsuite/gdb.tui/info-win.exp
@@ -0,0 +1,61 @@
+# Copyright 2022 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test 'info win'.
+
+tuiterm_env
+
+standard_testfile
+
+Term::clean_restart 24 80
+
+if {![Term::enter_tui]} {
+    unsupported "TUI not supported"
+    return
+}
+
+Term::command "layout src"
+Term::command "info win"
+Term::check_region_contents "info win, layout src" \
+    0 16 80 8 [multi_line "info win\\s+" \
+		   "Name\\s+Lines\\s+Columns\\s+Focus\\s+" \
+		   "src\\s+15\\s+80\\s+\\(has focus\\)\\s+" \
+		   "status\\s+1\\s+80\\s+" \
+		   "cmd\\s+8\\s+80\\s+"]
+
+Term::command "tui new-layout h { -horizontal src 1 asm 1 } 1 status 0 cmd 1"
+Term::command "layout h"
+Term::command "winheight cmd + 3"
+
+# As the tuiterm.exp library just waits for the prompt and command to
+# be echo'ed bcak to the screen, multiple 'info win' calls like this
+# have a problem.  Dejagnu will send the command to gdb, but will then
+# immediately see the '(gdb) info win' output from the first use
+# above.  This means we end up rushing ahead, and some tests might
+# fail.
+#
+# To work around this, I'm sending a unique command 'p 1' here, that
+# only happens after the second 'info win' call.  When the 'p 1'
+# completes, I know the second 'info win' has also completed.
+Term::command "info win"
+Term::command "p 1"
+
+Term::check_region_contents "info win, layout h" \
+    0 13 80 11 [multi_line "info win\\s+" \
+		   "Name\\s+Lines\\s+Columns\\s+Focus\\s+" \
+		   "src\\s+12\\s+40\\s+\\(has focus\\)\\s+" \
+		   "asm\\s+12\\s+41\\s+" \
+		   "status\\s+1\\s+80\\s+" \
+		   "cmd\\s+11\\s+80\\s+"]
diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c
index c85dfd4e882..fd6ca59a728 100644
--- a/gdb/tui/tui-win.c
+++ b/gdb/tui/tui-win.c
@@ -714,9 +714,10 @@ tui_all_windows_info (const char *arg, int from_tty)
   struct tui_win_info *win_with_focus = tui_win_with_focus ();
   struct ui_out *uiout = current_uiout;
 
-  ui_out_emit_table table_emitter (uiout, 3, -1, "tui-windows");
+  ui_out_emit_table table_emitter (uiout, 4, -1, "tui-windows");
   uiout->table_header (10, ui_left, "name", "Name");
   uiout->table_header (5, ui_right, "lines", "Lines");
+  uiout->table_header (7, ui_right, "columns", "Columns");
   uiout->table_header (10, ui_left, "focus", "Focus");
   uiout->table_body ();
 
@@ -727,6 +728,7 @@ tui_all_windows_info (const char *arg, int from_tty)
 
 	uiout->field_string ("name", win_info->name ());
 	uiout->field_signed ("lines", win_info->height);
+	uiout->field_signed ("columns", win_info->width);
 	if (win_with_focus == win_info)
 	  uiout->field_string ("focus", _("(has focus)"));
 	else
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCH 2/7] gdb/doc: update docs for 'info win' and 'winheight' commands
  2022-01-28 15:55 [PATCH 0/7] TUI command changes, including new winwidth command Andrew Burgess
  2022-01-28 15:55 ` [PATCH 1/7] gdb/tui: add window width information to 'info win' output Andrew Burgess
@ 2022-01-28 15:55 ` Andrew Burgess
  2022-01-28 17:03   ` Eli Zaretskii
  2022-01-28 15:55 ` [PATCH 3/7] gdb: move some commands into the tui namespace Andrew Burgess
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 74+ messages in thread
From: Andrew Burgess @ 2022-01-28 15:55 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

This started by noticing that the docs for 'winheight' are out of
date, the docs currently give a specific list of possible window
names.  However, now that windows can be implemented in Python, it is
not possible to list all possible names.

I now link the user to a mechanism by which they can discover the
valid names for themselves at run time (by using 'info win').  That,
and the fact that gdb provides tab-completion of the name at the
command line, feels good enough.

Finally, I noticed that the docs for 'win info' don't explicitly say
that the name of the window is given in the output.  This could
probably have been inferred, but given I'm now linking to this as a
mechanism to find the window name, I'd prefer to mention that the name
can be found in the output.
---
 gdb/doc/gdb.texinfo | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index fe81687a66c..e72fa4aaaae 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -28812,9 +28812,10 @@
 @kindex tui disable
 Disable TUI mode, returning to the console interpreter.
 
+@anchor{info_win_command}
 @item info win
 @kindex info win
-List and give the size of all displayed windows.
+List the names and sizes of all currently displayed windows.
 
 @item tui new-layout @var{name} @var{window} @var{weight} @r{[}@var{window} @var{weight}@dots{}@r{]}
 @kindex tui new-layout
@@ -28961,11 +28962,11 @@
 @item winheight @var{name} +@var{count}
 @itemx winheight @var{name} -@var{count}
 @kindex winheight
-Change the height of the window @var{name} by @var{count}
-lines.  Positive counts increase the height, while negative counts
-decrease it.  The @var{name} parameter can be one of @code{src} (the
-source window), @code{cmd} (the command window), @code{asm} (the
-disassembly window), or @code{regs} (the register display window).
+Change the height of the window @var{name} by @var{count} lines.
+Positive counts increase the height, while negative counts decrease
+it.  The @var{name} parameter can be the name of any currently visible
+window.  The names of the currently visible windows can be discovered
+using @code{info win} (@pxref{info_win_command,,info win}).
 @end table
 
 @node TUI Configuration
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCH 3/7] gdb: move some commands into the tui namespace
  2022-01-28 15:55 [PATCH 0/7] TUI command changes, including new winwidth command Andrew Burgess
  2022-01-28 15:55 ` [PATCH 1/7] gdb/tui: add window width information to 'info win' output Andrew Burgess
  2022-01-28 15:55 ` [PATCH 2/7] gdb/doc: update docs for 'info win' and 'winheight' commands Andrew Burgess
@ 2022-01-28 15:55 ` Andrew Burgess
  2022-01-28 17:04   ` Eli Zaretskii
  2022-01-28 15:55 ` [PATCH 4/7] gdb/tui: rename tui_layout_base::adjust_size to ::set_height Andrew Burgess
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 74+ messages in thread
From: Andrew Burgess @ 2022-01-28 15:55 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

There are a lot of tui related commands that live in the top-level
command name space, e.g. layout, focus, refresh, winheight.

Having them at the top level means less typing for the user, which is
good, but, I think, makes command discovery harder.

In this commit, I propose moving all of the above mentioned commands
into the tui namespace, so 'layout' becomes 'tui layout', etc.  But I
will then add aliases so that the old commands will still work,
e.g. I'll make 'layout' an alias for 'tui layout'.

The benefit I see in this work is that tui related commands can be
more easily discovered by typing 'tui ' and then tab-completing.  Also
the "official" command is now a tui-sub-command, this is visible in,
for example, the help output, e.g.:

  (gdb) help layout
  tui layout, layout
  Change the layout of windows.
  Usage: tui layout prev | next | LAYOUT-NAME

  List of tui layout subcommands:

  tui layout asm -- Apply the "asm" layout.
  tui layout next -- Apply the next TUI layout.
  tui layout prev -- Apply the previous TUI layout.
  tui layout regs -- Apply the TUI register layout.
  tui layout split -- Apply the "split" layout.
  tui layout src -- Apply the "src" layout.

Which I think is a good thing, it makes it clearer that this is a tui
command.

I've added a NEWS entry and updated the docs to mention the new and
old command names, with the new name being mentioned first.
---
 gdb/NEWS             | 15 +++++++++++++++
 gdb/doc/gdb.texinfo  | 18 +++++++++++++-----
 gdb/tui/tui-layout.c | 16 +++++++++++++---
 gdb/tui/tui-win.c    | 40 ++++++++++++++++++++++++++++++++--------
 4 files changed, 73 insertions(+), 16 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 8da68c88def..f97f643b6ee 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -81,6 +81,14 @@ maint show gnu-source-highlight enabled
   styling to a particular source file, then the Python Pygments
   library will be used instead.
 
+tui layout
+tui focus
+tui refresh
+tui window height
+  These are the new names for the old 'layout', 'focus', 'refresh',
+  and 'winheight' tui commands respectively.  The old names still
+  exist as aliases to these new commands.
+
 * Changed commands
 
 maint packet
@@ -106,6 +114,13 @@ info win
   This command now includes information about the width of the tui
   windows in its output.
 
+layout
+focus
+refresh
+winheight
+  These commands are now aliases for the 'tui layout', 'tui focus',
+  'tui refresh', and 'tui window height' commands respectively.
+
 * Python API
 
   ** New function gdb.add_history(), which takes a gdb.Value object
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index e72fa4aaaae..df35887a304 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -28866,8 +28866,10 @@
 width of the terminal.  Because they have weight 2, the source and
 assembly windows will be twice the height of the command window.
 
-@item layout @var{name}
+@kindex tui layout
 @kindex layout
+@item tui layout @var{name}
+@itemx layout @var{name}
 Changes which TUI windows are displayed.  The @var{name} parameter
 controls which layout is shown.  It can be either one of the built-in
 layout names, or the name of a layout defined by the user using
@@ -28897,8 +28899,9 @@
 register, assembler, and command windows.
 @end table
 
-@item focus @var{name}
 @kindex focus
+@item tui focus @var{name}
+@itemx focus @var{name}
 Changes which TUI window is currently active for scrolling.  The
 @var{name} parameter can be any of the following:
 
@@ -28922,8 +28925,10 @@
 Make the command window active for scrolling.
 @end table
 
-@item refresh
+@kindex tui refresh
 @kindex refresh
+@item tui refresh
+@itemx refresh
 Refresh the screen.  This is similar to typing @kbd{C-L}.
 
 @item tui reg @var{group}
@@ -28959,9 +28964,12 @@
 @kindex update
 Update the source window and the current execution point.
 
-@item winheight @var{name} +@var{count}
-@itemx winheight @var{name} -@var{count}
+@kindex tui window height
 @kindex winheight
+@item tui window height @var{name} +@var{count}
+@itemx tui window height @var{name} -@var{count}
+@itemx winheight @var{name} +@var{count}
+@itemx winheight @var{name} -@var{count}
 Change the height of the window @var{name} by @var{count} lines.
 Positive counts increase the height, while negative counts decrease
 it.  The @var{name} parameter can be the name of any currently visible
diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index cef9190c3e1..f8388e3fca5 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -839,6 +839,14 @@ destroy_layout (struct cmd_list_element *self, void *context)
 
 static struct cmd_list_element *layout_list;
 
+/* Called to implement 'tui layout'.  */
+
+static void
+tui_layout_command (const char *args, int from_tty)
+{
+  help_list (layout_list, "tui layout ", all_commands, gdb_stdout);
+}
+
 /* Add a "layout" command with name NAME that switches to LAYOUT.  */
 
 static struct cmd_list_element *
@@ -1017,10 +1025,12 @@ void _initialize_tui_layout ();
 void
 _initialize_tui_layout ()
 {
-  add_basic_prefix_cmd ("layout", class_tui, _("\
+  struct cmd_list_element *layout_cmd
+    = add_prefix_cmd ("layout", class_tui, tui_layout_command, _("\
 Change the layout of windows.\n\
-Usage: layout prev | next | LAYOUT-NAME"),
-			&layout_list, 0, &cmdlist);
+Usage: tui layout prev | next | LAYOUT-NAME"),
+		      &layout_list, 0, tui_get_cmd_list ());
+  add_com_alias ("layout", layout_cmd, class_tui, 0);
 
   add_cmd ("next", class_tui, tui_next_layout_command,
 	   _("Apply the next TUI layout."),
diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c
index fd6ca59a728..ba6aca3d078 100644
--- a/gdb/tui/tui-win.c
+++ b/gdb/tui/tui-win.c
@@ -977,6 +977,18 @@ parse_scrolling_args (const char *arg,
     }
 }
 
+/* The list of 'tui window' sub-commands.  */
+
+static cmd_list_element *tui_window_cmds = nullptr;
+
+/* Called to implement 'tui window'.  */
+
+static void
+tui_window_command (const char *args, int from_tty)
+{
+  help_list (tui_window_cmds, "tui window ", all_commands, gdb_stdout);
+}
+
 /* Function to initialize gdb commands, for tui window
    manipulation.  */
 
@@ -995,8 +1007,11 @@ _initialize_tui_win ()
 			  &tui_setlist, &tui_showlist,
 			  &setlist, &showlist);
 
-  add_com ("refresh", class_tui, tui_refresh_all_command,
-	   _("Refresh the terminal display."));
+  cmd_list_element *refresh_cmd
+    = add_cmd ("refresh", class_tui, tui_refresh_all_command,
+	       _("Refresh the terminal display."),
+	       tui_get_cmd_list ());
+  add_com_alias ("refresh", refresh_cmd, class_tui, 0);
 
   cmd_list_element *tabset_cmd
     = add_com ("tabset", class_tui, tui_set_tab_width_command, _("\
@@ -1004,21 +1019,30 @@ Set the width (in characters) of tab stops.\n\
 Usage: tabset N"));
   deprecate_cmd (tabset_cmd, "set tui tab-width");
 
+  /* Setup the 'tui window' list of command.  */
+  add_prefix_cmd ("window", class_tui, tui_window_command,
+		  _("Text User Interface window commands."),
+		  &tui_window_cmds, 1, tui_get_cmd_list ());
+
   cmd_list_element *winheight_cmd
-    = add_com ("winheight", class_tui, tui_set_win_height_command, _("\
+    = add_cmd ("height", class_tui, tui_set_win_height_command, _("\
 Set or modify the height of a specified window.\n\
-Usage: winheight WINDOW-NAME [+ | -] NUM-LINES\n\
-Use \"info win\" to see the names of the windows currently being displayed."));
+Usage: tui window height WINDOW-NAME [+ | -] NUM-LINES\n\
+Use \"info win\" to see the names of the windows currently being displayed."),
+	       &tui_window_cmds);
+  add_com_alias ("winheight", winheight_cmd, class_tui, 0);
   add_com_alias ("wh", winheight_cmd, class_tui, 0);
   set_cmd_completer (winheight_cmd, winheight_completer);
   add_info ("win", tui_all_windows_info,
 	    _("List of all displayed windows.\n\
 Usage: info win"));
   cmd_list_element *focus_cmd
-    = add_com ("focus", class_tui, tui_set_focus_command, _("\
+    = add_cmd ("focus", class_tui, tui_set_focus_command, _("\
 Set focus to named window or next/prev window.\n\
-Usage: focus [WINDOW-NAME | next | prev]\n\
-Use \"info win\" to see the names of the windows currently being displayed."));
+Usage: tui focus [WINDOW-NAME | next | prev]\n\
+Use \"info win\" to see the names of the windows currently being displayed."),
+	       tui_get_cmd_list ());
+  add_com_alias ("focus", focus_cmd, class_tui, 0);
   add_com_alias ("fs", focus_cmd, class_tui, 0);
   set_cmd_completer (focus_cmd, focus_completer);
   add_com ("+", class_tui, tui_scroll_forward_command, _("\
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCH 4/7] gdb/tui: rename tui_layout_base::adjust_size to ::set_height
  2022-01-28 15:55 [PATCH 0/7] TUI command changes, including new winwidth command Andrew Burgess
                   ` (2 preceding siblings ...)
  2022-01-28 15:55 ` [PATCH 3/7] gdb: move some commands into the tui namespace Andrew Burgess
@ 2022-01-28 15:55 ` Andrew Burgess
  2022-01-28 15:55 ` [PATCH 5/7] gdb/tui: rename tui_layout_split:set_weights_from_heights Andrew Burgess
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-01-28 15:55 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

Rename tui_layout_base::adjust_size to tui_layout_base::set_height,
the new name more accurately reflects what this member function does,
and makes it easier for a later commit to add a new
tui_layout_base::set_width member function.

There should be no user visible changes after this commit.
---
 gdb/tui/tui-layout.c | 6 +++---
 gdb/tui/tui-layout.h | 8 ++++----
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index f8388e3fca5..4c355c79d65 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -118,7 +118,7 @@ tui_apply_current_layout ()
 void
 tui_adjust_window_height (struct tui_win_info *win, int new_height)
 {
-  applied_layout->adjust_size (win->name (), new_height);
+  applied_layout->set_height (win->name (), new_height);
 }
 
 /* Set the current layout to LAYOUT.  */
@@ -570,7 +570,7 @@ tui_layout_split::set_weights_from_heights ()
 /* See tui-layout.h.  */
 
 tui_adjust_result
-tui_layout_split::adjust_size (const char *name, int new_height)
+tui_layout_split::set_height (const char *name, int new_height)
 {
   /* Look through the children.  If one is a layout holding the named
      window, we're done; or if one actually is the named window,
@@ -579,7 +579,7 @@ tui_layout_split::adjust_size (const char *name, int new_height)
   for (int i = 0; i < m_splits.size (); ++i)
     {
       tui_adjust_result adjusted
-	= m_splits[i].layout->adjust_size (name, new_height);
+	= m_splits[i].layout->set_height (name, new_height);
       if (adjusted == HANDLED)
 	return HANDLED;
       if (adjusted == FOUND)
diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h
index b9a5d9b898d..acea7ac8f64 100644
--- a/gdb/tui/tui-layout.h
+++ b/gdb/tui/tui-layout.h
@@ -75,9 +75,9 @@ class tui_layout_base
     return nullptr;
   }
 
-  /* Adjust the size of the window named NAME to NEW_HEIGHT, updating
+  /* Set the height of the window named NAME to NEW_HEIGHT, updating
      the sizes of the other windows around it.  */
-  virtual tui_adjust_result adjust_size (const char *name, int new_height) = 0;
+  virtual tui_adjust_result set_height (const char *name, int new_height) = 0;
 
   /* Remove some windows from the layout, leaving the command window
      and the window being passed in here.  */
@@ -127,7 +127,7 @@ class tui_layout_window : public tui_layout_base
     return m_contents.c_str ();
   }
 
-  tui_adjust_result adjust_size (const char *name, int new_height) override
+  tui_adjust_result set_height (const char *name, int new_height) override
   {
     return m_contents == name ? FOUND : NOT_FOUND;
   }
@@ -192,7 +192,7 @@ class tui_layout_split : public tui_layout_base
 
   void apply (int x, int y, int width, int height) override;
 
-  tui_adjust_result adjust_size (const char *name, int new_height) override;
+  tui_adjust_result set_height (const char *name, int new_height) override;
 
   bool top_boxed_p () const override;
 
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCH 5/7] gdb/tui: rename tui_layout_split:set_weights_from_heights
  2022-01-28 15:55 [PATCH 0/7] TUI command changes, including new winwidth command Andrew Burgess
                   ` (3 preceding siblings ...)
  2022-01-28 15:55 ` [PATCH 4/7] gdb/tui: rename tui_layout_base::adjust_size to ::set_height Andrew Burgess
@ 2022-01-28 15:55 ` Andrew Burgess
  2022-01-28 15:55 ` [PATCH 6/7] gdb/testing/tui: add new functionality to tuiterm.exp Andrew Burgess
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-01-28 15:55 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

In a following commit I'm going to add the ability to change the width
of a tui window (when in a horizontal layout).  As a result, some of
the places where we currently hard-code references to height need to
be changed to handle either height, or width, based on whether we are
in a vertical, or horizontal layout.

This commit renames set_weights_from_heights to
set_weights_from_sizes, and makes the function use either the height,
or width as appropriate.

Currently, the only place that we call this function is from the
tui_layout_split::set_height function, in a part of the code we will
only reach for vertical layouts, so the new code is not actually being
used, but, this small change will help make later patches smaller, so
I'm proposing this as a stand alone change.

There should be no user visible changes after this commit.
---
 gdb/tui/tui-layout.c | 9 +++++----
 gdb/tui/tui-layout.h | 5 +++--
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index 4c355c79d65..9e856ccf3fa 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -561,10 +561,11 @@ tui_layout_split::bottom_boxed_p () const
 /* See tui-layout.h.  */
 
 void
-tui_layout_split::set_weights_from_heights ()
+tui_layout_split::set_weights_from_sizes ()
 {
   for (int i = 0; i < m_splits.size (); ++i)
-    m_splits[i].weight = m_splits[i].layout->height;
+    m_splits[i].weight
+      = m_vertical ? m_splits[i].layout->height : m_splits[i].layout->width;
 }
 
 /* See tui-layout.h.  */
@@ -596,7 +597,7 @@ tui_layout_split::set_height (const char *name, int new_height)
   if (m_splits[found_index].layout->height == new_height)
     return HANDLED;
 
-  set_weights_from_heights ();
+  set_weights_from_sizes ();
   int delta = m_splits[found_index].weight - new_height;
   m_splits[found_index].weight = new_height;
 
@@ -634,7 +635,7 @@ tui_layout_split::set_height (const char *name, int new_height)
     {
       warning (_("Invalid window height specified"));
       /* Effectively undo any modifications made here.  */
-      set_weights_from_heights ();
+      set_weights_from_sizes ();
     }
   else
     {
diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h
index acea7ac8f64..8f41835b94c 100644
--- a/gdb/tui/tui-layout.h
+++ b/gdb/tui/tui-layout.h
@@ -217,8 +217,9 @@ class tui_layout_split : public tui_layout_base
 
 private:
 
-  /* Set the weights from the current heights.  */
-  void set_weights_from_heights ();
+  /* Set the weights from the current heights (when m_vertical is true) or
+     widths (when m_vertical is false).  */
+  void set_weights_from_sizes ();
 
   struct split
   {
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCH 6/7] gdb/testing/tui: add new functionality to tuiterm.exp
  2022-01-28 15:55 [PATCH 0/7] TUI command changes, including new winwidth command Andrew Burgess
                   ` (4 preceding siblings ...)
  2022-01-28 15:55 ` [PATCH 5/7] gdb/tui: rename tui_layout_split:set_weights_from_heights Andrew Burgess
@ 2022-01-28 15:55 ` Andrew Burgess
  2022-01-28 15:55 ` [PATCH 7/7] gdb/tui: add new 'tui window width' command and 'winwidth' alias Andrew Burgess
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-01-28 15:55 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

While working on the next patch in this series, I was sending
additional commands to the terminal with Term::command.  There was
nothing special about these commands, just normal "print EXPRESSION"
type things, but I clearly poked ncurses in just the right way so that
it started sending two previously unseen control sequences, 'Insert
Line' and 'Delete Characters'.

Now, the Term::command calls I added above were only done to help be
debug the test, without them, these two control sequences are not
triggered.  But, given I've gone to the effort of adding these
features to tuiterm.exp, I figure I might as well share this work.

Additionally, I noticed a bug in 'Erase in Line' that this commit
fixes; in mode 1 the erase should be from the start of the line
through to the cursor, not to the character before the cursor.  This
bug would mean that random characters would sometimes be left in the
terminal output.
---
 gdb/testsuite/lib/tuiterm.exp | 54 ++++++++++++++++++++++++++++++++++-
 1 file changed, 53 insertions(+), 1 deletion(-)

diff --git a/gdb/testsuite/lib/tuiterm.exp b/gdb/testsuite/lib/tuiterm.exp
index 38948015e96..f2be3394db0 100644
--- a/gdb/testsuite/lib/tuiterm.exp
+++ b/gdb/testsuite/lib/tuiterm.exp
@@ -317,13 +317,40 @@ namespace eval Term {
 		# From cursor to end.
 		_clear_in_line $_cur_col $_cols $_cur_row
 	    } elseif {$arg == 1} {
-		_clear_in_line 0 $_cur_col $_cur_row
+		_clear_in_line 0 [expr $_cur_col + 1] $_cur_row
 	    } elseif {$arg == 2} {
 		_clear_in_line 0 $_cols $_cur_row
 	    }
 	}
     }
 
+    # Insert Line
+    #
+    # https://vt100.net/docs/vt510-rm/IL.html
+    proc _csi_L {args} {
+	set arg [_default [lindex $args 0] 1]
+
+	_log_cur "Insert Line ($arg)" {
+	    variable _cur_col
+	    variable _cur_row
+	    variable _rows
+	    variable _cols
+	    variable _chars
+
+	    set y [expr $_rows - 2]
+	    set next_y [expr $y + 1]
+	    while {$y >= $_cur_row} {
+		for {set x 0} {$x < $_cols} {incr x} {
+		    set _chars($x,$next_y) $_chars($x,$y)
+		}
+		incr y -1
+		incr next_y -1
+	    }
+
+	    _clear_lines $_cur_row $_rows
+	}
+    }
+
     # Delete line.
     #
     # https://vt100.net/docs/vt510-rm/DL.html
@@ -349,6 +376,31 @@ namespace eval Term {
 	}
     }
 
+    # Delete Characters
+    #
+    # https://vt100.net/docs/vt510-rm/DCH.html
+    proc _csi_P {args} {
+	set count [_default [lindex $args 0] 1]
+
+	_log_cur "Delete Character ($count)" {
+	    variable _cur_col
+	    variable _cur_row
+	    variable _cols
+	    variable _chars
+
+	    set dx [expr $_cur_col + 1]
+	    set sx [expr $_cur_col + 1 + $count]
+	    set y $_cur_row
+
+	    while {$sx < $_cols} {
+		set _chars($dx,$y) $_chars($sx,$y)
+		incr sx
+		incr dx
+	    }
+	    _clear_in_line $dx $sx $y
+	}
+    }
+
     # Erase chars.
     #
     # https://vt100.net/docs/vt510-rm/ECH.html
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCH 7/7] gdb/tui: add new 'tui window width' command and 'winwidth' alias
  2022-01-28 15:55 [PATCH 0/7] TUI command changes, including new winwidth command Andrew Burgess
                   ` (5 preceding siblings ...)
  2022-01-28 15:55 ` [PATCH 6/7] gdb/testing/tui: add new functionality to tuiterm.exp Andrew Burgess
@ 2022-01-28 15:55 ` Andrew Burgess
  2022-01-28 17:05   ` Eli Zaretskii
  2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess
  2022-03-04 17:23 ` [PATCH 0/7] TUI command changes, including new winwidth command Tom Tromey
  8 siblings, 1 reply; 74+ messages in thread
From: Andrew Burgess @ 2022-01-28 15:55 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

This commit adds a new command 'tui window width', and an alias
'winwidth'.  This command is equivalent to the old 'winheight'
command (which was recently renamed 'tui window height').

Even though I recently moved the old tui commands under the tui
namespace, and I would strongly encourage all new tui commands to be
added as 'tui ....' only (users can create their own top-level aliases
if they want), I'm breaking that suggestion here, and adding a
'winwidth' alias.

Given that we already have 'winheight' and have done for years, it
just didn't seem right to no have the matching 'winwidth'.

You might notice in the test that the window resizing doesn't quite
work right.  I setup a horizontal layout, then grow and shrink the
windows.  At the end of the test the windows should be back to their
original size...

... they are not.  This isn't my fault, honest!  GDB's window resizing
is a little ... temperamental, and is prone to getting things slightly
wrong during resizes, off by 1 type things.  This is true for height
resizing, as well as the new width resizing.

I'm currently working on a patch to improve the resizing algorithm,
which should improve things in this area.  For now, I'm happy that the
width resizing is as good as the height resizing, given the existing
quirks.

As for the changes in gdb itself, I've mostly just templated the
existing height adjustment code so that the two functions
tui_layout_split::adjust_size (tui-layout.c) and
tui_set_win_height_command (tui-win.c) now have a template parameter
"policy", this policy allows me to specialise the functions for either
width or height adjustment.  Function arguments, and locals, are
renamed, replacing 'height' with 'size'.
---
 gdb/NEWS                           |   6 ++
 gdb/doc/gdb.texinfo                |  12 ++++
 gdb/testsuite/gdb.tui/winwidth.exp |  62 +++++++++++++++++
 gdb/tui/tui-layout.c               |  23 +++++--
 gdb/tui/tui-layout.h               | 104 ++++++++++++++++++++++++++++-
 gdb/tui/tui-win.c                  |  99 +++++++++++++++++++++++++--
 6 files changed, 291 insertions(+), 15 deletions(-)
 create mode 100644 gdb/testsuite/gdb.tui/winwidth.exp

diff --git a/gdb/NEWS b/gdb/NEWS
index f97f643b6ee..1faef78056a 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -89,6 +89,12 @@ tui window height
   and 'winheight' tui commands respectively.  The old names still
   exist as aliases to these new commands.
 
+tui window width
+winwidth
+  The new command 'tui window width', and the alias 'winwidth' allow
+  the width of a tui window to be adjusted when windows are laid out
+  in horizontal mode.
+
 * Changed commands
 
 maint packet
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index df35887a304..cb5cfbaefc1 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -28975,6 +28975,18 @@
 it.  The @var{name} parameter can be the name of any currently visible
 window.  The names of the currently visible windows can be discovered
 using @code{info win} (@pxref{info_win_command,,info win}).
+
+@kindex tui window width
+@kindex winwidth
+@item tui window width @var{name} +@var{count}
+@itemx tui window width @var{name} -@var{count}
+@itemx winwidth @var{name} +@var{count}
+@itemx winwidth @var{name} -@var{count}
+Change the width of the window @var{name} by @var{count} columns.
+Positive counts increase the width, while negative counts decrease it.
+The @var{name} parameter can be the name of any currently visible
+window.  The names of the currently visible windows can be discovered
+using @code{info win} (@pxref{info_win_command,,info win}).
 @end table
 
 @node TUI Configuration
diff --git a/gdb/testsuite/gdb.tui/winwidth.exp b/gdb/testsuite/gdb.tui/winwidth.exp
new file mode 100644
index 00000000000..b0a838b578f
--- /dev/null
+++ b/gdb/testsuite/gdb.tui/winwidth.exp
@@ -0,0 +1,62 @@
+# Copyright 2022 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test the "winwidth" command.
+
+tuiterm_env
+
+standard_testfile tui-layout.c
+
+if {[build_executable "failed to prepare" ${testfile} ${srcfile}] == -1} {
+    return -1
+}
+
+Term::clean_restart 24 80 $testfile
+if {![Term::enter_tui]} {
+    unsupported "TUI not supported"
+    return
+}
+
+Term::command "tui new-layout h { -horizontal src 1 asm 1 } 1 status 0 cmd 1"
+Term::command "layout h"
+
+with_test_prefix "original window sizes" {
+    Term::check_box "source box" 0 0 40 15
+    Term::check_box "asm box" 39 0 41 15
+    Term::command "winwidth src +5"
+}
+
+with_test_prefix "after src +5" {
+    Term::check_box "source box" 0 0 44 15
+    Term::check_box "asm box" 43 0 37 15
+    Term::command "winwidth asm -5"
+}
+
+with_test_prefix "after asm -5" {
+    Term::check_box "source box" 0 0 48 15
+    Term::check_box "asm box" 47 0 33 15
+    Term::command "winwidth asm +8"
+}
+
+with_test_prefix "after asm +8" {
+    Term::check_box "source box" 0 0 39 15
+    Term::check_box "asm box" 38 0 42 15
+    Term::command "winwidth src -2"
+}
+
+with_test_prefix "after src -2" {
+    Term::check_box "source box" 0 0 36 15
+    Term::check_box "asm box" 35 0 45 15
+}
diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index 9e856ccf3fa..13e4d462426 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -121,6 +121,14 @@ tui_adjust_window_height (struct tui_win_info *win, int new_height)
   applied_layout->set_height (win->name (), new_height);
 }
 
+/* See tui-layout.  */
+
+void
+tui_adjust_window_width (struct tui_win_info *win, int new_width)
+{
+  applied_layout->set_width (win->name (), new_width);
+}
+
 /* Set the current layout to LAYOUT.  */
 
 static void
@@ -570,8 +578,9 @@ tui_layout_split::set_weights_from_sizes ()
 
 /* See tui-layout.h.  */
 
+template<class Policy>
 tui_adjust_result
-tui_layout_split::set_height (const char *name, int new_height)
+tui_layout_split::set_size (const char *name, int new_size)
 {
   /* Look through the children.  If one is a layout holding the named
      window, we're done; or if one actually is the named window,
@@ -580,12 +589,12 @@ tui_layout_split::set_height (const char *name, int new_height)
   for (int i = 0; i < m_splits.size (); ++i)
     {
       tui_adjust_result adjusted
-	= m_splits[i].layout->set_height (name, new_height);
+	= Policy::set_size (m_splits[i].layout, name, new_size);
       if (adjusted == HANDLED)
 	return HANDLED;
       if (adjusted == FOUND)
 	{
-	  if (!m_vertical)
+	  if (!Policy::can_adjust (this))
 	    return FOUND;
 	  found_index = i;
 	  break;
@@ -594,12 +603,12 @@ tui_layout_split::set_height (const char *name, int new_height)
 
   if (found_index == -1)
     return NOT_FOUND;
-  if (m_splits[found_index].layout->height == new_height)
+  if (Policy::current_size (m_splits[found_index].layout) == new_size)
     return HANDLED;
 
   set_weights_from_sizes ();
-  int delta = m_splits[found_index].weight - new_height;
-  m_splits[found_index].weight = new_height;
+  int delta = m_splits[found_index].weight - new_size;
+  m_splits[found_index].weight = new_size;
 
   /* Distribute the "delta" over the next window; but if the next
      window cannot hold it all, keep going until we either find a
@@ -633,7 +642,7 @@ tui_layout_split::set_height (const char *name, int new_height)
 
   if (delta != 0)
     {
-      warning (_("Invalid window height specified"));
+      Policy::invalid_size_warning ();
       /* Effectively undo any modifications made here.  */
       set_weights_from_sizes ();
     }
diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h
index 8f41835b94c..f4ef0895f1f 100644
--- a/gdb/tui/tui-layout.h
+++ b/gdb/tui/tui-layout.h
@@ -79,6 +79,10 @@ class tui_layout_base
      the sizes of the other windows around it.  */
   virtual tui_adjust_result set_height (const char *name, int new_height) = 0;
 
+  /* Set the width of the window named NAME to NEW_WIDTH, updating
+     the sizes of the other windows around it.  */
+  virtual tui_adjust_result set_width (const char *name, int new_width) = 0;
+
   /* Remove some windows from the layout, leaving the command window
      and the window being passed in here.  */
   virtual void remove_windows (const char *name) = 0;
@@ -132,6 +136,11 @@ class tui_layout_window : public tui_layout_base
     return m_contents == name ? FOUND : NOT_FOUND;
   }
 
+  tui_adjust_result set_width (const char *name, int new_width) override
+  {
+    return m_contents == name ? FOUND : NOT_FOUND;
+  }
+
   bool top_boxed_p () const override;
 
   bool bottom_boxed_p () const override;
@@ -192,7 +201,15 @@ class tui_layout_split : public tui_layout_base
 
   void apply (int x, int y, int width, int height) override;
 
-  tui_adjust_result set_height (const char *name, int new_height) override;
+  tui_adjust_result set_height (const char *name, int new_height) override
+  {
+    return set_size<tui_layout_split::set_height_policy> (name, new_height);
+  }
+
+  tui_adjust_result set_width (const char *name, int new_width) override
+  {
+    return set_size<tui_layout_split::set_width_policy> (name, new_width);
+  }
 
   bool top_boxed_p () const override;
 
@@ -217,6 +234,87 @@ class tui_layout_split : public tui_layout_base
 
 private:
 
+  /* Used to implement set_height and set_width member functions.  Set
+     either the height or width of the window named NAME to NEW_SIZE,
+     updating the sizes of the other windows around it as needed.  The
+     POLICY is used to specialize this function to adjust either the height
+     or the width.  */
+
+  template <class Policy>
+  tui_adjust_result set_size (const char *name, int new_size);
+
+  /* A policy class for use with the set_size member function, use when we
+     want to adjust the height of a named window.  */
+
+  struct set_height_policy
+  {
+    /* Set the height of window named NAME to NEW_HEIGHT in LAYOUT.  */
+    static tui_adjust_result
+    set_size (std::unique_ptr<tui_layout_base> &layout,
+	      const char *name,
+	      int new_height)
+    {
+      return layout->set_height (name, new_height);
+    }
+
+    /* Can we adjust the heights of windows in SPLIT?  */
+    static bool
+    can_adjust (const tui_layout_split *split)
+    {
+      return split->m_vertical;
+    }
+
+    /* What is the current height of LAYOUT.  */
+    static int
+    current_size (std::unique_ptr<tui_layout_base> &layout)
+    {
+      return layout->height;
+    }
+
+    /* Warn about invalid height specification.  */
+    static void
+    invalid_size_warning ()
+    {
+      warning (_("Invalid window height specified"));
+    }
+  };
+
+  /* A policy class for use with the set_size member function, use when we
+     want to adjust the width of a named window.  */
+
+  struct set_width_policy
+  {
+    /* Set the width of window named NAME to NEW_HEIGHT in LAYOUT.  */
+    static tui_adjust_result
+    set_size (std::unique_ptr<tui_layout_base> &layout,
+	      const char *name,
+	      int new_width)
+    {
+      return layout->set_width (name, new_width);
+    }
+
+    /* Can we adjust the widths of windows in SPLIT?  */
+    static bool
+    can_adjust (const tui_layout_split *split)
+    {
+      return !split->m_vertical;
+    }
+
+    /* What is the current width of LAYOUT.  */
+    static int
+    current_size (std::unique_ptr<tui_layout_base> &layout)
+    {
+      return layout->width;
+    }
+
+    /* Warn about invalid height specification.  */
+    static void
+    invalid_size_warning ()
+    {
+      warning (_("Invalid window width specified"));
+    }
+  };
+
   /* Set the weights from the current heights (when m_vertical is true) or
      widths (when m_vertical is false).  */
   void set_weights_from_sizes ();
@@ -266,6 +364,10 @@ extern void tui_apply_current_layout ();
 extern void tui_adjust_window_height (struct tui_win_info *win,
 				      int new_height);
 
+/* Adjust the window width of WIN to NEW_WIDTH.  */
+extern void tui_adjust_window_width (struct tui_win_info *win,
+				     int new_width);
+
 /* The type of a function that is used to create a TUI window.  */
 
 typedef std::function<tui_win_info * (const char *name)> window_factory;
diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c
index ba6aca3d078..953af640c93 100644
--- a/gdb/tui/tui-win.c
+++ b/gdb/tui/tui-win.c
@@ -842,10 +842,21 @@ tui_set_tab_width_command (const char *arg, int from_tty)
     }
 }
 
+/* Helper function for the user commands to adjust a window's width or
+   height.  The ARG string contains the command line arguments from the
+   user, which should give the name of a window, and how to adjust the
+   size.
 
-/* Set the height of the specified window.  */
+   The Policy type is used to specialise this function for updating either
+   the width or height of the window.
+
+   On invalid input, or if the size can't be adjusted as requested, then an
+   error is thrown, otherwise, the window sizes are adjusted, and the
+   windows redrawn.  */
+
+template<typename Policy>
 static void
-tui_set_win_height_command (const char *arg, int from_tty)
+tui_set_win_size (const char *arg)
 {
   /* Make sure the curses mode is enabled.  */
   tui_enable ();
@@ -854,7 +865,7 @@ tui_set_win_height_command (const char *arg, int from_tty)
 
   const char *buf = arg;
   const char *buf_ptr = buf;
-  int new_height;
+  int new_size;
   struct tui_win_info *win_info;
 
   buf_ptr = skip_to_space (buf_ptr);
@@ -890,18 +901,82 @@ tui_set_win_height_command (const char *arg, int from_tty)
 	  if (negate)
 	    input_no *= (-1);
 	  if (fixed_size)
-	    new_height = input_no;
+	    new_size = input_no;
 	  else
-	    new_height = win_info->height + input_no;
+	    new_size = Policy::existing_window_size (win_info) + input_no;
 
 	  /* Now change the window's height, and adjust
 	     all other windows around it.  */
-	  tui_adjust_window_height (win_info, new_height);
+	  Policy::adjust_window_size (win_info, new_size);
 	  tui_update_gdb_sizes ();
 	}
       else
-	error (_("Invalid window height specified"));
+	Policy::invalid_size_error ();
+    }
+}
+
+/* Implement the 'tui window height' command (alias 'winheight').  */
+
+static void
+tui_set_win_height_command (const char *arg, int from_tty)
+{
+  /* Policy class for use with tui_set_win_size, this policy adjusts the
+     height of a window.  */
+  struct height_adjustment_policy
+  {
+    /* Called when the size specified is invalid.  */
+    static void invalid_size_error ()
+    {
+      error (_("Invalid window height specified"));
+    }
+
+    /* Return the existing size, height in this case, of a window WIN_INFO.  */
+    static int existing_window_size (struct tui_win_info *win_info)
+    {
+      return win_info->height;
+    }
+
+    /* Set the size, height in this case, of WIN_INFO to NEW_SIZE.  */
+    static void adjust_window_size (struct tui_win_info *win_info,
+				    int new_size)
+    {
+      tui_adjust_window_height (win_info, new_size);
+    }
+  };
+
+  tui_set_win_size<height_adjustment_policy> (arg);
+}
+
+/* Implement the 'tui window width' command (alias 'winwidth').  */
+
+static void
+tui_set_win_width_command (const char *arg, int from_tty)
+{
+  /* Policy class for use with tui_set_win_size, this policy adjusts the
+     width of a window.  */
+  struct width_adjustment_policy
+  {
+    /* Called when the size specified is invalid.  */
+    static void invalid_size_error ()
+    {
+      error (_("Invalid window width specified"));
     }
+
+    /* Return the existing size, width in this case, of a window WIN_INFO.  */
+    static int existing_window_size (struct tui_win_info *win_info)
+    {
+      return win_info->width;
+    }
+
+    /* Set the size, width in this case, of WIN_INFO to NEW_SIZE.  */
+    static void adjust_window_size (struct tui_win_info *win_info,
+				    int new_size)
+    {
+      tui_adjust_window_width (win_info, new_size);
+    }
+  };
+
+  tui_set_win_size<width_adjustment_policy> (arg);
 }
 
 /* See tui-data.h.  */
@@ -1033,6 +1108,16 @@ Use \"info win\" to see the names of the windows currently being displayed."),
   add_com_alias ("winheight", winheight_cmd, class_tui, 0);
   add_com_alias ("wh", winheight_cmd, class_tui, 0);
   set_cmd_completer (winheight_cmd, winheight_completer);
+
+  cmd_list_element *winwidth_cmd
+    = add_cmd ("width", class_tui, tui_set_win_width_command, _("\
+Set or modify the width of a specified window.\n\
+Usage: tui window width WINDOW-NAME [+ | -] NUM-LINES\n\
+Use \"info win\" to see the names of the windows currently being displayed."),
+	       &tui_window_cmds);
+  add_com_alias ("winwidth", winwidth_cmd, class_tui, 0);
+  set_cmd_completer (winwidth_cmd, winheight_completer);
+
   add_info ("win", tui_all_windows_info,
 	    _("List of all displayed windows.\n\
 Usage: info win"));
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 1/7] gdb/tui: add window width information to 'info win' output
  2022-01-28 15:55 ` [PATCH 1/7] gdb/tui: add window width information to 'info win' output Andrew Burgess
@ 2022-01-28 17:00   ` Eli Zaretskii
  2022-02-06 13:43   ` Andrew Burgess
  1 sibling, 0 replies; 74+ messages in thread
From: Eli Zaretskii @ 2022-01-28 17:00 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches

> Date: Fri, 28 Jan 2022 15:55:02 +0000
> From: Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org>
> Cc: Andrew Burgess <aburgess@redhat.com>
> 
> diff --git a/gdb/NEWS b/gdb/NEWS
> index e1900596ca7..8da68c88def 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -102,6 +102,10 @@ show debug lin-lwp
>    debug linux-nat' and 'show debug linux-nat' should be used
>    instead.
>  
> +info win
> +  This command now includes information about the width of the tui
> +  windows in its output.
> +

This part is OK, thanks.

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 2/7] gdb/doc: update docs for 'info win' and 'winheight' commands
  2022-01-28 15:55 ` [PATCH 2/7] gdb/doc: update docs for 'info win' and 'winheight' commands Andrew Burgess
@ 2022-01-28 17:03   ` Eli Zaretskii
  2022-02-06 13:43     ` Andrew Burgess
  0 siblings, 1 reply; 74+ messages in thread
From: Eli Zaretskii @ 2022-01-28 17:03 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches

> Date: Fri, 28 Jan 2022 15:55:03 +0000
> From: Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org>
> Cc: Andrew Burgess <aburgess@redhat.com>
> 
>  gdb/doc/gdb.texinfo | 13 +++++++------
>  1 file changed, 7 insertions(+), 6 deletions(-)
> 
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index fe81687a66c..e72fa4aaaae 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo

This is okay, but...

> +Change the height of the window @var{name} by @var{count} lines.
> +Positive counts increase the height, while negative counts decrease
> +it.  The @var{name} parameter can be the name of any currently visible
> +window.  The names of the currently visible windows can be discovered
> +using @code{info win} (@pxref{info_win_command,,info win}).
         ^^^^^
Please use @kbd there, not @code.

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 3/7] gdb: move some commands into the tui namespace
  2022-01-28 15:55 ` [PATCH 3/7] gdb: move some commands into the tui namespace Andrew Burgess
@ 2022-01-28 17:04   ` Eli Zaretskii
  0 siblings, 0 replies; 74+ messages in thread
From: Eli Zaretskii @ 2022-01-28 17:04 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches

> Date: Fri, 28 Jan 2022 15:55:04 +0000
> From: Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org>
> Cc: Andrew Burgess <aburgess@redhat.com>
> 
>  gdb/NEWS             | 15 +++++++++++++++
>  gdb/doc/gdb.texinfo  | 18 +++++++++++++-----
>  gdb/tui/tui-layout.c | 16 +++++++++++++---
>  gdb/tui/tui-win.c    | 40 ++++++++++++++++++++++++++++++++--------
>  4 files changed, 73 insertions(+), 16 deletions(-)

Thanks, the documentation parts are OK.

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 7/7] gdb/tui: add new 'tui window width' command and 'winwidth' alias
  2022-01-28 15:55 ` [PATCH 7/7] gdb/tui: add new 'tui window width' command and 'winwidth' alias Andrew Burgess
@ 2022-01-28 17:05   ` Eli Zaretskii
  0 siblings, 0 replies; 74+ messages in thread
From: Eli Zaretskii @ 2022-01-28 17:05 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches

> Date: Fri, 28 Jan 2022 15:55:08 +0000
> From: Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org>
> Cc: Andrew Burgess <aburgess@redhat.com>
> 
>  gdb/NEWS                           |   6 ++
>  gdb/doc/gdb.texinfo                |  12 ++++
>  gdb/testsuite/gdb.tui/winwidth.exp |  62 +++++++++++++++++
>  gdb/tui/tui-layout.c               |  23 +++++--
>  gdb/tui/tui-layout.h               | 104 ++++++++++++++++++++++++++++-
>  gdb/tui/tui-win.c                  |  99 +++++++++++++++++++++++++--
>  6 files changed, 291 insertions(+), 15 deletions(-)
>  create mode 100644 gdb/testsuite/gdb.tui/winwidth.exp

The documentation parts are OK, thanks.

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 1/7] gdb/tui: add window width information to 'info win' output
  2022-01-28 15:55 ` [PATCH 1/7] gdb/tui: add window width information to 'info win' output Andrew Burgess
  2022-01-28 17:00   ` Eli Zaretskii
@ 2022-02-06 13:43   ` Andrew Burgess
  1 sibling, 0 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-02-06 13:43 UTC (permalink / raw)
  To: gdb-patches

* Andrew Burgess <aburgess@redhat.com> [2022-01-28 15:55:02 +0000]:

> Now that we support horizontal window placement in the tui, it makes
> sense to have 'info win' include the width, as well as the height, of
> the currently visible windows.
> 
> That's what this commit does.  Example output is now:
> 
>   (gdb) info win
>   Name       Lines Columns Focus
>   src           12      40 (has focus)
>   asm           12      41
>   status         1      80
>   cmd           11      80
> 
> I've added a NEWS entry, but the documentation was already suitably
> vague, it just says that 'info win' displays the size of the visible
> windows, so I don't think anything needs to be added there.
> 
> I've also added some tests, as far as I could find, the 'info win'
> command was previously untested.

I've gone ahead and pushed this patch, I think this is the obvious
solution for adding this information to gdb.

If anyone disagrees, feel free to say.

Thanks,
Andrew



> ---
>  gdb/NEWS                           |  4 ++
>  gdb/testsuite/gdb.tui/info-win.exp | 61 ++++++++++++++++++++++++++++++
>  gdb/tui/tui-win.c                  |  4 +-
>  3 files changed, 68 insertions(+), 1 deletion(-)
>  create mode 100644 gdb/testsuite/gdb.tui/info-win.exp
> 
> diff --git a/gdb/NEWS b/gdb/NEWS
> index e1900596ca7..8da68c88def 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -102,6 +102,10 @@ show debug lin-lwp
>    debug linux-nat' and 'show debug linux-nat' should be used
>    instead.
>  
> +info win
> +  This command now includes information about the width of the tui
> +  windows in its output.
> +
>  * Python API
>  
>    ** New function gdb.add_history(), which takes a gdb.Value object
> diff --git a/gdb/testsuite/gdb.tui/info-win.exp b/gdb/testsuite/gdb.tui/info-win.exp
> new file mode 100644
> index 00000000000..2607d5be493
> --- /dev/null
> +++ b/gdb/testsuite/gdb.tui/info-win.exp
> @@ -0,0 +1,61 @@
> +# Copyright 2022 Free Software Foundation, Inc.
> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see <http://www.gnu.org/licenses/>.
> +
> +# Test 'info win'.
> +
> +tuiterm_env
> +
> +standard_testfile
> +
> +Term::clean_restart 24 80
> +
> +if {![Term::enter_tui]} {
> +    unsupported "TUI not supported"
> +    return
> +}
> +
> +Term::command "layout src"
> +Term::command "info win"
> +Term::check_region_contents "info win, layout src" \
> +    0 16 80 8 [multi_line "info win\\s+" \
> +		   "Name\\s+Lines\\s+Columns\\s+Focus\\s+" \
> +		   "src\\s+15\\s+80\\s+\\(has focus\\)\\s+" \
> +		   "status\\s+1\\s+80\\s+" \
> +		   "cmd\\s+8\\s+80\\s+"]
> +
> +Term::command "tui new-layout h { -horizontal src 1 asm 1 } 1 status 0 cmd 1"
> +Term::command "layout h"
> +Term::command "winheight cmd + 3"
> +
> +# As the tuiterm.exp library just waits for the prompt and command to
> +# be echo'ed bcak to the screen, multiple 'info win' calls like this
> +# have a problem.  Dejagnu will send the command to gdb, but will then
> +# immediately see the '(gdb) info win' output from the first use
> +# above.  This means we end up rushing ahead, and some tests might
> +# fail.
> +#
> +# To work around this, I'm sending a unique command 'p 1' here, that
> +# only happens after the second 'info win' call.  When the 'p 1'
> +# completes, I know the second 'info win' has also completed.
> +Term::command "info win"
> +Term::command "p 1"
> +
> +Term::check_region_contents "info win, layout h" \
> +    0 13 80 11 [multi_line "info win\\s+" \
> +		   "Name\\s+Lines\\s+Columns\\s+Focus\\s+" \
> +		   "src\\s+12\\s+40\\s+\\(has focus\\)\\s+" \
> +		   "asm\\s+12\\s+41\\s+" \
> +		   "status\\s+1\\s+80\\s+" \
> +		   "cmd\\s+11\\s+80\\s+"]
> diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c
> index c85dfd4e882..fd6ca59a728 100644
> --- a/gdb/tui/tui-win.c
> +++ b/gdb/tui/tui-win.c
> @@ -714,9 +714,10 @@ tui_all_windows_info (const char *arg, int from_tty)
>    struct tui_win_info *win_with_focus = tui_win_with_focus ();
>    struct ui_out *uiout = current_uiout;
>  
> -  ui_out_emit_table table_emitter (uiout, 3, -1, "tui-windows");
> +  ui_out_emit_table table_emitter (uiout, 4, -1, "tui-windows");
>    uiout->table_header (10, ui_left, "name", "Name");
>    uiout->table_header (5, ui_right, "lines", "Lines");
> +  uiout->table_header (7, ui_right, "columns", "Columns");
>    uiout->table_header (10, ui_left, "focus", "Focus");
>    uiout->table_body ();
>  
> @@ -727,6 +728,7 @@ tui_all_windows_info (const char *arg, int from_tty)
>  
>  	uiout->field_string ("name", win_info->name ());
>  	uiout->field_signed ("lines", win_info->height);
> +	uiout->field_signed ("columns", win_info->width);
>  	if (win_with_focus == win_info)
>  	  uiout->field_string ("focus", _("(has focus)"));
>  	else
> -- 
> 2.25.4
> 


^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 2/7] gdb/doc: update docs for 'info win' and 'winheight' commands
  2022-01-28 17:03   ` Eli Zaretskii
@ 2022-02-06 13:43     ` Andrew Burgess
  0 siblings, 0 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-02-06 13:43 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches

* Eli Zaretskii via Gdb-patches <gdb-patches@sourceware.org> [2022-01-28 19:03:21 +0200]:

> > Date: Fri, 28 Jan 2022 15:55:03 +0000
> > From: Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org>
> > Cc: Andrew Burgess <aburgess@redhat.com>
> > 
> >  gdb/doc/gdb.texinfo | 13 +++++++------
> >  1 file changed, 7 insertions(+), 6 deletions(-)
> > 
> > diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> > index fe81687a66c..e72fa4aaaae 100644
> > --- a/gdb/doc/gdb.texinfo
> > +++ b/gdb/doc/gdb.texinfo
> 
> This is okay, but...
> 
> > +Change the height of the window @var{name} by @var{count} lines.
> > +Positive counts increase the height, while negative counts decrease
> > +it.  The @var{name} parameter can be the name of any currently visible
> > +window.  The names of the currently visible windows can be discovered
> > +using @code{info win} (@pxref{info_win_command,,info win}).
>          ^^^^^
> Please use @kbd there, not @code.

Thanks, I made this fix, and pushed this patch.

Andrew


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes
  2022-01-28 15:55 [PATCH 0/7] TUI command changes, including new winwidth command Andrew Burgess
                   ` (6 preceding siblings ...)
  2022-01-28 15:55 ` [PATCH 7/7] gdb/tui: add new 'tui window width' command and 'winwidth' alias Andrew Burgess
@ 2022-02-06 14:12 ` Andrew Burgess
  2022-02-06 14:12   ` [PATCHv2 01/15] gdb: move some commands into the tui namespace Andrew Burgess
                     ` (16 more replies)
  2022-03-04 17:23 ` [PATCH 0/7] TUI command changes, including new winwidth command Tom Tromey
  8 siblings, 17 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

I pushed the first two patches from the v1 series, but the rest of
that original series does need reviewing - those paches are included
in v2 as patches 1 to 5.

The remaining 10 patches in the v2 series mostly relate to changing
how window resizing, and window layout occurs.

The docs content in patches 1 and 5 of the v2 series is unchanged from
v1, and was already reviewed, so no new docs review is required there.

There is some new docs content in patch 6, but its pretty minor; a
docs review is always welcome though.

I'm hoping most of the changes in this series will be pretty
non-controversial, the only patch which I think might be more of a
personal taste issue is the very last one (left last for that reason).
I'd suggest selecting the split layout, and then playing with window
resizing to get a feel for the new behaviour.  Feedback welcome.

Thanks,
Andrew

---

Andrew Burgess (15):
  gdb: move some commands into the tui namespace
  gdb/tui: rename tui_layout_base::adjust_size to ::set_height
  gdb/tui: rename tui_layout_split:set_weights_from_heights
  gdb/testing/tui: add new functionality to tuiterm.exp
  gdb/tui: add new 'tui window width' command and 'winwidth' alias
  gdb/tui: add a tui debugging flag
  gdb/tui: add left_boxed_p and right_boxed_p member functions
  gdb/tui/testsuite: refactor new-layout.exp test
  gdb/tui: avoid fp exception when applying layouts
  gdb/tui: fairer distribution of excess space during apply
  gdb/tui: allow cmd window to change size in tui_layout_split::apply
  gdb/tui: support placing the cmd window into a horizontal layout
  gdb/testsuite: some additional tests in gdb.tui/scroll.exp
  gdb/tui: relax restrictions on window max height and width
  gdb/tui: fair split of delta after a resize

 gdb/NEWS                             |  25 ++
 gdb/doc/gdb.texinfo                  |  41 ++-
 gdb/testsuite/gdb.tui/basic.exp      |   4 +-
 gdb/testsuite/gdb.tui/empty.exp      |  14 +-
 gdb/testsuite/gdb.tui/new-layout.exp | 100 +++++--
 gdb/testsuite/gdb.tui/regs.exp       |   4 +-
 gdb/testsuite/gdb.tui/scroll.exp     |   4 +
 gdb/testsuite/gdb.tui/winheight.exp  |  77 +++++
 gdb/testsuite/gdb.tui/winwidth.exp   |  63 ++++
 gdb/testsuite/lib/tuiterm.exp        |  82 +++++-
 gdb/tui/tui-command.c                |   6 -
 gdb/tui/tui-command.h                |   2 -
 gdb/tui/tui-layout.c                 | 419 +++++++++++++++++++++++----
 gdb/tui/tui-layout.h                 | 201 ++++++++++++-
 gdb/tui/tui-win.c                    | 149 ++++++++--
 gdb/tui/tui.c                        |  26 ++
 gdb/tui/tui.h                        |  14 +
 17 files changed, 1089 insertions(+), 142 deletions(-)
 create mode 100644 gdb/testsuite/gdb.tui/winwidth.exp

-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv2 01/15] gdb: move some commands into the tui namespace
  2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess
@ 2022-02-06 14:12   ` Andrew Burgess
  2022-02-06 15:50     ` Eli Zaretskii
  2022-02-06 14:12   ` [PATCHv2 02/15] gdb/tui: rename tui_layout_base::adjust_size to ::set_height Andrew Burgess
                     ` (15 subsequent siblings)
  16 siblings, 1 reply; 74+ messages in thread
From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

There are a lot of tui related commands that live in the top-level
command name space, e.g. layout, focus, refresh, winheight.

Having them at the top level means less typing for the user, which is
good, but, I think, makes command discovery harder.

In this commit, I propose moving all of the above mentioned commands
into the tui namespace, so 'layout' becomes 'tui layout', etc.  But I
will then add aliases so that the old commands will still work,
e.g. I'll make 'layout' an alias for 'tui layout'.

The benefit I see in this work is that tui related commands can be
more easily discovered by typing 'tui ' and then tab-completing.  Also
the "official" command is now a tui-sub-command, this is visible in,
for example, the help output, e.g.:

  (gdb) help layout
  tui layout, layout
  Change the layout of windows.
  Usage: tui layout prev | next | LAYOUT-NAME

  List of tui layout subcommands:

  tui layout asm -- Apply the "asm" layout.
  tui layout next -- Apply the next TUI layout.
  tui layout prev -- Apply the previous TUI layout.
  tui layout regs -- Apply the TUI register layout.
  tui layout split -- Apply the "split" layout.
  tui layout src -- Apply the "src" layout.

Which I think is a good thing, it makes it clearer that this is a tui
command.

I've added a NEWS entry and updated the docs to mention the new and
old command names, with the new name being mentioned first.
---
 gdb/NEWS             | 15 +++++++++++++++
 gdb/doc/gdb.texinfo  | 18 +++++++++++++-----
 gdb/tui/tui-layout.c | 16 +++++++++++++---
 gdb/tui/tui-win.c    | 40 ++++++++++++++++++++++++++++++++--------
 4 files changed, 73 insertions(+), 16 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 8da68c88def..f97f643b6ee 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -81,6 +81,14 @@ maint show gnu-source-highlight enabled
   styling to a particular source file, then the Python Pygments
   library will be used instead.
 
+tui layout
+tui focus
+tui refresh
+tui window height
+  These are the new names for the old 'layout', 'focus', 'refresh',
+  and 'winheight' tui commands respectively.  The old names still
+  exist as aliases to these new commands.
+
 * Changed commands
 
 maint packet
@@ -106,6 +114,13 @@ info win
   This command now includes information about the width of the tui
   windows in its output.
 
+layout
+focus
+refresh
+winheight
+  These commands are now aliases for the 'tui layout', 'tui focus',
+  'tui refresh', and 'tui window height' commands respectively.
+
 * Python API
 
   ** New function gdb.add_history(), which takes a gdb.Value object
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 2073d929099..4d91741bcbd 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -28866,8 +28866,10 @@
 width of the terminal.  Because they have weight 2, the source and
 assembly windows will be twice the height of the command window.
 
-@item layout @var{name}
+@kindex tui layout
 @kindex layout
+@item tui layout @var{name}
+@itemx layout @var{name}
 Changes which TUI windows are displayed.  The @var{name} parameter
 controls which layout is shown.  It can be either one of the built-in
 layout names, or the name of a layout defined by the user using
@@ -28897,8 +28899,9 @@
 register, assembler, and command windows.
 @end table
 
-@item focus @var{name}
 @kindex focus
+@item tui focus @var{name}
+@itemx focus @var{name}
 Changes which TUI window is currently active for scrolling.  The
 @var{name} parameter can be any of the following:
 
@@ -28922,8 +28925,10 @@
 Make the command window active for scrolling.
 @end table
 
-@item refresh
+@kindex tui refresh
 @kindex refresh
+@item tui refresh
+@itemx refresh
 Refresh the screen.  This is similar to typing @kbd{C-L}.
 
 @item tui reg @var{group}
@@ -28959,9 +28964,12 @@
 @kindex update
 Update the source window and the current execution point.
 
-@item winheight @var{name} +@var{count}
-@itemx winheight @var{name} -@var{count}
+@kindex tui window height
 @kindex winheight
+@item tui window height @var{name} +@var{count}
+@itemx tui window height @var{name} -@var{count}
+@itemx winheight @var{name} +@var{count}
+@itemx winheight @var{name} -@var{count}
 Change the height of the window @var{name} by @var{count} lines.
 Positive counts increase the height, while negative counts decrease
 it.  The @var{name} parameter can be the name of any currently visible
diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index cef9190c3e1..f8388e3fca5 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -839,6 +839,14 @@ destroy_layout (struct cmd_list_element *self, void *context)
 
 static struct cmd_list_element *layout_list;
 
+/* Called to implement 'tui layout'.  */
+
+static void
+tui_layout_command (const char *args, int from_tty)
+{
+  help_list (layout_list, "tui layout ", all_commands, gdb_stdout);
+}
+
 /* Add a "layout" command with name NAME that switches to LAYOUT.  */
 
 static struct cmd_list_element *
@@ -1017,10 +1025,12 @@ void _initialize_tui_layout ();
 void
 _initialize_tui_layout ()
 {
-  add_basic_prefix_cmd ("layout", class_tui, _("\
+  struct cmd_list_element *layout_cmd
+    = add_prefix_cmd ("layout", class_tui, tui_layout_command, _("\
 Change the layout of windows.\n\
-Usage: layout prev | next | LAYOUT-NAME"),
-			&layout_list, 0, &cmdlist);
+Usage: tui layout prev | next | LAYOUT-NAME"),
+		      &layout_list, 0, tui_get_cmd_list ());
+  add_com_alias ("layout", layout_cmd, class_tui, 0);
 
   add_cmd ("next", class_tui, tui_next_layout_command,
 	   _("Apply the next TUI layout."),
diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c
index fd6ca59a728..ba6aca3d078 100644
--- a/gdb/tui/tui-win.c
+++ b/gdb/tui/tui-win.c
@@ -977,6 +977,18 @@ parse_scrolling_args (const char *arg,
     }
 }
 
+/* The list of 'tui window' sub-commands.  */
+
+static cmd_list_element *tui_window_cmds = nullptr;
+
+/* Called to implement 'tui window'.  */
+
+static void
+tui_window_command (const char *args, int from_tty)
+{
+  help_list (tui_window_cmds, "tui window ", all_commands, gdb_stdout);
+}
+
 /* Function to initialize gdb commands, for tui window
    manipulation.  */
 
@@ -995,8 +1007,11 @@ _initialize_tui_win ()
 			  &tui_setlist, &tui_showlist,
 			  &setlist, &showlist);
 
-  add_com ("refresh", class_tui, tui_refresh_all_command,
-	   _("Refresh the terminal display."));
+  cmd_list_element *refresh_cmd
+    = add_cmd ("refresh", class_tui, tui_refresh_all_command,
+	       _("Refresh the terminal display."),
+	       tui_get_cmd_list ());
+  add_com_alias ("refresh", refresh_cmd, class_tui, 0);
 
   cmd_list_element *tabset_cmd
     = add_com ("tabset", class_tui, tui_set_tab_width_command, _("\
@@ -1004,21 +1019,30 @@ Set the width (in characters) of tab stops.\n\
 Usage: tabset N"));
   deprecate_cmd (tabset_cmd, "set tui tab-width");
 
+  /* Setup the 'tui window' list of command.  */
+  add_prefix_cmd ("window", class_tui, tui_window_command,
+		  _("Text User Interface window commands."),
+		  &tui_window_cmds, 1, tui_get_cmd_list ());
+
   cmd_list_element *winheight_cmd
-    = add_com ("winheight", class_tui, tui_set_win_height_command, _("\
+    = add_cmd ("height", class_tui, tui_set_win_height_command, _("\
 Set or modify the height of a specified window.\n\
-Usage: winheight WINDOW-NAME [+ | -] NUM-LINES\n\
-Use \"info win\" to see the names of the windows currently being displayed."));
+Usage: tui window height WINDOW-NAME [+ | -] NUM-LINES\n\
+Use \"info win\" to see the names of the windows currently being displayed."),
+	       &tui_window_cmds);
+  add_com_alias ("winheight", winheight_cmd, class_tui, 0);
   add_com_alias ("wh", winheight_cmd, class_tui, 0);
   set_cmd_completer (winheight_cmd, winheight_completer);
   add_info ("win", tui_all_windows_info,
 	    _("List of all displayed windows.\n\
 Usage: info win"));
   cmd_list_element *focus_cmd
-    = add_com ("focus", class_tui, tui_set_focus_command, _("\
+    = add_cmd ("focus", class_tui, tui_set_focus_command, _("\
 Set focus to named window or next/prev window.\n\
-Usage: focus [WINDOW-NAME | next | prev]\n\
-Use \"info win\" to see the names of the windows currently being displayed."));
+Usage: tui focus [WINDOW-NAME | next | prev]\n\
+Use \"info win\" to see the names of the windows currently being displayed."),
+	       tui_get_cmd_list ());
+  add_com_alias ("focus", focus_cmd, class_tui, 0);
   add_com_alias ("fs", focus_cmd, class_tui, 0);
   set_cmd_completer (focus_cmd, focus_completer);
   add_com ("+", class_tui, tui_scroll_forward_command, _("\
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv2 02/15] gdb/tui: rename tui_layout_base::adjust_size to ::set_height
  2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess
  2022-02-06 14:12   ` [PATCHv2 01/15] gdb: move some commands into the tui namespace Andrew Burgess
@ 2022-02-06 14:12   ` Andrew Burgess
  2022-02-06 14:12   ` [PATCHv2 03/15] gdb/tui: rename tui_layout_split:set_weights_from_heights Andrew Burgess
                     ` (14 subsequent siblings)
  16 siblings, 0 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

Rename tui_layout_base::adjust_size to tui_layout_base::set_height,
the new name more accurately reflects what this member function does,
and makes it easier for a later commit to add a new
tui_layout_base::set_width member function.

There should be no user visible changes after this commit.
---
 gdb/tui/tui-layout.c | 6 +++---
 gdb/tui/tui-layout.h | 8 ++++----
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index f8388e3fca5..4c355c79d65 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -118,7 +118,7 @@ tui_apply_current_layout ()
 void
 tui_adjust_window_height (struct tui_win_info *win, int new_height)
 {
-  applied_layout->adjust_size (win->name (), new_height);
+  applied_layout->set_height (win->name (), new_height);
 }
 
 /* Set the current layout to LAYOUT.  */
@@ -570,7 +570,7 @@ tui_layout_split::set_weights_from_heights ()
 /* See tui-layout.h.  */
 
 tui_adjust_result
-tui_layout_split::adjust_size (const char *name, int new_height)
+tui_layout_split::set_height (const char *name, int new_height)
 {
   /* Look through the children.  If one is a layout holding the named
      window, we're done; or if one actually is the named window,
@@ -579,7 +579,7 @@ tui_layout_split::adjust_size (const char *name, int new_height)
   for (int i = 0; i < m_splits.size (); ++i)
     {
       tui_adjust_result adjusted
-	= m_splits[i].layout->adjust_size (name, new_height);
+	= m_splits[i].layout->set_height (name, new_height);
       if (adjusted == HANDLED)
 	return HANDLED;
       if (adjusted == FOUND)
diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h
index b9a5d9b898d..acea7ac8f64 100644
--- a/gdb/tui/tui-layout.h
+++ b/gdb/tui/tui-layout.h
@@ -75,9 +75,9 @@ class tui_layout_base
     return nullptr;
   }
 
-  /* Adjust the size of the window named NAME to NEW_HEIGHT, updating
+  /* Set the height of the window named NAME to NEW_HEIGHT, updating
      the sizes of the other windows around it.  */
-  virtual tui_adjust_result adjust_size (const char *name, int new_height) = 0;
+  virtual tui_adjust_result set_height (const char *name, int new_height) = 0;
 
   /* Remove some windows from the layout, leaving the command window
      and the window being passed in here.  */
@@ -127,7 +127,7 @@ class tui_layout_window : public tui_layout_base
     return m_contents.c_str ();
   }
 
-  tui_adjust_result adjust_size (const char *name, int new_height) override
+  tui_adjust_result set_height (const char *name, int new_height) override
   {
     return m_contents == name ? FOUND : NOT_FOUND;
   }
@@ -192,7 +192,7 @@ class tui_layout_split : public tui_layout_base
 
   void apply (int x, int y, int width, int height) override;
 
-  tui_adjust_result adjust_size (const char *name, int new_height) override;
+  tui_adjust_result set_height (const char *name, int new_height) override;
 
   bool top_boxed_p () const override;
 
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv2 03/15] gdb/tui: rename tui_layout_split:set_weights_from_heights
  2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess
  2022-02-06 14:12   ` [PATCHv2 01/15] gdb: move some commands into the tui namespace Andrew Burgess
  2022-02-06 14:12   ` [PATCHv2 02/15] gdb/tui: rename tui_layout_base::adjust_size to ::set_height Andrew Burgess
@ 2022-02-06 14:12   ` Andrew Burgess
  2022-02-06 14:12   ` [PATCHv2 04/15] gdb/testing/tui: add new functionality to tuiterm.exp Andrew Burgess
                     ` (13 subsequent siblings)
  16 siblings, 0 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

In a following commit I'm going to add the ability to change the width
of a tui window (when in a horizontal layout).  As a result, some of
the places where we currently hard-code references to height need to
be changed to handle either height, or width, based on whether we are
in a vertical, or horizontal layout.

This commit renames set_weights_from_heights to
set_weights_from_sizes, and makes the function use either the height,
or width as appropriate.

Currently, the only place that we call this function is from the
tui_layout_split::set_height function, in a part of the code we will
only reach for vertical layouts, so the new code is not actually being
used, but, this small change will help make later patches smaller, so
I'm proposing this as a stand alone change.

There should be no user visible changes after this commit.
---
 gdb/tui/tui-layout.c | 9 +++++----
 gdb/tui/tui-layout.h | 5 +++--
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index 4c355c79d65..9e856ccf3fa 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -561,10 +561,11 @@ tui_layout_split::bottom_boxed_p () const
 /* See tui-layout.h.  */
 
 void
-tui_layout_split::set_weights_from_heights ()
+tui_layout_split::set_weights_from_sizes ()
 {
   for (int i = 0; i < m_splits.size (); ++i)
-    m_splits[i].weight = m_splits[i].layout->height;
+    m_splits[i].weight
+      = m_vertical ? m_splits[i].layout->height : m_splits[i].layout->width;
 }
 
 /* See tui-layout.h.  */
@@ -596,7 +597,7 @@ tui_layout_split::set_height (const char *name, int new_height)
   if (m_splits[found_index].layout->height == new_height)
     return HANDLED;
 
-  set_weights_from_heights ();
+  set_weights_from_sizes ();
   int delta = m_splits[found_index].weight - new_height;
   m_splits[found_index].weight = new_height;
 
@@ -634,7 +635,7 @@ tui_layout_split::set_height (const char *name, int new_height)
     {
       warning (_("Invalid window height specified"));
       /* Effectively undo any modifications made here.  */
-      set_weights_from_heights ();
+      set_weights_from_sizes ();
     }
   else
     {
diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h
index acea7ac8f64..8f41835b94c 100644
--- a/gdb/tui/tui-layout.h
+++ b/gdb/tui/tui-layout.h
@@ -217,8 +217,9 @@ class tui_layout_split : public tui_layout_base
 
 private:
 
-  /* Set the weights from the current heights.  */
-  void set_weights_from_heights ();
+  /* Set the weights from the current heights (when m_vertical is true) or
+     widths (when m_vertical is false).  */
+  void set_weights_from_sizes ();
 
   struct split
   {
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv2 04/15] gdb/testing/tui: add new functionality to tuiterm.exp
  2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess
                     ` (2 preceding siblings ...)
  2022-02-06 14:12   ` [PATCHv2 03/15] gdb/tui: rename tui_layout_split:set_weights_from_heights Andrew Burgess
@ 2022-02-06 14:12   ` Andrew Burgess
  2022-03-04 16:29     ` Tom Tromey
  2022-02-06 14:12   ` [PATCHv2 05/15] gdb/tui: add new 'tui window width' command and 'winwidth' alias Andrew Burgess
                     ` (12 subsequent siblings)
  16 siblings, 1 reply; 74+ messages in thread
From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

While working on later patches in this series, I was running into csi
control codes being emitted from ncurses that are not currently
handled by out gdb/testsuite/lib/tuiterm.exp.

This commit adds support for these additional control sequences.

The new sequences are 'Insert Line', 'Delete Characters', and 'Scroll
Down'.

There are no new tests in this commit, but I was running into these
sequences while developing later patches in this series.  However,
which control sequences ncurses emits can vary wildly depending on the
screen contents.  It is possible that I only hit some of these
sequences while debugging the later patches (i.e. printing extra
content to the terminal), some of these might no longer be needed
given the tests as now written.

Still, I think it is worth merging these to improve tuiterm.exp.

Additionally, I noticed a bug in 'Erase in Line' that this commit
fixes; in mode 1 the erase should be from the start of the line
through to the cursor, not to the character before the cursor.  This
bug would mean that random characters would sometimes be left in the
terminal output.
---
 gdb/testsuite/lib/tuiterm.exp | 82 ++++++++++++++++++++++++++++++++++-
 1 file changed, 81 insertions(+), 1 deletion(-)

diff --git a/gdb/testsuite/lib/tuiterm.exp b/gdb/testsuite/lib/tuiterm.exp
index 38948015e96..06d2e091ca5 100644
--- a/gdb/testsuite/lib/tuiterm.exp
+++ b/gdb/testsuite/lib/tuiterm.exp
@@ -317,13 +317,40 @@ namespace eval Term {
 		# From cursor to end.
 		_clear_in_line $_cur_col $_cols $_cur_row
 	    } elseif {$arg == 1} {
-		_clear_in_line 0 $_cur_col $_cur_row
+		_clear_in_line 0 [expr $_cur_col + 1] $_cur_row
 	    } elseif {$arg == 2} {
 		_clear_in_line 0 $_cols $_cur_row
 	    }
 	}
     }
 
+    # Insert Line
+    #
+    # https://vt100.net/docs/vt510-rm/IL.html
+    proc _csi_L {args} {
+	set arg [_default [lindex $args 0] 1]
+
+	_log_cur "Insert Line ($arg)" {
+	    variable _cur_col
+	    variable _cur_row
+	    variable _rows
+	    variable _cols
+	    variable _chars
+
+	    set y [expr $_rows - 2]
+	    set next_y [expr $y + 1]
+	    while {$y >= $_cur_row} {
+		for {set x 0} {$x < $_cols} {incr x} {
+		    set _chars($x,$next_y) $_chars($x,$y)
+		}
+		incr y -1
+		incr next_y -1
+	    }
+
+	    _clear_lines $_cur_row $_rows
+	}
+    }
+
     # Delete line.
     #
     # https://vt100.net/docs/vt510-rm/DL.html
@@ -349,6 +376,59 @@ namespace eval Term {
 	}
     }
 
+    # Delete Characters
+    #
+    # https://vt100.net/docs/vt510-rm/DCH.html
+    proc _csi_P {args} {
+	set count [_default [lindex $args 0] 1]
+
+	_log_cur "Delete Character ($count)" {
+	    variable _cur_col
+	    variable _cur_row
+	    variable _cols
+	    variable _chars
+
+	    set dx [expr $_cur_col + 1]
+	    set sx [expr $_cur_col + 1 + $count]
+	    set y $_cur_row
+
+	    while {$sx < $_cols} {
+		set _chars($dx,$y) $_chars($sx,$y)
+		incr sx
+		incr dx
+	    }
+	    _clear_in_line $dx $sx $y
+	}
+    }
+
+    # Pan Down
+    #
+    # https://vt100.net/docs/vt510-rm/SU.html
+    proc _csi_S {args} {
+	set count [_default [lindex $args 0] 1]
+
+	_log_cur "Pan Down ($count)" {
+	    variable _cur_col
+	    variable _cur_row
+	    variable _cols
+	    variable _rows
+	    variable _chars
+
+	    set dy 0
+	    set y $count
+
+	    while {$y < $_rows} {
+		for {set x 0} {$x < $_cols} {incr x} {
+		    set _chars($x,$dy) $_chars($x,$y)
+		}
+		incr y 1
+		incr dy 1
+	    }
+
+	    _clear_lines $dy $_rows
+	}
+    }
+
     # Erase chars.
     #
     # https://vt100.net/docs/vt510-rm/ECH.html
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv2 05/15] gdb/tui: add new 'tui window width' command and 'winwidth' alias
  2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess
                     ` (3 preceding siblings ...)
  2022-02-06 14:12   ` [PATCHv2 04/15] gdb/testing/tui: add new functionality to tuiterm.exp Andrew Burgess
@ 2022-02-06 14:12   ` Andrew Burgess
  2022-02-06 15:52     ` Eli Zaretskii
  2022-03-03 18:52     ` Pedro Alves
  2022-02-06 14:12   ` [PATCHv2 06/15] gdb/tui: add a tui debugging flag Andrew Burgess
                     ` (11 subsequent siblings)
  16 siblings, 2 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

This commit adds a new command 'tui window width', and an alias
'winwidth'.  This command is equivalent to the old 'winheight'
command (which was recently renamed 'tui window height').

Even though I recently moved the old tui commands under the tui
namespace, and I would strongly encourage all new tui commands to be
added as 'tui ....' only (users can create their own top-level aliases
if they want), I'm breaking that suggestion here, and adding a
'winwidth' alias.

Given that we already have 'winheight' and have done for years, it
just didn't seem right to no have the matching 'winwidth'.

You might notice in the test that the window resizing doesn't quite
work right.  I setup a horizontal layout, then grow and shrink the
windows.  At the end of the test the windows should be back to their
original size...

... they are not.  This isn't my fault, honest!  GDB's window resizing
is a little ... temperamental, and is prone to getting things slightly
wrong during resizes, off by 1 type things.  This is true for height
resizing, as well as the new width resizing.

I'm currently working on a patch to improve the resizing algorithm,
which should improve things in this area.  For now, I'm happy that the
width resizing is as good as the height resizing, given the existing
quirks.

As for the changes in gdb itself, I've mostly just templated the
existing height adjustment code so that the two functions
tui_layout_split::adjust_size (tui-layout.c) and
tui_set_win_height_command (tui-win.c) now have a template parameter
"policy", this policy allows me to specialise the functions for either
width or height adjustment.  Function arguments, and locals, are
renamed, replacing 'height' with 'size'.
---
 gdb/NEWS                           |   6 ++
 gdb/doc/gdb.texinfo                |  12 ++++
 gdb/testsuite/gdb.tui/winwidth.exp |  62 +++++++++++++++++
 gdb/tui/tui-layout.c               |  23 +++++--
 gdb/tui/tui-layout.h               | 104 ++++++++++++++++++++++++++++-
 gdb/tui/tui-win.c                  |  99 +++++++++++++++++++++++++--
 6 files changed, 291 insertions(+), 15 deletions(-)
 create mode 100644 gdb/testsuite/gdb.tui/winwidth.exp

diff --git a/gdb/NEWS b/gdb/NEWS
index f97f643b6ee..1faef78056a 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -89,6 +89,12 @@ tui window height
   and 'winheight' tui commands respectively.  The old names still
   exist as aliases to these new commands.
 
+tui window width
+winwidth
+  The new command 'tui window width', and the alias 'winwidth' allow
+  the width of a tui window to be adjusted when windows are laid out
+  in horizontal mode.
+
 * Changed commands
 
 maint packet
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 4d91741bcbd..4793a054f7e 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -28975,6 +28975,18 @@
 it.  The @var{name} parameter can be the name of any currently visible
 window.  The names of the currently visible windows can be discovered
 using @kbd{info win} (@pxref{info_win_command,,info win}).
+
+@kindex tui window width
+@kindex winwidth
+@item tui window width @var{name} +@var{count}
+@itemx tui window width @var{name} -@var{count}
+@itemx winwidth @var{name} +@var{count}
+@itemx winwidth @var{name} -@var{count}
+Change the width of the window @var{name} by @var{count} columns.
+Positive counts increase the width, while negative counts decrease it.
+The @var{name} parameter can be the name of any currently visible
+window.  The names of the currently visible windows can be discovered
+using @code{info win} (@pxref{info_win_command,,info win}).
 @end table
 
 @node TUI Configuration
diff --git a/gdb/testsuite/gdb.tui/winwidth.exp b/gdb/testsuite/gdb.tui/winwidth.exp
new file mode 100644
index 00000000000..b0a838b578f
--- /dev/null
+++ b/gdb/testsuite/gdb.tui/winwidth.exp
@@ -0,0 +1,62 @@
+# Copyright 2022 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test the "winwidth" command.
+
+tuiterm_env
+
+standard_testfile tui-layout.c
+
+if {[build_executable "failed to prepare" ${testfile} ${srcfile}] == -1} {
+    return -1
+}
+
+Term::clean_restart 24 80 $testfile
+if {![Term::enter_tui]} {
+    unsupported "TUI not supported"
+    return
+}
+
+Term::command "tui new-layout h { -horizontal src 1 asm 1 } 1 status 0 cmd 1"
+Term::command "layout h"
+
+with_test_prefix "original window sizes" {
+    Term::check_box "source box" 0 0 40 15
+    Term::check_box "asm box" 39 0 41 15
+    Term::command "winwidth src +5"
+}
+
+with_test_prefix "after src +5" {
+    Term::check_box "source box" 0 0 44 15
+    Term::check_box "asm box" 43 0 37 15
+    Term::command "winwidth asm -5"
+}
+
+with_test_prefix "after asm -5" {
+    Term::check_box "source box" 0 0 48 15
+    Term::check_box "asm box" 47 0 33 15
+    Term::command "winwidth asm +8"
+}
+
+with_test_prefix "after asm +8" {
+    Term::check_box "source box" 0 0 39 15
+    Term::check_box "asm box" 38 0 42 15
+    Term::command "winwidth src -2"
+}
+
+with_test_prefix "after src -2" {
+    Term::check_box "source box" 0 0 36 15
+    Term::check_box "asm box" 35 0 45 15
+}
diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index 9e856ccf3fa..13e4d462426 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -121,6 +121,14 @@ tui_adjust_window_height (struct tui_win_info *win, int new_height)
   applied_layout->set_height (win->name (), new_height);
 }
 
+/* See tui-layout.  */
+
+void
+tui_adjust_window_width (struct tui_win_info *win, int new_width)
+{
+  applied_layout->set_width (win->name (), new_width);
+}
+
 /* Set the current layout to LAYOUT.  */
 
 static void
@@ -570,8 +578,9 @@ tui_layout_split::set_weights_from_sizes ()
 
 /* See tui-layout.h.  */
 
+template<class Policy>
 tui_adjust_result
-tui_layout_split::set_height (const char *name, int new_height)
+tui_layout_split::set_size (const char *name, int new_size)
 {
   /* Look through the children.  If one is a layout holding the named
      window, we're done; or if one actually is the named window,
@@ -580,12 +589,12 @@ tui_layout_split::set_height (const char *name, int new_height)
   for (int i = 0; i < m_splits.size (); ++i)
     {
       tui_adjust_result adjusted
-	= m_splits[i].layout->set_height (name, new_height);
+	= Policy::set_size (m_splits[i].layout, name, new_size);
       if (adjusted == HANDLED)
 	return HANDLED;
       if (adjusted == FOUND)
 	{
-	  if (!m_vertical)
+	  if (!Policy::can_adjust (this))
 	    return FOUND;
 	  found_index = i;
 	  break;
@@ -594,12 +603,12 @@ tui_layout_split::set_height (const char *name, int new_height)
 
   if (found_index == -1)
     return NOT_FOUND;
-  if (m_splits[found_index].layout->height == new_height)
+  if (Policy::current_size (m_splits[found_index].layout) == new_size)
     return HANDLED;
 
   set_weights_from_sizes ();
-  int delta = m_splits[found_index].weight - new_height;
-  m_splits[found_index].weight = new_height;
+  int delta = m_splits[found_index].weight - new_size;
+  m_splits[found_index].weight = new_size;
 
   /* Distribute the "delta" over the next window; but if the next
      window cannot hold it all, keep going until we either find a
@@ -633,7 +642,7 @@ tui_layout_split::set_height (const char *name, int new_height)
 
   if (delta != 0)
     {
-      warning (_("Invalid window height specified"));
+      Policy::invalid_size_warning ();
       /* Effectively undo any modifications made here.  */
       set_weights_from_sizes ();
     }
diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h
index 8f41835b94c..f4ef0895f1f 100644
--- a/gdb/tui/tui-layout.h
+++ b/gdb/tui/tui-layout.h
@@ -79,6 +79,10 @@ class tui_layout_base
      the sizes of the other windows around it.  */
   virtual tui_adjust_result set_height (const char *name, int new_height) = 0;
 
+  /* Set the width of the window named NAME to NEW_WIDTH, updating
+     the sizes of the other windows around it.  */
+  virtual tui_adjust_result set_width (const char *name, int new_width) = 0;
+
   /* Remove some windows from the layout, leaving the command window
      and the window being passed in here.  */
   virtual void remove_windows (const char *name) = 0;
@@ -132,6 +136,11 @@ class tui_layout_window : public tui_layout_base
     return m_contents == name ? FOUND : NOT_FOUND;
   }
 
+  tui_adjust_result set_width (const char *name, int new_width) override
+  {
+    return m_contents == name ? FOUND : NOT_FOUND;
+  }
+
   bool top_boxed_p () const override;
 
   bool bottom_boxed_p () const override;
@@ -192,7 +201,15 @@ class tui_layout_split : public tui_layout_base
 
   void apply (int x, int y, int width, int height) override;
 
-  tui_adjust_result set_height (const char *name, int new_height) override;
+  tui_adjust_result set_height (const char *name, int new_height) override
+  {
+    return set_size<tui_layout_split::set_height_policy> (name, new_height);
+  }
+
+  tui_adjust_result set_width (const char *name, int new_width) override
+  {
+    return set_size<tui_layout_split::set_width_policy> (name, new_width);
+  }
 
   bool top_boxed_p () const override;
 
@@ -217,6 +234,87 @@ class tui_layout_split : public tui_layout_base
 
 private:
 
+  /* Used to implement set_height and set_width member functions.  Set
+     either the height or width of the window named NAME to NEW_SIZE,
+     updating the sizes of the other windows around it as needed.  The
+     POLICY is used to specialize this function to adjust either the height
+     or the width.  */
+
+  template <class Policy>
+  tui_adjust_result set_size (const char *name, int new_size);
+
+  /* A policy class for use with the set_size member function, use when we
+     want to adjust the height of a named window.  */
+
+  struct set_height_policy
+  {
+    /* Set the height of window named NAME to NEW_HEIGHT in LAYOUT.  */
+    static tui_adjust_result
+    set_size (std::unique_ptr<tui_layout_base> &layout,
+	      const char *name,
+	      int new_height)
+    {
+      return layout->set_height (name, new_height);
+    }
+
+    /* Can we adjust the heights of windows in SPLIT?  */
+    static bool
+    can_adjust (const tui_layout_split *split)
+    {
+      return split->m_vertical;
+    }
+
+    /* What is the current height of LAYOUT.  */
+    static int
+    current_size (std::unique_ptr<tui_layout_base> &layout)
+    {
+      return layout->height;
+    }
+
+    /* Warn about invalid height specification.  */
+    static void
+    invalid_size_warning ()
+    {
+      warning (_("Invalid window height specified"));
+    }
+  };
+
+  /* A policy class for use with the set_size member function, use when we
+     want to adjust the width of a named window.  */
+
+  struct set_width_policy
+  {
+    /* Set the width of window named NAME to NEW_HEIGHT in LAYOUT.  */
+    static tui_adjust_result
+    set_size (std::unique_ptr<tui_layout_base> &layout,
+	      const char *name,
+	      int new_width)
+    {
+      return layout->set_width (name, new_width);
+    }
+
+    /* Can we adjust the widths of windows in SPLIT?  */
+    static bool
+    can_adjust (const tui_layout_split *split)
+    {
+      return !split->m_vertical;
+    }
+
+    /* What is the current width of LAYOUT.  */
+    static int
+    current_size (std::unique_ptr<tui_layout_base> &layout)
+    {
+      return layout->width;
+    }
+
+    /* Warn about invalid height specification.  */
+    static void
+    invalid_size_warning ()
+    {
+      warning (_("Invalid window width specified"));
+    }
+  };
+
   /* Set the weights from the current heights (when m_vertical is true) or
      widths (when m_vertical is false).  */
   void set_weights_from_sizes ();
@@ -266,6 +364,10 @@ extern void tui_apply_current_layout ();
 extern void tui_adjust_window_height (struct tui_win_info *win,
 				      int new_height);
 
+/* Adjust the window width of WIN to NEW_WIDTH.  */
+extern void tui_adjust_window_width (struct tui_win_info *win,
+				     int new_width);
+
 /* The type of a function that is used to create a TUI window.  */
 
 typedef std::function<tui_win_info * (const char *name)> window_factory;
diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c
index ba6aca3d078..953af640c93 100644
--- a/gdb/tui/tui-win.c
+++ b/gdb/tui/tui-win.c
@@ -842,10 +842,21 @@ tui_set_tab_width_command (const char *arg, int from_tty)
     }
 }
 
+/* Helper function for the user commands to adjust a window's width or
+   height.  The ARG string contains the command line arguments from the
+   user, which should give the name of a window, and how to adjust the
+   size.
 
-/* Set the height of the specified window.  */
+   The Policy type is used to specialise this function for updating either
+   the width or height of the window.
+
+   On invalid input, or if the size can't be adjusted as requested, then an
+   error is thrown, otherwise, the window sizes are adjusted, and the
+   windows redrawn.  */
+
+template<typename Policy>
 static void
-tui_set_win_height_command (const char *arg, int from_tty)
+tui_set_win_size (const char *arg)
 {
   /* Make sure the curses mode is enabled.  */
   tui_enable ();
@@ -854,7 +865,7 @@ tui_set_win_height_command (const char *arg, int from_tty)
 
   const char *buf = arg;
   const char *buf_ptr = buf;
-  int new_height;
+  int new_size;
   struct tui_win_info *win_info;
 
   buf_ptr = skip_to_space (buf_ptr);
@@ -890,18 +901,82 @@ tui_set_win_height_command (const char *arg, int from_tty)
 	  if (negate)
 	    input_no *= (-1);
 	  if (fixed_size)
-	    new_height = input_no;
+	    new_size = input_no;
 	  else
-	    new_height = win_info->height + input_no;
+	    new_size = Policy::existing_window_size (win_info) + input_no;
 
 	  /* Now change the window's height, and adjust
 	     all other windows around it.  */
-	  tui_adjust_window_height (win_info, new_height);
+	  Policy::adjust_window_size (win_info, new_size);
 	  tui_update_gdb_sizes ();
 	}
       else
-	error (_("Invalid window height specified"));
+	Policy::invalid_size_error ();
+    }
+}
+
+/* Implement the 'tui window height' command (alias 'winheight').  */
+
+static void
+tui_set_win_height_command (const char *arg, int from_tty)
+{
+  /* Policy class for use with tui_set_win_size, this policy adjusts the
+     height of a window.  */
+  struct height_adjustment_policy
+  {
+    /* Called when the size specified is invalid.  */
+    static void invalid_size_error ()
+    {
+      error (_("Invalid window height specified"));
+    }
+
+    /* Return the existing size, height in this case, of a window WIN_INFO.  */
+    static int existing_window_size (struct tui_win_info *win_info)
+    {
+      return win_info->height;
+    }
+
+    /* Set the size, height in this case, of WIN_INFO to NEW_SIZE.  */
+    static void adjust_window_size (struct tui_win_info *win_info,
+				    int new_size)
+    {
+      tui_adjust_window_height (win_info, new_size);
+    }
+  };
+
+  tui_set_win_size<height_adjustment_policy> (arg);
+}
+
+/* Implement the 'tui window width' command (alias 'winwidth').  */
+
+static void
+tui_set_win_width_command (const char *arg, int from_tty)
+{
+  /* Policy class for use with tui_set_win_size, this policy adjusts the
+     width of a window.  */
+  struct width_adjustment_policy
+  {
+    /* Called when the size specified is invalid.  */
+    static void invalid_size_error ()
+    {
+      error (_("Invalid window width specified"));
     }
+
+    /* Return the existing size, width in this case, of a window WIN_INFO.  */
+    static int existing_window_size (struct tui_win_info *win_info)
+    {
+      return win_info->width;
+    }
+
+    /* Set the size, width in this case, of WIN_INFO to NEW_SIZE.  */
+    static void adjust_window_size (struct tui_win_info *win_info,
+				    int new_size)
+    {
+      tui_adjust_window_width (win_info, new_size);
+    }
+  };
+
+  tui_set_win_size<width_adjustment_policy> (arg);
 }
 
 /* See tui-data.h.  */
@@ -1033,6 +1108,16 @@ Use \"info win\" to see the names of the windows currently being displayed."),
   add_com_alias ("winheight", winheight_cmd, class_tui, 0);
   add_com_alias ("wh", winheight_cmd, class_tui, 0);
   set_cmd_completer (winheight_cmd, winheight_completer);
+
+  cmd_list_element *winwidth_cmd
+    = add_cmd ("width", class_tui, tui_set_win_width_command, _("\
+Set or modify the width of a specified window.\n\
+Usage: tui window width WINDOW-NAME [+ | -] NUM-LINES\n\
+Use \"info win\" to see the names of the windows currently being displayed."),
+	       &tui_window_cmds);
+  add_com_alias ("winwidth", winwidth_cmd, class_tui, 0);
+  set_cmd_completer (winwidth_cmd, winheight_completer);
+
   add_info ("win", tui_all_windows_info,
 	    _("List of all displayed windows.\n\
 Usage: info win"));
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv2 06/15] gdb/tui: add a tui debugging flag
  2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess
                     ` (4 preceding siblings ...)
  2022-02-06 14:12   ` [PATCHv2 05/15] gdb/tui: add new 'tui window width' command and 'winwidth' alias Andrew Burgess
@ 2022-02-06 14:12   ` Andrew Burgess
  2022-02-06 15:53     ` Eli Zaretskii
  2022-03-04 16:35     ` Tom Tromey
  2022-02-06 14:12   ` [PATCHv2 07/15] gdb/tui: add left_boxed_p and right_boxed_p member functions Andrew Burgess
                     ` (10 subsequent siblings)
  16 siblings, 2 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

This commit adds 'set debug tui on|off' and 'show debug tui'.  This
commit adds the control variable, and the printing macros in
tui/tui.h.  I've then added some uses of these in tui.c and
tui-layout.c.

To help produce more useful debug output in tui-layout.c, I've added
some helper member functions in the class tui_layout_split, and also
moved the size_info struct out of tui_layout_split::apply into the
tui_layout_split class.

If tui debug is not turned on, then there should be no user visible
changes after this commit.

One thing to note is that, due to the way that the tui terminal is
often cleared, the only way I've found this useful is when I do:

  (gdb) tui enable
  (gdb) set logging file /path/to/file
  (gdb) set logging debugredirect on
  (gdb) set logging enable on

Additionally, gdb has some quirks when it comes to setting up logging
redirect and switching interpreters.  Thus, the above only really
works if the logging is enabled after the tui is enabled, and disabled
again before the tui is disabled.

Enabling logging and switching interpreters can cause undefined
results, including crashes.  This is an existing bug in gdb, and has
nothing directly to do with tui debug, but it is worth mentioning here
I think.
---
 gdb/NEWS             |  4 ++
 gdb/doc/gdb.texinfo  | 11 +++++
 gdb/tui/tui-layout.c | 99 +++++++++++++++++++++++++++++++++++++++-----
 gdb/tui/tui-layout.h | 25 +++++++++++
 gdb/tui/tui.c        | 26 ++++++++++++
 gdb/tui/tui.h        | 14 +++++++
 6 files changed, 168 insertions(+), 11 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 1faef78056a..73d5548ba19 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -95,6 +95,10 @@ winwidth
   the width of a tui window to be adjusted when windows are laid out
   in horizontal mode.
 
+set debug tui on|off
+show debug tui
+  Control the display of debug output about GDB's tui.
+
 * Changed commands
 
 maint packet
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 4793a054f7e..47fbb8d78b1 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -29055,6 +29055,17 @@
 source text at the next tab stop; the compact display uses only as
 much space as is needed for the line numbers in the current file, and
 only a single space to separate the line numbers from the source.
+
+@kindex set debug tui
+@item set debug tui @r{[}on|off@r{]}
+Turn on or off display of @value{GDBN} internal debug messages relating
+to the TUI.
+
+@kindex show debug tui
+@item show debug tui
+Show the current status of displaying @value{GDBN} internal debug
+messages relating to the TUI.
+
 @end table
 
 Note that the colors of the TUI borders can be controlled using the
diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index 13e4d462426..1ce912b3cdb 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -426,8 +426,14 @@ tui_layout_window::apply (int x_, int y_, int width_, int height_)
 void
 tui_layout_window::get_sizes (bool height, int *min_value, int *max_value)
 {
+  TUI_SCOPED_DEBUG_ENTER_EXIT;
+
   if (m_window == nullptr)
     m_window = tui_get_window_by_name (m_contents);
+
+  tui_debug_printf ("window = %s, getting %s",
+		    m_window->name (), (height ? "height" : "width"));
+
   if (height)
     {
       *min_value = m_window->min_height ();
@@ -438,6 +444,8 @@ tui_layout_window::get_sizes (bool height, int *min_value, int *max_value)
       *min_value = m_window->min_width ();
       *max_value = m_window->max_width ();
     }
+
+  tui_debug_printf ("min = %d, max = %d", *min_value, *max_value);
 }
 
 /* See tui-layout.h.  */
@@ -522,6 +530,8 @@ tui_layout_split::clone () const
 void
 tui_layout_split::get_sizes (bool height, int *min_value, int *max_value)
 {
+  TUI_SCOPED_DEBUG_ENTER_EXIT;
+
   *min_value = 0;
   *max_value = 0;
   bool first_time = true;
@@ -544,6 +554,8 @@ tui_layout_split::get_sizes (bool height, int *min_value, int *max_value)
 	}
       first_time = false;
     }
+
+  tui_debug_printf ("min_value = %d, max_value = %d", *min_value, *max_value);
 }
 
 /* See tui-layout.h.  */
@@ -578,10 +590,47 @@ tui_layout_split::set_weights_from_sizes ()
 
 /* See tui-layout.h.  */
 
+std::string
+tui_layout_split::tui_debug_weights_to_string () const
+{
+  std::string str;
+
+  for (int i = 0; i < m_splits.size (); ++i)
+    {
+      if (i > 0)
+       str += ", ";
+      str += string_printf ("[%d] %d", i, m_splits[i].weight);
+    }
+
+  return str;
+}
+
+/* See tui-layout.h.  */
+
+void
+tui_layout_split::tui_debug_print_size_info
+  (const std::vector<tui_layout_split::size_info> &info)
+{
+  gdb_assert (debug_tui);
+
+  tui_debug_printf ("current size info data:");
+  for (int i = 0; i < info.size (); ++i)
+    tui_debug_printf ("  [%d] { size = %d, min = %d, max = %d, share_box = %d }",
+                     i, info[i].size, info[i].min_size,
+                     info[i].max_size, info[i].share_box);
+}
+
+/* See tui-layout.h.  */
+
 template<class Policy>
 tui_adjust_result
 tui_layout_split::set_size (const char *name, int new_size)
 {
+  TUI_SCOPED_DEBUG_ENTER_EXIT;
+
+  tui_debug_printf ("this = %p, name = %s, new_size = %d",
+		    this, name, new_size);
+
   /* Look through the children.  If one is a layout holding the named
      window, we're done; or if one actually is the named window,
      update it.  */
@@ -606,10 +655,15 @@ tui_layout_split::set_size (const char *name, int new_size)
   if (Policy::current_size (m_splits[found_index].layout) == new_size)
     return HANDLED;
 
+  tui_debug_printf ("found window %s at index %d", name, found_index);
+
   set_weights_from_sizes ();
   int delta = m_splits[found_index].weight - new_size;
   m_splits[found_index].weight = new_size;
 
+  tui_debug_printf ("before delta (%d) distribution, weights: %s",
+		    delta, tui_debug_weights_to_string ().c_str ());
+
   /* Distribute the "delta" over the next window; but if the next
      window cannot hold it all, keep going until we either find a
      window that does, or until we loop all the way around.  */
@@ -638,8 +692,14 @@ tui_layout_split::set_size (const char *name, int new_size)
 	  m_splits[index].weight += grow_by;
 	  delta -= grow_by;
 	}
+
+      tui_debug_printf ("index = %d, weight now: %d",
+			index, m_splits[index].weight);
     }
 
+  tui_debug_printf ("after delta (%d) distribution, weights: %s",
+		    delta, tui_debug_weights_to_string ().c_str ());
+
   if (delta != 0)
     {
       Policy::invalid_size_warning ();
@@ -660,23 +720,18 @@ tui_layout_split::set_size (const char *name, int new_size)
 void
 tui_layout_split::apply (int x_, int y_, int width_, int height_)
 {
+  TUI_SCOPED_DEBUG_ENTER_EXIT;
+
   x = x_;
   y = y_;
   width = width_;
   height = height_;
 
-  struct size_info
-  {
-    int size;
-    int min_size;
-    int max_size;
-    /* True if this window will share a box border with the previous
-       window in the list.  */
-    bool share_box;
-  };
-
   std::vector<size_info> info (m_splits.size ());
 
+  tui_debug_printf ("weights are: %s",
+		    tui_debug_weights_to_string ().c_str ());
+
   /* Step 1: Find the min and max size of each sub-layout.
      Fixed-sized layouts are given their desired size, and then the
      remaining space is distributed among the remaining windows
@@ -752,9 +807,31 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_)
 	}
     }
 
+  if (debug_tui)
+    {
+      tui_debug_printf ("after initial size calculation");
+      tui_debug_printf ("available_size = %d, used_size = %d",
+			available_size, used_size);
+      tui_debug_printf ("total_weight = %d, last_index = %d",
+			total_weight, last_index);
+      tui_debug_print_size_info (info);
+    }
+
   /* Allocate any leftover size.  */
   if (available_size >= used_size && last_index != -1)
-    info[last_index].size += available_size - used_size;
+    {
+      info[last_index].size += available_size - used_size;
+
+      if (debug_tui)
+	{
+	  tui_debug_printf ("after final size calculation");
+	  tui_debug_printf ("available_size = %d, used_size = %d",
+			    available_size, used_size);
+	  tui_debug_printf ("total_weight = %d, last_index = %d",
+			    total_weight, last_index);
+	  tui_debug_print_size_info (info);
+	}
+    }
 
   /* Step 3: Resize.  */
   int size_accum = 0;
diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h
index f4ef0895f1f..ebfcae74356 100644
--- a/gdb/tui/tui-layout.h
+++ b/gdb/tui/tui-layout.h
@@ -319,6 +319,31 @@ class tui_layout_split : public tui_layout_base
      widths (when m_vertical is false).  */
   void set_weights_from_sizes ();
 
+  /* Structure used when resizing, or applying a layout.  An instance of
+     this structure is created for each sub-layout.  */
+  struct size_info
+  {
+    /* The calculated size for this sub-layout.  */
+    int size;
+
+    /* The minimum and maximum sizes for this sub-layout, obtained by
+       calling the get_sizes member function.  */
+    int min_size;
+    int max_size;
+
+    /* True if this window will share a box border with the previous
+       window in the list.  */
+    bool share_box;
+  };
+
+  /* Used for debug, prints the contents of INFO using tui_debug_printf.
+     Only call this when the global debug_tui is true.  */
+  static void tui_debug_print_size_info (const std::vector<size_info> &info);
+
+  /* Used for debug, returns a string describing the current weight of each
+     sub-layout.  */
+  std::string tui_debug_weights_to_string () const;
+
   struct split
   {
     /* The requested weight.  */
diff --git a/gdb/tui/tui.c b/gdb/tui/tui.c
index 776dccf0bb2..6332eceb4af 100644
--- a/gdb/tui/tui.c
+++ b/gdb/tui/tui.c
@@ -50,6 +50,19 @@
 #include "gdb_curses.h"
 #include "interps.h"
 
+/* See tui.h.  */
+
+bool debug_tui = false;
+
+/* Implement 'show debug tui'.  */
+
+static void
+show_tui_debug (struct ui_file *file, int from_tty,
+		struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("TUI debugging is \"%s\".\n"), value);
+}
+
 /* This redefines CTRL if it is not already defined, so it must come
    after terminal state releated include files like <term.h> and
    "gdb_curses.h".  */
@@ -354,6 +367,8 @@ gdb_getenv_term (void)
 void
 tui_enable (void)
 {
+  TUI_SCOPED_DEBUG_ENTER_EXIT;
+
   if (tui_active)
     return;
 
@@ -494,6 +509,8 @@ tui_enable (void)
 void
 tui_disable (void)
 {
+  TUI_SCOPED_DEBUG_ENTER_EXIT;
+
   if (!tui_active)
     return;
 
@@ -587,4 +604,13 @@ Usage: tui enable"),
 	   _("Disable TUI display mode.\n\
 Usage: tui disable"),
 	   tuicmd);
+
+  /* Debug this tui internals.  */
+  add_setshow_boolean_cmd ("tui", class_maintenance, &debug_tui,  _("\
+Set tui debugging."), _("\
+Show tui debugging."), _("\
+When true, tui specific internal debugging is enabled."),
+			   NULL,
+			   show_tui_debug,
+			   &setdebuglist, &showdebuglist);
 }
diff --git a/gdb/tui/tui.h b/gdb/tui/tui.h
index a4df66f17fc..924d91daa7e 100644
--- a/gdb/tui/tui.h
+++ b/gdb/tui/tui.h
@@ -22,6 +22,20 @@
 #ifndef TUI_TUI_H
 #define TUI_TUI_H
 
+/* Flag to control tui debugging.  */
+
+extern bool debug_tui;
+
+/* Print a "tui" debug statement.  */
+
+#define tui_debug_printf(fmt, ...) \
+  debug_prefixed_printf_cond (debug_tui, "tui", fmt, ##__VA_ARGS__)
+
+/* Print "tui" enter/exit debug statements.  */
+
+#define TUI_SCOPED_DEBUG_ENTER_EXIT \
+  scoped_debug_enter_exit (debug_tui, "tui")
+
 struct ui_file;
 
 /* Types of error returns.  */
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv2 07/15] gdb/tui: add left_boxed_p and right_boxed_p member functions
  2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess
                     ` (5 preceding siblings ...)
  2022-02-06 14:12   ` [PATCHv2 06/15] gdb/tui: add a tui debugging flag Andrew Burgess
@ 2022-02-06 14:12   ` Andrew Burgess
  2022-03-04 16:37     ` Tom Tromey
  2022-02-06 14:12   ` [PATCHv2 08/15] gdb/tui/testsuite: refactor new-layout.exp test Andrew Burgess
                     ` (9 subsequent siblings)
  16 siblings, 1 reply; 74+ messages in thread
From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

When I initially saw this code in tui_layout_split::apply, I assumed
that this must be a bug:

    /* Two adjacent boxed windows will share a border, making a bit
       more size available.  */
    if (i > 0
        && m_splits[i - 1].layout->bottom_boxed_p ()
        && m_splits[i].layout->top_boxed_p ())
      ...

After all, the apply might be laying out a horizontal layout, right,
so checking bottom_boxed_p and top_boxed_p is clearly wrong.

Well, turns on, that due to the implementations of these things,
bottom_boxed_p is equivalent to an imagined right_boxed_p, and
top_boxed_p is equivalent to an imagined left_boxed_p.

I did consider just adding a comment about this to the above code, but
this still doesn't feel great.  So, in this commit, I've just filled
in the API to add right_boxed_p and left_boxed_p, and now I call these
instead of bottom_boxed_p and top_boxed_p if appropriate.

Maybe it's just pointless noise....

... I'd rather the main apply function not have to have special
knowledge about the implementation of these things coded into it.

There should be no user visible changes after this commit.
---
 gdb/tui/tui-layout.c | 46 ++++++++++++++++++++++++++++++++++++++++++--
 gdb/tui/tui-layout.h | 14 ++++++++++++++
 2 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index 1ce912b3cdb..ca901e5c85d 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -468,6 +468,24 @@ tui_layout_window::bottom_boxed_p () const
 
 /* See tui-layout.h.  */
 
+bool
+tui_layout_window::left_boxed_p () const
+{
+  gdb_assert (m_window != nullptr);
+  return m_window->can_box ();
+}
+
+/* See tui-layout.h.  */
+
+bool
+tui_layout_window::right_boxed_p () const
+{
+  gdb_assert (m_window != nullptr);
+  return m_window->can_box ();
+}
+
+/* See tui-layout.h.  */
+
 void
 tui_layout_window::replace_window (const char *name, const char *new_window)
 {
@@ -580,6 +598,26 @@ tui_layout_split::bottom_boxed_p () const
 
 /* See tui-layout.h.  */
 
+bool
+tui_layout_split::left_boxed_p () const
+{
+  if (m_splits.empty ())
+    return false;
+  return m_splits[0].layout->left_boxed_p ();
+}
+
+/* See tui-layout.h.  */
+
+bool
+tui_layout_split::right_boxed_p () const
+{
+  if (m_splits.empty ())
+    return false;
+  return m_splits.back ().layout->right_boxed_p ();
+}
+
+/* See tui-layout.h.  */
+
 void
 tui_layout_split::set_weights_from_sizes ()
 {
@@ -777,8 +815,12 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_)
       /* Two adjacent boxed windows will share a border, making a bit
 	 more size available.  */
       if (i > 0
-	  && m_splits[i - 1].layout->bottom_boxed_p ()
-	  && m_splits[i].layout->top_boxed_p ())
+	  && ((m_vertical
+	       && m_splits[i - 1].layout->bottom_boxed_p ()
+	       && m_splits[i].layout->top_boxed_p ())
+	      || (!m_vertical
+		  && m_splits[i - 1].layout->right_boxed_p ()
+		  && m_splits[i].layout->left_boxed_p ())))
 	info[i].share_box = true;
     }
 
diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h
index ebfcae74356..e160eaa2256 100644
--- a/gdb/tui/tui-layout.h
+++ b/gdb/tui/tui-layout.h
@@ -68,6 +68,12 @@ class tui_layout_base
   /* True if the bottommost item in this layout is boxed.  */
   virtual bool bottom_boxed_p () const = 0;
 
+  /* True if the leftmost item in this layout is boxed.  */
+  virtual bool left_boxed_p () const = 0;
+
+  /* True if the rightmost item in this layout is boxed.  */
+  virtual bool right_boxed_p () const = 0;
+
   /* Return the name of this layout's window, or nullptr if this
      layout does not represent a single window.  */
   virtual const char *get_name () const
@@ -145,6 +151,10 @@ class tui_layout_window : public tui_layout_base
 
   bool bottom_boxed_p () const override;
 
+  bool left_boxed_p () const override;
+
+  bool right_boxed_p () const override;
+
   void remove_windows (const char *name) override
   {
   }
@@ -215,6 +225,10 @@ class tui_layout_split : public tui_layout_base
 
   bool bottom_boxed_p () const override;
 
+  bool left_boxed_p () const override;
+
+  bool right_boxed_p () const override;
+
   void remove_windows (const char *name) override;
 
   void replace_window (const char *name, const char *new_window) override;
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv2 08/15] gdb/tui/testsuite: refactor new-layout.exp test
  2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess
                     ` (6 preceding siblings ...)
  2022-02-06 14:12   ` [PATCHv2 07/15] gdb/tui: add left_boxed_p and right_boxed_p member functions Andrew Burgess
@ 2022-02-06 14:12   ` Andrew Burgess
  2022-02-06 14:12   ` [PATCHv2 09/15] gdb/tui: avoid fp exception when applying layouts Andrew Burgess
                     ` (8 subsequent siblings)
  16 siblings, 0 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

This commit changes the gdb.tui/new-layout.exp test to make use of a
list of test descriptions, and a loop to check each description in
turn.  There's no change to what is actually tested after this commit.

In future commits I plan to add additional tests to this file, and
this will be easier now that all I have to do is add a new test
description to the list.
---
 gdb/testsuite/gdb.tui/new-layout.exp | 83 +++++++++++++++++++---------
 1 file changed, 56 insertions(+), 27 deletions(-)

diff --git a/gdb/testsuite/gdb.tui/new-layout.exp b/gdb/testsuite/gdb.tui/new-layout.exp
index 2b5e07db612..d3d34af7439 100644
--- a/gdb/testsuite/gdb.tui/new-layout.exp
+++ b/gdb/testsuite/gdb.tui/new-layout.exp
@@ -55,20 +55,39 @@ if { [tcl_version_at_least 8 6] } {
 	"Missing '\}' in layout specification"
 }
 
-gdb_test_no_output "tui new-layout example asm 1 status 0 cmd 1"
-
-gdb_test "help layout example" \
-    "Apply the \"example\" layout.*tui new-layout example asm 1 status 0 cmd 1"
-
-gdb_test_no_output "tui new-layout example2 {asm 1 status 0} 1 cmd 1"
-
-gdb_test "help layout example2" \
-    "Apply the \"example2\" layout.*tui new-layout example2 {asm 1 status 0} 1 cmd 1"
-
-gdb_test_no_output "tui new-layout h {-horizontal asm 1 src 1} 1 status 0 cmd 1"
+# Each entry of this list describes a layout, and some associated
+# tests.  The items within each entry are:
+# 1. layout name,
+# 2. a string used to create the layout,
+# 3. a list of boxes to check for once the layout is selected,
+# 4. a regexp to match against the whole screen contents, this
+#    can be empty to skip this check.
+set layouts \
+    [list \
+	 [list example "asm 1 status 0 cmd 1" \
+	      {{0 0 80 15}} "$hex <main>"] \
+	 [list example2 "{asm 1 status 0} 1 cmd 1" \
+	      {{0 0 80 15}} ""] \
+	 [list h "{-horizontal asm 1 src 1} 1 status 0 cmd 1" \
+	      {{0 0 40 15} {39 0 41 15}} \
+	      "$hex <main>.*21.*return 0"]]
+
+# Helper function to verify a list of boxes.
+proc check_boxes {boxes} {
+    set boxno 1
+    foreach box $boxes {
+	eval Term::check_box [list "box $boxno"] $box
+	incr boxno
+    }
+}
 
-gdb_test "help layout h" \
-    "Apply the \"h\" layout.*tui new-layout h {-horizontal asm 1 src 1} 1 status 0 cmd 1"
+# Now create the layouts.
+foreach layout $layouts {
+    lassign $layout name desc
+    gdb_test_no_output "tui new-layout $name $desc"
+    gdb_test "help layout $name" \
+	"Apply the \"$name\" layout.*tui new-layout $name $desc"
+}
 
 if {![Term::enter_tui]} {
     unsupported "TUI not supported"
@@ -79,20 +98,30 @@ set text [Term::get_all_lines]
 gdb_assert {![string match "No Source Available" $text]} \
     "initial source listing"
 
-Term::command "layout example"
-Term::check_contents "example layout shows assembly" \
-    "$hex <main>"
+foreach_with_prefix layout $layouts {
+    lassign $layout name desc boxes content_pattern
+
+    # Reset the layout to a known starting configuration.
+    Term::command "layout src"
+    Term::command "winheight cmd 8"
+
+    # Apply our test layout.
+    Term::command "layout $name"
+    check_boxes $boxes
 
-Term::command "layout h"
-Term::check_box "left window box" 0 0 40 15
-Term::check_box "right window box" 39 0 41 15
-Term::check_contents "horizontal display" \
-    "$hex <main>.*21.*return 0"
+    if {$content_pattern != ""} {
+	Term::check_contents "contents in layout $name" \
+	    "${content_pattern}"
+    }
 
-Term::command "winheight src - 5"
-Term::check_box "left window box after shrink" 0 0 40 10
-Term::check_box "right window box after shrink" 39 0 41 10
+    # Some additional tests for the 'h' layout.
+    if {$name == "h"} {
+	Term::command "winheight src - 5"
+	Term::check_box "left window box after shrink" 0 0 40 10
+	Term::check_box "right window box after shrink" 39 0 41 10
 
-Term::command "winheight src + 5"
-Term::check_box "left window box after grow" 0 0 40 15
-Term::check_box "right window box after grow" 39 0 41 15
+	Term::command "winheight src + 5"
+	Term::check_box "left window box after grow" 0 0 40 15
+	Term::check_box "right window box after grow" 39 0 41 15
+    }
+}
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv2 09/15] gdb/tui: avoid fp exception when applying layouts
  2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess
                     ` (7 preceding siblings ...)
  2022-02-06 14:12   ` [PATCHv2 08/15] gdb/tui/testsuite: refactor new-layout.exp test Andrew Burgess
@ 2022-02-06 14:12   ` Andrew Burgess
  2022-02-06 14:12   ` [PATCHv2 10/15] gdb/tui: fairer distribution of excess space during apply Andrew Burgess
                     ` (7 subsequent siblings)
  16 siblings, 0 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

Consider:

  (gdb) tui enable
  (gdb) layout src
  (gdb) tui new-layout conly cmd 1
  (gdb) layout conly

After this, with current master, gdb crashes with a floating-point
exception.

The problem is that in tui_layout_split::apply, when we switch from
'src' to 'conly', we will try to retain the cmd window height.  As
such, the cmd window will become a fixed size window, which decreases
the available_size, but doesn't count towards the total_weight.

As the cmd window is the only window, the total_weight stays at zero,
and, when we move into step 2, where we attempt to size the windows,
we perform a divide by zero, and crash.

After this commit we avoid the divide by zero, and just directly set
the window size based on the fixed size.

There is still a problem after this commit, when the conly layout is
selected the cmd window retains its original height, which will only
be part of the terminal.  The rest of the terminal is left unused.
This issue will be addressed in a later commit, this commit is just
about the floating-point exception.
---
 gdb/testsuite/gdb.tui/new-layout.exp |  3 ++-
 gdb/tui/tui-layout.c                 | 30 ++++++++++++++++++----------
 2 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/gdb/testsuite/gdb.tui/new-layout.exp b/gdb/testsuite/gdb.tui/new-layout.exp
index d3d34af7439..66048e65238 100644
--- a/gdb/testsuite/gdb.tui/new-layout.exp
+++ b/gdb/testsuite/gdb.tui/new-layout.exp
@@ -70,7 +70,8 @@ set layouts \
 	      {{0 0 80 15}} ""] \
 	 [list h "{-horizontal asm 1 src 1} 1 status 0 cmd 1" \
 	      {{0 0 40 15} {39 0 41 15}} \
-	      "$hex <main>.*21.*return 0"]]
+	      "$hex <main>.*21.*return 0"] \
+	 [list cmd_only "cmd 1" {} ""]]
 
 # Helper function to verify a list of boxes.
 proc check_boxes {boxes} {
diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index ca901e5c85d..1de34c34e62 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -824,29 +824,37 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_)
 	info[i].share_box = true;
     }
 
+  /* If last_index is set then we have a window that is not of a fixed
+     size.  This window will have its size calculated below, which requires
+     that the total_weight not be zero (we divide by total_weight, so don't
+     want a floating-point exception).  */
+  gdb_assert (last_index == -1 || total_weight > 0);
+
   /* Step 2: Compute the size of each sub-layout.  Fixed-sized items
      are given their fixed size, while others are resized according to
      their weight.  */
   int used_size = 0;
   for (int i = 0; i < m_splits.size (); ++i)
     {
-      /* Compute the height and clamp to the allowable range.  */
-      info[i].size = available_size * m_splits[i].weight / total_weight;
-      if (info[i].size > info[i].max_size)
-	info[i].size = info[i].max_size;
-      if (info[i].size < info[i].min_size)
-	info[i].size = info[i].min_size;
-      /* If there is any leftover size, just redistribute it to the
-	 last resizeable window, by dropping it from the allocated
-	 size.  We could try to be fancier here perhaps, by
-	 redistributing this size among all windows, not just the
-	 last window.  */
       if (info[i].min_size != info[i].max_size)
 	{
+	  /* Compute the height and clamp to the allowable range.  */
+	  info[i].size = available_size * m_splits[i].weight / total_weight;
+	  if (info[i].size > info[i].max_size)
+	    info[i].size = info[i].max_size;
+	  if (info[i].size < info[i].min_size)
+	    info[i].size = info[i].min_size;
+	  /* If there is any leftover size, just redistribute it to the
+	     last resizeable window, by dropping it from the allocated
+	     size.  We could try to be fancier here perhaps, by
+	     redistributing this size among all windows, not just the
+	     last window.  */
 	  used_size += info[i].size;
 	  if (info[i].share_box)
 	    --used_size;
 	}
+      else
+	info[i].size = info[i].min_size;
     }
 
   if (debug_tui)
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv2 10/15] gdb/tui: fairer distribution of excess space during apply
  2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess
                     ` (8 preceding siblings ...)
  2022-02-06 14:12   ` [PATCHv2 09/15] gdb/tui: avoid fp exception when applying layouts Andrew Burgess
@ 2022-02-06 14:12   ` Andrew Burgess
  2022-03-04 16:42     ` Tom Tromey
  2022-02-06 14:12   ` [PATCHv2 11/15] gdb/tui: allow cmd window to change size in tui_layout_split::apply Andrew Burgess
                     ` (6 subsequent siblings)
  16 siblings, 1 reply; 74+ messages in thread
From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

When applying layouts gdb computes the size of each window (or rather,
each sub-layout within a layout) using integer arithmetic.  As this
rounds down the results, then, when all sub-layouts are sized, there
is the possibility that we have some space left over.

Currently, this space is just assigned to an arbitrary sub-layout.

This can result in some unbalanced results.  Consider this set of
steps with current master:

  (gdb) tui enable
  (gdb) layout regs
  (gdb) info win
  Name       Lines Columns Focus
  regs           7      80
  src            9      80 (has focus)
  status         1      80
  cmd            8      80

Notice the weird split between the src and regs windows, the original
layout specification has these windows given equal weight.  The
problem is that, with rounding, both the regs and src windows are
initially sized to 7, the extra 2 lines are then arbitrarily added to
the src window.

In this commit, rather than add all the extra space to one single
window, I instead hand out the extra space 1 line at a time, looping
over all the sub-layouts.  We take care to respect the min/max sizes,
and so, we now get this result:

  (gdb) tui enable
  (gdb) layout regs
  (gdb) info win
  Name       Lines Columns Focus
  regs           8      80
  src            8      80 (has focus)
  status         1      80
  cmd            8      80

This looks more natural to me.

This is obviously a change in behaviour, and so, lots of the existing
tests need to be updated to take this into account.  None of the
changes are huge, it's just a line or two (or column for width) moved
between windows.
---
 gdb/testsuite/gdb.tui/basic.exp    |  4 ++--
 gdb/testsuite/gdb.tui/empty.exp    | 14 +++++++++-----
 gdb/testsuite/gdb.tui/regs.exp     |  4 ++--
 gdb/testsuite/gdb.tui/winwidth.exp | 17 +++++++++--------
 gdb/tui/tui-layout.c               | 28 ++++++++++++++++++++++++++--
 5 files changed, 48 insertions(+), 19 deletions(-)

diff --git a/gdb/testsuite/gdb.tui/basic.exp b/gdb/testsuite/gdb.tui/basic.exp
index 0e9f2e3eab2..7afb28b0858 100644
--- a/gdb/testsuite/gdb.tui/basic.exp
+++ b/gdb/testsuite/gdb.tui/basic.exp
@@ -104,5 +104,5 @@ Term::command "layout split"
 Term::check_contents "split layout contents" \
     "$main_line *$main_re.*$hex <main>"
 
-Term::check_box "source box in split layout" 0 0 80 7
-Term::check_box "asm box in split layout" 0 6 80 9
+Term::check_box "source box in split layout" 0 0 80 8
+Term::check_box "asm box in split layout" 0 7 80 8
diff --git a/gdb/testsuite/gdb.tui/empty.exp b/gdb/testsuite/gdb.tui/empty.exp
index ef14fe4dac0..3efa55d812e 100644
--- a/gdb/testsuite/gdb.tui/empty.exp
+++ b/gdb/testsuite/gdb.tui/empty.exp
@@ -35,26 +35,26 @@ if {![Term::enter_tui]} {
 set layouts {
     {src src {{0 0 80 15}} {{0 0 90 26}}
 	{{"no source" "No Source Available"}}}
-    {regs src-regs {{0 0 80 7} {0 6 80 9}} {{0 0 90 13} {0 12 90 13}}
+    {regs src-regs {{0 0 80 8} {0 7 80 8}} {{0 0 90 13} {0 12 90 13}}
 	{
 	    {"no source" "No Source Available"}
 	    {"no regs" "Register Values Unavailable"}
 	}}
-    {asm asm {{0 0 80 13}} {{0 0 90 26}}
+    {asm asm {{0 0 80 15}} {{0 0 90 26}}
 	{
 	    {"no asm" "No Assembly Available"}
 	}}
-    {regs asm-regs {{0 0 80 7} {0 6 80 9}} {{0 0 90 13} {0 12 90 13}}
+    {regs asm-regs {{0 0 80 8} {0 7 80 8}} {{0 0 90 13} {0 12 90 13}}
 	{
 	    {"no asm" "No Assembly Available"}
 	    {"no regs" "Register Values Unavailable"}
 	}}
-    {split split {{0 0 80 6} {0 5 80 8}} {{0 0 90 13} {0 12 90 13}}
+    {split split {{0 0 80 8} {0 7 80 8}} {{0 0 90 13} {0 12 90 13}}
 	{
 	    {"no source" "No Source Available"}
 	    {"no asm" "No Assembly Available"}
 	}}
-    {regs split-regs {{0 0 80 6} {0 5 80 8}} {{0 0 90 13} {0 12 90 13}}
+    {regs split-regs {{0 0 80 8} {0 7 80 8}} {{0 0 90 13} {0 12 90 13}}
 	{
 	    {"no asm" "No Assembly Available"}
 	    {"no regs" "Register Values Unavailable"}
@@ -97,5 +97,9 @@ foreach layout $layouts {
 	    check_text $text_list
 	}
 	Term::resize 24 80
+	with_test_prefix "80x24 again" {
+	    check_boxes $small_boxes
+	    check_text $text_list
+	}
     }
 }
diff --git a/gdb/testsuite/gdb.tui/regs.exp b/gdb/testsuite/gdb.tui/regs.exp
index 178eba03f19..2f3482f5d38 100644
--- a/gdb/testsuite/gdb.tui/regs.exp
+++ b/gdb/testsuite/gdb.tui/regs.exp
@@ -38,8 +38,8 @@ if {![Term::enter_tui]} {
 Term::check_contents "source at startup" "\\|.*21 *return 0"
 
 Term::command "layout regs"
-Term::check_box "register box" 0 0 80 7
-Term::check_box "source box in regs layout" 0 6 80 9
+Term::check_box "register box" 0 0 80 8
+Term::check_box "source box in regs layout" 0 7 80 8
 
 set text [Term::get_line 1]
 # Just check for any register window content at all.
diff --git a/gdb/testsuite/gdb.tui/winwidth.exp b/gdb/testsuite/gdb.tui/winwidth.exp
index b0a838b578f..1767b25c8d3 100644
--- a/gdb/testsuite/gdb.tui/winwidth.exp
+++ b/gdb/testsuite/gdb.tui/winwidth.exp
@@ -39,24 +39,25 @@ with_test_prefix "original window sizes" {
 }
 
 with_test_prefix "after src +5" {
-    Term::check_box "source box" 0 0 44 15
-    Term::check_box "asm box" 43 0 37 15
+    Term::check_box "source box" 0 0 45 15
+    Term::check_box "asm box" 44 0 36 15
     Term::command "winwidth asm -5"
 }
 
 with_test_prefix "after asm -5" {
-    Term::check_box "source box" 0 0 48 15
-    Term::check_box "asm box" 47 0 33 15
+    Term::dump_screen
+    Term::check_box "source box" 0 0 50 15
+    Term::check_box "asm box" 49 0 31 15
     Term::command "winwidth asm +8"
 }
 
 with_test_prefix "after asm +8" {
-    Term::check_box "source box" 0 0 39 15
-    Term::check_box "asm box" 38 0 42 15
+    Term::check_box "source box" 0 0 42 15
+    Term::check_box "asm box" 41 0 39 15
     Term::command "winwidth src -2"
 }
 
 with_test_prefix "after src -2" {
-    Term::check_box "source box" 0 0 36 15
-    Term::check_box "asm box" 35 0 45 15
+    Term::check_box "source box" 0 0 40 15
+    Term::check_box "asm box" 39 0 41 15
 }
diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index 1de34c34e62..8ba54a68fab 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -868,9 +868,33 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_)
     }
 
   /* Allocate any leftover size.  */
-  if (available_size >= used_size && last_index != -1)
+  if (available_size > used_size && last_index != -1)
     {
-      info[last_index].size += available_size - used_size;
+      /* Loop over all windows until all available space is used up.  */
+      bool found_window_that_can_grow_p = true;
+      for (int idx = last_index;
+	   available_size > used_size;
+	   idx = (idx + 1) % m_splits.size ())
+	{
+	  /* Once we have visited all of the windows, check that we did
+	     manage to allocate some more space.  This prevents us getting
+	     stuck in the loop forever if we can't allocate anything
+	     more.  */
+	  if (idx == last_index)
+	    {
+	      if (!found_window_that_can_grow_p)
+		break;
+	      found_window_that_can_grow_p = false;
+	    }
+
+	  if (available_size > used_size
+	      && info[idx].size < info[idx].max_size)
+	    {
+	      found_window_that_can_grow_p = true;
+	      info[idx].size += 1;
+	      used_size += 1;
+	    }
+	}
 
       if (debug_tui)
 	{
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv2 11/15] gdb/tui: allow cmd window to change size in tui_layout_split::apply
  2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess
                     ` (9 preceding siblings ...)
  2022-02-06 14:12   ` [PATCHv2 10/15] gdb/tui: fairer distribution of excess space during apply Andrew Burgess
@ 2022-02-06 14:12   ` Andrew Burgess
  2022-02-06 14:12   ` [PATCHv2 12/15] gdb/tui: support placing the cmd window into a horizontal layout Andrew Burgess
                     ` (5 subsequent siblings)
  16 siblings, 0 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

When we switch layouts we call the tui_layout_split::apply member
function to reapply the layout, and recalculate all the window sizes.

One special case is the cmd window, which we try to keep at its
existing size.

However, in some cases it is not appropriate to keep the cmd window at
its existing size.  I will describe two such cases here, in one, we
want the cmd window to reduce in size, and in the other, we want the
cmd window to grow in size.

Try these steps in a 80 columns, by 24 lines terminal:

  (gdb) tui enable
  (gdb) layout src
  (gdb) winheight cmd 20
  (gdb) layout split

You should see that the status window is missing from the new layout,
and that the cmd window has been placed over the border of the asm
window.  The 'info win' output is:

  (gdb) info win
  Name       Lines Columns Focus
  src            3      80 (has focus)
  asm            3      80
  status         1      80
  cmd           20      80

Notice that gdb has assigned 27 lines of screen space, even with the
border overlap between the src and asm windows, this is still 2 lines
too many.

The problem here is that after switching layouts, gdb has forced the
cmd window to retain its 20 line height.  Really, we want the cmd
window to reduce in height so that the src and asm windows can occupy
their minimum required space.

This commit allows this (details on how are below).  After this
commit, in the above situation, we now see the status window displayed
correctly, and the 'info win' output is:

  (gdb) info win
  Name       Lines Columns Focus
  src            3      80 (has focus)
  asm            3      80
  status         1      80
  cmd           18      80

The cmd window has been reduced in size by 2 lines so that everything
can fit on the screen.

The second example is one which was discussed in a recent commit,
consider this case (still in the 80 column, 24 line terminal):

  (gdb) tui enable
  (gdb) tui new-layout conly cmd 1
  (gdb) layout conly
  (gdb) info win
  Name       Lines Columns Focus
  cmd            8      80 (has focus)
  (gdb)

This layout only contains a cmd window, which we would expect to
occupy the entire terminal.  But instead, the cmd window only occupies
the first 8 lines, and the rest of the terminal is unused!

The reason is, again, that the cmd window is keeping its previous
size (8 lines).

After this commit things are slightly different, the 'info win' output
is now:

  (gdb) info win
  Name       Lines Columns Focus
  cmd           20      80 (has focus)

Which is a little better, but why only 20 lines?  Turns out there's
yet another bug hitting this case.  That bug will be addressed in a
later commit, so, for now, we're accepting the 20 lines.

What this commit does is modify the phase of tui_layout_split::apply
that handles any left over space.  Usually, in "Step 2", each
sub-layout has a size calculated.  As the size is an integer, then,
when all sizes are calculated we may have some space left over.

This extra space is then distributed between all the windows fairly
until all the space is used up.

When we consider windows minimum size, or fixed size windows, then it
is possible that we might try to use more space than is available,
this was our first example above.  The same code that added extra
space to the windows, can also be used to reclaim space (in the over
allocation case) to allow all windows to fit.

The problem then is the cmd window, which we often force to a fixed
size.  Inside the loop that handles the allocation of excess space, if
we find that we have tried every window, and still have space either
left to give, or we need to claim back more space, then, if the cmd
window was changed to a fixed size, we can change the cmd window back
to a non-fixed-size window, and proceed to either give, or take space
from the cmd window as needed.
---
 gdb/testsuite/gdb.tui/new-layout.exp |  9 +++
 gdb/testsuite/gdb.tui/winheight.exp  | 46 ++++++++++++++
 gdb/tui/tui-layout.c                 | 95 +++++++++++++++++++++++++---
 3 files changed, 142 insertions(+), 8 deletions(-)

diff --git a/gdb/testsuite/gdb.tui/new-layout.exp b/gdb/testsuite/gdb.tui/new-layout.exp
index 66048e65238..0d49d033be5 100644
--- a/gdb/testsuite/gdb.tui/new-layout.exp
+++ b/gdb/testsuite/gdb.tui/new-layout.exp
@@ -124,5 +124,14 @@ foreach_with_prefix layout $layouts {
 	Term::command "winheight src + 5"
 	Term::check_box "left window box after grow" 0 0 40 15
 	Term::check_box "right window box after grow" 39 0 41 15
+    } elseif {$name == "cmd_only"} {
+	Term::check_region_contents "bottom of cmd window is blank" \
+	    0 14 80 10 "^\\s+$"
+	Term::command "info win"
+	Term::check_region_contents "info win output" \
+	    0 0 80 24 [multi_line "info win\\s+" \
+			   "Name\\s+Lines\\s+Columns\\s+Focus\\s+" \
+			   "cmd\\s+20\\s+80\\s+\\(has focus\\)\\s+" \
+			   "$gdb_prompt\\s+"]
     }
 }
diff --git a/gdb/testsuite/gdb.tui/winheight.exp b/gdb/testsuite/gdb.tui/winheight.exp
index 0d0c886304d..b541c21b825 100644
--- a/gdb/testsuite/gdb.tui/winheight.exp
+++ b/gdb/testsuite/gdb.tui/winheight.exp
@@ -50,3 +50,49 @@ Term::check_box "larger source box again" 0 0 80 15
 Term::command "layout asm"
 Term::check_box "check for asm window" 0 0 80 15
 
+
+# Check what happens when we switch from src layout to split layout.
+# The interesting thing here is that the src layout has one flexible
+# window (the src), the status window, which is of fixed size, and the
+# cmd window, which tries to retain its size when a layout changes.
+#
+# In contrast, the split layout has both a src and asm window, plus
+# the same status and cmd windows.
+#
+# Of particular interest here is the first test, where we maximise the
+# cmd window before switching to split.  This requires gdb to realise
+# that it has to shrink the cmd window, even though this is something
+# gdb usually avoids doing.
+#
+# Each test here is a size for the src window in the 'src' layout.
+# The test then switches to the 'split' layout, and calculates the
+# expected window sizes.
+foreach_with_prefix cmd_size {20 12 5} {
+    set src_size_before [expr 24 - ${cmd_size} - 1]
+    set split_size [expr (24 - ${cmd_size}) / 2]
+
+    if { $split_size < 3 } {
+	# The minimum window size is 3, so force that.
+	set src_size_after 3
+	set asm_size_after 3
+    } elseif { [expr $split_size % 2] == 0 } {
+	# The remaining space can be divided evenly between the two
+	# windows.
+	set src_size_after ${split_size}
+	set asm_size_after ${split_size}
+    } else {
+	# The space can't be divided evenly, the asm window will get
+	# the extra line.
+	set src_size_after ${split_size}
+	set asm_size_after [expr ${split_size} + 1]
+    }
+
+    Term::command "layout src"
+    Term::command "winheight cmd ${cmd_size}"
+    Term::check_box "check for src window" 0 0 80 ${src_size_before}
+
+    # Both windows should be of equal size, which will be their minimum.
+    Term::command "layout split"
+    Term::check_box "check for src window in split" 0 0 80 ${src_size_after}
+    Term::check_box "check for asm window in split" 0 [expr ${src_size_after} - 1] 80 ${asm_size_after}
+}
diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index 8ba54a68fab..87097cb7166 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -765,6 +765,30 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_)
   width = width_;
   height = height_;
 
+  /* In some situations we fix the size of the cmd window.  However,
+     occasionally this turns out to be a mistake.  This struct is used to
+     hold the original information about the cmd window, so we can restore
+     it if needed.  */
+  struct old_size_info
+  {
+    /* Constructor.  */
+    old_size_info (int index_, int min_size_, int max_size_)
+      : index (index_),
+	min_size (min_size_),
+	max_size (max_size_)
+    { /* Nothing.  */ }
+
+    /* The index in m_splits where the cmd window was found.  */
+    int index;
+
+    /* The previous min/max size.  */
+    int min_size;
+    int max_size;
+  };
+
+  /* This is given a value only if we fix the size of the cmd window.  */
+  gdb::optional<old_size_info> old_cmd_info;
+
   std::vector<size_info> info (m_splits.size ());
 
   tui_debug_printf ("weights are: %s",
@@ -792,6 +816,10 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_)
 	  && m_splits[i].layout->get_name () != nullptr
 	  && strcmp (m_splits[i].layout->get_name (), "cmd") == 0)
 	{
+	  /* Save the old cmd window information, in case we need to
+	     restore it later.  */
+          old_cmd_info.emplace (i, info[i].min_size, info[i].max_size);
+
 	  /* If this layout has never been applied, then it means the
 	     user just changed the layout.  In this situation, it's
 	     desirable to keep the size of the command window the
@@ -867,22 +895,66 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_)
       tui_debug_print_size_info (info);
     }
 
+  /* If we didn't find any sub-layouts that were of a non-fixed size, but
+     we did find the cmd window, then we can consider that a sort-of
+     non-fixed size sub-layout.
+
+     The cmd window might, initially, be of a fixed size (see above), but,
+     we are willing to relax this constraint if required to correctly apply
+     this layout (see below).  */
+  if (last_index == -1 && old_cmd_info.has_value ())
+    last_index = old_cmd_info->index;
+
   /* Allocate any leftover size.  */
-  if (available_size > used_size && last_index != -1)
+  if (available_size != used_size && last_index != -1)
     {
-      /* Loop over all windows until all available space is used up.  */
+      /* Loop over all windows until the amount of used space is equal to
+	 the amount of available space.  There's an escape hatch within
+	 the loop in case we can't find any sub-layouts to resize.  */
       bool found_window_that_can_grow_p = true;
       for (int idx = last_index;
-	   available_size > used_size;
+	   available_size != used_size;
 	   idx = (idx + 1) % m_splits.size ())
 	{
-	  /* Once we have visited all of the windows, check that we did
-	     manage to allocate some more space.  This prevents us getting
-	     stuck in the loop forever if we can't allocate anything
-	     more.  */
+	  /* Every time we get back to last_index, which is where the loop
+	     started, we check to make sure that we did assign some space
+	     to a window, bringing used_size closer to available_size.
+
+	     If we didn't, but the cmd window is of a fixed size, then we
+	     can make the console window non-fixed-size, and continue
+	     around the loop, hopefully, this will allow the layout to be
+	     applied correctly.
+
+	     If we still make it around the loop without moving used_size
+	     closer to available_size, then there's nothing more we can do,
+	     and we break out of the loop.  */
 	  if (idx == last_index)
 	    {
-	      if (!found_window_that_can_grow_p)
+	      /* If the used_size is greater than the available_size then
+		 this indicates that the fixed-sized sub-layouts claimed
+		 more space than is available.  This layout is not going to
+		 work.  Our only hope at this point is to make the cmd
+		 window non-fixed-size (if possible), and hope we can
+		 shrink this enough to fit the rest of the sub-layouts in.
+
+	         Alternatively, we've made it around the loop without
+	         adjusting any window's size.  This likely means all
+	         windows have hit their min or max size.  Again, our only
+	         hope is to make the cmd window non-fixed-size, and hope
+	         this fixes all our problems.  */
+	      if (old_cmd_info.has_value ()
+		  && ((available_size < used_size)
+		      || !found_window_that_can_grow_p))
+		{
+		  info[old_cmd_info->index].min_size = old_cmd_info->min_size;
+		  info[old_cmd_info->index].max_size = old_cmd_info->max_size;
+		  tui_debug_printf
+		    ("restoring index %d (cmd) size limits, min = %d, max = %d",
+		     old_cmd_info->index, old_cmd_info->min_size,
+		     old_cmd_info->max_size);
+		  old_cmd_info.reset ();
+		}
+	      else if (!found_window_that_can_grow_p)
 		break;
 	      found_window_that_can_grow_p = false;
 	    }
@@ -894,6 +966,13 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_)
 	      info[idx].size += 1;
 	      used_size += 1;
 	    }
+	  else if (available_size < used_size
+		   && info[idx].size > info[idx].min_size)
+	    {
+	      found_window_that_can_grow_p = true;
+	      info[idx].size -= 1;
+	      used_size -= 1;
+	    }
 	}
 
       if (debug_tui)
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv2 12/15] gdb/tui: support placing the cmd window into a horizontal layout
  2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess
                     ` (10 preceding siblings ...)
  2022-02-06 14:12   ` [PATCHv2 11/15] gdb/tui: allow cmd window to change size in tui_layout_split::apply Andrew Burgess
@ 2022-02-06 14:12   ` Andrew Burgess
  2022-03-04 17:17     ` Tom Tromey
  2022-02-06 14:12   ` [PATCHv2 13/15] gdb/testsuite: some additional tests in gdb.tui/scroll.exp Andrew Burgess
                     ` (4 subsequent siblings)
  16 siblings, 1 reply; 74+ messages in thread
From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

This commit allows the user to place the cmd window within horizontal
tui layouts.  Consider this set of steps, carried out in an 80 columns
by 24 lines terminal, using current master gdb:

  (gdb) tui new-layout hsrc { -horizontal src 1 cmd 1 } 1 status 1
  (gdb) tui layout hsrc

What you end up with is a full width cmd window with the status bar
beneath.  Where's the src window gone?  We then try:

  (gdb) info win
  Name       Lines Columns Focus
  src           23       3 (has focus)
  cmd           23      80
  status         1      80
  (gdb)

Something weird has gone on, gdb has overlapped the cmd window with
the src window.  If we trigger the src window to redraw is content,
for example, 'list main', then we see corruption in the cmd window as
the src window overwrites it.

So, what's going on?

The problem is some code in tui_layout_split::apply, in tui-layout.c.
Within 'Step 1', there is a loop that calculates the min/max window
sizes for all windows within a tui_layout_split.  However, there's a
special case for the cmd window.

This special case is trying to have the cmd window retain its current
size when a layout is re-applied, or a new layout is applied.  This
makes sense, consider moving from the 'src' layout to the 'asm'
layout, this looks something like this (status window removed):

    .-------.         .-------.
    |  src  |         |  asm  |
    |-------|  ====>  |-------|
    |  cmd  |         |  cmd  |
    '-------'         '-------'

If the user has gone to the effort of adjusting the cmd window size,
then, the thinking goes, we shouldn't reset the cmd window size when
switching layouts like this.

The problem though, is that when we do a switch more like this:

    .-----------.         .-----------.
    |    src    |         |     |     |
    |-----------|  ====>  | asm | cmd |
    |    cmd    |         |     |     |
    '-----------'         '-----------'

Now retaining the cmd window width makes no sense; the new layout has
a completely different placement for the cmd window, instead of sizing
by height, we're now sizing by width.  The existing code doesn't
understand this though, and tried to retain the full width for the cmd
window.

To solve this problem, I propose we introduce the idea of a layout
"fingerprint".  The fingerprint tries to capture, in an abstract way,
where the cmd window lives within the layout.

Only when two layouts have the same fingerprint will we attempt to
retain the cmd window size.

The fingerprint for a layout is represented as a string, the string is
a series of 'V' or 'H' characters, ending with a single 'C'
character.  The series of 'V' and 'H' characters represent the
vertical or horizontal layouts that must be passed through to find the
cmd window.

Here are a few examples:

  # This layout is equivalent to the builtin 'src' layout.
  # Fingerprint: VC
  tui new-layout example1 src 2 status 0 cmd 1

  # This layout is equivalent to the builtin 'split' layout.
  # Fingerprint: VC
  tui new-layout example2 src 1 asm 1 status 0 cmd 1

  # This is the same layout that was given at the top.
  # Fingerprint: VHC
  tui new-layout hsrc { -horizontal src 1 cmd 1 } 1 status 1

And so, when switching between example1 and example2, gdb knows that
the cmd window is, basically, in the same sort of position within the
layout, and will retain the cmd window size.

In contrast, when switching to the hsrc layout, gdb understands that
the position of the cmd window is different, and does not try to
retain the cmd window size.
---
 gdb/testsuite/gdb.tui/new-layout.exp |  5 ++
 gdb/tui/tui-layout.c                 | 69 ++++++++++++++++++++++------
 gdb/tui/tui-layout.h                 | 47 +++++++++++++++----
 gdb/tui/tui-win.c                    |  6 ++-
 4 files changed, 102 insertions(+), 25 deletions(-)

diff --git a/gdb/testsuite/gdb.tui/new-layout.exp b/gdb/testsuite/gdb.tui/new-layout.exp
index 0d49d033be5..883c7601be7 100644
--- a/gdb/testsuite/gdb.tui/new-layout.exp
+++ b/gdb/testsuite/gdb.tui/new-layout.exp
@@ -71,6 +71,11 @@ set layouts \
 	 [list h "{-horizontal asm 1 src 1} 1 status 0 cmd 1" \
 	      {{0 0 40 15} {39 0 41 15}} \
 	      "$hex <main>.*21.*return 0"] \
+	 [list example3 "{-horizontal src 1 cmd 1} 1 status 0 asm 1" \
+	      {{0 0 40 11} {0 12 80 12}} \
+	      "21.*return 0.*$hex <main>"] \
+	 [list example4 "src 1 status 0 {-horizontal cmd 1 regs 1} 1" \
+	      {{0 0 80 11} {40 12 40 12}} ""] \
 	 [list cmd_only "cmd 1" {} ""]]
 
 # Helper function to verify a list of boxes.
diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index 87097cb7166..ac03e88acbe 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -67,7 +67,7 @@ std::vector<tui_win_info *> tui_windows;
 /* See tui-layout.h.  */
 
 void
-tui_apply_current_layout ()
+tui_apply_current_layout (bool preserve_cmd_win_size_p)
 {
   struct gdbarch *gdbarch;
   CORE_ADDR addr;
@@ -77,7 +77,8 @@ tui_apply_current_layout ()
   for (tui_win_info *win_info : tui_windows)
     win_info->make_visible (false);
 
-  applied_layout->apply (0, 0, tui_term_width (), tui_term_height ());
+  applied_layout->apply (0, 0, tui_term_width (), tui_term_height (),
+			 preserve_cmd_win_size_p);
 
   /* Keep the list of internal windows up-to-date.  */
   for (int win_type = SRC_WIN; (win_type < MAX_MAJOR_WINDOWS); win_type++)
@@ -134,9 +135,18 @@ tui_adjust_window_width (struct tui_win_info *win, int new_width)
 static void
 tui_set_layout (tui_layout_split *layout)
 {
+  std::string old_fingerprint;
+  if (applied_layout != nullptr)
+    old_fingerprint = applied_layout->layout_fingerprint ();
+
   applied_skeleton = layout;
   applied_layout = layout->clone ();
-  tui_apply_current_layout ();
+
+  std::string new_fingerprint = applied_layout->layout_fingerprint ();
+  bool preserve_command_window_size
+    = (TUI_CMD_WIN != nullptr && old_fingerprint == new_fingerprint);
+
+  tui_apply_current_layout (preserve_command_window_size);
 }
 
 /* See tui-layout.h.  */
@@ -158,7 +168,7 @@ tui_add_win_to_layout (enum tui_win_type type)
 
   const char *name = type == SRC_WIN ? SRC_NAME : DISASSEM_NAME;
   applied_layout->replace_window (tui_win_list[other]->name (), name);
-  tui_apply_current_layout ();
+  tui_apply_current_layout (true);
 }
 
 /* Find LAYOUT in the "layouts" global and return its index.  */
@@ -271,7 +281,7 @@ tui_remove_some_windows ()
     }
 
   applied_layout->remove_windows (focus->name ());
-  tui_apply_current_layout ();
+  tui_apply_current_layout (true);
 }
 
 static void
@@ -411,7 +421,8 @@ tui_layout_window::clone () const
 /* See tui-layout.h.  */
 
 void
-tui_layout_window::apply (int x_, int y_, int width_, int height_)
+tui_layout_window::apply (int x_, int y_, int width_, int height_,
+			  bool preserve_cmd_win_size_p)
 {
   x = x_;
   y = y_;
@@ -510,6 +521,17 @@ tui_layout_window::specification (ui_file *output, int depth)
 
 /* See tui-layout.h.  */
 
+std::string
+tui_layout_window::layout_fingerprint () const
+{
+  if (strcmp (get_name (), "cmd") == 0)
+    return "C";
+  else
+    return "";
+}
+
+/* See tui-layout.h.  */
+
 void
 tui_layout_split::add_split (std::unique_ptr<tui_layout_split> &&layout,
 			     int weight)
@@ -746,8 +768,11 @@ tui_layout_split::set_size (const char *name, int new_size)
     }
   else
     {
-      /* Simply re-apply the updated layout.  */
-      apply (x, y, width, height);
+      /* Simply re-apply the updated layout.  We pass false here so that
+	 the cmd window can be resized.  However, we should have already
+	 resized everything above to be "just right", so the apply call
+	 here should not end up changing the sizes at all.  */
+      apply (x, y, width, height, false);
     }
 
   return HANDLED;
@@ -756,7 +781,8 @@ tui_layout_split::set_size (const char *name, int new_size)
 /* See tui-layout.h.  */
 
 void
-tui_layout_split::apply (int x_, int y_, int width_, int height_)
+tui_layout_split::apply (int x_, int y_, int width_, int height_,
+			 bool preserve_cmd_win_size_p)
 {
   TUI_SCOPED_DEBUG_ENTER_EXIT;
 
@@ -811,7 +837,7 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_)
       m_splits[i].layout->get_sizes (m_vertical, &info[i].min_size,
 				     &info[i].max_size);
 
-      if (!m_applied
+      if (preserve_cmd_win_size_p
 	  && cmd_win_already_exists
 	  && m_splits[i].layout->get_name () != nullptr
 	  && strcmp (m_splits[i].layout->get_name (), "cmd") == 0)
@@ -998,13 +1024,13 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_)
       else if (info[i].share_box)
 	--size_accum;
       if (m_vertical)
-	m_splits[i].layout->apply (x, y + size_accum, width, info[i].size);
+	m_splits[i].layout->apply (x, y + size_accum, width, info[i].size,
+				   preserve_cmd_win_size_p);
       else
-	m_splits[i].layout->apply (x + size_accum, y, info[i].size, height);
+	m_splits[i].layout->apply (x + size_accum, y, info[i].size, height,
+				   preserve_cmd_win_size_p);
       size_accum += info[i].size;
     }
-
-  m_applied = true;
 }
 
 /* See tui-layout.h.  */
@@ -1065,6 +1091,21 @@ tui_layout_split::specification (ui_file *output, int depth)
     fputs_unfiltered ("}", output);
 }
 
+/* See tui-layout.h.  */
+
+std::string
+tui_layout_split::layout_fingerprint () const
+{
+  for (auto &item : m_splits)
+    {
+      std::string fp = item.layout->layout_fingerprint ();
+      if (!fp.empty ())
+	return std::string (m_vertical ? "V" : "H") + fp;
+    }
+
+  return "";
+}
+
 /* Destroy the layout associated with SELF.  */
 
 static void
diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h
index e160eaa2256..32f9dd078ee 100644
--- a/gdb/tui/tui-layout.h
+++ b/gdb/tui/tui-layout.h
@@ -55,8 +55,12 @@ class tui_layout_base
      "skeleton" layout.  */
   virtual std::unique_ptr<tui_layout_base> clone () const = 0;
 
-  /* Change the size and location of this layout.  */
-  virtual void apply (int x, int y, int width, int height) = 0;
+  /* Change the size and location of this layout.  When
+     PRESERVE_CMD_WIN_SIZE_P is true the current size of the TUI_CMD_WIN
+     is preserved, otherwise, the TUI_CMD_WIN will resize just like any
+     other window.  */
+  virtual void apply (int x, int y, int width, int height,
+		      bool preserve_cmd_win_size_p) = 0;
 
   /* Return the minimum and maximum height or width of this layout.
      HEIGHT is true to fetch height, false to fetch width.  */
@@ -101,6 +105,26 @@ class tui_layout_base
      depth of this layout in the hierarchy (zero-based).  */
   virtual void specification (ui_file *output, int depth) = 0;
 
+  /* Return a FINGERPRINT string containing an abstract representation of
+     the location of the cmd window in this layout.
+
+     When called on a complete, top-level layout, the fingerprint will be a
+     non-empty string made of 'V' and 'H' characters, followed by a single
+     'C' character.  Each 'V' and 'H' represents a vertical or horizontal
+     layout that must be passed through in order to find the cmd
+     window.
+
+     Of course, layouts are built recursively, so, when called on a partial
+     layout, if this object represents a single window, then either the
+     empty string is returned (for non-cmd windows), or a string
+     containing a single 'C' is returned.
+
+     For object representing layouts, if the layout contains the cmd
+     window then we will get back a valid fingerprint string (contains 'V'
+     and 'H', ends with 'C'), or, if this layout doesn't contain the cmd
+     window, an empty string is returned.  */
+  virtual std::string layout_fingerprint () const = 0;
+
   /* Add all windows to the WINDOWS vector.  */
   virtual void get_windows (std::vector<tui_win_info *> *windows) = 0;
 
@@ -130,7 +154,8 @@ class tui_layout_window : public tui_layout_base
 
   std::unique_ptr<tui_layout_base> clone () const override;
 
-  void apply (int x, int y, int width, int height) override;
+  void apply (int x, int y, int width, int height,
+	      bool preserve_cmd_win_size_p) override;
 
   const char *get_name () const override
   {
@@ -163,6 +188,8 @@ class tui_layout_window : public tui_layout_base
 
   void specification (ui_file *output, int depth) override;
 
+  std::string layout_fingerprint () const override;
+
   /* See tui_layout_base::get_windows.  */
   void get_windows (std::vector<tui_win_info *> *windows) override
   {
@@ -209,7 +236,8 @@ class tui_layout_split : public tui_layout_base
 
   std::unique_ptr<tui_layout_base> clone () const override;
 
-  void apply (int x, int y, int width, int height) override;
+  void apply (int x, int y, int width, int height,
+	      bool preserve_cmd_win_size_p) override;
 
   tui_adjust_result set_height (const char *name, int new_height) override
   {
@@ -235,6 +263,8 @@ class tui_layout_split : public tui_layout_base
 
   void specification (ui_file *output, int depth) override;
 
+  std::string layout_fingerprint () const override;
+
   /* See tui_layout_base::get_windows.  */
   void get_windows (std::vector<tui_win_info *> *windows) override
   {
@@ -371,9 +401,6 @@ class tui_layout_split : public tui_layout_base
 
   /* True if the windows in this split are arranged vertically.  */
   bool m_vertical;
-
-  /* True if this layout has already been applied at least once.  */
-  bool m_applied = false;
 };
 
 /* Add the specified window to the layout in a logical way.  This
@@ -396,8 +423,10 @@ extern void tui_regs_layout ();
    some other window is chosen to remain.  */
 extern void tui_remove_some_windows ();
 
-/* Apply the current layout.  */
-extern void tui_apply_current_layout ();
+/* Apply the current layout.  When PRESERVE_CMD_WIN_SIZE_P is true the
+   current size of the TUI_CMD_WIN is preserved, otherwise, the TUI_CMD_WIN
+   will resize just like any other window.  */
+extern void tui_apply_current_layout (bool);
 
 /* Adjust the window height of WIN to NEW_HEIGHT.  */
 extern void tui_adjust_window_height (struct tui_win_info *win,
diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c
index 953af640c93..d7fd8411a66 100644
--- a/gdb/tui/tui-win.c
+++ b/gdb/tui/tui-win.c
@@ -511,8 +511,10 @@ tui_resize_all (void)
 	 AIX 5.3 does not define clear.  */
       erase ();
       clearok (curscr, TRUE);
-      tui_apply_current_layout ();
-      /* Turn keypad back on.  */
+      /* Apply the current layout.  The 'false' here allows the command
+	 window to resize proportionately with containing terminal, rather
+	 than maintaining a fixed size.  */
+      tui_apply_current_layout (false); /* Turn keypad back on.  */
       keypad (TUI_CMD_WIN->handle.get (), TRUE);
     }
 }
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv2 13/15] gdb/testsuite: some additional tests in gdb.tui/scroll.exp
  2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess
                     ` (11 preceding siblings ...)
  2022-02-06 14:12   ` [PATCHv2 12/15] gdb/tui: support placing the cmd window into a horizontal layout Andrew Burgess
@ 2022-02-06 14:12   ` Andrew Burgess
  2022-02-06 14:12   ` [PATCHv2 14/15] gdb/tui: relax restrictions on window max height and width Andrew Burgess
                     ` (3 subsequent siblings)
  16 siblings, 0 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

This commit just adds an extra check of the src window size prior to
sending all the commands to gdb.  We also set the cmd window height to
its existing height, this (obviously) shouldn't change the window
layout, which we check.

My main motivation was adding the initial window layout check, the
winheight and recheck are just extras.  All of these test pass both
before and after this commit.
---
 gdb/testsuite/gdb.tui/scroll.exp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/gdb/testsuite/gdb.tui/scroll.exp b/gdb/testsuite/gdb.tui/scroll.exp
index 4eaee0c14ee..c23cd2b9abf 100644
--- a/gdb/testsuite/gdb.tui/scroll.exp
+++ b/gdb/testsuite/gdb.tui/scroll.exp
@@ -55,6 +55,10 @@ Term::check_region_contents "check cmd window" 0 16 80 8 \
 Term::command "tui new-layout flip cmd 1 src 1"
 Term::command "layout flip"
 
+Term::check_box "src window" 0 8 80 16
+Term::command "winheight cmd 8"
+Term::check_box "src window after resize" 0 8 80 16
+
 for {set i 10} {$i < 20} {incr i 1} {
     Term::command "p $i"
 }
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv2 14/15] gdb/tui: relax restrictions on window max height and width
  2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess
                     ` (12 preceding siblings ...)
  2022-02-06 14:12   ` [PATCHv2 13/15] gdb/testsuite: some additional tests in gdb.tui/scroll.exp Andrew Burgess
@ 2022-02-06 14:12   ` Andrew Burgess
  2022-03-04 17:20     ` Tom Tromey
  2022-02-06 14:12   ` [PATCHv2 15/15] gdb/tui: fair split of delta after a resize Andrew Burgess
                     ` (2 subsequent siblings)
  16 siblings, 1 reply; 74+ messages in thread
From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

This commit removes some arbitrary adjustments made in
tui_cmd_window::max_height, tui_win_info::max_height, and
tui_win_info::max_width.

These member functions all subtract some constant from the theoretical
maximum height or width.  I've looked back through the history a
little and can see no real reason why these adjustments should be
needed, with these adjustments removed all the existing tui tests
still pass.

However, retaining these restrictions causes some bugs, consider:

  (gdb) tui new-layout hsrc {-horizontal src 1 cmd 1} 1

When this layout is selected with current master, gdb will leave a 4
line gap at the bottom of the terminal.

The problem is that the maximum height is restricted, for the cmd
window, to 4 less than the terminal height.

By removing this restriction gdb is able to size the windows to the
complete terminal height, and the layout is done correctly.

This 4 line restriction is also what prevents this layout from working
correctly:

  (gdb) tui new-layout conly cmd 1

Previously, this layout would present a cmd window only, but there
would be a 4 line gap at the bottom of the terminal.  This issue was
mentioned in an earlier commit in this series (when a different bug
was fixed), but with this commit, the above layout now correctly fills
the terminal.  The associated test is updated.

After removing the adjustment in tui_cmd_window::max_height, the
implementation is now the same as the implementation in the parent
class tui_win_info, so I've completely removed the max_height call
from tui_cmd_window.
---
 gdb/testsuite/gdb.tui/new-layout.exp | 4 +++-
 gdb/tui/tui-command.c                | 6 ------
 gdb/tui/tui-command.h                | 2 --
 gdb/tui/tui-win.c                    | 4 ++--
 4 files changed, 5 insertions(+), 11 deletions(-)

diff --git a/gdb/testsuite/gdb.tui/new-layout.exp b/gdb/testsuite/gdb.tui/new-layout.exp
index 883c7601be7..e662b1f0b18 100644
--- a/gdb/testsuite/gdb.tui/new-layout.exp
+++ b/gdb/testsuite/gdb.tui/new-layout.exp
@@ -76,6 +76,8 @@ set layouts \
 	      "21.*return 0.*$hex <main>"] \
 	 [list example4 "src 1 status 0 {-horizontal cmd 1 regs 1} 1" \
 	      {{0 0 80 11} {40 12 40 12}} ""] \
+	 [list example5 "{-horizontal src 1 cmd 1} 1 status 0" \
+	      {{0 0 40 23}} ""] \
 	 [list cmd_only "cmd 1" {} ""]]
 
 # Helper function to verify a list of boxes.
@@ -136,7 +138,7 @@ foreach_with_prefix layout $layouts {
 	Term::check_region_contents "info win output" \
 	    0 0 80 24 [multi_line "info win\\s+" \
 			   "Name\\s+Lines\\s+Columns\\s+Focus\\s+" \
-			   "cmd\\s+20\\s+80\\s+\\(has focus\\)\\s+" \
+			   "cmd\\s+24\\s+80\\s+\\(has focus\\)\\s+" \
 			   "$gdb_prompt\\s+"]
     }
 }
diff --git a/gdb/tui/tui-command.c b/gdb/tui/tui-command.c
index fa8af970b0a..0f6c395f567 100644
--- a/gdb/tui/tui-command.c
+++ b/gdb/tui/tui-command.c
@@ -31,12 +31,6 @@
 
 /* See tui-command.h.  */
 
-int
-tui_cmd_window::max_height () const
-{
-  return tui_term_height () - 4;
-}
-
 void
 tui_cmd_window::resize (int height_, int width_, int origin_x, int origin_y)
 {
diff --git a/gdb/tui/tui-command.h b/gdb/tui/tui-command.h
index 06cc24f6faf..6c354361d1d 100644
--- a/gdb/tui/tui-command.h
+++ b/gdb/tui/tui-command.h
@@ -31,8 +31,6 @@ struct tui_cmd_window : public tui_win_info
 
   DISABLE_COPY_AND_ASSIGN (tui_cmd_window);
 
-  int max_height () const override;
-
   void refresh_window () override
   {
   }
diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c
index d7fd8411a66..6ff65052396 100644
--- a/gdb/tui/tui-win.c
+++ b/gdb/tui/tui-win.c
@@ -986,7 +986,7 @@ tui_set_win_width_command (const char *arg, int from_tty)
 int
 tui_win_info::max_height () const
 {
-  return tui_term_height () - 2;
+  return tui_term_height ();
 }
 
 /* See tui-data.h.  */
@@ -994,7 +994,7 @@ tui_win_info::max_height () const
 int
 tui_win_info::max_width () const
 {
-  return tui_term_width () - 2;
+  return tui_term_width ();
 }
 
 static void
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv2 15/15] gdb/tui: fair split of delta after a resize
  2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess
                     ` (13 preceding siblings ...)
  2022-02-06 14:12   ` [PATCHv2 14/15] gdb/tui: relax restrictions on window max height and width Andrew Burgess
@ 2022-02-06 14:12   ` Andrew Burgess
  2022-03-04 17:22     ` Tom Tromey
  2022-02-21 17:29   ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess
  2022-03-07 22:13   ` [PATCHv3 " Andrew Burgess
  16 siblings, 1 reply; 74+ messages in thread
From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

Currently, in master gdb, when a tui window is changed in size, the
screen delta is mostly just added to the next available window.  We
do take care to respect the min/max size, but in most cases, these
limits are just "the terminal size", and so, we end up placing the
whole delta on the next window.

Consider these steps in an 80 column, 24 line terminal:

  (gdb) tui enable
  (gdb) layout src
  (gdb) layout split
  (gdb) info win
  Name       Lines Columns Focus
  src            8      80 (has focus)
  asm            8      80
  status         1      80
  cmd            8      80
  (gdb) winheight cmd +2
  (gdb) info win
  Name       Lines Columns Focus
  src            6      80 (has focus)
  asm            8      80
  status         1      80
  cmd           10      80

Notice that initially, the windows were balanced, 8 lines each for the
major windows.  Then, when the cmd window was adjusted, the extra two
lines were given to the asm window.

I think it would be nicer if the delta was spread more evenly over the
available windows.  In the example above, after the adjustment the
layout now looks like:

  (gdb) info win
  Name       Lines Columns Focus
  src            7      80 (has focus)
  asm            7      80
  status         1      80
  cmd           10      80

This is achieved within tui_layout_split::set_size, by just handing
out the delta in increments of 1 to each window (except for the window
the user adjusted), until there's no more delta left.  Of course, we
continue to respect the min/max window sizes.
---
 gdb/testsuite/gdb.tui/winheight.exp | 31 +++++++++++++++++++++++++++++
 gdb/tui/tui-layout.c                | 30 +++++++++++++++++++---------
 2 files changed, 52 insertions(+), 9 deletions(-)

diff --git a/gdb/testsuite/gdb.tui/winheight.exp b/gdb/testsuite/gdb.tui/winheight.exp
index b541c21b825..8296dd79513 100644
--- a/gdb/testsuite/gdb.tui/winheight.exp
+++ b/gdb/testsuite/gdb.tui/winheight.exp
@@ -43,11 +43,42 @@ Term::check_box "smaller source box again" 0 0 80 10
 Term::command "winheight src +5"
 Term::check_box "larger source box again" 0 0 80 15
 
+# Check that attempting a window to be too large gives an error.
+Term::command "winheight src 100"
+Term::check_box "source box has not changed" 0 0 80 15
+Term::check_region_contents "check error message about src size 100" 0 16 80 8 \
+    [multi_line "$gdb_prompt winheight src 100\\s+" \
+     "warning: Invalid window height specified\\s+" \
+     "$gdb_prompt"]
+
+# Check that incrementing to a size that is "too big" will trigger an
+# error, and that the window doesn't resize.
+Term::command "winheight src 20"
+Term::check_box "source box is at its max size" 0 0 80 20
+Term::command "winheight src +1"
+Term::check_box "source box is still at its max size" 0 0 80 20
+Term::check_region_contents "check error message about src +1" 0 21 80 3 \
+    [multi_line "$gdb_prompt winheight src \\+1\\s+" \
+     "warning: Invalid window height specified\\s+" \
+     "$gdb_prompt"]
+
+# Reset the cmd window to a sane size.
+Term::command "winheight cmd 8"
+
+Term::command "layout regs"
+Term::check_box "register window" 0 0 80 8
+Term::check_box "source window" 0 7 80 8
+
+Term::command "winheight cmd 10"
+Term::check_box "register window after resize" 0 0 80 7
+Term::check_box "source window after resize" 0 6 80 7
+
 # At one point we had a bug where adjusting the winheight would result
 # in GDB keeping hold of duplicate window pointers, which it might
 # then try to delete when the layout was changed.  Running this test
 # under valgrind would expose that bug.
 Term::command "layout asm"
+Term::command "winheight cmd 8"
 Term::check_box "check for asm window" 0 0 80 15
 
 
diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index ac03e88acbe..ef98aaeef9d 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -727,9 +727,17 @@ tui_layout_split::set_size (const char *name, int new_size)
   /* Distribute the "delta" over the next window; but if the next
      window cannot hold it all, keep going until we either find a
      window that does, or until we loop all the way around.  */
-  for (int i = 0; delta != 0 && i < m_splits.size () - 1; ++i)
+  bool found_window_that_can_grow_p = true;
+  for (int i = 0; delta != 0; i = (i + 1) % m_splits.size ())
     {
       int index = (found_index + 1 + i) % m_splits.size ();
+      if (index == found_index)
+        {
+          if (!found_window_that_can_grow_p)
+            break;
+          found_window_that_can_grow_p = false;
+          continue;
+        }
 
       int new_min, new_max;
       m_splits[index].layout->get_sizes (m_vertical, &new_min, &new_max);
@@ -738,19 +746,23 @@ tui_layout_split::set_size (const char *name, int new_size)
 	{
 	  /* The primary window grew, so we are trying to shrink other
 	     windows.  */
-	  int available = m_splits[index].weight - new_min;
-	  int shrink_by = std::min (available, -delta);
-	  m_splits[index].weight -= shrink_by;
-	  delta += shrink_by;
+	  if (m_splits[index].weight > new_min)
+	    {
+	      m_splits[index].weight -= 1;
+	      delta += 1;
+	      found_window_that_can_grow_p = true;
+	    }
 	}
       else
 	{
 	  /* The primary window shrank, so we are trying to grow other
 	     windows.  */
-	  int available = new_max - m_splits[index].weight;
-	  int grow_by = std::min (available, delta);
-	  m_splits[index].weight += grow_by;
-	  delta -= grow_by;
+	  if (m_splits[index].weight < new_max)
+	    {
+	      m_splits[index].weight += 1;
+	      delta -= 1;
+	      found_window_that_can_grow_p = true;
+	    }
 	}
 
       tui_debug_printf ("index = %d, weight now: %d",
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCHv2 01/15] gdb: move some commands into the tui namespace
  2022-02-06 14:12   ` [PATCHv2 01/15] gdb: move some commands into the tui namespace Andrew Burgess
@ 2022-02-06 15:50     ` Eli Zaretskii
  0 siblings, 0 replies; 74+ messages in thread
From: Eli Zaretskii @ 2022-02-06 15:50 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches

> Date: Sun,  6 Feb 2022 14:12:39 +0000
> From: Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org>
> Cc: Andrew Burgess <aburgess@redhat.com>
> 
>  gdb/NEWS             | 15 +++++++++++++++
>  gdb/doc/gdb.texinfo  | 18 +++++++++++++-----
>  gdb/tui/tui-layout.c | 16 +++++++++++++---
>  gdb/tui/tui-win.c    | 40 ++++++++++++++++++++++++++++++++--------
>  4 files changed, 73 insertions(+), 16 deletions(-)

OK for the documentation parts.

It is up to you whether to advertise the old commands (which are now
aliases) in the manual.  We could remove them from there.

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCHv2 05/15] gdb/tui: add new 'tui window width' command and 'winwidth' alias
  2022-02-06 14:12   ` [PATCHv2 05/15] gdb/tui: add new 'tui window width' command and 'winwidth' alias Andrew Burgess
@ 2022-02-06 15:52     ` Eli Zaretskii
  2022-02-09 15:33       ` Andrew Burgess
  2022-03-03 18:52     ` Pedro Alves
  1 sibling, 1 reply; 74+ messages in thread
From: Eli Zaretskii @ 2022-02-06 15:52 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches

> Date: Sun,  6 Feb 2022 14:12:43 +0000
> From: Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org>
> Cc: Andrew Burgess <aburgess@redhat.com>
> 
>  gdb/NEWS                           |   6 ++
>  gdb/doc/gdb.texinfo                |  12 ++++
>  gdb/testsuite/gdb.tui/winwidth.exp |  62 +++++++++++++++++
>  gdb/tui/tui-layout.c               |  23 +++++--
>  gdb/tui/tui-layout.h               | 104 ++++++++++++++++++++++++++++-
>  gdb/tui/tui-win.c                  |  99 +++++++++++++++++++++++++--
>  6 files changed, 291 insertions(+), 15 deletions(-)
>  create mode 100644 gdb/testsuite/gdb.tui/winwidth.exp

OK for the documentation parts.

Btw, should we mention that this new command will only have effect if
more than one window is displayed?

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCHv2 06/15] gdb/tui: add a tui debugging flag
  2022-02-06 14:12   ` [PATCHv2 06/15] gdb/tui: add a tui debugging flag Andrew Burgess
@ 2022-02-06 15:53     ` Eli Zaretskii
  2022-03-04 16:35     ` Tom Tromey
  1 sibling, 0 replies; 74+ messages in thread
From: Eli Zaretskii @ 2022-02-06 15:53 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches

> Date: Sun,  6 Feb 2022 14:12:44 +0000
> From: Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org>
> Cc: Andrew Burgess <aburgess@redhat.com>
> 
>  gdb/NEWS             |  4 ++
>  gdb/doc/gdb.texinfo  | 11 +++++
>  gdb/tui/tui-layout.c | 99 +++++++++++++++++++++++++++++++++++++++-----
>  gdb/tui/tui-layout.h | 25 +++++++++++
>  gdb/tui/tui.c        | 26 ++++++++++++
>  gdb/tui/tui.h        | 14 +++++++
>  6 files changed, 168 insertions(+), 11 deletions(-)

Thanks, the documentation parts are okay.

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCHv2 05/15] gdb/tui: add new 'tui window width' command and 'winwidth' alias
  2022-02-06 15:52     ` Eli Zaretskii
@ 2022-02-09 15:33       ` Andrew Burgess
  2022-02-09 17:03         ` Eli Zaretskii
  0 siblings, 1 reply; 74+ messages in thread
From: Andrew Burgess @ 2022-02-09 15:33 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches

Eli Zaretskii via Gdb-patches <gdb-patches@sourceware.org> writes:

>> Date: Sun,  6 Feb 2022 14:12:43 +0000
>> From: Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org>
>> Cc: Andrew Burgess <aburgess@redhat.com>
>> 
>>  gdb/NEWS                           |   6 ++
>>  gdb/doc/gdb.texinfo                |  12 ++++
>>  gdb/testsuite/gdb.tui/winwidth.exp |  62 +++++++++++++++++
>>  gdb/tui/tui-layout.c               |  23 +++++--
>>  gdb/tui/tui-layout.h               | 104 ++++++++++++++++++++++++++++-
>>  gdb/tui/tui-win.c                  |  99 +++++++++++++++++++++++++--
>>  6 files changed, 291 insertions(+), 15 deletions(-)
>>  create mode 100644 gdb/testsuite/gdb.tui/winwidth.exp
>
> OK for the documentation parts.
>
> Btw, should we mention that this new command will only have effect if
> more than one window is displayed?

What about this for the description of 'tui window width'?  The second
paragraph is new:

  @kindex tui window width
  @kindex winwidth
  @item tui window width @var{name} +@var{count}
  @itemx tui window width @var{name} -@var{count}
  @itemx winwidth @var{name} +@var{count}
  @itemx winwidth @var{name} -@var{count}
  Change the width of the window @var{name} by @var{count} columns.
  Positive counts increase the width, while negative counts decrease it.
  The @var{name} parameter can be the name of any currently visible
  window.  The names of the currently visible windows can be discovered
  using @code{info win} (@pxref{info_win_command,,info win}).
  
  The set of currently visible windows must always fill the terminal,
  and so, it is only possible to resize on window if there are other
  visible windows that can either give or receive the extra terminal
  space.

If this is OK, then I would propose adding the same paragraph to the
description of 'tui window height' which obviously has the same
restrictions.

The complete patch, including the new paragraphs is included below.

Thanks,
Andrew

---

commit 3fd38b7966faa8371f91c70c4e4914b6c786b6ef
Author: Andrew Burgess <aburgess@redhat.com>
Date:   Mon Jan 24 22:02:59 2022 +0000

    gdb/tui: add new 'tui window width' command and 'winwidth' alias
    
    This commit adds a new command 'tui window width', and an alias
    'winwidth'.  This command is equivalent to the old 'winheight'
    command (which was recently renamed 'tui window height').
    
    Even though I recently moved the old tui commands under the tui
    namespace, and I would strongly encourage all new tui commands to be
    added as 'tui ....' only (users can create their own top-level aliases
    if they want), I'm breaking that suggestion here, and adding a
    'winwidth' alias.
    
    Given that we already have 'winheight' and have done for years, it
    just didn't seem right to no have the matching 'winwidth'.
    
    You might notice in the test that the window resizing doesn't quite
    work right.  I setup a horizontal layout, then grow and shrink the
    windows.  At the end of the test the windows should be back to their
    original size...
    
    ... they are not.  This isn't my fault, honest!  GDB's window resizing
    is a little ... temperamental, and is prone to getting things slightly
    wrong during resizes, off by 1 type things.  This is true for height
    resizing, as well as the new width resizing.
    
    Later patches in this series will rework the resizing algorithm, which
    should improve things in this area.  For now, I'm happy that the width
    resizing is as good as the height resizing, given the existing quirks.
    
    For the docs side I include a paragraph that explains how multiple
    windows are required before the width can be adjusted.  For
    completeness, I've added the same paragraph to the winheight
    description.  With the predefined layouts this extra paragraph is not
    really needed for winheight, as there are always multiple windows on
    the screen.  However, with custom layouts, this might not be true, so
    adding the paragraph seems like a good idea.
    
    As for the changes in gdb itself, I've mostly just templated the
    existing height adjustment code so that the two functions
    tui_layout_split::adjust_size (tui-layout.c) and
    tui_set_win_height_command (tui-win.c) now have a template parameter
    "policy", this policy allows me to specialise the functions for either
    width or height adjustment.  Function arguments, and locals, are
    renamed, replacing 'height' with 'size'.

diff --git a/gdb/NEWS b/gdb/NEWS
index b06eb473ffb..3a05b95a3d9 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -97,6 +97,12 @@ tui window height
   and 'winheight' tui commands respectively.  The old names still
   exist as aliases to these new commands.
 
+tui window width
+winwidth
+  The new command 'tui window width', and the alias 'winwidth' allow
+  the width of a tui window to be adjusted when windows are laid out
+  in horizontal mode.
+
 * Changed commands
 
 maint packet
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 6ddcc099cd8..e144255df69 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -29044,6 +29044,28 @@
 it.  The @var{name} parameter can be the name of any currently visible
 window.  The names of the currently visible windows can be discovered
 using @kbd{info win} (@pxref{info_win_command,,info win}).
+
+The set of currently visible windows must always fill the terminal,
+and so, it is only possible to resize on window if there are other
+visible windows that can either give or receive the extra terminal
+space.
+
+@kindex tui window width
+@kindex winwidth
+@item tui window width @var{name} +@var{count}
+@itemx tui window width @var{name} -@var{count}
+@itemx winwidth @var{name} +@var{count}
+@itemx winwidth @var{name} -@var{count}
+Change the width of the window @var{name} by @var{count} columns.
+Positive counts increase the width, while negative counts decrease it.
+The @var{name} parameter can be the name of any currently visible
+window.  The names of the currently visible windows can be discovered
+using @code{info win} (@pxref{info_win_command,,info win}).
+
+The set of currently visible windows must always fill the terminal,
+and so, it is only possible to resize on window if there are other
+visible windows that can either give or receive the extra terminal
+space.
 @end table
 
 @node TUI Configuration
diff --git a/gdb/testsuite/gdb.tui/winwidth.exp b/gdb/testsuite/gdb.tui/winwidth.exp
new file mode 100644
index 00000000000..b0a838b578f
--- /dev/null
+++ b/gdb/testsuite/gdb.tui/winwidth.exp
@@ -0,0 +1,62 @@
+# Copyright 2022 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test the "winwidth" command.
+
+tuiterm_env
+
+standard_testfile tui-layout.c
+
+if {[build_executable "failed to prepare" ${testfile} ${srcfile}] == -1} {
+    return -1
+}
+
+Term::clean_restart 24 80 $testfile
+if {![Term::enter_tui]} {
+    unsupported "TUI not supported"
+    return
+}
+
+Term::command "tui new-layout h { -horizontal src 1 asm 1 } 1 status 0 cmd 1"
+Term::command "layout h"
+
+with_test_prefix "original window sizes" {
+    Term::check_box "source box" 0 0 40 15
+    Term::check_box "asm box" 39 0 41 15
+    Term::command "winwidth src +5"
+}
+
+with_test_prefix "after src +5" {
+    Term::check_box "source box" 0 0 44 15
+    Term::check_box "asm box" 43 0 37 15
+    Term::command "winwidth asm -5"
+}
+
+with_test_prefix "after asm -5" {
+    Term::check_box "source box" 0 0 48 15
+    Term::check_box "asm box" 47 0 33 15
+    Term::command "winwidth asm +8"
+}
+
+with_test_prefix "after asm +8" {
+    Term::check_box "source box" 0 0 39 15
+    Term::check_box "asm box" 38 0 42 15
+    Term::command "winwidth src -2"
+}
+
+with_test_prefix "after src -2" {
+    Term::check_box "source box" 0 0 36 15
+    Term::check_box "asm box" 35 0 45 15
+}
diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index 9e856ccf3fa..13e4d462426 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -121,6 +121,14 @@ tui_adjust_window_height (struct tui_win_info *win, int new_height)
   applied_layout->set_height (win->name (), new_height);
 }
 
+/* See tui-layout.  */
+
+void
+tui_adjust_window_width (struct tui_win_info *win, int new_width)
+{
+  applied_layout->set_width (win->name (), new_width);
+}
+
 /* Set the current layout to LAYOUT.  */
 
 static void
@@ -570,8 +578,9 @@ tui_layout_split::set_weights_from_sizes ()
 
 /* See tui-layout.h.  */
 
+template<class Policy>
 tui_adjust_result
-tui_layout_split::set_height (const char *name, int new_height)
+tui_layout_split::set_size (const char *name, int new_size)
 {
   /* Look through the children.  If one is a layout holding the named
      window, we're done; or if one actually is the named window,
@@ -580,12 +589,12 @@ tui_layout_split::set_height (const char *name, int new_height)
   for (int i = 0; i < m_splits.size (); ++i)
     {
       tui_adjust_result adjusted
-	= m_splits[i].layout->set_height (name, new_height);
+	= Policy::set_size (m_splits[i].layout, name, new_size);
       if (adjusted == HANDLED)
 	return HANDLED;
       if (adjusted == FOUND)
 	{
-	  if (!m_vertical)
+	  if (!Policy::can_adjust (this))
 	    return FOUND;
 	  found_index = i;
 	  break;
@@ -594,12 +603,12 @@ tui_layout_split::set_height (const char *name, int new_height)
 
   if (found_index == -1)
     return NOT_FOUND;
-  if (m_splits[found_index].layout->height == new_height)
+  if (Policy::current_size (m_splits[found_index].layout) == new_size)
     return HANDLED;
 
   set_weights_from_sizes ();
-  int delta = m_splits[found_index].weight - new_height;
-  m_splits[found_index].weight = new_height;
+  int delta = m_splits[found_index].weight - new_size;
+  m_splits[found_index].weight = new_size;
 
   /* Distribute the "delta" over the next window; but if the next
      window cannot hold it all, keep going until we either find a
@@ -633,7 +642,7 @@ tui_layout_split::set_height (const char *name, int new_height)
 
   if (delta != 0)
     {
-      warning (_("Invalid window height specified"));
+      Policy::invalid_size_warning ();
       /* Effectively undo any modifications made here.  */
       set_weights_from_sizes ();
     }
diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h
index 8f41835b94c..f4ef0895f1f 100644
--- a/gdb/tui/tui-layout.h
+++ b/gdb/tui/tui-layout.h
@@ -79,6 +79,10 @@ class tui_layout_base
      the sizes of the other windows around it.  */
   virtual tui_adjust_result set_height (const char *name, int new_height) = 0;
 
+  /* Set the width of the window named NAME to NEW_WIDTH, updating
+     the sizes of the other windows around it.  */
+  virtual tui_adjust_result set_width (const char *name, int new_width) = 0;
+
   /* Remove some windows from the layout, leaving the command window
      and the window being passed in here.  */
   virtual void remove_windows (const char *name) = 0;
@@ -132,6 +136,11 @@ class tui_layout_window : public tui_layout_base
     return m_contents == name ? FOUND : NOT_FOUND;
   }
 
+  tui_adjust_result set_width (const char *name, int new_width) override
+  {
+    return m_contents == name ? FOUND : NOT_FOUND;
+  }
+
   bool top_boxed_p () const override;
 
   bool bottom_boxed_p () const override;
@@ -192,7 +201,15 @@ class tui_layout_split : public tui_layout_base
 
   void apply (int x, int y, int width, int height) override;
 
-  tui_adjust_result set_height (const char *name, int new_height) override;
+  tui_adjust_result set_height (const char *name, int new_height) override
+  {
+    return set_size<tui_layout_split::set_height_policy> (name, new_height);
+  }
+
+  tui_adjust_result set_width (const char *name, int new_width) override
+  {
+    return set_size<tui_layout_split::set_width_policy> (name, new_width);
+  }
 
   bool top_boxed_p () const override;
 
@@ -217,6 +234,87 @@ class tui_layout_split : public tui_layout_base
 
 private:
 
+  /* Used to implement set_height and set_width member functions.  Set
+     either the height or width of the window named NAME to NEW_SIZE,
+     updating the sizes of the other windows around it as needed.  The
+     POLICY is used to specialize this function to adjust either the height
+     or the width.  */
+
+  template <class Policy>
+  tui_adjust_result set_size (const char *name, int new_size);
+
+  /* A policy class for use with the set_size member function, use when we
+     want to adjust the height of a named window.  */
+
+  struct set_height_policy
+  {
+    /* Set the height of window named NAME to NEW_HEIGHT in LAYOUT.  */
+    static tui_adjust_result
+    set_size (std::unique_ptr<tui_layout_base> &layout,
+	      const char *name,
+	      int new_height)
+    {
+      return layout->set_height (name, new_height);
+    }
+
+    /* Can we adjust the heights of windows in SPLIT?  */
+    static bool
+    can_adjust (const tui_layout_split *split)
+    {
+      return split->m_vertical;
+    }
+
+    /* What is the current height of LAYOUT.  */
+    static int
+    current_size (std::unique_ptr<tui_layout_base> &layout)
+    {
+      return layout->height;
+    }
+
+    /* Warn about invalid height specification.  */
+    static void
+    invalid_size_warning ()
+    {
+      warning (_("Invalid window height specified"));
+    }
+  };
+
+  /* A policy class for use with the set_size member function, use when we
+     want to adjust the width of a named window.  */
+
+  struct set_width_policy
+  {
+    /* Set the width of window named NAME to NEW_HEIGHT in LAYOUT.  */
+    static tui_adjust_result
+    set_size (std::unique_ptr<tui_layout_base> &layout,
+	      const char *name,
+	      int new_width)
+    {
+      return layout->set_width (name, new_width);
+    }
+
+    /* Can we adjust the widths of windows in SPLIT?  */
+    static bool
+    can_adjust (const tui_layout_split *split)
+    {
+      return !split->m_vertical;
+    }
+
+    /* What is the current width of LAYOUT.  */
+    static int
+    current_size (std::unique_ptr<tui_layout_base> &layout)
+    {
+      return layout->width;
+    }
+
+    /* Warn about invalid height specification.  */
+    static void
+    invalid_size_warning ()
+    {
+      warning (_("Invalid window width specified"));
+    }
+  };
+
   /* Set the weights from the current heights (when m_vertical is true) or
      widths (when m_vertical is false).  */
   void set_weights_from_sizes ();
@@ -266,6 +364,10 @@ extern void tui_apply_current_layout ();
 extern void tui_adjust_window_height (struct tui_win_info *win,
 				      int new_height);
 
+/* Adjust the window width of WIN to NEW_WIDTH.  */
+extern void tui_adjust_window_width (struct tui_win_info *win,
+				     int new_width);
+
 /* The type of a function that is used to create a TUI window.  */
 
 typedef std::function<tui_win_info * (const char *name)> window_factory;
diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c
index ba6aca3d078..953af640c93 100644
--- a/gdb/tui/tui-win.c
+++ b/gdb/tui/tui-win.c
@@ -842,10 +842,21 @@ tui_set_tab_width_command (const char *arg, int from_tty)
     }
 }
 
+/* Helper function for the user commands to adjust a window's width or
+   height.  The ARG string contains the command line arguments from the
+   user, which should give the name of a window, and how to adjust the
+   size.
 
-/* Set the height of the specified window.  */
+   The Policy type is used to specialise this function for updating either
+   the width or height of the window.
+
+   On invalid input, or if the size can't be adjusted as requested, then an
+   error is thrown, otherwise, the window sizes are adjusted, and the
+   windows redrawn.  */
+
+template<typename Policy>
 static void
-tui_set_win_height_command (const char *arg, int from_tty)
+tui_set_win_size (const char *arg)
 {
   /* Make sure the curses mode is enabled.  */
   tui_enable ();
@@ -854,7 +865,7 @@ tui_set_win_height_command (const char *arg, int from_tty)
 
   const char *buf = arg;
   const char *buf_ptr = buf;
-  int new_height;
+  int new_size;
   struct tui_win_info *win_info;
 
   buf_ptr = skip_to_space (buf_ptr);
@@ -890,18 +901,82 @@ tui_set_win_height_command (const char *arg, int from_tty)
 	  if (negate)
 	    input_no *= (-1);
 	  if (fixed_size)
-	    new_height = input_no;
+	    new_size = input_no;
 	  else
-	    new_height = win_info->height + input_no;
+	    new_size = Policy::existing_window_size (win_info) + input_no;
 
 	  /* Now change the window's height, and adjust
 	     all other windows around it.  */
-	  tui_adjust_window_height (win_info, new_height);
+	  Policy::adjust_window_size (win_info, new_size);
 	  tui_update_gdb_sizes ();
 	}
       else
-	error (_("Invalid window height specified"));
+	Policy::invalid_size_error ();
+    }
+}
+
+/* Implement the 'tui window height' command (alias 'winheight').  */
+
+static void
+tui_set_win_height_command (const char *arg, int from_tty)
+{
+  /* Policy class for use with tui_set_win_size, this policy adjusts the
+     height of a window.  */
+  struct height_adjustment_policy
+  {
+    /* Called when the size specified is invalid.  */
+    static void invalid_size_error ()
+    {
+      error (_("Invalid window height specified"));
+    }
+
+    /* Return the existing size, height in this case, of a window WIN_INFO.  */
+    static int existing_window_size (struct tui_win_info *win_info)
+    {
+      return win_info->height;
+    }
+
+    /* Set the size, height in this case, of WIN_INFO to NEW_SIZE.  */
+    static void adjust_window_size (struct tui_win_info *win_info,
+				    int new_size)
+    {
+      tui_adjust_window_height (win_info, new_size);
+    }
+  };
+
+  tui_set_win_size<height_adjustment_policy> (arg);
+}
+
+/* Implement the 'tui window width' command (alias 'winwidth').  */
+
+static void
+tui_set_win_width_command (const char *arg, int from_tty)
+{
+  /* Policy class for use with tui_set_win_size, this policy adjusts the
+     width of a window.  */
+  struct width_adjustment_policy
+  {
+    /* Called when the size specified is invalid.  */
+    static void invalid_size_error ()
+    {
+      error (_("Invalid window width specified"));
     }
+
+    /* Return the existing size, width in this case, of a window WIN_INFO.  */
+    static int existing_window_size (struct tui_win_info *win_info)
+    {
+      return win_info->width;
+    }
+
+    /* Set the size, width in this case, of WIN_INFO to NEW_SIZE.  */
+    static void adjust_window_size (struct tui_win_info *win_info,
+				    int new_size)
+    {
+      tui_adjust_window_width (win_info, new_size);
+    }
+  };
+
+  tui_set_win_size<width_adjustment_policy> (arg);
 }
 
 /* See tui-data.h.  */
@@ -1033,6 +1108,16 @@ Use \"info win\" to see the names of the windows currently being displayed."),
   add_com_alias ("winheight", winheight_cmd, class_tui, 0);
   add_com_alias ("wh", winheight_cmd, class_tui, 0);
   set_cmd_completer (winheight_cmd, winheight_completer);
+
+  cmd_list_element *winwidth_cmd
+    = add_cmd ("width", class_tui, tui_set_win_width_command, _("\
+Set or modify the width of a specified window.\n\
+Usage: tui window width WINDOW-NAME [+ | -] NUM-LINES\n\
+Use \"info win\" to see the names of the windows currently being displayed."),
+	       &tui_window_cmds);
+  add_com_alias ("winwidth", winwidth_cmd, class_tui, 0);
+  set_cmd_completer (winwidth_cmd, winheight_completer);
+
   add_info ("win", tui_all_windows_info,
 	    _("List of all displayed windows.\n\
 Usage: info win"));


^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCHv2 05/15] gdb/tui: add new 'tui window width' command and 'winwidth' alias
  2022-02-09 15:33       ` Andrew Burgess
@ 2022-02-09 17:03         ` Eli Zaretskii
  0 siblings, 0 replies; 74+ messages in thread
From: Eli Zaretskii @ 2022-02-09 17:03 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches

> From: Andrew Burgess <aburgess@redhat.com>
> Cc: gdb-patches@sourceware.org
> Date: Wed, 09 Feb 2022 15:33:30 +0000
> 
> > Btw, should we mention that this new command will only have effect if
> > more than one window is displayed?
> 
> What about this for the description of 'tui window width'?  The second
> paragraph is new:

It's fine, thanks.

> If this is OK, then I would propose adding the same paragraph to the
> description of 'tui window height' which obviously has the same
> restrictions.

Right.

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes
  2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess
                     ` (14 preceding siblings ...)
  2022-02-06 14:12   ` [PATCHv2 15/15] gdb/tui: fair split of delta after a resize Andrew Burgess
@ 2022-02-21 17:29   ` Andrew Burgess
  2022-03-02 17:59     ` Andrew Burgess
  2022-03-07 22:13   ` [PATCHv3 " Andrew Burgess
  16 siblings, 1 reply; 74+ messages in thread
From: Andrew Burgess @ 2022-02-21 17:29 UTC (permalink / raw)
  To: gdb-patches


Ping!

Thanks,
Andrew


Andrew Burgess <aburgess@redhat.com> writes:

> I pushed the first two patches from the v1 series, but the rest of
> that original series does need reviewing - those paches are included
> in v2 as patches 1 to 5.
>
> The remaining 10 patches in the v2 series mostly relate to changing
> how window resizing, and window layout occurs.
>
> The docs content in patches 1 and 5 of the v2 series is unchanged from
> v1, and was already reviewed, so no new docs review is required there.
>
> There is some new docs content in patch 6, but its pretty minor; a
> docs review is always welcome though.
>
> I'm hoping most of the changes in this series will be pretty
> non-controversial, the only patch which I think might be more of a
> personal taste issue is the very last one (left last for that reason).
> I'd suggest selecting the split layout, and then playing with window
> resizing to get a feel for the new behaviour.  Feedback welcome.
>
> Thanks,
> Andrew
>
> ---
>
> Andrew Burgess (15):
>   gdb: move some commands into the tui namespace
>   gdb/tui: rename tui_layout_base::adjust_size to ::set_height
>   gdb/tui: rename tui_layout_split:set_weights_from_heights
>   gdb/testing/tui: add new functionality to tuiterm.exp
>   gdb/tui: add new 'tui window width' command and 'winwidth' alias
>   gdb/tui: add a tui debugging flag
>   gdb/tui: add left_boxed_p and right_boxed_p member functions
>   gdb/tui/testsuite: refactor new-layout.exp test
>   gdb/tui: avoid fp exception when applying layouts
>   gdb/tui: fairer distribution of excess space during apply
>   gdb/tui: allow cmd window to change size in tui_layout_split::apply
>   gdb/tui: support placing the cmd window into a horizontal layout
>   gdb/testsuite: some additional tests in gdb.tui/scroll.exp
>   gdb/tui: relax restrictions on window max height and width
>   gdb/tui: fair split of delta after a resize
>
>  gdb/NEWS                             |  25 ++
>  gdb/doc/gdb.texinfo                  |  41 ++-
>  gdb/testsuite/gdb.tui/basic.exp      |   4 +-
>  gdb/testsuite/gdb.tui/empty.exp      |  14 +-
>  gdb/testsuite/gdb.tui/new-layout.exp | 100 +++++--
>  gdb/testsuite/gdb.tui/regs.exp       |   4 +-
>  gdb/testsuite/gdb.tui/scroll.exp     |   4 +
>  gdb/testsuite/gdb.tui/winheight.exp  |  77 +++++
>  gdb/testsuite/gdb.tui/winwidth.exp   |  63 ++++
>  gdb/testsuite/lib/tuiterm.exp        |  82 +++++-
>  gdb/tui/tui-command.c                |   6 -
>  gdb/tui/tui-command.h                |   2 -
>  gdb/tui/tui-layout.c                 | 419 +++++++++++++++++++++++----
>  gdb/tui/tui-layout.h                 | 201 ++++++++++++-
>  gdb/tui/tui-win.c                    | 149 ++++++++--
>  gdb/tui/tui.c                        |  26 ++
>  gdb/tui/tui.h                        |  14 +
>  17 files changed, 1089 insertions(+), 142 deletions(-)
>  create mode 100644 gdb/testsuite/gdb.tui/winwidth.exp
>
> -- 
> 2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes
  2022-02-21 17:29   ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess
@ 2022-03-02 17:59     ` Andrew Burgess
  0 siblings, 0 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-03-02 17:59 UTC (permalink / raw)
  To: gdb-patches


Ping!

Thanks,
Andrew


Andrew Burgess <aburgess@redhat.com> writes:

> Ping!
>
> Thanks,
> Andrew
>
>
> Andrew Burgess <aburgess@redhat.com> writes:
>
>> I pushed the first two patches from the v1 series, but the rest of
>> that original series does need reviewing - those paches are included
>> in v2 as patches 1 to 5.
>>
>> The remaining 10 patches in the v2 series mostly relate to changing
>> how window resizing, and window layout occurs.
>>
>> The docs content in patches 1 and 5 of the v2 series is unchanged from
>> v1, and was already reviewed, so no new docs review is required there.
>>
>> There is some new docs content in patch 6, but its pretty minor; a
>> docs review is always welcome though.
>>
>> I'm hoping most of the changes in this series will be pretty
>> non-controversial, the only patch which I think might be more of a
>> personal taste issue is the very last one (left last for that reason).
>> I'd suggest selecting the split layout, and then playing with window
>> resizing to get a feel for the new behaviour.  Feedback welcome.
>>
>> Thanks,
>> Andrew
>>
>> ---
>>
>> Andrew Burgess (15):
>>   gdb: move some commands into the tui namespace
>>   gdb/tui: rename tui_layout_base::adjust_size to ::set_height
>>   gdb/tui: rename tui_layout_split:set_weights_from_heights
>>   gdb/testing/tui: add new functionality to tuiterm.exp
>>   gdb/tui: add new 'tui window width' command and 'winwidth' alias
>>   gdb/tui: add a tui debugging flag
>>   gdb/tui: add left_boxed_p and right_boxed_p member functions
>>   gdb/tui/testsuite: refactor new-layout.exp test
>>   gdb/tui: avoid fp exception when applying layouts
>>   gdb/tui: fairer distribution of excess space during apply
>>   gdb/tui: allow cmd window to change size in tui_layout_split::apply
>>   gdb/tui: support placing the cmd window into a horizontal layout
>>   gdb/testsuite: some additional tests in gdb.tui/scroll.exp
>>   gdb/tui: relax restrictions on window max height and width
>>   gdb/tui: fair split of delta after a resize
>>
>>  gdb/NEWS                             |  25 ++
>>  gdb/doc/gdb.texinfo                  |  41 ++-
>>  gdb/testsuite/gdb.tui/basic.exp      |   4 +-
>>  gdb/testsuite/gdb.tui/empty.exp      |  14 +-
>>  gdb/testsuite/gdb.tui/new-layout.exp | 100 +++++--
>>  gdb/testsuite/gdb.tui/regs.exp       |   4 +-
>>  gdb/testsuite/gdb.tui/scroll.exp     |   4 +
>>  gdb/testsuite/gdb.tui/winheight.exp  |  77 +++++
>>  gdb/testsuite/gdb.tui/winwidth.exp   |  63 ++++
>>  gdb/testsuite/lib/tuiterm.exp        |  82 +++++-
>>  gdb/tui/tui-command.c                |   6 -
>>  gdb/tui/tui-command.h                |   2 -
>>  gdb/tui/tui-layout.c                 | 419 +++++++++++++++++++++++----
>>  gdb/tui/tui-layout.h                 | 201 ++++++++++++-
>>  gdb/tui/tui-win.c                    | 149 ++++++++--
>>  gdb/tui/tui.c                        |  26 ++
>>  gdb/tui/tui.h                        |  14 +
>>  17 files changed, 1089 insertions(+), 142 deletions(-)
>>  create mode 100644 gdb/testsuite/gdb.tui/winwidth.exp
>>
>> -- 
>> 2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCHv2 05/15] gdb/tui: add new 'tui window width' command and 'winwidth' alias
  2022-02-06 14:12   ` [PATCHv2 05/15] gdb/tui: add new 'tui window width' command and 'winwidth' alias Andrew Burgess
  2022-02-06 15:52     ` Eli Zaretskii
@ 2022-03-03 18:52     ` Pedro Alves
  1 sibling, 0 replies; 74+ messages in thread
From: Pedro Alves @ 2022-03-03 18:52 UTC (permalink / raw)
  To: Andrew Burgess, gdb-patches

On 2022-02-06 14:12, Andrew Burgess via Gdb-patches wrote:

> As for the changes in gdb itself, I've mostly just templated the
> existing height adjustment code so that the two functions
> tui_layout_split::adjust_size (tui-layout.c) and
> tui_set_win_height_command (tui-win.c) now have a template parameter
> "policy", this policy allows me to specialise the functions for either
> width or height adjustment.  Function arguments, and locals, are
> renamed, replacing 'height' with 'size'.

Do you envision that there will be more policies going forward, other than
width and height?  Template policies are a good thing when the number of
policies is open ended, such as with library utility classes where you want the
user of the utility be able to configure your type.  But here, you only have
two modes of operation and they are totally known upfront, which seems like could
be just as well handled with a bool or enum.  The disadvantage of the policy
approach is that leads to code bloat, as the compiler basically duplicates the
functions.

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCHv2 04/15] gdb/testing/tui: add new functionality to tuiterm.exp
  2022-02-06 14:12   ` [PATCHv2 04/15] gdb/testing/tui: add new functionality to tuiterm.exp Andrew Burgess
@ 2022-03-04 16:29     ` Tom Tromey
  0 siblings, 0 replies; 74+ messages in thread
From: Tom Tromey @ 2022-03-04 16:29 UTC (permalink / raw)
  To: Andrew Burgess via Gdb-patches; +Cc: Andrew Burgess

>>>>> "Andrew" == Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> writes:

Andrew> There are no new tests in this commit, but I was running into these
Andrew> sequences while developing later patches in this series.  However,
Andrew> which control sequences ncurses emits can vary wildly depending on the
Andrew> screen contents.  It is possible that I only hit some of these
Andrew> sequences while debugging the later patches (i.e. printing extra
Andrew> content to the terminal), some of these might no longer be needed
Andrew> given the tests as now written.

Andrew> Still, I think it is worth merging these to improve tuiterm.exp.

Agreed, and just to be clear, the history of tuiterm.exp is that I
implemented more or less the minimum needed based on the tests I had
written.  I wouldn't be surprised if future tests find other holes.

Tom

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCHv2 06/15] gdb/tui: add a tui debugging flag
  2022-02-06 14:12   ` [PATCHv2 06/15] gdb/tui: add a tui debugging flag Andrew Burgess
  2022-02-06 15:53     ` Eli Zaretskii
@ 2022-03-04 16:35     ` Tom Tromey
  1 sibling, 0 replies; 74+ messages in thread
From: Tom Tromey @ 2022-03-04 16:35 UTC (permalink / raw)
  To: Andrew Burgess via Gdb-patches; +Cc: Andrew Burgess

Andrew> Enabling logging and switching interpreters can cause undefined
Andrew> results, including crashes.  This is an existing bug in gdb, and has
Andrew> nothing directly to do with tui debug, but it is worth mentioning here
Andrew> I think.

Is this in bugzilla already?

Tom

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCHv2 07/15] gdb/tui: add left_boxed_p and right_boxed_p member functions
  2022-02-06 14:12   ` [PATCHv2 07/15] gdb/tui: add left_boxed_p and right_boxed_p member functions Andrew Burgess
@ 2022-03-04 16:37     ` Tom Tromey
  0 siblings, 0 replies; 74+ messages in thread
From: Tom Tromey @ 2022-03-04 16:37 UTC (permalink / raw)
  To: Andrew Burgess via Gdb-patches; +Cc: Andrew Burgess

>>>>> "Andrew" == Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> writes:

Andrew> I did consider just adding a comment about this to the above code, but
Andrew> this still doesn't feel great.  So, in this commit, I've just filled
Andrew> in the API to add right_boxed_p and left_boxed_p, and now I call these
Andrew> instead of bottom_boxed_p and top_boxed_p if appropriate.

Andrew> Maybe it's just pointless noise....

Andrew> ... I'd rather the main apply function not have to have special
Andrew> knowledge about the implementation of these things coded into it.

It seems fine but I wonder if just renaming these methods would yield
the same effective result without duplicating code.

Tom

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCHv2 10/15] gdb/tui: fairer distribution of excess space during apply
  2022-02-06 14:12   ` [PATCHv2 10/15] gdb/tui: fairer distribution of excess space during apply Andrew Burgess
@ 2022-03-04 16:42     ` Tom Tromey
  0 siblings, 0 replies; 74+ messages in thread
From: Tom Tromey @ 2022-03-04 16:42 UTC (permalink / raw)
  To: Andrew Burgess via Gdb-patches; +Cc: Andrew Burgess

>>>>> "Andrew" == Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> writes:

Andrew> In this commit, rather than add all the extra space to one single
Andrew> window, I instead hand out the extra space 1 line at a time, looping
Andrew> over all the sub-layouts.  We take care to respect the min/max sizes,
Andrew> and so, we now get this result:

I think this patch should also update this comment a bit earlier in the
function:

      /* If there is any leftover size, just redistribute it to the
	 last resizeable window, by dropping it from the allocated
	 size.  We could try to be fancier here perhaps, by
	 redistributing this size among all windows, not just the
	 last window.  */

... because now the fancier thing is done.

I'm not sure any more if this comment correctly explains the following
'if', so I don't know if the comment can just be removed or if it needs
some kind of rewording.

Tom

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCHv2 12/15] gdb/tui: support placing the cmd window into a horizontal layout
  2022-02-06 14:12   ` [PATCHv2 12/15] gdb/tui: support placing the cmd window into a horizontal layout Andrew Burgess
@ 2022-03-04 17:17     ` Tom Tromey
  2022-03-07 20:05       ` Andrew Burgess
  0 siblings, 1 reply; 74+ messages in thread
From: Tom Tromey @ 2022-03-04 17:17 UTC (permalink / raw)
  To: Andrew Burgess via Gdb-patches; +Cc: Andrew Burgess

>>>>> "Andrew" == Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> writes:

Andrew> This commit allows the user to place the cmd window within horizontal
Andrew> tui layouts.

Do these really work?  I forget exactly why, but I vaguely recall that
there is some reason the command window doesn't interact nicely with
arbitrary layouts.

It might be because the command window is unboxed, so the rendering
looks strange.  Or maybe it affects the pager somehow?

Anyway, I'm all for it working if possible.

Tom

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCHv2 14/15] gdb/tui: relax restrictions on window max height and width
  2022-02-06 14:12   ` [PATCHv2 14/15] gdb/tui: relax restrictions on window max height and width Andrew Burgess
@ 2022-03-04 17:20     ` Tom Tromey
  2022-03-07 20:08       ` Andrew Burgess
  0 siblings, 1 reply; 74+ messages in thread
From: Tom Tromey @ 2022-03-04 17:20 UTC (permalink / raw)
  To: Andrew Burgess via Gdb-patches; +Cc: Andrew Burgess

>>>>> "Andrew" == Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> writes:

Andrew>  int
Andrew>  tui_win_info::max_height () const
Andrew>  {
Andrew> -  return tui_term_height () - 2;
Andrew> +  return tui_term_height ();

I suspect this kind of thing is to ensure there's room for the box.
It's also possible this is just ancient code.  Despite the big TUI
refactorings, there's still some leftover weird stuff in there.

Tom

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCHv2 15/15] gdb/tui: fair split of delta after a resize
  2022-02-06 14:12   ` [PATCHv2 15/15] gdb/tui: fair split of delta after a resize Andrew Burgess
@ 2022-03-04 17:22     ` Tom Tromey
  2022-03-07 22:07       ` Andrew Burgess
  0 siblings, 1 reply; 74+ messages in thread
From: Tom Tromey @ 2022-03-04 17:22 UTC (permalink / raw)
  To: Andrew Burgess via Gdb-patches; +Cc: Andrew Burgess

>>>>> "Andrew" == Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> writes:

Andrew> Currently, in master gdb, when a tui window is changed in size, the
Andrew> screen delta is mostly just added to the next available window.  We
Andrew> do take care to respect the min/max size, but in most cases, these
Andrew> limits are just "the terminal size", and so, we end up placing the
Andrew> whole delta on the next window.

This seems like a change that corresponds to the same change in the
patch to change how layouts are applied.  That is, the resize-one-window
code and the layout-from-scratch code ought to agree algorithmically.
So maybe this should have been merged into that one -- though I'm not
really too picky about that kind of thing.

Tom

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 0/7] TUI command changes, including new winwidth command
  2022-01-28 15:55 [PATCH 0/7] TUI command changes, including new winwidth command Andrew Burgess
                   ` (7 preceding siblings ...)
  2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess
@ 2022-03-04 17:23 ` Tom Tromey
  8 siblings, 0 replies; 74+ messages in thread
From: Tom Tromey @ 2022-03-04 17:23 UTC (permalink / raw)
  To: Andrew Burgess via Gdb-patches; +Cc: Andrew Burgess

>>>>> "Andrew" == Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> writes:

Andrew> I'm working on a patch to improve the TUI's window sizing and resizing
Andrew> behaviour.  That's still a work in progress.  But, as part of that
Andrew> work I needed to add support for resizing the width of a window.

Andrew> Given that we have horizontal window layout support, I think it makes
Andrew> sense to have this functionality whether or not I finish my bigger
Andrew> window resizing work.

I sent some notes, but nothing serious.  I think it looks great overall,
though I did also have the same question as Pedro for patch #5.

Tom

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCHv2 12/15] gdb/tui: support placing the cmd window into a horizontal layout
  2022-03-04 17:17     ` Tom Tromey
@ 2022-03-07 20:05       ` Andrew Burgess
  2022-03-07 21:24         ` Tom Tromey
  0 siblings, 1 reply; 74+ messages in thread
From: Andrew Burgess @ 2022-03-07 20:05 UTC (permalink / raw)
  To: Tom Tromey, Andrew Burgess via Gdb-patches

Tom Tromey <tom@tromey.com> writes:

>>>>>> "Andrew" == Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> writes:
>
> Andrew> This commit allows the user to place the cmd window within horizontal
> Andrew> tui layouts.
>
> Do these really work?  I forget exactly why, but I vaguely recall that
> there is some reason the command window doesn't interact nicely with
> arbitrary layouts.
>
> It might be because the command window is unboxed, so the rendering
> looks strange.  Or maybe it affects the pager somehow?

I've not noticed anything particularly strange so far.  At least,
nothing so strange that I think we should not go ahead with this
change.

I have seen a couple of weird page issues when I created a particularly
narrow CMD window - it almost seemed like the page was confused about
how many lines it had drawn.

But for the most part everything seemed OK.

My preference would be to get this in (after I've addressed the other
feedback), then if we see problems we can start to address issues.  I
don't think that the user experience is so bad that we should go ahead
with this.

Let me know if you're happy with this approach.

Thanks,
Andrew


^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCHv2 14/15] gdb/tui: relax restrictions on window max height and width
  2022-03-04 17:20     ` Tom Tromey
@ 2022-03-07 20:08       ` Andrew Burgess
  0 siblings, 0 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-03-07 20:08 UTC (permalink / raw)
  To: Tom Tromey, Andrew Burgess via Gdb-patches

Tom Tromey <tom@tromey.com> writes:

>>>>>> "Andrew" == Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> writes:
>
> Andrew>  int
> Andrew>  tui_win_info::max_height () const
> Andrew>  {
> Andrew> -  return tui_term_height () - 2;
> Andrew> +  return tui_term_height ();
>
> I suspect this kind of thing is to ensure there's room for the box.
> It's also possible this is just ancient code.  Despite the big TUI
> refactorings, there's still some leftover weird stuff in there.

Maybe it was once, but I assume that if it was still needed then I'd see
issues once it was removed.  And I don't.

As far as I understand things, the layout algorithm takes
tui_term_height and assigns that space out to the container windows.
The space allocated to a window is expected to include the windows
border.

So limiting the max window size like this just means we can never have a
single window fill the terminal.

I'll do more testing while I'm addressing the other feedback issues, and
if you have any suggestions for things to try that might reveal a bug
related to this change, then I'm happy to give it a go.

But otherwise, as far as I can tell, the above change is fine.

Thanks,
Andrew


^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCHv2 12/15] gdb/tui: support placing the cmd window into a horizontal layout
  2022-03-07 20:05       ` Andrew Burgess
@ 2022-03-07 21:24         ` Tom Tromey
  0 siblings, 0 replies; 74+ messages in thread
From: Tom Tromey @ 2022-03-07 21:24 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: Tom Tromey, Andrew Burgess via Gdb-patches

Andrew> But for the most part everything seemed OK.

Andrew> My preference would be to get this in (after I've addressed the other
Andrew> feedback), then if we see problems we can start to address issues.  I
Andrew> don't think that the user experience is so bad that we should go ahead
Andrew> with this.

Andrew> Let me know if you're happy with this approach.

Yeah, it's fine by me.

Tom

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCHv2 15/15] gdb/tui: fair split of delta after a resize
  2022-03-04 17:22     ` Tom Tromey
@ 2022-03-07 22:07       ` Andrew Burgess
  2022-03-07 23:42         ` Tom Tromey
  0 siblings, 1 reply; 74+ messages in thread
From: Andrew Burgess @ 2022-03-07 22:07 UTC (permalink / raw)
  To: Tom Tromey, Andrew Burgess via Gdb-patches

Tom Tromey <tom@tromey.com> writes:

>>>>>> "Andrew" == Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> writes:
>
> Andrew> Currently, in master gdb, when a tui window is changed in size, the
> Andrew> screen delta is mostly just added to the next available window.  We
> Andrew> do take care to respect the min/max size, but in most cases, these
> Andrew> limits are just "the terminal size", and so, we end up placing the
> Andrew> whole delta on the next window.
>
> This seems like a change that corresponds to the same change in the
> patch to change how layouts are applied.  That is, the resize-one-window
> code and the layout-from-scratch code ought to agree algorithmically.
> So maybe this should have been merged into that one -- though I'm not
> really too picky about that kind of thing.

Originally, I did try to do this, but in the end I decided not too as
the amount of change seemed much bigger than needed.

The problem is that we end up needing to add a mechanism to "lock" a
window size - we have a layout with windows A, B, and C.  The user sets
the size of window B.

With the code in my patch we set the size of B as the user requested,
and then resize A and C around B.

If we try to use apply, then, after changing the size of B, we need some
way to tell ::apply that it must not change the size of B again.

This is totally doable, at one point I had a version of this patch that
did just this, but it was a big code change.

I'd much rather push this smaller change, which allows me to get
additional tests into place, then, if we want, we can try to refactor
things later, and merge the two code paths together.

Would this be OK?

Thanks,
Andrew


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv3 00/15] TUI changes, new winwidth command and resizing changes
  2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess
                     ` (15 preceding siblings ...)
  2022-02-21 17:29   ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess
@ 2022-03-07 22:13   ` Andrew Burgess
  2022-03-07 22:13     ` [PATCHv3 01/15] gdb: move some commands into the tui namespace Andrew Burgess
                       ` (15 more replies)
  16 siblings, 16 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

Since v2:

  - Rebased onto current upstream/master,

  - Patch #5 - Rewritten to not use templates!

  - Patch #6 - Added a bug in bugzilla, and referenced this from the
    commit message,

  - Patch #7 - Renamed the existing methods rather than adding 2 new
    methods,

  - Patch #10 - Updated the comment Tom identified as being out of
    date,

  - Patch #15 - Have updated a comment that I spotted was out of date.

Thanks,
Andrew


---

Andrew Burgess (15):
  gdb: move some commands into the tui namespace
  gdb/tui: rename tui_layout_base::adjust_size to ::set_height
  gdb/tui: rename tui_layout_split:set_weights_from_heights
  gdb/testing/tui: add new functionality to tuiterm.exp
  gdb/tui: add new 'tui window width' command and 'winwidth' alias
  gdb/tui: add a tui debugging flag
  gdb/tui: add left_boxed_p and right_boxed_p member functions
  gdb/tui/testsuite: refactor new-layout.exp test
  gdb/tui: avoid fp exception when applying layouts
  gdb/tui: fairer distribution of excess space during apply
  gdb/tui: allow cmd window to change size in tui_layout_split::apply
  gdb/tui: support placing the cmd window into a horizontal layout
  gdb/testsuite: some additional tests in gdb.tui/scroll.exp
  gdb/tui: relax restrictions on window max height and width
  gdb/tui: fair split of delta after a resize

 gdb/NEWS                             |  25 ++
 gdb/doc/gdb.texinfo                  |  51 +++-
 gdb/testsuite/gdb.tui/basic.exp      |   4 +-
 gdb/testsuite/gdb.tui/empty.exp      |  14 +-
 gdb/testsuite/gdb.tui/new-layout.exp | 100 +++++--
 gdb/testsuite/gdb.tui/regs.exp       |   4 +-
 gdb/testsuite/gdb.tui/scroll.exp     |   4 +
 gdb/testsuite/gdb.tui/winheight.exp  |  77 +++++
 gdb/testsuite/gdb.tui/winwidth.exp   |  63 +++++
 gdb/testsuite/lib/tuiterm.exp        |  82 +++++-
 gdb/tui/tui-command.c                |   6 -
 gdb/tui/tui-command.h                |   2 -
 gdb/tui/tui-layout.c                 | 406 ++++++++++++++++++++++-----
 gdb/tui/tui-layout.h                 | 135 +++++++--
 gdb/tui/tui-win.c                    | 118 ++++++--
 gdb/tui/tui.c                        |  26 ++
 gdb/tui/tui.h                        |  14 +
 17 files changed, 971 insertions(+), 160 deletions(-)
 create mode 100644 gdb/testsuite/gdb.tui/winwidth.exp

-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv3 01/15] gdb: move some commands into the tui namespace
  2022-03-07 22:13   ` [PATCHv3 " Andrew Burgess
@ 2022-03-07 22:13     ` Andrew Burgess
  2022-03-07 22:13     ` [PATCHv3 02/15] gdb/tui: rename tui_layout_base::adjust_size to ::set_height Andrew Burgess
                       ` (14 subsequent siblings)
  15 siblings, 0 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

There are a lot of tui related commands that live in the top-level
command name space, e.g. layout, focus, refresh, winheight.

Having them at the top level means less typing for the user, which is
good, but, I think, makes command discovery harder.

In this commit, I propose moving all of the above mentioned commands
into the tui namespace, so 'layout' becomes 'tui layout', etc.  But I
will then add aliases so that the old commands will still work,
e.g. I'll make 'layout' an alias for 'tui layout'.

The benefit I see in this work is that tui related commands can be
more easily discovered by typing 'tui ' and then tab-completing.  Also
the "official" command is now a tui-sub-command, this is visible in,
for example, the help output, e.g.:

  (gdb) help layout
  tui layout, layout
  Change the layout of windows.
  Usage: tui layout prev | next | LAYOUT-NAME

  List of tui layout subcommands:

  tui layout asm -- Apply the "asm" layout.
  tui layout next -- Apply the next TUI layout.
  tui layout prev -- Apply the previous TUI layout.
  tui layout regs -- Apply the TUI register layout.
  tui layout split -- Apply the "split" layout.
  tui layout src -- Apply the "src" layout.

Which I think is a good thing, it makes it clearer that this is a tui
command.

I've added a NEWS entry and updated the docs to mention the new and
old command names, with the new name being mentioned first.
---
 gdb/NEWS             | 15 +++++++++++++++
 gdb/doc/gdb.texinfo  | 18 +++++++++++++-----
 gdb/tui/tui-layout.c | 16 +++++++++++++---
 gdb/tui/tui-win.c    | 40 ++++++++++++++++++++++++++++++++--------
 4 files changed, 73 insertions(+), 16 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index cf1e084fed6..3c3e0bbb2fb 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -119,6 +119,14 @@ show ada source-charset
   values for this follow the values that can be passed to the GNAT
   compiler via the '-gnati' option.  The default is ISO-8859-1.
 
+tui layout
+tui focus
+tui refresh
+tui window height
+  These are the new names for the old 'layout', 'focus', 'refresh',
+  and 'winheight' tui commands respectively.  The old names still
+  exist as aliases to these new commands.
+
 * Changed commands
 
 maint packet
@@ -144,6 +152,13 @@ info win
   This command now includes information about the width of the tui
   windows in its output.
 
+layout
+focus
+refresh
+winheight
+  These commands are now aliases for the 'tui layout', 'tui focus',
+  'tui refresh', and 'tui window height' commands respectively.
+
 * GDB's Ada parser now supports an extension for specifying the exact
   byte contents of a floating-point literal.  This can be useful for
   setting floating-point registers to a precise value without loss of
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 132b94c6487..fd4c110569e 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -29006,8 +29006,10 @@
 width of the terminal.  Because they have weight 2, the source and
 assembly windows will be twice the height of the command window.
 
-@item layout @var{name}
+@kindex tui layout
 @kindex layout
+@item tui layout @var{name}
+@itemx layout @var{name}
 Changes which TUI windows are displayed.  The @var{name} parameter
 controls which layout is shown.  It can be either one of the built-in
 layout names, or the name of a layout defined by the user using
@@ -29037,8 +29039,9 @@
 register, assembler, and command windows.
 @end table
 
-@item focus @var{name}
 @kindex focus
+@item tui focus @var{name}
+@itemx focus @var{name}
 Changes which TUI window is currently active for scrolling.  The
 @var{name} parameter can be any of the following:
 
@@ -29062,8 +29065,10 @@
 Make the command window active for scrolling.
 @end table
 
-@item refresh
+@kindex tui refresh
 @kindex refresh
+@item tui refresh
+@itemx refresh
 Refresh the screen.  This is similar to typing @kbd{C-L}.
 
 @item tui reg @var{group}
@@ -29099,9 +29104,12 @@
 @kindex update
 Update the source window and the current execution point.
 
-@item winheight @var{name} +@var{count}
-@itemx winheight @var{name} -@var{count}
+@kindex tui window height
 @kindex winheight
+@item tui window height @var{name} +@var{count}
+@itemx tui window height @var{name} -@var{count}
+@itemx winheight @var{name} +@var{count}
+@itemx winheight @var{name} -@var{count}
 Change the height of the window @var{name} by @var{count} lines.
 Positive counts increase the height, while negative counts decrease
 it.  The @var{name} parameter can be the name of any currently visible
diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index cef9190c3e1..f8388e3fca5 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -839,6 +839,14 @@ destroy_layout (struct cmd_list_element *self, void *context)
 
 static struct cmd_list_element *layout_list;
 
+/* Called to implement 'tui layout'.  */
+
+static void
+tui_layout_command (const char *args, int from_tty)
+{
+  help_list (layout_list, "tui layout ", all_commands, gdb_stdout);
+}
+
 /* Add a "layout" command with name NAME that switches to LAYOUT.  */
 
 static struct cmd_list_element *
@@ -1017,10 +1025,12 @@ void _initialize_tui_layout ();
 void
 _initialize_tui_layout ()
 {
-  add_basic_prefix_cmd ("layout", class_tui, _("\
+  struct cmd_list_element *layout_cmd
+    = add_prefix_cmd ("layout", class_tui, tui_layout_command, _("\
 Change the layout of windows.\n\
-Usage: layout prev | next | LAYOUT-NAME"),
-			&layout_list, 0, &cmdlist);
+Usage: tui layout prev | next | LAYOUT-NAME"),
+		      &layout_list, 0, tui_get_cmd_list ());
+  add_com_alias ("layout", layout_cmd, class_tui, 0);
 
   add_cmd ("next", class_tui, tui_next_layout_command,
 	   _("Apply the next TUI layout."),
diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c
index fd6ca59a728..ba6aca3d078 100644
--- a/gdb/tui/tui-win.c
+++ b/gdb/tui/tui-win.c
@@ -977,6 +977,18 @@ parse_scrolling_args (const char *arg,
     }
 }
 
+/* The list of 'tui window' sub-commands.  */
+
+static cmd_list_element *tui_window_cmds = nullptr;
+
+/* Called to implement 'tui window'.  */
+
+static void
+tui_window_command (const char *args, int from_tty)
+{
+  help_list (tui_window_cmds, "tui window ", all_commands, gdb_stdout);
+}
+
 /* Function to initialize gdb commands, for tui window
    manipulation.  */
 
@@ -995,8 +1007,11 @@ _initialize_tui_win ()
 			  &tui_setlist, &tui_showlist,
 			  &setlist, &showlist);
 
-  add_com ("refresh", class_tui, tui_refresh_all_command,
-	   _("Refresh the terminal display."));
+  cmd_list_element *refresh_cmd
+    = add_cmd ("refresh", class_tui, tui_refresh_all_command,
+	       _("Refresh the terminal display."),
+	       tui_get_cmd_list ());
+  add_com_alias ("refresh", refresh_cmd, class_tui, 0);
 
   cmd_list_element *tabset_cmd
     = add_com ("tabset", class_tui, tui_set_tab_width_command, _("\
@@ -1004,21 +1019,30 @@ Set the width (in characters) of tab stops.\n\
 Usage: tabset N"));
   deprecate_cmd (tabset_cmd, "set tui tab-width");
 
+  /* Setup the 'tui window' list of command.  */
+  add_prefix_cmd ("window", class_tui, tui_window_command,
+		  _("Text User Interface window commands."),
+		  &tui_window_cmds, 1, tui_get_cmd_list ());
+
   cmd_list_element *winheight_cmd
-    = add_com ("winheight", class_tui, tui_set_win_height_command, _("\
+    = add_cmd ("height", class_tui, tui_set_win_height_command, _("\
 Set or modify the height of a specified window.\n\
-Usage: winheight WINDOW-NAME [+ | -] NUM-LINES\n\
-Use \"info win\" to see the names of the windows currently being displayed."));
+Usage: tui window height WINDOW-NAME [+ | -] NUM-LINES\n\
+Use \"info win\" to see the names of the windows currently being displayed."),
+	       &tui_window_cmds);
+  add_com_alias ("winheight", winheight_cmd, class_tui, 0);
   add_com_alias ("wh", winheight_cmd, class_tui, 0);
   set_cmd_completer (winheight_cmd, winheight_completer);
   add_info ("win", tui_all_windows_info,
 	    _("List of all displayed windows.\n\
 Usage: info win"));
   cmd_list_element *focus_cmd
-    = add_com ("focus", class_tui, tui_set_focus_command, _("\
+    = add_cmd ("focus", class_tui, tui_set_focus_command, _("\
 Set focus to named window or next/prev window.\n\
-Usage: focus [WINDOW-NAME | next | prev]\n\
-Use \"info win\" to see the names of the windows currently being displayed."));
+Usage: tui focus [WINDOW-NAME | next | prev]\n\
+Use \"info win\" to see the names of the windows currently being displayed."),
+	       tui_get_cmd_list ());
+  add_com_alias ("focus", focus_cmd, class_tui, 0);
   add_com_alias ("fs", focus_cmd, class_tui, 0);
   set_cmd_completer (focus_cmd, focus_completer);
   add_com ("+", class_tui, tui_scroll_forward_command, _("\
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv3 02/15] gdb/tui: rename tui_layout_base::adjust_size to ::set_height
  2022-03-07 22:13   ` [PATCHv3 " Andrew Burgess
  2022-03-07 22:13     ` [PATCHv3 01/15] gdb: move some commands into the tui namespace Andrew Burgess
@ 2022-03-07 22:13     ` Andrew Burgess
  2022-03-07 22:13     ` [PATCHv3 03/15] gdb/tui: rename tui_layout_split:set_weights_from_heights Andrew Burgess
                       ` (13 subsequent siblings)
  15 siblings, 0 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

Rename tui_layout_base::adjust_size to tui_layout_base::set_height,
the new name more accurately reflects what this member function does,
and makes it easier for a later commit to add a new
tui_layout_base::set_width member function.

There should be no user visible changes after this commit.
---
 gdb/tui/tui-layout.c | 6 +++---
 gdb/tui/tui-layout.h | 8 ++++----
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index f8388e3fca5..4c355c79d65 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -118,7 +118,7 @@ tui_apply_current_layout ()
 void
 tui_adjust_window_height (struct tui_win_info *win, int new_height)
 {
-  applied_layout->adjust_size (win->name (), new_height);
+  applied_layout->set_height (win->name (), new_height);
 }
 
 /* Set the current layout to LAYOUT.  */
@@ -570,7 +570,7 @@ tui_layout_split::set_weights_from_heights ()
 /* See tui-layout.h.  */
 
 tui_adjust_result
-tui_layout_split::adjust_size (const char *name, int new_height)
+tui_layout_split::set_height (const char *name, int new_height)
 {
   /* Look through the children.  If one is a layout holding the named
      window, we're done; or if one actually is the named window,
@@ -579,7 +579,7 @@ tui_layout_split::adjust_size (const char *name, int new_height)
   for (int i = 0; i < m_splits.size (); ++i)
     {
       tui_adjust_result adjusted
-	= m_splits[i].layout->adjust_size (name, new_height);
+	= m_splits[i].layout->set_height (name, new_height);
       if (adjusted == HANDLED)
 	return HANDLED;
       if (adjusted == FOUND)
diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h
index b9a5d9b898d..acea7ac8f64 100644
--- a/gdb/tui/tui-layout.h
+++ b/gdb/tui/tui-layout.h
@@ -75,9 +75,9 @@ class tui_layout_base
     return nullptr;
   }
 
-  /* Adjust the size of the window named NAME to NEW_HEIGHT, updating
+  /* Set the height of the window named NAME to NEW_HEIGHT, updating
      the sizes of the other windows around it.  */
-  virtual tui_adjust_result adjust_size (const char *name, int new_height) = 0;
+  virtual tui_adjust_result set_height (const char *name, int new_height) = 0;
 
   /* Remove some windows from the layout, leaving the command window
      and the window being passed in here.  */
@@ -127,7 +127,7 @@ class tui_layout_window : public tui_layout_base
     return m_contents.c_str ();
   }
 
-  tui_adjust_result adjust_size (const char *name, int new_height) override
+  tui_adjust_result set_height (const char *name, int new_height) override
   {
     return m_contents == name ? FOUND : NOT_FOUND;
   }
@@ -192,7 +192,7 @@ class tui_layout_split : public tui_layout_base
 
   void apply (int x, int y, int width, int height) override;
 
-  tui_adjust_result adjust_size (const char *name, int new_height) override;
+  tui_adjust_result set_height (const char *name, int new_height) override;
 
   bool top_boxed_p () const override;
 
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv3 03/15] gdb/tui: rename tui_layout_split:set_weights_from_heights
  2022-03-07 22:13   ` [PATCHv3 " Andrew Burgess
  2022-03-07 22:13     ` [PATCHv3 01/15] gdb: move some commands into the tui namespace Andrew Burgess
  2022-03-07 22:13     ` [PATCHv3 02/15] gdb/tui: rename tui_layout_base::adjust_size to ::set_height Andrew Burgess
@ 2022-03-07 22:13     ` Andrew Burgess
  2022-03-07 22:13     ` [PATCHv3 04/15] gdb/testing/tui: add new functionality to tuiterm.exp Andrew Burgess
                       ` (12 subsequent siblings)
  15 siblings, 0 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

In a following commit I'm going to add the ability to change the width
of a tui window (when in a horizontal layout).  As a result, some of
the places where we currently hard-code references to height need to
be changed to handle either height, or width, based on whether we are
in a vertical, or horizontal layout.

This commit renames set_weights_from_heights to
set_weights_from_sizes, and makes the function use either the height,
or width as appropriate.

Currently, the only place that we call this function is from the
tui_layout_split::set_height function, in a part of the code we will
only reach for vertical layouts, so the new code is not actually being
used, but, this small change will help make later patches smaller, so
I'm proposing this as a stand alone change.

There should be no user visible changes after this commit.
---
 gdb/tui/tui-layout.c | 9 +++++----
 gdb/tui/tui-layout.h | 5 +++--
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index 4c355c79d65..9e856ccf3fa 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -561,10 +561,11 @@ tui_layout_split::bottom_boxed_p () const
 /* See tui-layout.h.  */
 
 void
-tui_layout_split::set_weights_from_heights ()
+tui_layout_split::set_weights_from_sizes ()
 {
   for (int i = 0; i < m_splits.size (); ++i)
-    m_splits[i].weight = m_splits[i].layout->height;
+    m_splits[i].weight
+      = m_vertical ? m_splits[i].layout->height : m_splits[i].layout->width;
 }
 
 /* See tui-layout.h.  */
@@ -596,7 +597,7 @@ tui_layout_split::set_height (const char *name, int new_height)
   if (m_splits[found_index].layout->height == new_height)
     return HANDLED;
 
-  set_weights_from_heights ();
+  set_weights_from_sizes ();
   int delta = m_splits[found_index].weight - new_height;
   m_splits[found_index].weight = new_height;
 
@@ -634,7 +635,7 @@ tui_layout_split::set_height (const char *name, int new_height)
     {
       warning (_("Invalid window height specified"));
       /* Effectively undo any modifications made here.  */
-      set_weights_from_heights ();
+      set_weights_from_sizes ();
     }
   else
     {
diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h
index acea7ac8f64..8f41835b94c 100644
--- a/gdb/tui/tui-layout.h
+++ b/gdb/tui/tui-layout.h
@@ -217,8 +217,9 @@ class tui_layout_split : public tui_layout_base
 
 private:
 
-  /* Set the weights from the current heights.  */
-  void set_weights_from_heights ();
+  /* Set the weights from the current heights (when m_vertical is true) or
+     widths (when m_vertical is false).  */
+  void set_weights_from_sizes ();
 
   struct split
   {
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv3 04/15] gdb/testing/tui: add new functionality to tuiterm.exp
  2022-03-07 22:13   ` [PATCHv3 " Andrew Burgess
                       ` (2 preceding siblings ...)
  2022-03-07 22:13     ` [PATCHv3 03/15] gdb/tui: rename tui_layout_split:set_weights_from_heights Andrew Burgess
@ 2022-03-07 22:13     ` Andrew Burgess
  2022-03-07 22:13     ` [PATCHv3 05/15] gdb/tui: add new 'tui window width' command and 'winwidth' alias Andrew Burgess
                       ` (11 subsequent siblings)
  15 siblings, 0 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

While working on later patches in this series, I was running into csi
control codes being emitted from ncurses that are not currently
handled by out gdb/testsuite/lib/tuiterm.exp.

This commit adds support for these additional control sequences.

The new sequences are 'Insert Line', 'Delete Characters', and 'Scroll
Down'.

There are no new tests in this commit, but I was running into these
sequences while developing later patches in this series.  However,
which control sequences ncurses emits can vary wildly depending on the
screen contents.  It is possible that I only hit some of these
sequences while debugging the later patches (i.e. printing extra
content to the terminal), some of these might no longer be needed
given the tests as now written.

Still, I think it is worth merging these to improve tuiterm.exp.

Additionally, I noticed a bug in 'Erase in Line' that this commit
fixes; in mode 1 the erase should be from the start of the line
through to the cursor, not to the character before the cursor.  This
bug would mean that random characters would sometimes be left in the
terminal output.
---
 gdb/testsuite/lib/tuiterm.exp | 82 ++++++++++++++++++++++++++++++++++-
 1 file changed, 81 insertions(+), 1 deletion(-)

diff --git a/gdb/testsuite/lib/tuiterm.exp b/gdb/testsuite/lib/tuiterm.exp
index 38948015e96..06d2e091ca5 100644
--- a/gdb/testsuite/lib/tuiterm.exp
+++ b/gdb/testsuite/lib/tuiterm.exp
@@ -317,13 +317,40 @@ namespace eval Term {
 		# From cursor to end.
 		_clear_in_line $_cur_col $_cols $_cur_row
 	    } elseif {$arg == 1} {
-		_clear_in_line 0 $_cur_col $_cur_row
+		_clear_in_line 0 [expr $_cur_col + 1] $_cur_row
 	    } elseif {$arg == 2} {
 		_clear_in_line 0 $_cols $_cur_row
 	    }
 	}
     }
 
+    # Insert Line
+    #
+    # https://vt100.net/docs/vt510-rm/IL.html
+    proc _csi_L {args} {
+	set arg [_default [lindex $args 0] 1]
+
+	_log_cur "Insert Line ($arg)" {
+	    variable _cur_col
+	    variable _cur_row
+	    variable _rows
+	    variable _cols
+	    variable _chars
+
+	    set y [expr $_rows - 2]
+	    set next_y [expr $y + 1]
+	    while {$y >= $_cur_row} {
+		for {set x 0} {$x < $_cols} {incr x} {
+		    set _chars($x,$next_y) $_chars($x,$y)
+		}
+		incr y -1
+		incr next_y -1
+	    }
+
+	    _clear_lines $_cur_row $_rows
+	}
+    }
+
     # Delete line.
     #
     # https://vt100.net/docs/vt510-rm/DL.html
@@ -349,6 +376,59 @@ namespace eval Term {
 	}
     }
 
+    # Delete Characters
+    #
+    # https://vt100.net/docs/vt510-rm/DCH.html
+    proc _csi_P {args} {
+	set count [_default [lindex $args 0] 1]
+
+	_log_cur "Delete Character ($count)" {
+	    variable _cur_col
+	    variable _cur_row
+	    variable _cols
+	    variable _chars
+
+	    set dx [expr $_cur_col + 1]
+	    set sx [expr $_cur_col + 1 + $count]
+	    set y $_cur_row
+
+	    while {$sx < $_cols} {
+		set _chars($dx,$y) $_chars($sx,$y)
+		incr sx
+		incr dx
+	    }
+	    _clear_in_line $dx $sx $y
+	}
+    }
+
+    # Pan Down
+    #
+    # https://vt100.net/docs/vt510-rm/SU.html
+    proc _csi_S {args} {
+	set count [_default [lindex $args 0] 1]
+
+	_log_cur "Pan Down ($count)" {
+	    variable _cur_col
+	    variable _cur_row
+	    variable _cols
+	    variable _rows
+	    variable _chars
+
+	    set dy 0
+	    set y $count
+
+	    while {$y < $_rows} {
+		for {set x 0} {$x < $_cols} {incr x} {
+		    set _chars($x,$dy) $_chars($x,$y)
+		}
+		incr y 1
+		incr dy 1
+	    }
+
+	    _clear_lines $dy $_rows
+	}
+    }
+
     # Erase chars.
     #
     # https://vt100.net/docs/vt510-rm/ECH.html
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv3 05/15] gdb/tui: add new 'tui window width' command and 'winwidth' alias
  2022-03-07 22:13   ` [PATCHv3 " Andrew Burgess
                       ` (3 preceding siblings ...)
  2022-03-07 22:13     ` [PATCHv3 04/15] gdb/testing/tui: add new functionality to tuiterm.exp Andrew Burgess
@ 2022-03-07 22:13     ` Andrew Burgess
  2022-03-07 22:13     ` [PATCHv3 06/15] gdb/tui: add a tui debugging flag Andrew Burgess
                       ` (10 subsequent siblings)
  15 siblings, 0 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

This commit adds a new command 'tui window width', and an alias
'winwidth'.  This command is equivalent to the old 'winheight'
command (which was recently renamed 'tui window height').

Even though I recently moved the old tui commands under the tui
namespace, and I would strongly encourage all new tui commands to be
added as 'tui ....' only (users can create their own top-level aliases
if they want), I'm breaking that suggestion here, and adding a
'winwidth' alias.

Given that we already have 'winheight' and have done for years, it
just didn't seem right to no have the matching 'winwidth'.

You might notice in the test that the window resizing doesn't quite
work right.  I setup a horizontal layout, then grow and shrink the
windows.  At the end of the test the windows should be back to their
original size...

... they are not.  This isn't my fault, honest!  GDB's window resizing
is a little ... temperamental, and is prone to getting things slightly
wrong during resizes, off by 1 type things.  This is true for height
resizing, as well as the new width resizing.

Later patches in this series will rework the resizing algorithm, which
should improve things in this area.  For now, I'm happy that the width
resizing is as good as the height resizing, given the existing quirks.

For the docs side I include a paragraph that explains how multiple
windows are required before the width can be adjusted.  For
completeness, I've added the same paragraph to the winheight
description.  With the predefined layouts this extra paragraph is not
really needed for winheight, as there are always multiple windows on
the screen.  However, with custom layouts, this might not be true, so
adding the paragraph seems like a good idea.

As for the changes in gdb itself, I've mostly just taken the existing
height adjustment code, changed the name to make it generic 'size'
adjustment, and added a boolean flag to indicate if we are adjusting
the width or the height.
---
 gdb/NEWS                           |  6 +++
 gdb/doc/gdb.texinfo                | 22 ++++++++++
 gdb/testsuite/gdb.tui/winwidth.exp | 62 +++++++++++++++++++++++++++
 gdb/tui/tui-layout.c               | 33 +++++++++++----
 gdb/tui/tui-layout.h               | 34 ++++++++++++++-
 gdb/tui/tui-win.c                  | 68 +++++++++++++++++++++++++++---
 6 files changed, 209 insertions(+), 16 deletions(-)
 create mode 100644 gdb/testsuite/gdb.tui/winwidth.exp

diff --git a/gdb/NEWS b/gdb/NEWS
index 3c3e0bbb2fb..1275d967a2d 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -127,6 +127,12 @@ tui window height
   and 'winheight' tui commands respectively.  The old names still
   exist as aliases to these new commands.
 
+tui window width
+winwidth
+  The new command 'tui window width', and the alias 'winwidth' allow
+  the width of a tui window to be adjusted when windows are laid out
+  in horizontal mode.
+
 * Changed commands
 
 maint packet
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index fd4c110569e..6081aa85af4 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -29115,6 +29115,28 @@
 it.  The @var{name} parameter can be the name of any currently visible
 window.  The names of the currently visible windows can be discovered
 using @kbd{info win} (@pxref{info_win_command,,info win}).
+
+The set of currently visible windows must always fill the terminal,
+and so, it is only possible to resize on window if there are other
+visible windows that can either give or receive the extra terminal
+space.
+
+@kindex tui window width
+@kindex winwidth
+@item tui window width @var{name} +@var{count}
+@itemx tui window width @var{name} -@var{count}
+@itemx winwidth @var{name} +@var{count}
+@itemx winwidth @var{name} -@var{count}
+Change the width of the window @var{name} by @var{count} columns.
+Positive counts increase the width, while negative counts decrease it.
+The @var{name} parameter can be the name of any currently visible
+window.  The names of the currently visible windows can be discovered
+using @code{info win} (@pxref{info_win_command,,info win}).
+
+The set of currently visible windows must always fill the terminal,
+and so, it is only possible to resize on window if there are other
+visible windows that can either give or receive the extra terminal
+space.
 @end table
 
 @node TUI Configuration
diff --git a/gdb/testsuite/gdb.tui/winwidth.exp b/gdb/testsuite/gdb.tui/winwidth.exp
new file mode 100644
index 00000000000..b0a838b578f
--- /dev/null
+++ b/gdb/testsuite/gdb.tui/winwidth.exp
@@ -0,0 +1,62 @@
+# Copyright 2022 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test the "winwidth" command.
+
+tuiterm_env
+
+standard_testfile tui-layout.c
+
+if {[build_executable "failed to prepare" ${testfile} ${srcfile}] == -1} {
+    return -1
+}
+
+Term::clean_restart 24 80 $testfile
+if {![Term::enter_tui]} {
+    unsupported "TUI not supported"
+    return
+}
+
+Term::command "tui new-layout h { -horizontal src 1 asm 1 } 1 status 0 cmd 1"
+Term::command "layout h"
+
+with_test_prefix "original window sizes" {
+    Term::check_box "source box" 0 0 40 15
+    Term::check_box "asm box" 39 0 41 15
+    Term::command "winwidth src +5"
+}
+
+with_test_prefix "after src +5" {
+    Term::check_box "source box" 0 0 44 15
+    Term::check_box "asm box" 43 0 37 15
+    Term::command "winwidth asm -5"
+}
+
+with_test_prefix "after asm -5" {
+    Term::check_box "source box" 0 0 48 15
+    Term::check_box "asm box" 47 0 33 15
+    Term::command "winwidth asm +8"
+}
+
+with_test_prefix "after asm +8" {
+    Term::check_box "source box" 0 0 39 15
+    Term::check_box "asm box" 38 0 42 15
+    Term::command "winwidth src -2"
+}
+
+with_test_prefix "after src -2" {
+    Term::check_box "source box" 0 0 36 15
+    Term::check_box "asm box" 35 0 45 15
+}
diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index 9e856ccf3fa..4e5740fd6d3 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -121,6 +121,14 @@ tui_adjust_window_height (struct tui_win_info *win, int new_height)
   applied_layout->set_height (win->name (), new_height);
 }
 
+/* See tui-layout.  */
+
+void
+tui_adjust_window_width (struct tui_win_info *win, int new_width)
+{
+  applied_layout->set_width (win->name (), new_width);
+}
+
 /* Set the current layout to LAYOUT.  */
 
 static void
@@ -571,7 +579,7 @@ tui_layout_split::set_weights_from_sizes ()
 /* See tui-layout.h.  */
 
 tui_adjust_result
-tui_layout_split::set_height (const char *name, int new_height)
+tui_layout_split::set_size (const char *name, int new_size, bool set_width_p)
 {
   /* Look through the children.  If one is a layout holding the named
      window, we're done; or if one actually is the named window,
@@ -579,13 +587,16 @@ tui_layout_split::set_height (const char *name, int new_height)
   int found_index = -1;
   for (int i = 0; i < m_splits.size (); ++i)
     {
-      tui_adjust_result adjusted
-	= m_splits[i].layout->set_height (name, new_height);
+      tui_adjust_result adjusted;
+      if (set_width_p)
+	adjusted = m_splits[i].layout->set_width (name, new_size);
+      else
+	adjusted = m_splits[i].layout->set_height (name, new_size);
       if (adjusted == HANDLED)
 	return HANDLED;
       if (adjusted == FOUND)
 	{
-	  if (!m_vertical)
+	  if (set_width_p ? m_vertical : !m_vertical)
 	    return FOUND;
 	  found_index = i;
 	  break;
@@ -594,12 +605,15 @@ tui_layout_split::set_height (const char *name, int new_height)
 
   if (found_index == -1)
     return NOT_FOUND;
-  if (m_splits[found_index].layout->height == new_height)
+  int curr_size = (set_width_p
+		   ? m_splits[found_index].layout->width
+		   : m_splits[found_index].layout->height);
+  if (curr_size == new_size)
     return HANDLED;
 
   set_weights_from_sizes ();
-  int delta = m_splits[found_index].weight - new_height;
-  m_splits[found_index].weight = new_height;
+  int delta = m_splits[found_index].weight - new_size;
+  m_splits[found_index].weight = new_size;
 
   /* Distribute the "delta" over the next window; but if the next
      window cannot hold it all, keep going until we either find a
@@ -633,7 +647,10 @@ tui_layout_split::set_height (const char *name, int new_height)
 
   if (delta != 0)
     {
-      warning (_("Invalid window height specified"));
+      if (set_width_p)
+	warning (_("Invalid window width specified"));
+      else
+	warning (_("Invalid window height specified"));
       /* Effectively undo any modifications made here.  */
       set_weights_from_sizes ();
     }
diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h
index 8f41835b94c..79ad0b8dafc 100644
--- a/gdb/tui/tui-layout.h
+++ b/gdb/tui/tui-layout.h
@@ -79,6 +79,10 @@ class tui_layout_base
      the sizes of the other windows around it.  */
   virtual tui_adjust_result set_height (const char *name, int new_height) = 0;
 
+  /* Set the width of the window named NAME to NEW_WIDTH, updating
+     the sizes of the other windows around it.  */
+  virtual tui_adjust_result set_width (const char *name, int new_width) = 0;
+
   /* Remove some windows from the layout, leaving the command window
      and the window being passed in here.  */
   virtual void remove_windows (const char *name) = 0;
@@ -132,6 +136,11 @@ class tui_layout_window : public tui_layout_base
     return m_contents == name ? FOUND : NOT_FOUND;
   }
 
+  tui_adjust_result set_width (const char *name, int new_width) override
+  {
+    return m_contents == name ? FOUND : NOT_FOUND;
+  }
+
   bool top_boxed_p () const override;
 
   bool bottom_boxed_p () const override;
@@ -192,7 +201,17 @@ class tui_layout_split : public tui_layout_base
 
   void apply (int x, int y, int width, int height) override;
 
-  tui_adjust_result set_height (const char *name, int new_height) override;
+  tui_adjust_result set_height (const char *name, int new_height) override
+  {
+    /* Pass false as the final argument to indicate change of height.  */
+    return set_size (name, new_height, false);
+  }
+
+  tui_adjust_result set_width (const char *name, int new_width) override
+  {
+    /* Pass true as the final argument to indicate change of width.  */
+    return set_size (name, new_width, true);
+  }
 
   bool top_boxed_p () const override;
 
@@ -217,6 +236,15 @@ class tui_layout_split : public tui_layout_base
 
 private:
 
+  /* Used to implement set_height and set_width member functions.  When
+     SET_WIDTH_P is true, set the width, otherwise, set the height of the
+     window named NAME to NEW_SIZE, updating the sizes of the other windows
+     around it as needed.  The result indicates if the window NAME was
+     found and had its size adjusted, was found but was not adjusted, or
+     was not found at all.  */
+  tui_adjust_result set_size (const char *name, int new_size,
+			      bool set_width_p);
+
   /* Set the weights from the current heights (when m_vertical is true) or
      widths (when m_vertical is false).  */
   void set_weights_from_sizes ();
@@ -266,6 +294,10 @@ extern void tui_apply_current_layout ();
 extern void tui_adjust_window_height (struct tui_win_info *win,
 				      int new_height);
 
+/* Adjust the window width of WIN to NEW_WIDTH.  */
+extern void tui_adjust_window_width (struct tui_win_info *win,
+				     int new_width);
+
 /* The type of a function that is used to create a TUI window.  */
 
 typedef std::function<tui_win_info * (const char *name)> window_factory;
diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c
index ba6aca3d078..512ea52b694 100644
--- a/gdb/tui/tui-win.c
+++ b/gdb/tui/tui-win.c
@@ -842,10 +842,21 @@ tui_set_tab_width_command (const char *arg, int from_tty)
     }
 }
 
+/* Helper function for the user commands to adjust a window's width or
+   height.  The ARG string contains the command line arguments from the
+   user, which should give the name of a window, and how to adjust the
+   size.
+
+   When SET_WIDTH_P is true the width of the window is adjusted based on
+   ARG, and when SET_WIDTH_P is false, the height of the window is adjusted
+   based on ARG.
+
+   On invalid input, or if the size can't be adjusted as requested, then an
+   error is thrown, otherwise, the window sizes are adjusted, and the
+   windows redrawn.  */
 
-/* Set the height of the specified window.  */
 static void
-tui_set_win_height_command (const char *arg, int from_tty)
+tui_set_win_size (const char *arg, bool set_width_p)
 {
   /* Make sure the curses mode is enabled.  */
   tui_enable ();
@@ -854,7 +865,7 @@ tui_set_win_height_command (const char *arg, int from_tty)
 
   const char *buf = arg;
   const char *buf_ptr = buf;
-  int new_height;
+  int new_size;
   struct tui_win_info *win_info;
 
   buf_ptr = skip_to_space (buf_ptr);
@@ -890,20 +901,53 @@ tui_set_win_height_command (const char *arg, int from_tty)
 	  if (negate)
 	    input_no *= (-1);
 	  if (fixed_size)
-	    new_height = input_no;
+	    new_size = input_no;
 	  else
-	    new_height = win_info->height + input_no;
+	    {
+	      int curr_size;
+	      if (set_width_p)
+		curr_size = win_info->width;
+	      else
+		curr_size = win_info->height;
+	      new_size = curr_size + input_no;
+	    }
 
 	  /* Now change the window's height, and adjust
 	     all other windows around it.  */
-	  tui_adjust_window_height (win_info, new_height);
+	  if (set_width_p)
+	    tui_adjust_window_width (win_info, new_size);
+	  else
+	    tui_adjust_window_height (win_info, new_size);
 	  tui_update_gdb_sizes ();
 	}
       else
-	error (_("Invalid window height specified"));
+	{
+	  if (set_width_p)
+	    error (_("Invalid window width specified"));
+	  else
+	    error (_("Invalid window height specified"));
+	}
     }
 }
 
+/* Implement the 'tui window height' command (alias 'winheight').  */
+
+static void
+tui_set_win_height_command (const char *arg, int from_tty)
+{
+  /* Pass false as the final argument to set the height.  */
+  tui_set_win_size (arg, false);
+}
+
+/* Implement the 'tui window width' command (alias 'winwidth').  */
+
+static void
+tui_set_win_width_command (const char *arg, int from_tty)
+{
+  /* Pass true as the final argument to set the width.  */
+  tui_set_win_size (arg, true);
+}
+
 /* See tui-data.h.  */
 
 int
@@ -1033,6 +1077,16 @@ Use \"info win\" to see the names of the windows currently being displayed."),
   add_com_alias ("winheight", winheight_cmd, class_tui, 0);
   add_com_alias ("wh", winheight_cmd, class_tui, 0);
   set_cmd_completer (winheight_cmd, winheight_completer);
+
+  cmd_list_element *winwidth_cmd
+    = add_cmd ("width", class_tui, tui_set_win_width_command, _("\
+Set or modify the width of a specified window.\n\
+Usage: tui window width WINDOW-NAME [+ | -] NUM-LINES\n\
+Use \"info win\" to see the names of the windows currently being displayed."),
+	       &tui_window_cmds);
+  add_com_alias ("winwidth", winwidth_cmd, class_tui, 0);
+  set_cmd_completer (winwidth_cmd, winheight_completer);
+
   add_info ("win", tui_all_windows_info,
 	    _("List of all displayed windows.\n\
 Usage: info win"));
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv3 06/15] gdb/tui: add a tui debugging flag
  2022-03-07 22:13   ` [PATCHv3 " Andrew Burgess
                       ` (4 preceding siblings ...)
  2022-03-07 22:13     ` [PATCHv3 05/15] gdb/tui: add new 'tui window width' command and 'winwidth' alias Andrew Burgess
@ 2022-03-07 22:13     ` Andrew Burgess
  2022-03-08 12:16       ` Eli Zaretskii
  2022-03-07 22:13     ` [PATCHv3 07/15] gdb/tui: add left_boxed_p and right_boxed_p member functions Andrew Burgess
                       ` (9 subsequent siblings)
  15 siblings, 1 reply; 74+ messages in thread
From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

This commit adds 'set debug tui on|off' and 'show debug tui'.  This
commit adds the control variable, and the printing macros in
tui/tui.h.  I've then added some uses of these in tui.c and
tui-layout.c.

To help produce more useful debug output in tui-layout.c, I've added
some helper member functions in the class tui_layout_split, and also
moved the size_info struct out of tui_layout_split::apply into the
tui_layout_split class.

If tui debug is not turned on, then there should be no user visible
changes after this commit.

One thing to note is that, due to the way that the tui terminal is
often cleared, the only way I've found this useful is when I do:

  (gdb) tui enable
  (gdb) set logging file /path/to/file
  (gdb) set logging debugredirect on
  (gdb) set logging enable on

Additionally, gdb has some quirks when it comes to setting up logging
redirect and switching interpreters.  Thus, the above only really
works if the logging is enabled after the tui is enabled, and disabled
again before the tui is disabled.

Enabling logging and switching interpreters can cause undefined
results, including crashes.  This is an existing bug in gdb[1], and
has nothing directly to do with tui debug, but it is worth mentioning
here I think.

[1] https://sourceware.org/bugzilla/show_bug.cgi?id=28948
---
 gdb/NEWS             |  4 ++
 gdb/doc/gdb.texinfo  | 11 +++++
 gdb/tui/tui-layout.c | 99 +++++++++++++++++++++++++++++++++++++++-----
 gdb/tui/tui-layout.h | 25 +++++++++++
 gdb/tui/tui.c        | 26 ++++++++++++
 gdb/tui/tui.h        | 14 +++++++
 6 files changed, 168 insertions(+), 11 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 1275d967a2d..eb18ac47804 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -133,6 +133,10 @@ winwidth
   the width of a tui window to be adjusted when windows are laid out
   in horizontal mode.
 
+set debug tui on|off
+show debug tui
+  Control the display of debug output about GDB's tui.
+
 * Changed commands
 
 maint packet
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 6081aa85af4..60173e07747 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -29205,6 +29205,17 @@
 source text at the next tab stop; the compact display uses only as
 much space as is needed for the line numbers in the current file, and
 only a single space to separate the line numbers from the source.
+
+@kindex set debug tui
+@item set debug tui @r{[}on|off@r{]}
+Turn on or off display of @value{GDBN} internal debug messages relating
+to the TUI.
+
+@kindex show debug tui
+@item show debug tui
+Show the current status of displaying @value{GDBN} internal debug
+messages relating to the TUI.
+
 @end table
 
 Note that the colors of the TUI borders can be controlled using the
diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index 4e5740fd6d3..8e8b4538c7e 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -426,8 +426,14 @@ tui_layout_window::apply (int x_, int y_, int width_, int height_)
 void
 tui_layout_window::get_sizes (bool height, int *min_value, int *max_value)
 {
+  TUI_SCOPED_DEBUG_ENTER_EXIT;
+
   if (m_window == nullptr)
     m_window = tui_get_window_by_name (m_contents);
+
+  tui_debug_printf ("window = %s, getting %s",
+		    m_window->name (), (height ? "height" : "width"));
+
   if (height)
     {
       *min_value = m_window->min_height ();
@@ -438,6 +444,8 @@ tui_layout_window::get_sizes (bool height, int *min_value, int *max_value)
       *min_value = m_window->min_width ();
       *max_value = m_window->max_width ();
     }
+
+  tui_debug_printf ("min = %d, max = %d", *min_value, *max_value);
 }
 
 /* See tui-layout.h.  */
@@ -522,6 +530,8 @@ tui_layout_split::clone () const
 void
 tui_layout_split::get_sizes (bool height, int *min_value, int *max_value)
 {
+  TUI_SCOPED_DEBUG_ENTER_EXIT;
+
   *min_value = 0;
   *max_value = 0;
   bool first_time = true;
@@ -544,6 +554,8 @@ tui_layout_split::get_sizes (bool height, int *min_value, int *max_value)
 	}
       first_time = false;
     }
+
+  tui_debug_printf ("min_value = %d, max_value = %d", *min_value, *max_value);
 }
 
 /* See tui-layout.h.  */
@@ -578,9 +590,46 @@ tui_layout_split::set_weights_from_sizes ()
 
 /* See tui-layout.h.  */
 
+std::string
+tui_layout_split::tui_debug_weights_to_string () const
+{
+  std::string str;
+
+  for (int i = 0; i < m_splits.size (); ++i)
+    {
+      if (i > 0)
+       str += ", ";
+      str += string_printf ("[%d] %d", i, m_splits[i].weight);
+    }
+
+  return str;
+}
+
+/* See tui-layout.h.  */
+
+void
+tui_layout_split::tui_debug_print_size_info
+  (const std::vector<tui_layout_split::size_info> &info)
+{
+  gdb_assert (debug_tui);
+
+  tui_debug_printf ("current size info data:");
+  for (int i = 0; i < info.size (); ++i)
+    tui_debug_printf ("  [%d] { size = %d, min = %d, max = %d, share_box = %d }",
+		      i, info[i].size, info[i].min_size,
+		      info[i].max_size, info[i].share_box);
+}
+
+/* See tui-layout.h.  */
+
 tui_adjust_result
 tui_layout_split::set_size (const char *name, int new_size, bool set_width_p)
 {
+  TUI_SCOPED_DEBUG_ENTER_EXIT;
+
+  tui_debug_printf ("this = %p, name = %s, new_size = %d",
+		    this, name, new_size);
+
   /* Look through the children.  If one is a layout holding the named
      window, we're done; or if one actually is the named window,
      update it.  */
@@ -611,10 +660,15 @@ tui_layout_split::set_size (const char *name, int new_size, bool set_width_p)
   if (curr_size == new_size)
     return HANDLED;
 
+  tui_debug_printf ("found window %s at index %d", name, found_index);
+
   set_weights_from_sizes ();
   int delta = m_splits[found_index].weight - new_size;
   m_splits[found_index].weight = new_size;
 
+  tui_debug_printf ("before delta (%d) distribution, weights: %s",
+		    delta, tui_debug_weights_to_string ().c_str ());
+
   /* Distribute the "delta" over the next window; but if the next
      window cannot hold it all, keep going until we either find a
      window that does, or until we loop all the way around.  */
@@ -643,8 +697,14 @@ tui_layout_split::set_size (const char *name, int new_size, bool set_width_p)
 	  m_splits[index].weight += grow_by;
 	  delta -= grow_by;
 	}
+
+      tui_debug_printf ("index = %d, weight now: %d",
+			index, m_splits[index].weight);
     }
 
+  tui_debug_printf ("after delta (%d) distribution, weights: %s",
+		    delta, tui_debug_weights_to_string ().c_str ());
+
   if (delta != 0)
     {
       if (set_width_p)
@@ -668,23 +728,18 @@ tui_layout_split::set_size (const char *name, int new_size, bool set_width_p)
 void
 tui_layout_split::apply (int x_, int y_, int width_, int height_)
 {
+  TUI_SCOPED_DEBUG_ENTER_EXIT;
+
   x = x_;
   y = y_;
   width = width_;
   height = height_;
 
-  struct size_info
-  {
-    int size;
-    int min_size;
-    int max_size;
-    /* True if this window will share a box border with the previous
-       window in the list.  */
-    bool share_box;
-  };
-
   std::vector<size_info> info (m_splits.size ());
 
+  tui_debug_printf ("weights are: %s",
+		    tui_debug_weights_to_string ().c_str ());
+
   /* Step 1: Find the min and max size of each sub-layout.
      Fixed-sized layouts are given their desired size, and then the
      remaining space is distributed among the remaining windows
@@ -760,9 +815,31 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_)
 	}
     }
 
+  if (debug_tui)
+    {
+      tui_debug_printf ("after initial size calculation");
+      tui_debug_printf ("available_size = %d, used_size = %d",
+			available_size, used_size);
+      tui_debug_printf ("total_weight = %d, last_index = %d",
+			total_weight, last_index);
+      tui_debug_print_size_info (info);
+    }
+
   /* Allocate any leftover size.  */
   if (available_size >= used_size && last_index != -1)
-    info[last_index].size += available_size - used_size;
+    {
+      info[last_index].size += available_size - used_size;
+
+      if (debug_tui)
+	{
+	  tui_debug_printf ("after final size calculation");
+	  tui_debug_printf ("available_size = %d, used_size = %d",
+			    available_size, used_size);
+	  tui_debug_printf ("total_weight = %d, last_index = %d",
+			    total_weight, last_index);
+	  tui_debug_print_size_info (info);
+	}
+    }
 
   /* Step 3: Resize.  */
   int size_accum = 0;
diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h
index 79ad0b8dafc..26de3c3a979 100644
--- a/gdb/tui/tui-layout.h
+++ b/gdb/tui/tui-layout.h
@@ -249,6 +249,31 @@ class tui_layout_split : public tui_layout_base
      widths (when m_vertical is false).  */
   void set_weights_from_sizes ();
 
+  /* Structure used when resizing, or applying a layout.  An instance of
+     this structure is created for each sub-layout.  */
+  struct size_info
+  {
+    /* The calculated size for this sub-layout.  */
+    int size;
+
+    /* The minimum and maximum sizes for this sub-layout, obtained by
+       calling the get_sizes member function.  */
+    int min_size;
+    int max_size;
+
+    /* True if this window will share a box border with the previous
+       window in the list.  */
+    bool share_box;
+  };
+
+  /* Used for debug, prints the contents of INFO using tui_debug_printf.
+     Only call this when the global debug_tui is true.  */
+  static void tui_debug_print_size_info (const std::vector<size_info> &info);
+
+  /* Used for debug, returns a string describing the current weight of each
+     sub-layout.  */
+  std::string tui_debug_weights_to_string () const;
+
   struct split
   {
     /* The requested weight.  */
diff --git a/gdb/tui/tui.c b/gdb/tui/tui.c
index 776dccf0bb2..6332eceb4af 100644
--- a/gdb/tui/tui.c
+++ b/gdb/tui/tui.c
@@ -50,6 +50,19 @@
 #include "gdb_curses.h"
 #include "interps.h"
 
+/* See tui.h.  */
+
+bool debug_tui = false;
+
+/* Implement 'show debug tui'.  */
+
+static void
+show_tui_debug (struct ui_file *file, int from_tty,
+		struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("TUI debugging is \"%s\".\n"), value);
+}
+
 /* This redefines CTRL if it is not already defined, so it must come
    after terminal state releated include files like <term.h> and
    "gdb_curses.h".  */
@@ -354,6 +367,8 @@ gdb_getenv_term (void)
 void
 tui_enable (void)
 {
+  TUI_SCOPED_DEBUG_ENTER_EXIT;
+
   if (tui_active)
     return;
 
@@ -494,6 +509,8 @@ tui_enable (void)
 void
 tui_disable (void)
 {
+  TUI_SCOPED_DEBUG_ENTER_EXIT;
+
   if (!tui_active)
     return;
 
@@ -587,4 +604,13 @@ Usage: tui enable"),
 	   _("Disable TUI display mode.\n\
 Usage: tui disable"),
 	   tuicmd);
+
+  /* Debug this tui internals.  */
+  add_setshow_boolean_cmd ("tui", class_maintenance, &debug_tui,  _("\
+Set tui debugging."), _("\
+Show tui debugging."), _("\
+When true, tui specific internal debugging is enabled."),
+			   NULL,
+			   show_tui_debug,
+			   &setdebuglist, &showdebuglist);
 }
diff --git a/gdb/tui/tui.h b/gdb/tui/tui.h
index a4df66f17fc..924d91daa7e 100644
--- a/gdb/tui/tui.h
+++ b/gdb/tui/tui.h
@@ -22,6 +22,20 @@
 #ifndef TUI_TUI_H
 #define TUI_TUI_H
 
+/* Flag to control tui debugging.  */
+
+extern bool debug_tui;
+
+/* Print a "tui" debug statement.  */
+
+#define tui_debug_printf(fmt, ...) \
+  debug_prefixed_printf_cond (debug_tui, "tui", fmt, ##__VA_ARGS__)
+
+/* Print "tui" enter/exit debug statements.  */
+
+#define TUI_SCOPED_DEBUG_ENTER_EXIT \
+  scoped_debug_enter_exit (debug_tui, "tui")
+
 struct ui_file;
 
 /* Types of error returns.  */
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv3 07/15] gdb/tui: add left_boxed_p and right_boxed_p member functions
  2022-03-07 22:13   ` [PATCHv3 " Andrew Burgess
                       ` (5 preceding siblings ...)
  2022-03-07 22:13     ` [PATCHv3 06/15] gdb/tui: add a tui debugging flag Andrew Burgess
@ 2022-03-07 22:13     ` Andrew Burgess
  2022-03-07 22:13     ` [PATCHv3 08/15] gdb/tui/testsuite: refactor new-layout.exp test Andrew Burgess
                       ` (8 subsequent siblings)
  15 siblings, 0 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

When I initially saw this code in tui_layout_split::apply, I assumed
that this must be a bug:

    /* Two adjacent boxed windows will share a border, making a bit
       more size available.  */
    if (i > 0
        && m_splits[i - 1].layout->bottom_boxed_p ()
        && m_splits[i].layout->top_boxed_p ())
      ...

After all, the apply might be laying out a horizontal layout, right?
So checking bottom_boxed_p and top_boxed_p is clearly wrong.

Well, it turns on, that due to the implementations of these things,
bottom_boxed_p is equivalent to an imagined right_boxed_p, and
top_boxed_p is equivalent to an imagined left_boxed_p.

In this commit I've renamed both top_boxed_p and bottom_boxed_p to
first_edge_has_border_p and last_edge_has_border_p respectively, and
extended the comments in tui_layout_base to mention that these methods
handle both horizontal and vertical layouts.

Now, hopefully, the code shouldn't look like it only applies for
vertical layouts.

There should be no user visible changes after this commit.
---
 gdb/tui/tui-layout.c | 16 ++++++++--------
 gdb/tui/tui-layout.h | 18 ++++++++++--------
 2 files changed, 18 insertions(+), 16 deletions(-)

diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index 8e8b4538c7e..3e1c5804460 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -451,7 +451,7 @@ tui_layout_window::get_sizes (bool height, int *min_value, int *max_value)
 /* See tui-layout.h.  */
 
 bool
-tui_layout_window::top_boxed_p () const
+tui_layout_window::first_edge_has_border_p () const
 {
   gdb_assert (m_window != nullptr);
   return m_window->can_box ();
@@ -460,7 +460,7 @@ tui_layout_window::top_boxed_p () const
 /* See tui-layout.h.  */
 
 bool
-tui_layout_window::bottom_boxed_p () const
+tui_layout_window::last_edge_has_border_p () const
 {
   gdb_assert (m_window != nullptr);
   return m_window->can_box ();
@@ -561,21 +561,21 @@ tui_layout_split::get_sizes (bool height, int *min_value, int *max_value)
 /* See tui-layout.h.  */
 
 bool
-tui_layout_split::top_boxed_p () const
+tui_layout_split::first_edge_has_border_p () const
 {
   if (m_splits.empty ())
     return false;
-  return m_splits[0].layout->top_boxed_p ();
+  return m_splits[0].layout->first_edge_has_border_p ();
 }
 
 /* See tui-layout.h.  */
 
 bool
-tui_layout_split::bottom_boxed_p () const
+tui_layout_split::last_edge_has_border_p () const
 {
   if (m_splits.empty ())
     return false;
-  return m_splits.back ().layout->top_boxed_p ();
+  return m_splits.back ().layout->last_edge_has_border_p ();
 }
 
 /* See tui-layout.h.  */
@@ -785,8 +785,8 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_)
       /* Two adjacent boxed windows will share a border, making a bit
 	 more size available.  */
       if (i > 0
-	  && m_splits[i - 1].layout->bottom_boxed_p ()
-	  && m_splits[i].layout->top_boxed_p ())
+	  && m_splits[i - 1].layout->last_edge_has_border_p ()
+	  && m_splits[i].layout->first_edge_has_border_p ())
 	info[i].share_box = true;
     }
 
diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h
index 26de3c3a979..9cfcfb8e81f 100644
--- a/gdb/tui/tui-layout.h
+++ b/gdb/tui/tui-layout.h
@@ -62,11 +62,13 @@ class tui_layout_base
      HEIGHT is true to fetch height, false to fetch width.  */
   virtual void get_sizes (bool height, int *min_value, int *max_value) = 0;
 
-  /* True if the topmost item in this layout is boxed.  */
-  virtual bool top_boxed_p () const = 0;
+  /* True if the topmost (for vertical layouts), or the leftmost (for
+     horizontal layouts) item in this layout is boxed.  */
+  virtual bool first_edge_has_border_p () const = 0;
 
-  /* True if the bottommost item in this layout is boxed.  */
-  virtual bool bottom_boxed_p () const = 0;
+  /* True if the bottommost (for vertical layouts), or the rightmost (for
+     horizontal layouts) item in this layout is boxed.  */
+  virtual bool last_edge_has_border_p () const = 0;
 
   /* Return the name of this layout's window, or nullptr if this
      layout does not represent a single window.  */
@@ -141,9 +143,9 @@ class tui_layout_window : public tui_layout_base
     return m_contents == name ? FOUND : NOT_FOUND;
   }
 
-  bool top_boxed_p () const override;
+  bool first_edge_has_border_p () const override;
 
-  bool bottom_boxed_p () const override;
+  bool last_edge_has_border_p () const override;
 
   void remove_windows (const char *name) override
   {
@@ -213,9 +215,9 @@ class tui_layout_split : public tui_layout_base
     return set_size (name, new_width, true);
   }
 
-  bool top_boxed_p () const override;
+  bool first_edge_has_border_p () const override;
 
-  bool bottom_boxed_p () const override;
+  bool last_edge_has_border_p () const override;
 
   void remove_windows (const char *name) override;
 
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv3 08/15] gdb/tui/testsuite: refactor new-layout.exp test
  2022-03-07 22:13   ` [PATCHv3 " Andrew Burgess
                       ` (6 preceding siblings ...)
  2022-03-07 22:13     ` [PATCHv3 07/15] gdb/tui: add left_boxed_p and right_boxed_p member functions Andrew Burgess
@ 2022-03-07 22:13     ` Andrew Burgess
  2022-03-07 22:13     ` [PATCHv3 09/15] gdb/tui: avoid fp exception when applying layouts Andrew Burgess
                       ` (7 subsequent siblings)
  15 siblings, 0 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

This commit changes the gdb.tui/new-layout.exp test to make use of a
list of test descriptions, and a loop to check each description in
turn.  There's no change to what is actually tested after this commit.

In future commits I plan to add additional tests to this file, and
this will be easier now that all I have to do is add a new test
description to the list.
---
 gdb/testsuite/gdb.tui/new-layout.exp | 83 +++++++++++++++++++---------
 1 file changed, 56 insertions(+), 27 deletions(-)

diff --git a/gdb/testsuite/gdb.tui/new-layout.exp b/gdb/testsuite/gdb.tui/new-layout.exp
index 2b5e07db612..d3d34af7439 100644
--- a/gdb/testsuite/gdb.tui/new-layout.exp
+++ b/gdb/testsuite/gdb.tui/new-layout.exp
@@ -55,20 +55,39 @@ if { [tcl_version_at_least 8 6] } {
 	"Missing '\}' in layout specification"
 }
 
-gdb_test_no_output "tui new-layout example asm 1 status 0 cmd 1"
-
-gdb_test "help layout example" \
-    "Apply the \"example\" layout.*tui new-layout example asm 1 status 0 cmd 1"
-
-gdb_test_no_output "tui new-layout example2 {asm 1 status 0} 1 cmd 1"
-
-gdb_test "help layout example2" \
-    "Apply the \"example2\" layout.*tui new-layout example2 {asm 1 status 0} 1 cmd 1"
-
-gdb_test_no_output "tui new-layout h {-horizontal asm 1 src 1} 1 status 0 cmd 1"
+# Each entry of this list describes a layout, and some associated
+# tests.  The items within each entry are:
+# 1. layout name,
+# 2. a string used to create the layout,
+# 3. a list of boxes to check for once the layout is selected,
+# 4. a regexp to match against the whole screen contents, this
+#    can be empty to skip this check.
+set layouts \
+    [list \
+	 [list example "asm 1 status 0 cmd 1" \
+	      {{0 0 80 15}} "$hex <main>"] \
+	 [list example2 "{asm 1 status 0} 1 cmd 1" \
+	      {{0 0 80 15}} ""] \
+	 [list h "{-horizontal asm 1 src 1} 1 status 0 cmd 1" \
+	      {{0 0 40 15} {39 0 41 15}} \
+	      "$hex <main>.*21.*return 0"]]
+
+# Helper function to verify a list of boxes.
+proc check_boxes {boxes} {
+    set boxno 1
+    foreach box $boxes {
+	eval Term::check_box [list "box $boxno"] $box
+	incr boxno
+    }
+}
 
-gdb_test "help layout h" \
-    "Apply the \"h\" layout.*tui new-layout h {-horizontal asm 1 src 1} 1 status 0 cmd 1"
+# Now create the layouts.
+foreach layout $layouts {
+    lassign $layout name desc
+    gdb_test_no_output "tui new-layout $name $desc"
+    gdb_test "help layout $name" \
+	"Apply the \"$name\" layout.*tui new-layout $name $desc"
+}
 
 if {![Term::enter_tui]} {
     unsupported "TUI not supported"
@@ -79,20 +98,30 @@ set text [Term::get_all_lines]
 gdb_assert {![string match "No Source Available" $text]} \
     "initial source listing"
 
-Term::command "layout example"
-Term::check_contents "example layout shows assembly" \
-    "$hex <main>"
+foreach_with_prefix layout $layouts {
+    lassign $layout name desc boxes content_pattern
+
+    # Reset the layout to a known starting configuration.
+    Term::command "layout src"
+    Term::command "winheight cmd 8"
+
+    # Apply our test layout.
+    Term::command "layout $name"
+    check_boxes $boxes
 
-Term::command "layout h"
-Term::check_box "left window box" 0 0 40 15
-Term::check_box "right window box" 39 0 41 15
-Term::check_contents "horizontal display" \
-    "$hex <main>.*21.*return 0"
+    if {$content_pattern != ""} {
+	Term::check_contents "contents in layout $name" \
+	    "${content_pattern}"
+    }
 
-Term::command "winheight src - 5"
-Term::check_box "left window box after shrink" 0 0 40 10
-Term::check_box "right window box after shrink" 39 0 41 10
+    # Some additional tests for the 'h' layout.
+    if {$name == "h"} {
+	Term::command "winheight src - 5"
+	Term::check_box "left window box after shrink" 0 0 40 10
+	Term::check_box "right window box after shrink" 39 0 41 10
 
-Term::command "winheight src + 5"
-Term::check_box "left window box after grow" 0 0 40 15
-Term::check_box "right window box after grow" 39 0 41 15
+	Term::command "winheight src + 5"
+	Term::check_box "left window box after grow" 0 0 40 15
+	Term::check_box "right window box after grow" 39 0 41 15
+    }
+}
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv3 09/15] gdb/tui: avoid fp exception when applying layouts
  2022-03-07 22:13   ` [PATCHv3 " Andrew Burgess
                       ` (7 preceding siblings ...)
  2022-03-07 22:13     ` [PATCHv3 08/15] gdb/tui/testsuite: refactor new-layout.exp test Andrew Burgess
@ 2022-03-07 22:13     ` Andrew Burgess
  2022-03-07 22:13     ` [PATCHv3 10/15] gdb/tui: fairer distribution of excess space during apply Andrew Burgess
                       ` (6 subsequent siblings)
  15 siblings, 0 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

Consider:

  (gdb) tui enable
  (gdb) layout src
  (gdb) tui new-layout conly cmd 1
  (gdb) layout conly

After this, with current master, gdb crashes with a floating-point
exception.

The problem is that in tui_layout_split::apply, when we switch from
'src' to 'conly', we will try to retain the cmd window height.  As
such, the cmd window will become a fixed size window, which decreases
the available_size, but doesn't count towards the total_weight.

As the cmd window is the only window, the total_weight stays at zero,
and, when we move into step 2, where we attempt to size the windows,
we perform a divide by zero, and crash.

After this commit we avoid the divide by zero, and just directly set
the window size based on the fixed size.

There is still a problem after this commit, when the conly layout is
selected the cmd window retains its original height, which will only
be part of the terminal.  The rest of the terminal is left unused.
This issue will be addressed in a later commit, this commit is just
about the floating-point exception.
---
 gdb/testsuite/gdb.tui/new-layout.exp |  3 ++-
 gdb/tui/tui-layout.c                 | 30 ++++++++++++++++++----------
 2 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/gdb/testsuite/gdb.tui/new-layout.exp b/gdb/testsuite/gdb.tui/new-layout.exp
index d3d34af7439..66048e65238 100644
--- a/gdb/testsuite/gdb.tui/new-layout.exp
+++ b/gdb/testsuite/gdb.tui/new-layout.exp
@@ -70,7 +70,8 @@ set layouts \
 	      {{0 0 80 15}} ""] \
 	 [list h "{-horizontal asm 1 src 1} 1 status 0 cmd 1" \
 	      {{0 0 40 15} {39 0 41 15}} \
-	      "$hex <main>.*21.*return 0"]]
+	      "$hex <main>.*21.*return 0"] \
+	 [list cmd_only "cmd 1" {} ""]]
 
 # Helper function to verify a list of boxes.
 proc check_boxes {boxes} {
diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index 3e1c5804460..8758bfe70e7 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -790,29 +790,37 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_)
 	info[i].share_box = true;
     }
 
+  /* If last_index is set then we have a window that is not of a fixed
+     size.  This window will have its size calculated below, which requires
+     that the total_weight not be zero (we divide by total_weight, so don't
+     want a floating-point exception).  */
+  gdb_assert (last_index == -1 || total_weight > 0);
+
   /* Step 2: Compute the size of each sub-layout.  Fixed-sized items
      are given their fixed size, while others are resized according to
      their weight.  */
   int used_size = 0;
   for (int i = 0; i < m_splits.size (); ++i)
     {
-      /* Compute the height and clamp to the allowable range.  */
-      info[i].size = available_size * m_splits[i].weight / total_weight;
-      if (info[i].size > info[i].max_size)
-	info[i].size = info[i].max_size;
-      if (info[i].size < info[i].min_size)
-	info[i].size = info[i].min_size;
-      /* If there is any leftover size, just redistribute it to the
-	 last resizeable window, by dropping it from the allocated
-	 size.  We could try to be fancier here perhaps, by
-	 redistributing this size among all windows, not just the
-	 last window.  */
       if (info[i].min_size != info[i].max_size)
 	{
+	  /* Compute the height and clamp to the allowable range.  */
+	  info[i].size = available_size * m_splits[i].weight / total_weight;
+	  if (info[i].size > info[i].max_size)
+	    info[i].size = info[i].max_size;
+	  if (info[i].size < info[i].min_size)
+	    info[i].size = info[i].min_size;
+	  /* If there is any leftover size, just redistribute it to the
+	     last resizeable window, by dropping it from the allocated
+	     size.  We could try to be fancier here perhaps, by
+	     redistributing this size among all windows, not just the
+	     last window.  */
 	  used_size += info[i].size;
 	  if (info[i].share_box)
 	    --used_size;
 	}
+      else
+	info[i].size = info[i].min_size;
     }
 
   if (debug_tui)
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv3 10/15] gdb/tui: fairer distribution of excess space during apply
  2022-03-07 22:13   ` [PATCHv3 " Andrew Burgess
                       ` (8 preceding siblings ...)
  2022-03-07 22:13     ` [PATCHv3 09/15] gdb/tui: avoid fp exception when applying layouts Andrew Burgess
@ 2022-03-07 22:13     ` Andrew Burgess
  2022-03-07 22:13     ` [PATCHv3 11/15] gdb/tui: allow cmd window to change size in tui_layout_split::apply Andrew Burgess
                       ` (5 subsequent siblings)
  15 siblings, 0 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

When applying layouts gdb computes the size of each window (or rather,
each sub-layout within a layout) using integer arithmetic.  As this
rounds down the results, then, when all sub-layouts are sized, there
is the possibility that we have some space left over.

Currently, this space is just assigned to an arbitrary sub-layout.

This can result in some unbalanced results.  Consider this set of
steps with current master:

  (gdb) tui enable
  (gdb) layout regs
  (gdb) info win
  Name       Lines Columns Focus
  regs           7      80
  src            9      80 (has focus)
  status         1      80
  cmd            8      80

Notice the weird split between the src and regs windows, the original
layout specification has these windows given equal weight.  The
problem is that, with rounding, both the regs and src windows are
initially sized to 7, the extra 2 lines are then arbitrarily added to
the src window.

In this commit, rather than add all the extra space to one single
window, I instead hand out the extra space 1 line at a time, looping
over all the sub-layouts.  We take care to respect the min/max sizes,
and so, we now get this result:

  (gdb) tui enable
  (gdb) layout regs
  (gdb) info win
  Name       Lines Columns Focus
  regs           8      80
  src            8      80 (has focus)
  status         1      80
  cmd            8      80

This looks more natural to me.

This is obviously a change in behaviour, and so, lots of the existing
tests need to be updated to take this into account.  None of the
changes are huge, it's just a line or two (or column for width) moved
between windows.
---
 gdb/testsuite/gdb.tui/basic.exp    |  4 ++--
 gdb/testsuite/gdb.tui/empty.exp    | 14 +++++++----
 gdb/testsuite/gdb.tui/regs.exp     |  4 ++--
 gdb/testsuite/gdb.tui/winwidth.exp | 17 ++++++-------
 gdb/tui/tui-layout.c               | 38 ++++++++++++++++++++++++------
 5 files changed, 53 insertions(+), 24 deletions(-)

diff --git a/gdb/testsuite/gdb.tui/basic.exp b/gdb/testsuite/gdb.tui/basic.exp
index 0e9f2e3eab2..7afb28b0858 100644
--- a/gdb/testsuite/gdb.tui/basic.exp
+++ b/gdb/testsuite/gdb.tui/basic.exp
@@ -104,5 +104,5 @@ Term::command "layout split"
 Term::check_contents "split layout contents" \
     "$main_line *$main_re.*$hex <main>"
 
-Term::check_box "source box in split layout" 0 0 80 7
-Term::check_box "asm box in split layout" 0 6 80 9
+Term::check_box "source box in split layout" 0 0 80 8
+Term::check_box "asm box in split layout" 0 7 80 8
diff --git a/gdb/testsuite/gdb.tui/empty.exp b/gdb/testsuite/gdb.tui/empty.exp
index ef14fe4dac0..3efa55d812e 100644
--- a/gdb/testsuite/gdb.tui/empty.exp
+++ b/gdb/testsuite/gdb.tui/empty.exp
@@ -35,26 +35,26 @@ if {![Term::enter_tui]} {
 set layouts {
     {src src {{0 0 80 15}} {{0 0 90 26}}
 	{{"no source" "No Source Available"}}}
-    {regs src-regs {{0 0 80 7} {0 6 80 9}} {{0 0 90 13} {0 12 90 13}}
+    {regs src-regs {{0 0 80 8} {0 7 80 8}} {{0 0 90 13} {0 12 90 13}}
 	{
 	    {"no source" "No Source Available"}
 	    {"no regs" "Register Values Unavailable"}
 	}}
-    {asm asm {{0 0 80 13}} {{0 0 90 26}}
+    {asm asm {{0 0 80 15}} {{0 0 90 26}}
 	{
 	    {"no asm" "No Assembly Available"}
 	}}
-    {regs asm-regs {{0 0 80 7} {0 6 80 9}} {{0 0 90 13} {0 12 90 13}}
+    {regs asm-regs {{0 0 80 8} {0 7 80 8}} {{0 0 90 13} {0 12 90 13}}
 	{
 	    {"no asm" "No Assembly Available"}
 	    {"no regs" "Register Values Unavailable"}
 	}}
-    {split split {{0 0 80 6} {0 5 80 8}} {{0 0 90 13} {0 12 90 13}}
+    {split split {{0 0 80 8} {0 7 80 8}} {{0 0 90 13} {0 12 90 13}}
 	{
 	    {"no source" "No Source Available"}
 	    {"no asm" "No Assembly Available"}
 	}}
-    {regs split-regs {{0 0 80 6} {0 5 80 8}} {{0 0 90 13} {0 12 90 13}}
+    {regs split-regs {{0 0 80 8} {0 7 80 8}} {{0 0 90 13} {0 12 90 13}}
 	{
 	    {"no asm" "No Assembly Available"}
 	    {"no regs" "Register Values Unavailable"}
@@ -97,5 +97,9 @@ foreach layout $layouts {
 	    check_text $text_list
 	}
 	Term::resize 24 80
+	with_test_prefix "80x24 again" {
+	    check_boxes $small_boxes
+	    check_text $text_list
+	}
     }
 }
diff --git a/gdb/testsuite/gdb.tui/regs.exp b/gdb/testsuite/gdb.tui/regs.exp
index 178eba03f19..2f3482f5d38 100644
--- a/gdb/testsuite/gdb.tui/regs.exp
+++ b/gdb/testsuite/gdb.tui/regs.exp
@@ -38,8 +38,8 @@ if {![Term::enter_tui]} {
 Term::check_contents "source at startup" "\\|.*21 *return 0"
 
 Term::command "layout regs"
-Term::check_box "register box" 0 0 80 7
-Term::check_box "source box in regs layout" 0 6 80 9
+Term::check_box "register box" 0 0 80 8
+Term::check_box "source box in regs layout" 0 7 80 8
 
 set text [Term::get_line 1]
 # Just check for any register window content at all.
diff --git a/gdb/testsuite/gdb.tui/winwidth.exp b/gdb/testsuite/gdb.tui/winwidth.exp
index b0a838b578f..1767b25c8d3 100644
--- a/gdb/testsuite/gdb.tui/winwidth.exp
+++ b/gdb/testsuite/gdb.tui/winwidth.exp
@@ -39,24 +39,25 @@ with_test_prefix "original window sizes" {
 }
 
 with_test_prefix "after src +5" {
-    Term::check_box "source box" 0 0 44 15
-    Term::check_box "asm box" 43 0 37 15
+    Term::check_box "source box" 0 0 45 15
+    Term::check_box "asm box" 44 0 36 15
     Term::command "winwidth asm -5"
 }
 
 with_test_prefix "after asm -5" {
-    Term::check_box "source box" 0 0 48 15
-    Term::check_box "asm box" 47 0 33 15
+    Term::dump_screen
+    Term::check_box "source box" 0 0 50 15
+    Term::check_box "asm box" 49 0 31 15
     Term::command "winwidth asm +8"
 }
 
 with_test_prefix "after asm +8" {
-    Term::check_box "source box" 0 0 39 15
-    Term::check_box "asm box" 38 0 42 15
+    Term::check_box "source box" 0 0 42 15
+    Term::check_box "asm box" 41 0 39 15
     Term::command "winwidth src -2"
 }
 
 with_test_prefix "after src -2" {
-    Term::check_box "source box" 0 0 36 15
-    Term::check_box "asm box" 35 0 45 15
+    Term::check_box "source box" 0 0 40 15
+    Term::check_box "asm box" 39 0 41 15
 }
diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index 8758bfe70e7..4988d48a8d5 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -810,11 +810,11 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_)
 	    info[i].size = info[i].max_size;
 	  if (info[i].size < info[i].min_size)
 	    info[i].size = info[i].min_size;
-	  /* If there is any leftover size, just redistribute it to the
-	     last resizeable window, by dropping it from the allocated
-	     size.  We could try to be fancier here perhaps, by
-	     redistributing this size among all windows, not just the
-	     last window.  */
+	  /* Keep a total of all the size we've used so far (we gain some
+	     size back if this window can share a border with a preceding
+	     window).  Any unused space will be distributed between all of
+	     the other windows (while respecting min/max sizes) later in
+	     this function.  */
 	  used_size += info[i].size;
 	  if (info[i].share_box)
 	    --used_size;
@@ -834,9 +834,33 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_)
     }
 
   /* Allocate any leftover size.  */
-  if (available_size >= used_size && last_index != -1)
+  if (available_size > used_size && last_index != -1)
     {
-      info[last_index].size += available_size - used_size;
+      /* Loop over all windows until all available space is used up.  */
+      bool found_window_that_can_grow_p = true;
+      for (int idx = last_index;
+	   available_size > used_size;
+	   idx = (idx + 1) % m_splits.size ())
+	{
+	  /* Once we have visited all of the windows, check that we did
+	     manage to allocate some more space.  This prevents us getting
+	     stuck in the loop forever if we can't allocate anything
+	     more.  */
+	  if (idx == last_index)
+	    {
+	      if (!found_window_that_can_grow_p)
+		break;
+	      found_window_that_can_grow_p = false;
+	    }
+
+	  if (available_size > used_size
+	      && info[idx].size < info[idx].max_size)
+	    {
+	      found_window_that_can_grow_p = true;
+	      info[idx].size += 1;
+	      used_size += 1;
+	    }
+	}
 
       if (debug_tui)
 	{
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv3 11/15] gdb/tui: allow cmd window to change size in tui_layout_split::apply
  2022-03-07 22:13   ` [PATCHv3 " Andrew Burgess
                       ` (9 preceding siblings ...)
  2022-03-07 22:13     ` [PATCHv3 10/15] gdb/tui: fairer distribution of excess space during apply Andrew Burgess
@ 2022-03-07 22:13     ` Andrew Burgess
  2022-03-07 22:13     ` [PATCHv3 12/15] gdb/tui: support placing the cmd window into a horizontal layout Andrew Burgess
                       ` (4 subsequent siblings)
  15 siblings, 0 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

When we switch layouts we call the tui_layout_split::apply member
function to reapply the layout, and recalculate all the window sizes.

One special case is the cmd window, which we try to keep at its
existing size.

However, in some cases it is not appropriate to keep the cmd window at
its existing size.  I will describe two such cases here, in one, we
want the cmd window to reduce in size, and in the other, we want the
cmd window to grow in size.

Try these steps in a 80 columns, by 24 lines terminal:

  (gdb) tui enable
  (gdb) layout src
  (gdb) winheight cmd 20
  (gdb) layout split

You should see that the status window is missing from the new layout,
and that the cmd window has been placed over the border of the asm
window.  The 'info win' output is:

  (gdb) info win
  Name       Lines Columns Focus
  src            3      80 (has focus)
  asm            3      80
  status         1      80
  cmd           20      80

Notice that gdb has assigned 27 lines of screen space, even with the
border overlap between the src and asm windows, this is still 2 lines
too many.

The problem here is that after switching layouts, gdb has forced the
cmd window to retain its 20 line height.  Really, we want the cmd
window to reduce in height so that the src and asm windows can occupy
their minimum required space.

This commit allows this (details on how are below).  After this
commit, in the above situation, we now see the status window displayed
correctly, and the 'info win' output is:

  (gdb) info win
  Name       Lines Columns Focus
  src            3      80 (has focus)
  asm            3      80
  status         1      80
  cmd           18      80

The cmd window has been reduced in size by 2 lines so that everything
can fit on the screen.

The second example is one which was discussed in a recent commit,
consider this case (still in the 80 column, 24 line terminal):

  (gdb) tui enable
  (gdb) tui new-layout conly cmd 1
  (gdb) layout conly
  (gdb) info win
  Name       Lines Columns Focus
  cmd            8      80 (has focus)
  (gdb)

This layout only contains a cmd window, which we would expect to
occupy the entire terminal.  But instead, the cmd window only occupies
the first 8 lines, and the rest of the terminal is unused!

The reason is, again, that the cmd window is keeping its previous
size (8 lines).

After this commit things are slightly different, the 'info win' output
is now:

  (gdb) info win
  Name       Lines Columns Focus
  cmd           20      80 (has focus)

Which is a little better, but why only 20 lines?  Turns out there's
yet another bug hitting this case.  That bug will be addressed in a
later commit, so, for now, we're accepting the 20 lines.

What this commit does is modify the phase of tui_layout_split::apply
that handles any left over space.  Usually, in "Step 2", each
sub-layout has a size calculated.  As the size is an integer, then,
when all sizes are calculated we may have some space left over.

This extra space is then distributed between all the windows fairly
until all the space is used up.

When we consider windows minimum size, or fixed size windows, then it
is possible that we might try to use more space than is available,
this was our first example above.  The same code that added extra
space to the windows, can also be used to reclaim space (in the over
allocation case) to allow all windows to fit.

The problem then is the cmd window, which we often force to a fixed
size.  Inside the loop that handles the allocation of excess space, if
we find that we have tried every window, and still have space either
left to give, or we need to claim back more space, then, if the cmd
window was changed to a fixed size, we can change the cmd window back
to a non-fixed-size window, and proceed to either give, or take space
from the cmd window as needed.
---
 gdb/testsuite/gdb.tui/new-layout.exp |  9 +++
 gdb/testsuite/gdb.tui/winheight.exp  | 46 ++++++++++++++
 gdb/tui/tui-layout.c                 | 95 +++++++++++++++++++++++++---
 3 files changed, 142 insertions(+), 8 deletions(-)

diff --git a/gdb/testsuite/gdb.tui/new-layout.exp b/gdb/testsuite/gdb.tui/new-layout.exp
index 66048e65238..0d49d033be5 100644
--- a/gdb/testsuite/gdb.tui/new-layout.exp
+++ b/gdb/testsuite/gdb.tui/new-layout.exp
@@ -124,5 +124,14 @@ foreach_with_prefix layout $layouts {
 	Term::command "winheight src + 5"
 	Term::check_box "left window box after grow" 0 0 40 15
 	Term::check_box "right window box after grow" 39 0 41 15
+    } elseif {$name == "cmd_only"} {
+	Term::check_region_contents "bottom of cmd window is blank" \
+	    0 14 80 10 "^\\s+$"
+	Term::command "info win"
+	Term::check_region_contents "info win output" \
+	    0 0 80 24 [multi_line "info win\\s+" \
+			   "Name\\s+Lines\\s+Columns\\s+Focus\\s+" \
+			   "cmd\\s+20\\s+80\\s+\\(has focus\\)\\s+" \
+			   "$gdb_prompt\\s+"]
     }
 }
diff --git a/gdb/testsuite/gdb.tui/winheight.exp b/gdb/testsuite/gdb.tui/winheight.exp
index 0d0c886304d..b541c21b825 100644
--- a/gdb/testsuite/gdb.tui/winheight.exp
+++ b/gdb/testsuite/gdb.tui/winheight.exp
@@ -50,3 +50,49 @@ Term::check_box "larger source box again" 0 0 80 15
 Term::command "layout asm"
 Term::check_box "check for asm window" 0 0 80 15
 
+
+# Check what happens when we switch from src layout to split layout.
+# The interesting thing here is that the src layout has one flexible
+# window (the src), the status window, which is of fixed size, and the
+# cmd window, which tries to retain its size when a layout changes.
+#
+# In contrast, the split layout has both a src and asm window, plus
+# the same status and cmd windows.
+#
+# Of particular interest here is the first test, where we maximise the
+# cmd window before switching to split.  This requires gdb to realise
+# that it has to shrink the cmd window, even though this is something
+# gdb usually avoids doing.
+#
+# Each test here is a size for the src window in the 'src' layout.
+# The test then switches to the 'split' layout, and calculates the
+# expected window sizes.
+foreach_with_prefix cmd_size {20 12 5} {
+    set src_size_before [expr 24 - ${cmd_size} - 1]
+    set split_size [expr (24 - ${cmd_size}) / 2]
+
+    if { $split_size < 3 } {
+	# The minimum window size is 3, so force that.
+	set src_size_after 3
+	set asm_size_after 3
+    } elseif { [expr $split_size % 2] == 0 } {
+	# The remaining space can be divided evenly between the two
+	# windows.
+	set src_size_after ${split_size}
+	set asm_size_after ${split_size}
+    } else {
+	# The space can't be divided evenly, the asm window will get
+	# the extra line.
+	set src_size_after ${split_size}
+	set asm_size_after [expr ${split_size} + 1]
+    }
+
+    Term::command "layout src"
+    Term::command "winheight cmd ${cmd_size}"
+    Term::check_box "check for src window" 0 0 80 ${src_size_before}
+
+    # Both windows should be of equal size, which will be their minimum.
+    Term::command "layout split"
+    Term::check_box "check for src window in split" 0 0 80 ${src_size_after}
+    Term::check_box "check for asm window in split" 0 [expr ${src_size_after} - 1] 80 ${asm_size_after}
+}
diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index 4988d48a8d5..4742f65f6cf 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -735,6 +735,30 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_)
   width = width_;
   height = height_;
 
+  /* In some situations we fix the size of the cmd window.  However,
+     occasionally this turns out to be a mistake.  This struct is used to
+     hold the original information about the cmd window, so we can restore
+     it if needed.  */
+  struct old_size_info
+  {
+    /* Constructor.  */
+    old_size_info (int index_, int min_size_, int max_size_)
+      : index (index_),
+	min_size (min_size_),
+	max_size (max_size_)
+    { /* Nothing.  */ }
+
+    /* The index in m_splits where the cmd window was found.  */
+    int index;
+
+    /* The previous min/max size.  */
+    int min_size;
+    int max_size;
+  };
+
+  /* This is given a value only if we fix the size of the cmd window.  */
+  gdb::optional<old_size_info> old_cmd_info;
+
   std::vector<size_info> info (m_splits.size ());
 
   tui_debug_printf ("weights are: %s",
@@ -762,6 +786,10 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_)
 	  && m_splits[i].layout->get_name () != nullptr
 	  && strcmp (m_splits[i].layout->get_name (), "cmd") == 0)
 	{
+	  /* Save the old cmd window information, in case we need to
+	     restore it later.  */
+          old_cmd_info.emplace (i, info[i].min_size, info[i].max_size);
+
 	  /* If this layout has never been applied, then it means the
 	     user just changed the layout.  In this situation, it's
 	     desirable to keep the size of the command window the
@@ -833,22 +861,66 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_)
       tui_debug_print_size_info (info);
     }
 
+  /* If we didn't find any sub-layouts that were of a non-fixed size, but
+     we did find the cmd window, then we can consider that a sort-of
+     non-fixed size sub-layout.
+
+     The cmd window might, initially, be of a fixed size (see above), but,
+     we are willing to relax this constraint if required to correctly apply
+     this layout (see below).  */
+  if (last_index == -1 && old_cmd_info.has_value ())
+    last_index = old_cmd_info->index;
+
   /* Allocate any leftover size.  */
-  if (available_size > used_size && last_index != -1)
+  if (available_size != used_size && last_index != -1)
     {
-      /* Loop over all windows until all available space is used up.  */
+      /* Loop over all windows until the amount of used space is equal to
+	 the amount of available space.  There's an escape hatch within
+	 the loop in case we can't find any sub-layouts to resize.  */
       bool found_window_that_can_grow_p = true;
       for (int idx = last_index;
-	   available_size > used_size;
+	   available_size != used_size;
 	   idx = (idx + 1) % m_splits.size ())
 	{
-	  /* Once we have visited all of the windows, check that we did
-	     manage to allocate some more space.  This prevents us getting
-	     stuck in the loop forever if we can't allocate anything
-	     more.  */
+	  /* Every time we get back to last_index, which is where the loop
+	     started, we check to make sure that we did assign some space
+	     to a window, bringing used_size closer to available_size.
+
+	     If we didn't, but the cmd window is of a fixed size, then we
+	     can make the console window non-fixed-size, and continue
+	     around the loop, hopefully, this will allow the layout to be
+	     applied correctly.
+
+	     If we still make it around the loop without moving used_size
+	     closer to available_size, then there's nothing more we can do,
+	     and we break out of the loop.  */
 	  if (idx == last_index)
 	    {
-	      if (!found_window_that_can_grow_p)
+	      /* If the used_size is greater than the available_size then
+		 this indicates that the fixed-sized sub-layouts claimed
+		 more space than is available.  This layout is not going to
+		 work.  Our only hope at this point is to make the cmd
+		 window non-fixed-size (if possible), and hope we can
+		 shrink this enough to fit the rest of the sub-layouts in.
+
+	         Alternatively, we've made it around the loop without
+	         adjusting any window's size.  This likely means all
+	         windows have hit their min or max size.  Again, our only
+	         hope is to make the cmd window non-fixed-size, and hope
+	         this fixes all our problems.  */
+	      if (old_cmd_info.has_value ()
+		  && ((available_size < used_size)
+		      || !found_window_that_can_grow_p))
+		{
+		  info[old_cmd_info->index].min_size = old_cmd_info->min_size;
+		  info[old_cmd_info->index].max_size = old_cmd_info->max_size;
+		  tui_debug_printf
+		    ("restoring index %d (cmd) size limits, min = %d, max = %d",
+		     old_cmd_info->index, old_cmd_info->min_size,
+		     old_cmd_info->max_size);
+		  old_cmd_info.reset ();
+		}
+	      else if (!found_window_that_can_grow_p)
 		break;
 	      found_window_that_can_grow_p = false;
 	    }
@@ -860,6 +932,13 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_)
 	      info[idx].size += 1;
 	      used_size += 1;
 	    }
+	  else if (available_size < used_size
+		   && info[idx].size > info[idx].min_size)
+	    {
+	      found_window_that_can_grow_p = true;
+	      info[idx].size -= 1;
+	      used_size -= 1;
+	    }
 	}
 
       if (debug_tui)
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv3 12/15] gdb/tui: support placing the cmd window into a horizontal layout
  2022-03-07 22:13   ` [PATCHv3 " Andrew Burgess
                       ` (10 preceding siblings ...)
  2022-03-07 22:13     ` [PATCHv3 11/15] gdb/tui: allow cmd window to change size in tui_layout_split::apply Andrew Burgess
@ 2022-03-07 22:13     ` Andrew Burgess
  2022-03-07 22:13     ` [PATCHv3 13/15] gdb/testsuite: some additional tests in gdb.tui/scroll.exp Andrew Burgess
                       ` (3 subsequent siblings)
  15 siblings, 0 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

This commit allows the user to place the cmd window within horizontal
tui layouts.  Consider this set of steps, carried out in an 80 columns
by 24 lines terminal, using current master gdb:

  (gdb) tui new-layout hsrc { -horizontal src 1 cmd 1 } 1 status 1
  (gdb) tui layout hsrc

What you end up with is a full width cmd window with the status bar
beneath.  Where's the src window gone?  We then try:

  (gdb) info win
  Name       Lines Columns Focus
  src           23       3 (has focus)
  cmd           23      80
  status         1      80
  (gdb)

Something weird has gone on, gdb has overlapped the cmd window with
the src window.  If we trigger the src window to redraw is content,
for example, 'list main', then we see corruption in the cmd window as
the src window overwrites it.

So, what's going on?

The problem is some code in tui_layout_split::apply, in tui-layout.c.
Within 'Step 1', there is a loop that calculates the min/max window
sizes for all windows within a tui_layout_split.  However, there's a
special case for the cmd window.

This special case is trying to have the cmd window retain its current
size when a layout is re-applied, or a new layout is applied.  This
makes sense, consider moving from the 'src' layout to the 'asm'
layout, this looks something like this (status window removed):

    .-------.         .-------.
    |  src  |         |  asm  |
    |-------|  ====>  |-------|
    |  cmd  |         |  cmd  |
    '-------'         '-------'

If the user has gone to the effort of adjusting the cmd window size,
then, the thinking goes, we shouldn't reset the cmd window size when
switching layouts like this.

The problem though, is that when we do a switch more like this:

    .-----------.         .-----------.
    |    src    |         |     |     |
    |-----------|  ====>  | asm | cmd |
    |    cmd    |         |     |     |
    '-----------'         '-----------'

Now retaining the cmd window width makes no sense; the new layout has
a completely different placement for the cmd window, instead of sizing
by height, we're now sizing by width.  The existing code doesn't
understand this though, and tried to retain the full width for the cmd
window.

To solve this problem, I propose we introduce the idea of a layout
"fingerprint".  The fingerprint tries to capture, in an abstract way,
where the cmd window lives within the layout.

Only when two layouts have the same fingerprint will we attempt to
retain the cmd window size.

The fingerprint for a layout is represented as a string, the string is
a series of 'V' or 'H' characters, ending with a single 'C'
character.  The series of 'V' and 'H' characters represent the
vertical or horizontal layouts that must be passed through to find the
cmd window.

Here are a few examples:

  # This layout is equivalent to the builtin 'src' layout.
  # Fingerprint: VC
  tui new-layout example1 src 2 status 0 cmd 1

  # This layout is equivalent to the builtin 'split' layout.
  # Fingerprint: VC
  tui new-layout example2 src 1 asm 1 status 0 cmd 1

  # This is the same layout that was given at the top.
  # Fingerprint: VHC
  tui new-layout hsrc { -horizontal src 1 cmd 1 } 1 status 1

And so, when switching between example1 and example2, gdb knows that
the cmd window is, basically, in the same sort of position within the
layout, and will retain the cmd window size.

In contrast, when switching to the hsrc layout, gdb understands that
the position of the cmd window is different, and does not try to
retain the cmd window size.
---
 gdb/testsuite/gdb.tui/new-layout.exp |  5 ++
 gdb/tui/tui-layout.c                 | 69 ++++++++++++++++++++++------
 gdb/tui/tui-layout.h                 | 47 +++++++++++++++----
 gdb/tui/tui-win.c                    |  6 ++-
 4 files changed, 102 insertions(+), 25 deletions(-)

diff --git a/gdb/testsuite/gdb.tui/new-layout.exp b/gdb/testsuite/gdb.tui/new-layout.exp
index 0d49d033be5..883c7601be7 100644
--- a/gdb/testsuite/gdb.tui/new-layout.exp
+++ b/gdb/testsuite/gdb.tui/new-layout.exp
@@ -71,6 +71,11 @@ set layouts \
 	 [list h "{-horizontal asm 1 src 1} 1 status 0 cmd 1" \
 	      {{0 0 40 15} {39 0 41 15}} \
 	      "$hex <main>.*21.*return 0"] \
+	 [list example3 "{-horizontal src 1 cmd 1} 1 status 0 asm 1" \
+	      {{0 0 40 11} {0 12 80 12}} \
+	      "21.*return 0.*$hex <main>"] \
+	 [list example4 "src 1 status 0 {-horizontal cmd 1 regs 1} 1" \
+	      {{0 0 80 11} {40 12 40 12}} ""] \
 	 [list cmd_only "cmd 1" {} ""]]
 
 # Helper function to verify a list of boxes.
diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index 4742f65f6cf..481a67827f9 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -67,7 +67,7 @@ std::vector<tui_win_info *> tui_windows;
 /* See tui-layout.h.  */
 
 void
-tui_apply_current_layout ()
+tui_apply_current_layout (bool preserve_cmd_win_size_p)
 {
   struct gdbarch *gdbarch;
   CORE_ADDR addr;
@@ -77,7 +77,8 @@ tui_apply_current_layout ()
   for (tui_win_info *win_info : tui_windows)
     win_info->make_visible (false);
 
-  applied_layout->apply (0, 0, tui_term_width (), tui_term_height ());
+  applied_layout->apply (0, 0, tui_term_width (), tui_term_height (),
+			 preserve_cmd_win_size_p);
 
   /* Keep the list of internal windows up-to-date.  */
   for (int win_type = SRC_WIN; (win_type < MAX_MAJOR_WINDOWS); win_type++)
@@ -134,9 +135,18 @@ tui_adjust_window_width (struct tui_win_info *win, int new_width)
 static void
 tui_set_layout (tui_layout_split *layout)
 {
+  std::string old_fingerprint;
+  if (applied_layout != nullptr)
+    old_fingerprint = applied_layout->layout_fingerprint ();
+
   applied_skeleton = layout;
   applied_layout = layout->clone ();
-  tui_apply_current_layout ();
+
+  std::string new_fingerprint = applied_layout->layout_fingerprint ();
+  bool preserve_command_window_size
+    = (TUI_CMD_WIN != nullptr && old_fingerprint == new_fingerprint);
+
+  tui_apply_current_layout (preserve_command_window_size);
 }
 
 /* See tui-layout.h.  */
@@ -158,7 +168,7 @@ tui_add_win_to_layout (enum tui_win_type type)
 
   const char *name = type == SRC_WIN ? SRC_NAME : DISASSEM_NAME;
   applied_layout->replace_window (tui_win_list[other]->name (), name);
-  tui_apply_current_layout ();
+  tui_apply_current_layout (true);
 }
 
 /* Find LAYOUT in the "layouts" global and return its index.  */
@@ -271,7 +281,7 @@ tui_remove_some_windows ()
     }
 
   applied_layout->remove_windows (focus->name ());
-  tui_apply_current_layout ();
+  tui_apply_current_layout (true);
 }
 
 static void
@@ -411,7 +421,8 @@ tui_layout_window::clone () const
 /* See tui-layout.h.  */
 
 void
-tui_layout_window::apply (int x_, int y_, int width_, int height_)
+tui_layout_window::apply (int x_, int y_, int width_, int height_,
+			  bool preserve_cmd_win_size_p)
 {
   x = x_;
   y = y_;
@@ -492,6 +503,17 @@ tui_layout_window::specification (ui_file *output, int depth)
 
 /* See tui-layout.h.  */
 
+std::string
+tui_layout_window::layout_fingerprint () const
+{
+  if (strcmp (get_name (), "cmd") == 0)
+    return "C";
+  else
+    return "";
+}
+
+/* See tui-layout.h.  */
+
 void
 tui_layout_split::add_split (std::unique_ptr<tui_layout_split> &&layout,
 			     int weight)
@@ -716,8 +738,11 @@ tui_layout_split::set_size (const char *name, int new_size, bool set_width_p)
     }
   else
     {
-      /* Simply re-apply the updated layout.  */
-      apply (x, y, width, height);
+      /* Simply re-apply the updated layout.  We pass false here so that
+	 the cmd window can be resized.  However, we should have already
+	 resized everything above to be "just right", so the apply call
+	 here should not end up changing the sizes at all.  */
+      apply (x, y, width, height, false);
     }
 
   return HANDLED;
@@ -726,7 +751,8 @@ tui_layout_split::set_size (const char *name, int new_size, bool set_width_p)
 /* See tui-layout.h.  */
 
 void
-tui_layout_split::apply (int x_, int y_, int width_, int height_)
+tui_layout_split::apply (int x_, int y_, int width_, int height_,
+			 bool preserve_cmd_win_size_p)
 {
   TUI_SCOPED_DEBUG_ENTER_EXIT;
 
@@ -781,7 +807,7 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_)
       m_splits[i].layout->get_sizes (m_vertical, &info[i].min_size,
 				     &info[i].max_size);
 
-      if (!m_applied
+      if (preserve_cmd_win_size_p
 	  && cmd_win_already_exists
 	  && m_splits[i].layout->get_name () != nullptr
 	  && strcmp (m_splits[i].layout->get_name (), "cmd") == 0)
@@ -964,13 +990,13 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_)
       else if (info[i].share_box)
 	--size_accum;
       if (m_vertical)
-	m_splits[i].layout->apply (x, y + size_accum, width, info[i].size);
+	m_splits[i].layout->apply (x, y + size_accum, width, info[i].size,
+				   preserve_cmd_win_size_p);
       else
-	m_splits[i].layout->apply (x + size_accum, y, info[i].size, height);
+	m_splits[i].layout->apply (x + size_accum, y, info[i].size, height,
+				   preserve_cmd_win_size_p);
       size_accum += info[i].size;
     }
-
-  m_applied = true;
 }
 
 /* See tui-layout.h.  */
@@ -1031,6 +1057,21 @@ tui_layout_split::specification (ui_file *output, int depth)
     fputs_unfiltered ("}", output);
 }
 
+/* See tui-layout.h.  */
+
+std::string
+tui_layout_split::layout_fingerprint () const
+{
+  for (auto &item : m_splits)
+    {
+      std::string fp = item.layout->layout_fingerprint ();
+      if (!fp.empty ())
+	return std::string (m_vertical ? "V" : "H") + fp;
+    }
+
+  return "";
+}
+
 /* Destroy the layout associated with SELF.  */
 
 static void
diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h
index 9cfcfb8e81f..32bc95171bf 100644
--- a/gdb/tui/tui-layout.h
+++ b/gdb/tui/tui-layout.h
@@ -55,8 +55,12 @@ class tui_layout_base
      "skeleton" layout.  */
   virtual std::unique_ptr<tui_layout_base> clone () const = 0;
 
-  /* Change the size and location of this layout.  */
-  virtual void apply (int x, int y, int width, int height) = 0;
+  /* Change the size and location of this layout.  When
+     PRESERVE_CMD_WIN_SIZE_P is true the current size of the TUI_CMD_WIN
+     is preserved, otherwise, the TUI_CMD_WIN will resize just like any
+     other window.  */
+  virtual void apply (int x, int y, int width, int height,
+		      bool preserve_cmd_win_size_p) = 0;
 
   /* Return the minimum and maximum height or width of this layout.
      HEIGHT is true to fetch height, false to fetch width.  */
@@ -97,6 +101,26 @@ class tui_layout_base
      depth of this layout in the hierarchy (zero-based).  */
   virtual void specification (ui_file *output, int depth) = 0;
 
+  /* Return a FINGERPRINT string containing an abstract representation of
+     the location of the cmd window in this layout.
+
+     When called on a complete, top-level layout, the fingerprint will be a
+     non-empty string made of 'V' and 'H' characters, followed by a single
+     'C' character.  Each 'V' and 'H' represents a vertical or horizontal
+     layout that must be passed through in order to find the cmd
+     window.
+
+     Of course, layouts are built recursively, so, when called on a partial
+     layout, if this object represents a single window, then either the
+     empty string is returned (for non-cmd windows), or a string
+     containing a single 'C' is returned.
+
+     For object representing layouts, if the layout contains the cmd
+     window then we will get back a valid fingerprint string (contains 'V'
+     and 'H', ends with 'C'), or, if this layout doesn't contain the cmd
+     window, an empty string is returned.  */
+  virtual std::string layout_fingerprint () const = 0;
+
   /* Add all windows to the WINDOWS vector.  */
   virtual void get_windows (std::vector<tui_win_info *> *windows) = 0;
 
@@ -126,7 +150,8 @@ class tui_layout_window : public tui_layout_base
 
   std::unique_ptr<tui_layout_base> clone () const override;
 
-  void apply (int x, int y, int width, int height) override;
+  void apply (int x, int y, int width, int height,
+	      bool preserve_cmd_win_size_p) override;
 
   const char *get_name () const override
   {
@@ -155,6 +180,8 @@ class tui_layout_window : public tui_layout_base
 
   void specification (ui_file *output, int depth) override;
 
+  std::string layout_fingerprint () const override;
+
   /* See tui_layout_base::get_windows.  */
   void get_windows (std::vector<tui_win_info *> *windows) override
   {
@@ -201,7 +228,8 @@ class tui_layout_split : public tui_layout_base
 
   std::unique_ptr<tui_layout_base> clone () const override;
 
-  void apply (int x, int y, int width, int height) override;
+  void apply (int x, int y, int width, int height,
+	      bool preserve_cmd_win_size_p) override;
 
   tui_adjust_result set_height (const char *name, int new_height) override
   {
@@ -225,6 +253,8 @@ class tui_layout_split : public tui_layout_base
 
   void specification (ui_file *output, int depth) override;
 
+  std::string layout_fingerprint () const override;
+
   /* See tui_layout_base::get_windows.  */
   void get_windows (std::vector<tui_win_info *> *windows) override
   {
@@ -289,9 +319,6 @@ class tui_layout_split : public tui_layout_base
 
   /* True if the windows in this split are arranged vertically.  */
   bool m_vertical;
-
-  /* True if this layout has already been applied at least once.  */
-  bool m_applied = false;
 };
 
 /* Add the specified window to the layout in a logical way.  This
@@ -314,8 +341,10 @@ extern void tui_regs_layout ();
    some other window is chosen to remain.  */
 extern void tui_remove_some_windows ();
 
-/* Apply the current layout.  */
-extern void tui_apply_current_layout ();
+/* Apply the current layout.  When PRESERVE_CMD_WIN_SIZE_P is true the
+   current size of the TUI_CMD_WIN is preserved, otherwise, the TUI_CMD_WIN
+   will resize just like any other window.  */
+extern void tui_apply_current_layout (bool);
 
 /* Adjust the window height of WIN to NEW_HEIGHT.  */
 extern void tui_adjust_window_height (struct tui_win_info *win,
diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c
index 512ea52b694..98dfcc76534 100644
--- a/gdb/tui/tui-win.c
+++ b/gdb/tui/tui-win.c
@@ -511,8 +511,10 @@ tui_resize_all (void)
 	 AIX 5.3 does not define clear.  */
       erase ();
       clearok (curscr, TRUE);
-      tui_apply_current_layout ();
-      /* Turn keypad back on.  */
+      /* Apply the current layout.  The 'false' here allows the command
+	 window to resize proportionately with containing terminal, rather
+	 than maintaining a fixed size.  */
+      tui_apply_current_layout (false); /* Turn keypad back on.  */
       keypad (TUI_CMD_WIN->handle.get (), TRUE);
     }
 }
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv3 13/15] gdb/testsuite: some additional tests in gdb.tui/scroll.exp
  2022-03-07 22:13   ` [PATCHv3 " Andrew Burgess
                       ` (11 preceding siblings ...)
  2022-03-07 22:13     ` [PATCHv3 12/15] gdb/tui: support placing the cmd window into a horizontal layout Andrew Burgess
@ 2022-03-07 22:13     ` Andrew Burgess
  2022-03-07 22:13     ` [PATCHv3 14/15] gdb/tui: relax restrictions on window max height and width Andrew Burgess
                       ` (2 subsequent siblings)
  15 siblings, 0 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

This commit just adds an extra check of the src window size prior to
sending all the commands to gdb.  We also set the cmd window height to
its existing height, this (obviously) shouldn't change the window
layout, which we check.

My main motivation was adding the initial window layout check, the
winheight and recheck are just extras.  All of these test pass both
before and after this commit.
---
 gdb/testsuite/gdb.tui/scroll.exp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/gdb/testsuite/gdb.tui/scroll.exp b/gdb/testsuite/gdb.tui/scroll.exp
index 4eaee0c14ee..c23cd2b9abf 100644
--- a/gdb/testsuite/gdb.tui/scroll.exp
+++ b/gdb/testsuite/gdb.tui/scroll.exp
@@ -55,6 +55,10 @@ Term::check_region_contents "check cmd window" 0 16 80 8 \
 Term::command "tui new-layout flip cmd 1 src 1"
 Term::command "layout flip"
 
+Term::check_box "src window" 0 8 80 16
+Term::command "winheight cmd 8"
+Term::check_box "src window after resize" 0 8 80 16
+
 for {set i 10} {$i < 20} {incr i 1} {
     Term::command "p $i"
 }
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv3 14/15] gdb/tui: relax restrictions on window max height and width
  2022-03-07 22:13   ` [PATCHv3 " Andrew Burgess
                       ` (12 preceding siblings ...)
  2022-03-07 22:13     ` [PATCHv3 13/15] gdb/testsuite: some additional tests in gdb.tui/scroll.exp Andrew Burgess
@ 2022-03-07 22:13     ` Andrew Burgess
  2022-03-07 22:13     ` [PATCHv3 15/15] gdb/tui: fair split of delta after a resize Andrew Burgess
  2022-03-21 17:52     ` [PATCHv3 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess
  15 siblings, 0 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

This commit removes some arbitrary adjustments made in
tui_cmd_window::max_height, tui_win_info::max_height, and
tui_win_info::max_width.

These member functions all subtract some constant from the theoretical
maximum height or width.  I've looked back through the history a
little and can see no real reason why these adjustments should be
needed, with these adjustments removed all the existing tui tests
still pass.

However, retaining these restrictions causes some bugs, consider:

  (gdb) tui new-layout hsrc {-horizontal src 1 cmd 1} 1

When this layout is selected with current master, gdb will leave a 4
line gap at the bottom of the terminal.

The problem is that the maximum height is restricted, for the cmd
window, to 4 less than the terminal height.

By removing this restriction gdb is able to size the windows to the
complete terminal height, and the layout is done correctly.

This 4 line restriction is also what prevents this layout from working
correctly:

  (gdb) tui new-layout conly cmd 1

Previously, this layout would present a cmd window only, but there
would be a 4 line gap at the bottom of the terminal.  This issue was
mentioned in an earlier commit in this series (when a different bug
was fixed), but with this commit, the above layout now correctly fills
the terminal.  The associated test is updated.

After removing the adjustment in tui_cmd_window::max_height, the
implementation is now the same as the implementation in the parent
class tui_win_info, so I've completely removed the max_height call
from tui_cmd_window.
---
 gdb/testsuite/gdb.tui/new-layout.exp | 4 +++-
 gdb/tui/tui-command.c                | 6 ------
 gdb/tui/tui-command.h                | 2 --
 gdb/tui/tui-win.c                    | 4 ++--
 4 files changed, 5 insertions(+), 11 deletions(-)

diff --git a/gdb/testsuite/gdb.tui/new-layout.exp b/gdb/testsuite/gdb.tui/new-layout.exp
index 883c7601be7..e662b1f0b18 100644
--- a/gdb/testsuite/gdb.tui/new-layout.exp
+++ b/gdb/testsuite/gdb.tui/new-layout.exp
@@ -76,6 +76,8 @@ set layouts \
 	      "21.*return 0.*$hex <main>"] \
 	 [list example4 "src 1 status 0 {-horizontal cmd 1 regs 1} 1" \
 	      {{0 0 80 11} {40 12 40 12}} ""] \
+	 [list example5 "{-horizontal src 1 cmd 1} 1 status 0" \
+	      {{0 0 40 23}} ""] \
 	 [list cmd_only "cmd 1" {} ""]]
 
 # Helper function to verify a list of boxes.
@@ -136,7 +138,7 @@ foreach_with_prefix layout $layouts {
 	Term::check_region_contents "info win output" \
 	    0 0 80 24 [multi_line "info win\\s+" \
 			   "Name\\s+Lines\\s+Columns\\s+Focus\\s+" \
-			   "cmd\\s+20\\s+80\\s+\\(has focus\\)\\s+" \
+			   "cmd\\s+24\\s+80\\s+\\(has focus\\)\\s+" \
 			   "$gdb_prompt\\s+"]
     }
 }
diff --git a/gdb/tui/tui-command.c b/gdb/tui/tui-command.c
index fa8af970b0a..0f6c395f567 100644
--- a/gdb/tui/tui-command.c
+++ b/gdb/tui/tui-command.c
@@ -31,12 +31,6 @@
 
 /* See tui-command.h.  */
 
-int
-tui_cmd_window::max_height () const
-{
-  return tui_term_height () - 4;
-}
-
 void
 tui_cmd_window::resize (int height_, int width_, int origin_x, int origin_y)
 {
diff --git a/gdb/tui/tui-command.h b/gdb/tui/tui-command.h
index 06cc24f6faf..6c354361d1d 100644
--- a/gdb/tui/tui-command.h
+++ b/gdb/tui/tui-command.h
@@ -31,8 +31,6 @@ struct tui_cmd_window : public tui_win_info
 
   DISABLE_COPY_AND_ASSIGN (tui_cmd_window);
 
-  int max_height () const override;
-
   void refresh_window () override
   {
   }
diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c
index 98dfcc76534..0165fe6c012 100644
--- a/gdb/tui/tui-win.c
+++ b/gdb/tui/tui-win.c
@@ -955,7 +955,7 @@ tui_set_win_width_command (const char *arg, int from_tty)
 int
 tui_win_info::max_height () const
 {
-  return tui_term_height () - 2;
+  return tui_term_height ();
 }
 
 /* See tui-data.h.  */
@@ -963,7 +963,7 @@ tui_win_info::max_height () const
 int
 tui_win_info::max_width () const
 {
-  return tui_term_width () - 2;
+  return tui_term_width ();
 }
 
 static void
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCHv3 15/15] gdb/tui: fair split of delta after a resize
  2022-03-07 22:13   ` [PATCHv3 " Andrew Burgess
                       ` (13 preceding siblings ...)
  2022-03-07 22:13     ` [PATCHv3 14/15] gdb/tui: relax restrictions on window max height and width Andrew Burgess
@ 2022-03-07 22:13     ` Andrew Burgess
  2022-03-21 17:52     ` [PATCHv3 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess
  15 siblings, 0 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

Currently, in master gdb, when a tui window is changed in size, the
screen delta is mostly just added to the next available window.  We
do take care to respect the min/max size, but in most cases, these
limits are just "the terminal size", and so, we end up placing the
whole delta on the next window.

Consider these steps in an 80 column, 24 line terminal:

  (gdb) tui enable
  (gdb) layout src
  (gdb) layout split
  (gdb) info win
  Name       Lines Columns Focus
  src            8      80 (has focus)
  asm            8      80
  status         1      80
  cmd            8      80
  (gdb) winheight cmd +2
  (gdb) info win
  Name       Lines Columns Focus
  src            6      80 (has focus)
  asm            8      80
  status         1      80
  cmd           10      80

Notice that initially, the windows were balanced, 8 lines each for the
major windows.  Then, when the cmd window was adjusted, the extra two
lines were given to the asm window.

I think it would be nicer if the delta was spread more evenly over the
available windows.  In the example above, after the adjustment the
layout now looks like:

  (gdb) info win
  Name       Lines Columns Focus
  src            7      80 (has focus)
  asm            7      80
  status         1      80
  cmd           10      80

This is achieved within tui_layout_split::set_size, by just handing
out the delta in increments of 1 to each window (except for the window
the user adjusted), until there's no more delta left.  Of course, we
continue to respect the min/max window sizes.
---
 gdb/testsuite/gdb.tui/winheight.exp | 31 ++++++++++++++++++++++++
 gdb/tui/tui-layout.c                | 37 +++++++++++++++++++----------
 2 files changed, 56 insertions(+), 12 deletions(-)

diff --git a/gdb/testsuite/gdb.tui/winheight.exp b/gdb/testsuite/gdb.tui/winheight.exp
index b541c21b825..8296dd79513 100644
--- a/gdb/testsuite/gdb.tui/winheight.exp
+++ b/gdb/testsuite/gdb.tui/winheight.exp
@@ -43,11 +43,42 @@ Term::check_box "smaller source box again" 0 0 80 10
 Term::command "winheight src +5"
 Term::check_box "larger source box again" 0 0 80 15
 
+# Check that attempting a window to be too large gives an error.
+Term::command "winheight src 100"
+Term::check_box "source box has not changed" 0 0 80 15
+Term::check_region_contents "check error message about src size 100" 0 16 80 8 \
+    [multi_line "$gdb_prompt winheight src 100\\s+" \
+     "warning: Invalid window height specified\\s+" \
+     "$gdb_prompt"]
+
+# Check that incrementing to a size that is "too big" will trigger an
+# error, and that the window doesn't resize.
+Term::command "winheight src 20"
+Term::check_box "source box is at its max size" 0 0 80 20
+Term::command "winheight src +1"
+Term::check_box "source box is still at its max size" 0 0 80 20
+Term::check_region_contents "check error message about src +1" 0 21 80 3 \
+    [multi_line "$gdb_prompt winheight src \\+1\\s+" \
+     "warning: Invalid window height specified\\s+" \
+     "$gdb_prompt"]
+
+# Reset the cmd window to a sane size.
+Term::command "winheight cmd 8"
+
+Term::command "layout regs"
+Term::check_box "register window" 0 0 80 8
+Term::check_box "source window" 0 7 80 8
+
+Term::command "winheight cmd 10"
+Term::check_box "register window after resize" 0 0 80 7
+Term::check_box "source window after resize" 0 6 80 7
+
 # At one point we had a bug where adjusting the winheight would result
 # in GDB keeping hold of duplicate window pointers, which it might
 # then try to delete when the layout was changed.  Running this test
 # under valgrind would expose that bug.
 Term::command "layout asm"
+Term::command "winheight cmd 8"
 Term::check_box "check for asm window" 0 0 80 15
 
 
diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index 481a67827f9..a40d2181968 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -691,12 +691,21 @@ tui_layout_split::set_size (const char *name, int new_size, bool set_width_p)
   tui_debug_printf ("before delta (%d) distribution, weights: %s",
 		    delta, tui_debug_weights_to_string ().c_str ());
 
-  /* Distribute the "delta" over the next window; but if the next
-     window cannot hold it all, keep going until we either find a
-     window that does, or until we loop all the way around.  */
-  for (int i = 0; delta != 0 && i < m_splits.size () - 1; ++i)
+  /* Distribute the "delta" over all other windows, while respecting their
+     min/max sizes.  We grow each window by 1 line at a time continually
+     looping over all the windows.  However, skip the window that the user
+     just resized, obviously we don't want to readjust that window.  */
+  bool found_window_that_can_grow_p = true;
+  for (int i = 0; delta != 0; i = (i + 1) % m_splits.size ())
     {
       int index = (found_index + 1 + i) % m_splits.size ();
+      if (index == found_index)
+	{
+	  if (!found_window_that_can_grow_p)
+	    break;
+	  found_window_that_can_grow_p = false;
+	  continue;
+	}
 
       int new_min, new_max;
       m_splits[index].layout->get_sizes (m_vertical, &new_min, &new_max);
@@ -705,19 +714,23 @@ tui_layout_split::set_size (const char *name, int new_size, bool set_width_p)
 	{
 	  /* The primary window grew, so we are trying to shrink other
 	     windows.  */
-	  int available = m_splits[index].weight - new_min;
-	  int shrink_by = std::min (available, -delta);
-	  m_splits[index].weight -= shrink_by;
-	  delta += shrink_by;
+	  if (m_splits[index].weight > new_min)
+	    {
+	      m_splits[index].weight -= 1;
+	      delta += 1;
+	      found_window_that_can_grow_p = true;
+	    }
 	}
       else
 	{
 	  /* The primary window shrank, so we are trying to grow other
 	     windows.  */
-	  int available = new_max - m_splits[index].weight;
-	  int grow_by = std::min (available, delta);
-	  m_splits[index].weight += grow_by;
-	  delta -= grow_by;
+	  if (m_splits[index].weight < new_max)
+	    {
+	      m_splits[index].weight += 1;
+	      delta -= 1;
+	      found_window_that_can_grow_p = true;
+	    }
 	}
 
       tui_debug_printf ("index = %d, weight now: %d",
-- 
2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCHv2 15/15] gdb/tui: fair split of delta after a resize
  2022-03-07 22:07       ` Andrew Burgess
@ 2022-03-07 23:42         ` Tom Tromey
  0 siblings, 0 replies; 74+ messages in thread
From: Tom Tromey @ 2022-03-07 23:42 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: Tom Tromey, Andrew Burgess via Gdb-patches

Andrew> Originally, I did try to do this, but in the end I decided not too as
Andrew> the amount of change seemed much bigger than needed.

Yeah, makes sense.

Andrew> I'd much rather push this smaller change, which allows me to get
Andrew> additional tests into place, then, if we want, we can try to refactor
Andrew> things later, and merge the two code paths together.

Andrew> Would this be OK?

We don't even really have to merge them.  Anyway it's all fine with me,
I appreciate you looking into this and the results seem good.

Tom

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCHv3 06/15] gdb/tui: add a tui debugging flag
  2022-03-07 22:13     ` [PATCHv3 06/15] gdb/tui: add a tui debugging flag Andrew Burgess
@ 2022-03-08 12:16       ` Eli Zaretskii
  2022-03-09 11:48         ` Andrew Burgess
  0 siblings, 1 reply; 74+ messages in thread
From: Eli Zaretskii @ 2022-03-08 12:16 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches

> Date: Mon,  7 Mar 2022 22:13:38 +0000
> From: Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org>
> Cc: Andrew Burgess <aburgess@redhat.com>
> 
> diff --git a/gdb/NEWS b/gdb/NEWS
> index 1275d967a2d..eb18ac47804 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -133,6 +133,10 @@ winwidth
>    the width of a tui window to be adjusted when windows are laid out
>    in horizontal mode.
>  
> +set debug tui on|off
> +show debug tui
> +  Control the display of debug output about GDB's tui.
> +
>  * Changed commands
>  
>  maint packet
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index 6081aa85af4..60173e07747 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -29205,6 +29205,17 @@
>  source text at the next tab stop; the compact display uses only as
>  much space as is needed for the line numbers in the current file, and
>  only a single space to separate the line numbers from the source.
> +
> +@kindex set debug tui
> +@item set debug tui @r{[}on|off@r{]}
> +Turn on or off display of @value{GDBN} internal debug messages relating
> +to the TUI.
> +
> +@kindex show debug tui
> +@item show debug tui
> +Show the current status of displaying @value{GDBN} internal debug
> +messages relating to the TUI.
> +

The documentation parts are OK, but I wonder whether we should mention
the caveats you described, at least in NEWS.  I'm aware that we don't
usually describe known bugs, but since you say this could cause
crashes, perhaps it justifies an exception?

Thanks.

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCHv3 06/15] gdb/tui: add a tui debugging flag
  2022-03-08 12:16       ` Eli Zaretskii
@ 2022-03-09 11:48         ` Andrew Burgess
  2022-03-09 12:58           ` Eli Zaretskii
  2022-03-09 17:53           ` Tom Tromey
  0 siblings, 2 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-03-09 11:48 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches

Eli Zaretskii via Gdb-patches <gdb-patches@sourceware.org> writes:

>> Date: Mon,  7 Mar 2022 22:13:38 +0000
>> From: Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org>
>> Cc: Andrew Burgess <aburgess@redhat.com>
>> 
>> diff --git a/gdb/NEWS b/gdb/NEWS
>> index 1275d967a2d..eb18ac47804 100644
>> --- a/gdb/NEWS
>> +++ b/gdb/NEWS
>> @@ -133,6 +133,10 @@ winwidth
>>    the width of a tui window to be adjusted when windows are laid out
>>    in horizontal mode.
>>  
>> +set debug tui on|off
>> +show debug tui
>> +  Control the display of debug output about GDB's tui.
>> +
>>  * Changed commands
>>  
>>  maint packet
>> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
>> index 6081aa85af4..60173e07747 100644
>> --- a/gdb/doc/gdb.texinfo
>> +++ b/gdb/doc/gdb.texinfo
>> @@ -29205,6 +29205,17 @@
>>  source text at the next tab stop; the compact display uses only as
>>  much space as is needed for the line numbers in the current file, and
>>  only a single space to separate the line numbers from the source.
>> +
>> +@kindex set debug tui
>> +@item set debug tui @r{[}on|off@r{]}
>> +Turn on or off display of @value{GDBN} internal debug messages relating
>> +to the TUI.
>> +
>> +@kindex show debug tui
>> +@item show debug tui
>> +Show the current status of displaying @value{GDBN} internal debug
>> +messages relating to the TUI.
>> +
>
> The documentation parts are OK, but I wonder whether we should mention
> the caveats you described, at least in NEWS.  I'm aware that we don't
> usually describe known bugs, but since you say this could cause
> crashes, perhaps it justifies an exception?

I don't know if that's really a route we want to start going down.  Why
would this bug deserve a NEWS entry over any other bug?

Additionally, the 'set debug ...' flags are really only used for
maintenance (I really with they were 'maint set debug ...', but they
are what they are).

My motivation for adding this text to the commit message is simply, that
if a bug _was_ reported in this area, and a GDB maintainer tries to
debug it, and they track it back to this commit ... then the commit
message acknowledges that there is an issue here.

Anyway, below is a patch that adds a NEWS entry for this bug.

Let me know your thoughts.

thanks,
Andrew

---

diff --git a/gdb/NEWS b/gdb/NEWS
index 4d282cb37dd..166b7f57353 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -9,6 +9,11 @@
   Python 2.  From GDB 13, it will only be possible to build GDB itself
   with Python 3 support.
 
+* Bug PR gdb/28948 exists, this can cause GDB to crash when logging
+  redirection is enabled, and the TUI interface is enabled and
+  disabled. See the following link for more details:
+  https://sourceware.org/bugzilla/show_bug.cgi?id=28948
+
 * Improved C++ template support
 
   GDB now treats functions/types involving C++ templates like it does function


^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCHv3 06/15] gdb/tui: add a tui debugging flag
  2022-03-09 11:48         ` Andrew Burgess
@ 2022-03-09 12:58           ` Eli Zaretskii
  2022-03-09 17:53           ` Tom Tromey
  1 sibling, 0 replies; 74+ messages in thread
From: Eli Zaretskii @ 2022-03-09 12:58 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches

> From: Andrew Burgess <aburgess@redhat.com>
> Cc: gdb-patches@sourceware.org
> Date: Wed, 09 Mar 2022 11:48:07 +0000
> 
> > The documentation parts are OK, but I wonder whether we should mention
> > the caveats you described, at least in NEWS.  I'm aware that we don't
> > usually describe known bugs, but since you say this could cause
> > crashes, perhaps it justifies an exception?
> 
> I don't know if that's really a route we want to start going down.  Why
> would this bug deserve a NEWS entry over any other bug?

Because users could crash their GDB session by doing completely
innocent and reasonable things?

But I see that the crashes are not related to the new setting you are
adding, so I withdraw my suggestion to mention the crashes in NEWS.

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCHv3 06/15] gdb/tui: add a tui debugging flag
  2022-03-09 11:48         ` Andrew Burgess
  2022-03-09 12:58           ` Eli Zaretskii
@ 2022-03-09 17:53           ` Tom Tromey
  1 sibling, 0 replies; 74+ messages in thread
From: Tom Tromey @ 2022-03-09 17:53 UTC (permalink / raw)
  To: Andrew Burgess via Gdb-patches; +Cc: Eli Zaretskii, Andrew Burgess

>>>>> "Andrew" == Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> writes:

Andrew> Additionally, the 'set debug ...' flags are really only used for
Andrew> maintenance (I really with they were 'maint set debug ...', but they
Andrew> are what they are).

I think that would be reasonable to change, actually.

Tom

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCHv3 00/15] TUI changes, new winwidth command and resizing changes
  2022-03-07 22:13   ` [PATCHv3 " Andrew Burgess
                       ` (14 preceding siblings ...)
  2022-03-07 22:13     ` [PATCHv3 15/15] gdb/tui: fair split of delta after a resize Andrew Burgess
@ 2022-03-21 17:52     ` Andrew Burgess
  2022-03-30  9:13       ` Andrew Burgess
  15 siblings, 1 reply; 74+ messages in thread
From: Andrew Burgess @ 2022-03-21 17:52 UTC (permalink / raw)
  To: gdb-patches


Ping!

Thanks,
Andrew


Andrew Burgess <aburgess@redhat.com> writes:

> Since v2:
>
>   - Rebased onto current upstream/master,
>
>   - Patch #5 - Rewritten to not use templates!
>
>   - Patch #6 - Added a bug in bugzilla, and referenced this from the
>     commit message,
>
>   - Patch #7 - Renamed the existing methods rather than adding 2 new
>     methods,
>
>   - Patch #10 - Updated the comment Tom identified as being out of
>     date,
>
>   - Patch #15 - Have updated a comment that I spotted was out of date.
>
> Thanks,
> Andrew
>
>
> ---
>
> Andrew Burgess (15):
>   gdb: move some commands into the tui namespace
>   gdb/tui: rename tui_layout_base::adjust_size to ::set_height
>   gdb/tui: rename tui_layout_split:set_weights_from_heights
>   gdb/testing/tui: add new functionality to tuiterm.exp
>   gdb/tui: add new 'tui window width' command and 'winwidth' alias
>   gdb/tui: add a tui debugging flag
>   gdb/tui: add left_boxed_p and right_boxed_p member functions
>   gdb/tui/testsuite: refactor new-layout.exp test
>   gdb/tui: avoid fp exception when applying layouts
>   gdb/tui: fairer distribution of excess space during apply
>   gdb/tui: allow cmd window to change size in tui_layout_split::apply
>   gdb/tui: support placing the cmd window into a horizontal layout
>   gdb/testsuite: some additional tests in gdb.tui/scroll.exp
>   gdb/tui: relax restrictions on window max height and width
>   gdb/tui: fair split of delta after a resize
>
>  gdb/NEWS                             |  25 ++
>  gdb/doc/gdb.texinfo                  |  51 +++-
>  gdb/testsuite/gdb.tui/basic.exp      |   4 +-
>  gdb/testsuite/gdb.tui/empty.exp      |  14 +-
>  gdb/testsuite/gdb.tui/new-layout.exp | 100 +++++--
>  gdb/testsuite/gdb.tui/regs.exp       |   4 +-
>  gdb/testsuite/gdb.tui/scroll.exp     |   4 +
>  gdb/testsuite/gdb.tui/winheight.exp  |  77 +++++
>  gdb/testsuite/gdb.tui/winwidth.exp   |  63 +++++
>  gdb/testsuite/lib/tuiterm.exp        |  82 +++++-
>  gdb/tui/tui-command.c                |   6 -
>  gdb/tui/tui-command.h                |   2 -
>  gdb/tui/tui-layout.c                 | 406 ++++++++++++++++++++++-----
>  gdb/tui/tui-layout.h                 | 135 +++++++--
>  gdb/tui/tui-win.c                    | 118 ++++++--
>  gdb/tui/tui.c                        |  26 ++
>  gdb/tui/tui.h                        |  14 +
>  17 files changed, 971 insertions(+), 160 deletions(-)
>  create mode 100644 gdb/testsuite/gdb.tui/winwidth.exp
>
> -- 
> 2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCHv3 00/15] TUI changes, new winwidth command and resizing changes
  2022-03-21 17:52     ` [PATCHv3 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess
@ 2022-03-30  9:13       ` Andrew Burgess
  2022-04-03 14:43         ` Andrew Burgess
  0 siblings, 1 reply; 74+ messages in thread
From: Andrew Burgess @ 2022-03-30  9:13 UTC (permalink / raw)
  To: gdb-patches


I'm planning to push this series soon(ish) unless someone complains.

The only series comments on v2 were for patch #5, which I believe are
now addressed.

As always, if there's any feedback post-commit, I'm happy to address
issues as they are raised.

Thanks,
Andrew


Andrew Burgess <aburgess@redhat.com> writes:

> Ping!
>
> Thanks,
> Andrew
>
>
> Andrew Burgess <aburgess@redhat.com> writes:
>
>> Since v2:
>>
>>   - Rebased onto current upstream/master,
>>
>>   - Patch #5 - Rewritten to not use templates!
>>
>>   - Patch #6 - Added a bug in bugzilla, and referenced this from the
>>     commit message,
>>
>>   - Patch #7 - Renamed the existing methods rather than adding 2 new
>>     methods,
>>
>>   - Patch #10 - Updated the comment Tom identified as being out of
>>     date,
>>
>>   - Patch #15 - Have updated a comment that I spotted was out of date.
>>
>> Thanks,
>> Andrew
>>
>>
>> ---
>>
>> Andrew Burgess (15):
>>   gdb: move some commands into the tui namespace
>>   gdb/tui: rename tui_layout_base::adjust_size to ::set_height
>>   gdb/tui: rename tui_layout_split:set_weights_from_heights
>>   gdb/testing/tui: add new functionality to tuiterm.exp
>>   gdb/tui: add new 'tui window width' command and 'winwidth' alias
>>   gdb/tui: add a tui debugging flag
>>   gdb/tui: add left_boxed_p and right_boxed_p member functions
>>   gdb/tui/testsuite: refactor new-layout.exp test
>>   gdb/tui: avoid fp exception when applying layouts
>>   gdb/tui: fairer distribution of excess space during apply
>>   gdb/tui: allow cmd window to change size in tui_layout_split::apply
>>   gdb/tui: support placing the cmd window into a horizontal layout
>>   gdb/testsuite: some additional tests in gdb.tui/scroll.exp
>>   gdb/tui: relax restrictions on window max height and width
>>   gdb/tui: fair split of delta after a resize
>>
>>  gdb/NEWS                             |  25 ++
>>  gdb/doc/gdb.texinfo                  |  51 +++-
>>  gdb/testsuite/gdb.tui/basic.exp      |   4 +-
>>  gdb/testsuite/gdb.tui/empty.exp      |  14 +-
>>  gdb/testsuite/gdb.tui/new-layout.exp | 100 +++++--
>>  gdb/testsuite/gdb.tui/regs.exp       |   4 +-
>>  gdb/testsuite/gdb.tui/scroll.exp     |   4 +
>>  gdb/testsuite/gdb.tui/winheight.exp  |  77 +++++
>>  gdb/testsuite/gdb.tui/winwidth.exp   |  63 +++++
>>  gdb/testsuite/lib/tuiterm.exp        |  82 +++++-
>>  gdb/tui/tui-command.c                |   6 -
>>  gdb/tui/tui-command.h                |   2 -
>>  gdb/tui/tui-layout.c                 | 406 ++++++++++++++++++++++-----
>>  gdb/tui/tui-layout.h                 | 135 +++++++--
>>  gdb/tui/tui-win.c                    | 118 ++++++--
>>  gdb/tui/tui.c                        |  26 ++
>>  gdb/tui/tui.h                        |  14 +
>>  17 files changed, 971 insertions(+), 160 deletions(-)
>>  create mode 100644 gdb/testsuite/gdb.tui/winwidth.exp
>>
>> -- 
>> 2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCHv3 00/15] TUI changes, new winwidth command and resizing changes
  2022-03-30  9:13       ` Andrew Burgess
@ 2022-04-03 14:43         ` Andrew Burgess
  0 siblings, 0 replies; 74+ messages in thread
From: Andrew Burgess @ 2022-04-03 14:43 UTC (permalink / raw)
  To: gdb-patches

Andrew Burgess <aburgess@redhat.com> writes:

> I'm planning to push this series soon(ish) unless someone complains.

I've now pushed this series.

Thanks,
Andrew


>
> The only series comments on v2 were for patch #5, which I believe are
> now addressed.
>
> As always, if there's any feedback post-commit, I'm happy to address
> issues as they are raised.
>
> Thanks,
> Andrew
>
>
> Andrew Burgess <aburgess@redhat.com> writes:
>
>> Ping!
>>
>> Thanks,
>> Andrew
>>
>>
>> Andrew Burgess <aburgess@redhat.com> writes:
>>
>>> Since v2:
>>>
>>>   - Rebased onto current upstream/master,
>>>
>>>   - Patch #5 - Rewritten to not use templates!
>>>
>>>   - Patch #6 - Added a bug in bugzilla, and referenced this from the
>>>     commit message,
>>>
>>>   - Patch #7 - Renamed the existing methods rather than adding 2 new
>>>     methods,
>>>
>>>   - Patch #10 - Updated the comment Tom identified as being out of
>>>     date,
>>>
>>>   - Patch #15 - Have updated a comment that I spotted was out of date.
>>>
>>> Thanks,
>>> Andrew
>>>
>>>
>>> ---
>>>
>>> Andrew Burgess (15):
>>>   gdb: move some commands into the tui namespace
>>>   gdb/tui: rename tui_layout_base::adjust_size to ::set_height
>>>   gdb/tui: rename tui_layout_split:set_weights_from_heights
>>>   gdb/testing/tui: add new functionality to tuiterm.exp
>>>   gdb/tui: add new 'tui window width' command and 'winwidth' alias
>>>   gdb/tui: add a tui debugging flag
>>>   gdb/tui: add left_boxed_p and right_boxed_p member functions
>>>   gdb/tui/testsuite: refactor new-layout.exp test
>>>   gdb/tui: avoid fp exception when applying layouts
>>>   gdb/tui: fairer distribution of excess space during apply
>>>   gdb/tui: allow cmd window to change size in tui_layout_split::apply
>>>   gdb/tui: support placing the cmd window into a horizontal layout
>>>   gdb/testsuite: some additional tests in gdb.tui/scroll.exp
>>>   gdb/tui: relax restrictions on window max height and width
>>>   gdb/tui: fair split of delta after a resize
>>>
>>>  gdb/NEWS                             |  25 ++
>>>  gdb/doc/gdb.texinfo                  |  51 +++-
>>>  gdb/testsuite/gdb.tui/basic.exp      |   4 +-
>>>  gdb/testsuite/gdb.tui/empty.exp      |  14 +-
>>>  gdb/testsuite/gdb.tui/new-layout.exp | 100 +++++--
>>>  gdb/testsuite/gdb.tui/regs.exp       |   4 +-
>>>  gdb/testsuite/gdb.tui/scroll.exp     |   4 +
>>>  gdb/testsuite/gdb.tui/winheight.exp  |  77 +++++
>>>  gdb/testsuite/gdb.tui/winwidth.exp   |  63 +++++
>>>  gdb/testsuite/lib/tuiterm.exp        |  82 +++++-
>>>  gdb/tui/tui-command.c                |   6 -
>>>  gdb/tui/tui-command.h                |   2 -
>>>  gdb/tui/tui-layout.c                 | 406 ++++++++++++++++++++++-----
>>>  gdb/tui/tui-layout.h                 | 135 +++++++--
>>>  gdb/tui/tui-win.c                    | 118 ++++++--
>>>  gdb/tui/tui.c                        |  26 ++
>>>  gdb/tui/tui.h                        |  14 +
>>>  17 files changed, 971 insertions(+), 160 deletions(-)
>>>  create mode 100644 gdb/testsuite/gdb.tui/winwidth.exp
>>>
>>> -- 
>>> 2.25.4


^ permalink raw reply	[flat|nested] 74+ messages in thread

end of thread, other threads:[~2022-04-03 14:43 UTC | newest]

Thread overview: 74+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-28 15:55 [PATCH 0/7] TUI command changes, including new winwidth command Andrew Burgess
2022-01-28 15:55 ` [PATCH 1/7] gdb/tui: add window width information to 'info win' output Andrew Burgess
2022-01-28 17:00   ` Eli Zaretskii
2022-02-06 13:43   ` Andrew Burgess
2022-01-28 15:55 ` [PATCH 2/7] gdb/doc: update docs for 'info win' and 'winheight' commands Andrew Burgess
2022-01-28 17:03   ` Eli Zaretskii
2022-02-06 13:43     ` Andrew Burgess
2022-01-28 15:55 ` [PATCH 3/7] gdb: move some commands into the tui namespace Andrew Burgess
2022-01-28 17:04   ` Eli Zaretskii
2022-01-28 15:55 ` [PATCH 4/7] gdb/tui: rename tui_layout_base::adjust_size to ::set_height Andrew Burgess
2022-01-28 15:55 ` [PATCH 5/7] gdb/tui: rename tui_layout_split:set_weights_from_heights Andrew Burgess
2022-01-28 15:55 ` [PATCH 6/7] gdb/testing/tui: add new functionality to tuiterm.exp Andrew Burgess
2022-01-28 15:55 ` [PATCH 7/7] gdb/tui: add new 'tui window width' command and 'winwidth' alias Andrew Burgess
2022-01-28 17:05   ` Eli Zaretskii
2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess
2022-02-06 14:12   ` [PATCHv2 01/15] gdb: move some commands into the tui namespace Andrew Burgess
2022-02-06 15:50     ` Eli Zaretskii
2022-02-06 14:12   ` [PATCHv2 02/15] gdb/tui: rename tui_layout_base::adjust_size to ::set_height Andrew Burgess
2022-02-06 14:12   ` [PATCHv2 03/15] gdb/tui: rename tui_layout_split:set_weights_from_heights Andrew Burgess
2022-02-06 14:12   ` [PATCHv2 04/15] gdb/testing/tui: add new functionality to tuiterm.exp Andrew Burgess
2022-03-04 16:29     ` Tom Tromey
2022-02-06 14:12   ` [PATCHv2 05/15] gdb/tui: add new 'tui window width' command and 'winwidth' alias Andrew Burgess
2022-02-06 15:52     ` Eli Zaretskii
2022-02-09 15:33       ` Andrew Burgess
2022-02-09 17:03         ` Eli Zaretskii
2022-03-03 18:52     ` Pedro Alves
2022-02-06 14:12   ` [PATCHv2 06/15] gdb/tui: add a tui debugging flag Andrew Burgess
2022-02-06 15:53     ` Eli Zaretskii
2022-03-04 16:35     ` Tom Tromey
2022-02-06 14:12   ` [PATCHv2 07/15] gdb/tui: add left_boxed_p and right_boxed_p member functions Andrew Burgess
2022-03-04 16:37     ` Tom Tromey
2022-02-06 14:12   ` [PATCHv2 08/15] gdb/tui/testsuite: refactor new-layout.exp test Andrew Burgess
2022-02-06 14:12   ` [PATCHv2 09/15] gdb/tui: avoid fp exception when applying layouts Andrew Burgess
2022-02-06 14:12   ` [PATCHv2 10/15] gdb/tui: fairer distribution of excess space during apply Andrew Burgess
2022-03-04 16:42     ` Tom Tromey
2022-02-06 14:12   ` [PATCHv2 11/15] gdb/tui: allow cmd window to change size in tui_layout_split::apply Andrew Burgess
2022-02-06 14:12   ` [PATCHv2 12/15] gdb/tui: support placing the cmd window into a horizontal layout Andrew Burgess
2022-03-04 17:17     ` Tom Tromey
2022-03-07 20:05       ` Andrew Burgess
2022-03-07 21:24         ` Tom Tromey
2022-02-06 14:12   ` [PATCHv2 13/15] gdb/testsuite: some additional tests in gdb.tui/scroll.exp Andrew Burgess
2022-02-06 14:12   ` [PATCHv2 14/15] gdb/tui: relax restrictions on window max height and width Andrew Burgess
2022-03-04 17:20     ` Tom Tromey
2022-03-07 20:08       ` Andrew Burgess
2022-02-06 14:12   ` [PATCHv2 15/15] gdb/tui: fair split of delta after a resize Andrew Burgess
2022-03-04 17:22     ` Tom Tromey
2022-03-07 22:07       ` Andrew Burgess
2022-03-07 23:42         ` Tom Tromey
2022-02-21 17:29   ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess
2022-03-02 17:59     ` Andrew Burgess
2022-03-07 22:13   ` [PATCHv3 " Andrew Burgess
2022-03-07 22:13     ` [PATCHv3 01/15] gdb: move some commands into the tui namespace Andrew Burgess
2022-03-07 22:13     ` [PATCHv3 02/15] gdb/tui: rename tui_layout_base::adjust_size to ::set_height Andrew Burgess
2022-03-07 22:13     ` [PATCHv3 03/15] gdb/tui: rename tui_layout_split:set_weights_from_heights Andrew Burgess
2022-03-07 22:13     ` [PATCHv3 04/15] gdb/testing/tui: add new functionality to tuiterm.exp Andrew Burgess
2022-03-07 22:13     ` [PATCHv3 05/15] gdb/tui: add new 'tui window width' command and 'winwidth' alias Andrew Burgess
2022-03-07 22:13     ` [PATCHv3 06/15] gdb/tui: add a tui debugging flag Andrew Burgess
2022-03-08 12:16       ` Eli Zaretskii
2022-03-09 11:48         ` Andrew Burgess
2022-03-09 12:58           ` Eli Zaretskii
2022-03-09 17:53           ` Tom Tromey
2022-03-07 22:13     ` [PATCHv3 07/15] gdb/tui: add left_boxed_p and right_boxed_p member functions Andrew Burgess
2022-03-07 22:13     ` [PATCHv3 08/15] gdb/tui/testsuite: refactor new-layout.exp test Andrew Burgess
2022-03-07 22:13     ` [PATCHv3 09/15] gdb/tui: avoid fp exception when applying layouts Andrew Burgess
2022-03-07 22:13     ` [PATCHv3 10/15] gdb/tui: fairer distribution of excess space during apply Andrew Burgess
2022-03-07 22:13     ` [PATCHv3 11/15] gdb/tui: allow cmd window to change size in tui_layout_split::apply Andrew Burgess
2022-03-07 22:13     ` [PATCHv3 12/15] gdb/tui: support placing the cmd window into a horizontal layout Andrew Burgess
2022-03-07 22:13     ` [PATCHv3 13/15] gdb/testsuite: some additional tests in gdb.tui/scroll.exp Andrew Burgess
2022-03-07 22:13     ` [PATCHv3 14/15] gdb/tui: relax restrictions on window max height and width Andrew Burgess
2022-03-07 22:13     ` [PATCHv3 15/15] gdb/tui: fair split of delta after a resize Andrew Burgess
2022-03-21 17:52     ` [PATCHv3 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess
2022-03-30  9:13       ` Andrew Burgess
2022-04-03 14:43         ` Andrew Burgess
2022-03-04 17:23 ` [PATCH 0/7] TUI command changes, including new winwidth command Tom Tromey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).