• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

GNU Binutils with patches for OS216


Commit MetaInfo

Revision7c043ba695a3cee067554b1e871e60f7934512b4 (tree)
Time2020-02-23 03:48:33
AuthorTom Tromey <tom@trom...>
CommiterTom Tromey

Log Message

Add horizontal splitting to TUI layout

This changes the TUI layout engine to add horizontal splitting. Now,
windows can be side-by-side.

A horizontal split is defined using the "-horizontal" parameter to
"tui new-layout".

This also adds the first "winheight" test to the test suite. One open
question is whether we want a new "winwidth" command, now that
horizontal layouts are possible. This is easily done using the
generic layout code.

gdb/ChangeLog
2020-02-22 Tom Tromey <tom@tromey.com>

PR tui/17850:
* tui/tui-win.c (tui_gen_win_info::max_width): New method.
* tui/tui-layout.h (class tui_layout_base) <get_sizes>: Add
"height" argument.
(class tui_layout_window) <get_sizes>: Likewise.
(class tui_layout_split) <tui_layout_split>: Add "vertical"
argument.
<get_sizes>: Add "height" argument.
<m_vertical>: New field.
* tui/tui-layout.c (tui_layout_split::clone): Update.
(tui_layout_split::get_sizes): Add "height" argument.
(tui_layout_split::adjust_size, tui_layout_split::apply): Update.
(tui_new_layout_command): Parse "-horizontal".
(_initialize_tui_layout): Update help string.
(tui_layout_split::specification): Add "-horizontal" when needed.
* tui/tui-layout.c (tui_layout_window::get_sizes): Add "height"
argument.
* tui/tui-data.h (struct tui_gen_win_info) <max_width, min_width>:
New methods.

gdb/doc/ChangeLog
2020-02-22 Tom Tromey <tom@tromey.com>

PR tui/17850:
* gdb.texinfo (TUI Commands): Document horizontal layouts.

gdb/testsuite/ChangeLog
2020-02-22 Tom Tromey <tom@tromey.com>

PR tui/17850:
* gdb.tui/new-layout.exp: Add horizontal layout and winheight
tests.

Change-Id: I38b35e504f34698578af86686be03c0fefd954ae

Change Summary

Incremental Difference

--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,27 @@
11 2020-02-22 Tom Tromey <tom@tromey.com>
22
3+ PR tui/17850:
4+ * tui/tui-win.c (tui_gen_win_info::max_width): New method.
5+ * tui/tui-layout.h (class tui_layout_base) <get_sizes>: Add
6+ "height" argument.
7+ (class tui_layout_window) <get_sizes>: Likewise.
8+ (class tui_layout_split) <tui_layout_split>: Add "vertical"
9+ argument.
10+ <get_sizes>: Add "height" argument.
11+ <m_vertical>: New field.
12+ * tui/tui-layout.c (tui_layout_split::clone): Update.
13+ (tui_layout_split::get_sizes): Add "height" argument.
14+ (tui_layout_split::adjust_size, tui_layout_split::apply): Update.
15+ (tui_new_layout_command): Parse "-horizontal".
16+ (_initialize_tui_layout): Update help string.
17+ (tui_layout_split::specification): Add "-horizontal" when needed.
18+ * tui/tui-layout.c (tui_layout_window::get_sizes): Add "height"
19+ argument.
20+ * tui/tui-data.h (struct tui_gen_win_info) <max_width, min_width>:
21+ New methods.
22+
23+2020-02-22 Tom Tromey <tom@tromey.com>
24+
325 * tui/tui-layout.h (enum tui_adjust_result): New.
426 (class tui_layout_base) <adjust_size>: Return tui_adjust_result.
527 (class tui_layout_window) <adjust_size>: Return
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -17,6 +17,8 @@
1717 * The $_siginfo convenience variable now also works on Windows targets,
1818 and will display the EXCEPTION_RECORD of the last handled exception.
1919
20+* TUI windows can now be arranged horizontally.
21+
2022 * New commands
2123
2224 set exec-file-mismatch -- Set exec-file-mismatch handling (ask|warn|off).
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,5 +1,10 @@
11 2020-02-22 Tom Tromey <tom@tromey.com>
22
3+ PR tui/17850:
4+ * gdb.texinfo (TUI Commands): Document horizontal layouts.
5+
6+2020-02-22 Tom Tromey <tom@tromey.com>
7+
38 * gdb.texinfo (TUI Overview): Mention user layouts.
49 (TUI Commands): Document "tui new-layout".
510
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -27998,11 +27998,23 @@ List and give the size of all displayed windows.
2799827998 Create a new TUI layout. The new layout will be named @var{name}, and
2799927999 can be accessed using the @code{layout} command (see below).
2800028000
28001-Each @var{window} parameter is the name of a window to display. The
28002-windows will be displayed from top to bottom in the order listed. The
28003-names of the windows are the same as the ones given to the
28001+Each @var{window} parameter is either the name of a window to display,
28002+or a window description. The windows will be displayed from top to
28003+bottom in the order listed.
28004+
28005+The names of the windows are the same as the ones given to the
2800428006 @code{focus} command (see below); additional, the @code{status}
28005-window can be specified.
28007+window can be specified. Note that, because it is of fixed height,
28008+the weight assigned to the status window is of no importance. It is
28009+conventional to use @samp{0} here.
28010+
28011+A window description looks a bit like an invocation of @code{tui
28012+new-layout}, and is of the form
28013+@{@r{[}@code{-horizontal}@r{]}@var{window} @var{weight} @r{[}@var{window} @var{weight}@dots{}@r{]}@}.
28014+
28015+This specifies a sub-layout. If @code{-horizontal} is given, the
28016+windows in this description will be arranged side-by-side, rather than
28017+top-to-bottom.
2800628018
2800728019 Each @var{weight} is an integer. It is the weight of this window
2800828020 relative to all the other windows in the layout. These numbers are
@@ -28019,6 +28031,17 @@ and register windows, followed by the status window, and then finally
2801928031 the command window. The non-status windows all have the same weight,
2802028032 so the terminal will be split into three roughly equal sections.
2802128033
28034+Here is a more complex example, showing a horizontal layout:
28035+
28036+@example
28037+(gdb) tui new-layout example @{-horizontal src 1 asm 1@} 2 status 0 cmd 1
28038+@end example
28039+
28040+This will result in side-by-side source and assembly windows; with the
28041+status and command window being beneath these, filling the entire
28042+width of the terminal. Because they have weight 2, the source and
28043+assembly windows will be twice the height of the command window.
28044+
2802228045 @item layout @var{name}
2802328046 @kindex layout
2802428047 Changes which TUI windows are displayed. The @var{name} parameter
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,11 @@
11 2020-02-22 Tom Tromey <tom@tromey.com>
22
3+ PR tui/17850:
4+ * gdb.tui/new-layout.exp: Add horizontal layout and winheight
5+ tests.
6+
7+2020-02-22 Tom Tromey <tom@tromey.com>
8+
39 * gdb.tui/new-layout.exp: Add sub-layout tests.
410
511 2020-02-22 Tom Tromey <tom@tromey.com>
--- a/gdb/testsuite/gdb.tui/new-layout.exp
+++ b/gdb/testsuite/gdb.tui/new-layout.exp
@@ -52,6 +52,11 @@ gdb_test_no_output "tui new-layout example2 {asm 1 status 0} 1 cmd 1"
5252 gdb_test "help layout example2" \
5353 "Apply the \"example2\" layout.*tui new-layout example2 {asm 1 status 0} 1 cmd 1"
5454
55+gdb_test_no_output "tui new-layout h {-horizontal asm 1 src 1} 1 status 0 cmd 1"
56+
57+gdb_test "help layout h" \
58+ "Apply the \"h\" layout.*tui new-layout h {-horizontal asm 1 src 1} 1 status 0 cmd 1"
59+
5560 if {![Term::enter_tui]} {
5661 unsupported "TUI not supported"
5762 }
@@ -62,4 +67,18 @@ gdb_assert {![string match "No Source Available" $text]} \
6267
6368 Term::command "layout example"
6469 Term::check_contents "example layout shows assembly" \
65- "No Assembly Available"
70+ "$hex <main>"
71+
72+Term::command "layout h"
73+Term::check_box "left window box" 0 0 40 15
74+Term::check_box "right window box" 39 0 41 15
75+Term::check_contents "horizontal display" \
76+ "$hex <main>.*21.*return 0"
77+
78+Term::command "winheight src - 5"
79+Term::check_box "left window box after shrink" 0 0 40 10
80+Term::check_box "right window box after shrink" 39 0 41 10
81+
82+Term::command "winheight src + 5"
83+Term::check_box "left window box after grow" 0 0 40 15
84+Term::check_box "right window box after grow" 39 0 41 15
--- a/gdb/tui/tui-data.h
+++ b/gdb/tui/tui-data.h
@@ -82,6 +82,15 @@ public:
8282 /* Compute the minimum height of this window. */
8383 virtual int min_height () const = 0;
8484
85+ /* Compute the maximum width of this window. */
86+ int max_width () const;
87+
88+ /* Compute the minimum width of this window. */
89+ int min_width () const
90+ {
91+ return 3;
92+ }
93+
8594 /* Return true if this window can be boxed. */
8695 virtual bool can_box () const
8796 {
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -355,12 +355,20 @@ tui_layout_window::apply (int x_, int y_, int width_, int height_)
355355 /* See tui-layout.h. */
356356
357357 void
358-tui_layout_window::get_sizes (int *min_height, int *max_height)
358+tui_layout_window::get_sizes (bool height, int *min_value, int *max_value)
359359 {
360360 if (m_window == nullptr)
361361 m_window = tui_get_window_by_name (m_contents);
362- *min_height = m_window->min_height ();
363- *max_height = m_window->max_height ();
362+ if (height)
363+ {
364+ *min_value = m_window->min_height ();
365+ *max_value = m_window->max_height ();
366+ }
367+ else
368+ {
369+ *min_value = m_window->min_width ();
370+ *max_value = m_window->max_width ();
371+ }
364372 }
365373
366374 /* See tui-layout.h. */
@@ -430,7 +438,7 @@ tui_layout_split::add_window (const char *name, int weight)
430438 std::unique_ptr<tui_layout_base>
431439 tui_layout_split::clone () const
432440 {
433- tui_layout_split *result = new tui_layout_split ();
441+ tui_layout_split *result = new tui_layout_split (m_vertical);
434442 for (const split &item : m_splits)
435443 {
436444 std::unique_ptr<tui_layout_base> next = item.layout->clone ();
@@ -443,16 +451,29 @@ tui_layout_split::clone () const
443451 /* See tui-layout.h. */
444452
445453 void
446-tui_layout_split::get_sizes (int *min_height, int *max_height)
454+tui_layout_split::get_sizes (bool height, int *min_value, int *max_value)
447455 {
448- *min_height = 0;
449- *max_height = 0;
456+ *min_value = 0;
457+ *max_value = 0;
458+ bool first_time = true;
450459 for (const split &item : m_splits)
451460 {
452461 int new_min, new_max;
453- item.layout->get_sizes (&new_min, &new_max);
454- *min_height += new_min;
455- *max_height += new_max;
462+ item.layout->get_sizes (height, &new_min, &new_max);
463+ /* For the mismatch case, the first time through we want to set
464+ the min and max to the computed values -- the "first_time"
465+ check here is just a funny way of doing that. */
466+ if (height == m_vertical || first_time)
467+ {
468+ *min_value += new_min;
469+ *max_value += new_max;
470+ }
471+ else
472+ {
473+ *min_value = std::max (*min_value, new_min);
474+ *max_value = std::min (*max_value, new_max);
475+ }
476+ first_time = false;
456477 }
457478 }
458479
@@ -502,6 +523,8 @@ tui_layout_split::adjust_size (const char *name, int new_height)
502523 return HANDLED;
503524 if (adjusted == FOUND)
504525 {
526+ if (!m_vertical)
527+ return FOUND;
505528 found_index = i;
506529 break;
507530 }
@@ -524,7 +547,7 @@ tui_layout_split::adjust_size (const char *name, int new_height)
524547 int index = (found_index + 1 + i) % m_splits.size ();
525548
526549 int new_min, new_max;
527- m_splits[index].layout->get_sizes (&new_min, &new_max);
550+ m_splits[index].layout->get_sizes (m_vertical, &new_min, &new_max);
528551
529552 if (delta < 0)
530553 {
@@ -571,23 +594,23 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_)
571594 width = width_;
572595 height = height_;
573596
574- struct height_info
597+ struct size_info
575598 {
576- int height;
577- int min_height;
578- int max_height;
599+ int size;
600+ int min_size;
601+ int max_size;
579602 /* True if this window will share a box border with the previous
580603 window in the list. */
581604 bool share_box;
582605 };
583606
584- std::vector<height_info> info (m_splits.size ());
607+ std::vector<size_info> info (m_splits.size ());
585608
586- /* Step 1: Find the min and max height of each sub-layout.
587- Fixed-sized layouts are given their desired height, and then the
609+ /* Step 1: Find the min and max size of each sub-layout.
610+ Fixed-sized layouts are given their desired size, and then the
588611 remaining space is distributed among the remaining windows
589612 according to the weights given. */
590- int available_height = height;
613+ int available_size = m_vertical ? height : width;
591614 int last_index = -1;
592615 int total_weight = 0;
593616 for (int i = 0; i < m_splits.size (); ++i)
@@ -597,7 +620,8 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_)
597620 /* Always call get_sizes, to ensure that the window is
598621 instantiated. This is a bit gross but less gross than adding
599622 special cases for this in other places. */
600- m_splits[i].layout->get_sizes (&info[i].min_height, &info[i].max_height);
623+ m_splits[i].layout->get_sizes (m_vertical, &info[i].min_size,
624+ &info[i].max_size);
601625
602626 if (!m_applied
603627 && cmd_win_already_exists
@@ -607,15 +631,17 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_)
607631 /* If this layout has never been applied, then it means the
608632 user just changed the layout. In this situation, it's
609633 desirable to keep the size of the command window the
610- same. Setting the min and max heights this way ensures
634+ same. Setting the min and max sizes this way ensures
611635 that the resizing step, below, does the right thing with
612636 this window. */
613- info[i].min_height = TUI_CMD_WIN->height;
614- info[i].max_height = TUI_CMD_WIN->height;
637+ info[i].min_size = (m_vertical
638+ ? TUI_CMD_WIN->height
639+ : TUI_CMD_WIN->width);
640+ info[i].max_size = info[i].min_size;
615641 }
616642
617- if (info[i].min_height == info[i].max_height)
618- available_height -= info[i].min_height;
643+ if (info[i].min_size == info[i].max_size)
644+ available_size -= info[i].min_size;
619645 else
620646 {
621647 last_index = i;
@@ -623,54 +649,58 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_)
623649 }
624650
625651 /* Two adjacent boxed windows will share a border, making a bit
626- more height available. */
652+ more size available. */
627653 if (i > 0
628654 && m_splits[i - 1].layout->bottom_boxed_p ()
629655 && m_splits[i].layout->top_boxed_p ())
630656 info[i].share_box = true;
631657 }
632658
633- /* Step 2: Compute the height of each sub-layout. Fixed-sized items
659+ /* Step 2: Compute the size of each sub-layout. Fixed-sized items
634660 are given their fixed size, while others are resized according to
635661 their weight. */
636- int used_height = 0;
662+ int used_size = 0;
637663 for (int i = 0; i < m_splits.size (); ++i)
638664 {
639665 /* Compute the height and clamp to the allowable range. */
640- info[i].height = available_height * m_splits[i].weight / total_weight;
641- if (info[i].height > info[i].max_height)
642- info[i].height = info[i].max_height;
643- if (info[i].height < info[i].min_height)
644- info[i].height = info[i].min_height;
645- /* If there is any leftover height, just redistribute it to the
666+ info[i].size = available_size * m_splits[i].weight / total_weight;
667+ if (info[i].size > info[i].max_size)
668+ info[i].size = info[i].max_size;
669+ if (info[i].size < info[i].min_size)
670+ info[i].size = info[i].min_size;
671+ /* If there is any leftover size, just redistribute it to the
646672 last resizeable window, by dropping it from the allocated
647- height. We could try to be fancier here perhaps, by
648- redistributing this height among all windows, not just the
673+ size. We could try to be fancier here perhaps, by
674+ redistributing this size among all windows, not just the
649675 last window. */
650- if (info[i].min_height != info[i].max_height)
676+ if (info[i].min_size != info[i].max_size)
651677 {
652- used_height += info[i].height;
678+ used_size += info[i].size;
653679 if (info[i].share_box)
654- --used_height;
680+ --used_size;
655681 }
656682 }
657683
658- /* Allocate any leftover height. */
659- if (available_height >= used_height && last_index != -1)
660- info[last_index].height += available_height - used_height;
684+ /* Allocate any leftover size. */
685+ if (available_size >= used_size && last_index != -1)
686+ info[last_index].size += available_size - used_size;
661687
662688 /* Step 3: Resize. */
663- int height_accum = 0;
689+ int size_accum = 0;
690+ const int maximum = m_vertical ? height : width;
664691 for (int i = 0; i < m_splits.size (); ++i)
665692 {
666693 /* If we fall off the bottom, just make allocations overlap.
667694 GIGO. */
668- if (height_accum + info[i].height > height)
669- height_accum = height - info[i].height;
695+ if (size_accum + info[i].size > maximum)
696+ size_accum = maximum - info[i].size;
670697 else if (info[i].share_box)
671- --height_accum;
672- m_splits[i].layout->apply (x, y + height_accum, width, info[i].height);
673- height_accum += info[i].height;
698+ --size_accum;
699+ if (m_vertical)
700+ m_splits[i].layout->apply (x, y + size_accum, width, info[i].size);
701+ else
702+ m_splits[i].layout->apply (x + size_accum, y, info[i].size, height);
703+ size_accum += info[i].size;
674704 }
675705
676706 m_applied = true;
@@ -716,6 +746,9 @@ tui_layout_split::specification (ui_file *output, int depth)
716746 if (depth > 0)
717747 fputs_unfiltered ("{", output);
718748
749+ if (!m_vertical)
750+ fputs_unfiltered ("-horizontal ", output);
751+
719752 bool first = true;
720753 for (auto &item : m_splits)
721754 {
@@ -839,8 +872,13 @@ tui_new_layout_command (const char *spec, int from_tty)
839872 if (new_name[0] == '-')
840873 error (_("Layout name cannot start with '-'"));
841874
875+ bool is_vertical = true;
876+ spec = skip_spaces (spec);
877+ if (check_for_argument (&spec, "-horizontal"))
878+ is_vertical = false;
879+
842880 std::vector<std::unique_ptr<tui_layout_split>> splits;
843- splits.emplace_back (new tui_layout_split);
881+ splits.emplace_back (new tui_layout_split (is_vertical));
844882 std::unordered_set<std::string> seen_windows;
845883 while (true)
846884 {
@@ -850,8 +888,11 @@ tui_new_layout_command (const char *spec, int from_tty)
850888
851889 if (spec[0] == '{')
852890 {
853- splits.emplace_back (new tui_layout_split);
854- ++spec;
891+ is_vertical = true;
892+ spec = skip_spaces (spec + 1);
893+ if (check_for_argument (&spec, "-horizontal"))
894+ is_vertical = false;
895+ splits.emplace_back (new tui_layout_split (is_vertical));
855896 continue;
856897 }
857898
@@ -940,12 +981,12 @@ Usage: layout prev | next | LAYOUT-NAME"),
940981
941982 add_cmd ("new-layout", class_tui, tui_new_layout_command,
942983 _("Create a new TUI layout.\n\
943-Usage: tui new-layout NAME WINDOW WEIGHT [WINDOW WEIGHT]...\n\
984+Usage: tui new-layout [-horizontal] NAME WINDOW WEIGHT [WINDOW WEIGHT]...\n\
944985 Create a new TUI layout. The new layout will be named NAME,\n\
945986 and can be accessed using \"layout NAME\".\n\
946987 The windows will be displayed in the specified order.\n\
947988 A WINDOW can also be of the form:\n\
948- { NAME WEIGHT [NAME WEIGHT]... }\n\
989+ { [-horizontal] NAME WEIGHT [NAME WEIGHT]... }\n\
949990 This form indicates a sub-frame.\n\
950991 Each WEIGHT is an integer, which holds the relative size\n\
951992 to be allocated to the window."),
--- a/gdb/tui/tui-layout.h
+++ b/gdb/tui/tui-layout.h
@@ -58,8 +58,9 @@ public:
5858 /* Change the size and location of this layout. */
5959 virtual void apply (int x, int y, int width, int height) = 0;
6060
61- /* Return the minimum and maximum height of this layout. */
62- virtual void get_sizes (int *min_height, int *max_height) = 0;
61+ /* Return the minimum and maximum height or width of this layout.
62+ HEIGHT is true to fetch height, false to fetch width. */
63+ virtual void get_sizes (bool height, int *min_value, int *max_value) = 0;
6364
6465 /* True if the topmost item in this layout is boxed. */
6566 virtual bool top_boxed_p () const = 0;
@@ -142,7 +143,7 @@ public:
142143
143144 protected:
144145
145- void get_sizes (int *min_height, int *max_height) override;
146+ void get_sizes (bool height, int *min_value, int *max_value) override;
146147
147148 private:
148149
@@ -159,7 +160,12 @@ class tui_layout_split : public tui_layout_base
159160 {
160161 public:
161162
162- tui_layout_split () = default;
163+ /* Create a new layout. If VERTICAL is true, then windows in this
164+ layout will be arranged vertically. */
165+ explicit tui_layout_split (bool vertical = true)
166+ : m_vertical (vertical)
167+ {
168+ }
163169
164170 DISABLE_COPY_AND_ASSIGN (tui_layout_split);
165171
@@ -191,7 +197,7 @@ public:
191197
192198 protected:
193199
194- void get_sizes (int *min_height, int *max_height) override;
200+ void get_sizes (bool height, int *min_value, int *max_value) override;
195201
196202 private:
197203
@@ -209,6 +215,9 @@ private:
209215 /* The splits. */
210216 std::vector<split> m_splits;
211217
218+ /* True if the windows in this split are arranged vertically. */
219+ bool m_vertical;
220+
212221 /* True if this layout has already been applied at least once. */
213222 bool m_applied = false;
214223 };
--- a/gdb/tui/tui-win.c
+++ b/gdb/tui/tui-win.c
@@ -952,6 +952,14 @@ tui_win_info::max_height () const
952952 return tui_term_height () - 2;
953953 }
954954
955+/* See tui-data.h. */
956+
957+int
958+tui_gen_win_info::max_width () const
959+{
960+ return tui_term_width () - 2;
961+}
962+
955963 static void
956964 parse_scrolling_args (const char *arg,
957965 struct tui_win_info **win_to_scroll,