GNU Binutils with patches for OS216
Revision | 7c043ba695a3cee067554b1e871e60f7934512b4 (tree) |
---|---|
Time | 2020-02-23 03:48:33 |
Author | Tom Tromey <tom@trom...> |
Commiter | Tom Tromey |
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
@@ -1,5 +1,27 @@ | ||
1 | 1 | 2020-02-22 Tom Tromey <tom@tromey.com> |
2 | 2 | |
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 | + | |
3 | 25 | * tui/tui-layout.h (enum tui_adjust_result): New. |
4 | 26 | (class tui_layout_base) <adjust_size>: Return tui_adjust_result. |
5 | 27 | (class tui_layout_window) <adjust_size>: Return |
@@ -17,6 +17,8 @@ | ||
17 | 17 | * The $_siginfo convenience variable now also works on Windows targets, |
18 | 18 | and will display the EXCEPTION_RECORD of the last handled exception. |
19 | 19 | |
20 | +* TUI windows can now be arranged horizontally. | |
21 | + | |
20 | 22 | * New commands |
21 | 23 | |
22 | 24 | set exec-file-mismatch -- Set exec-file-mismatch handling (ask|warn|off). |
@@ -1,5 +1,10 @@ | ||
1 | 1 | 2020-02-22 Tom Tromey <tom@tromey.com> |
2 | 2 | |
3 | + PR tui/17850: | |
4 | + * gdb.texinfo (TUI Commands): Document horizontal layouts. | |
5 | + | |
6 | +2020-02-22 Tom Tromey <tom@tromey.com> | |
7 | + | |
3 | 8 | * gdb.texinfo (TUI Overview): Mention user layouts. |
4 | 9 | (TUI Commands): Document "tui new-layout". |
5 | 10 |
@@ -27998,11 +27998,23 @@ List and give the size of all displayed windows. | ||
27998 | 27998 | Create a new TUI layout. The new layout will be named @var{name}, and |
27999 | 27999 | can be accessed using the @code{layout} command (see below). |
28000 | 28000 | |
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 | |
28004 | 28006 | @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. | |
28006 | 28018 | |
28007 | 28019 | Each @var{weight} is an integer. It is the weight of this window |
28008 | 28020 | 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 | ||
28019 | 28031 | the command window. The non-status windows all have the same weight, |
28020 | 28032 | so the terminal will be split into three roughly equal sections. |
28021 | 28033 | |
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 | + | |
28022 | 28045 | @item layout @var{name} |
28023 | 28046 | @kindex layout |
28024 | 28047 | Changes which TUI windows are displayed. The @var{name} parameter |
@@ -1,5 +1,11 @@ | ||
1 | 1 | 2020-02-22 Tom Tromey <tom@tromey.com> |
2 | 2 | |
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 | + | |
3 | 9 | * gdb.tui/new-layout.exp: Add sub-layout tests. |
4 | 10 | |
5 | 11 | 2020-02-22 Tom Tromey <tom@tromey.com> |
@@ -52,6 +52,11 @@ gdb_test_no_output "tui new-layout example2 {asm 1 status 0} 1 cmd 1" | ||
52 | 52 | gdb_test "help layout example2" \ |
53 | 53 | "Apply the \"example2\" layout.*tui new-layout example2 {asm 1 status 0} 1 cmd 1" |
54 | 54 | |
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 | + | |
55 | 60 | if {![Term::enter_tui]} { |
56 | 61 | unsupported "TUI not supported" |
57 | 62 | } |
@@ -62,4 +67,18 @@ gdb_assert {![string match "No Source Available" $text]} \ | ||
62 | 67 | |
63 | 68 | Term::command "layout example" |
64 | 69 | 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 |
@@ -82,6 +82,15 @@ public: | ||
82 | 82 | /* Compute the minimum height of this window. */ |
83 | 83 | virtual int min_height () const = 0; |
84 | 84 | |
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 | + | |
85 | 94 | /* Return true if this window can be boxed. */ |
86 | 95 | virtual bool can_box () const |
87 | 96 | { |
@@ -355,12 +355,20 @@ tui_layout_window::apply (int x_, int y_, int width_, int height_) | ||
355 | 355 | /* See tui-layout.h. */ |
356 | 356 | |
357 | 357 | 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) | |
359 | 359 | { |
360 | 360 | if (m_window == nullptr) |
361 | 361 | 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 | + } | |
364 | 372 | } |
365 | 373 | |
366 | 374 | /* See tui-layout.h. */ |
@@ -430,7 +438,7 @@ tui_layout_split::add_window (const char *name, int weight) | ||
430 | 438 | std::unique_ptr<tui_layout_base> |
431 | 439 | tui_layout_split::clone () const |
432 | 440 | { |
433 | - tui_layout_split *result = new tui_layout_split (); | |
441 | + tui_layout_split *result = new tui_layout_split (m_vertical); | |
434 | 442 | for (const split &item : m_splits) |
435 | 443 | { |
436 | 444 | std::unique_ptr<tui_layout_base> next = item.layout->clone (); |
@@ -443,16 +451,29 @@ tui_layout_split::clone () const | ||
443 | 451 | /* See tui-layout.h. */ |
444 | 452 | |
445 | 453 | 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) | |
447 | 455 | { |
448 | - *min_height = 0; | |
449 | - *max_height = 0; | |
456 | + *min_value = 0; | |
457 | + *max_value = 0; | |
458 | + bool first_time = true; | |
450 | 459 | for (const split &item : m_splits) |
451 | 460 | { |
452 | 461 | 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; | |
456 | 477 | } |
457 | 478 | } |
458 | 479 |
@@ -502,6 +523,8 @@ tui_layout_split::adjust_size (const char *name, int new_height) | ||
502 | 523 | return HANDLED; |
503 | 524 | if (adjusted == FOUND) |
504 | 525 | { |
526 | + if (!m_vertical) | |
527 | + return FOUND; | |
505 | 528 | found_index = i; |
506 | 529 | break; |
507 | 530 | } |
@@ -524,7 +547,7 @@ tui_layout_split::adjust_size (const char *name, int new_height) | ||
524 | 547 | int index = (found_index + 1 + i) % m_splits.size (); |
525 | 548 | |
526 | 549 | 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); | |
528 | 551 | |
529 | 552 | if (delta < 0) |
530 | 553 | { |
@@ -571,23 +594,23 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_) | ||
571 | 594 | width = width_; |
572 | 595 | height = height_; |
573 | 596 | |
574 | - struct height_info | |
597 | + struct size_info | |
575 | 598 | { |
576 | - int height; | |
577 | - int min_height; | |
578 | - int max_height; | |
599 | + int size; | |
600 | + int min_size; | |
601 | + int max_size; | |
579 | 602 | /* True if this window will share a box border with the previous |
580 | 603 | window in the list. */ |
581 | 604 | bool share_box; |
582 | 605 | }; |
583 | 606 | |
584 | - std::vector<height_info> info (m_splits.size ()); | |
607 | + std::vector<size_info> info (m_splits.size ()); | |
585 | 608 | |
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 | |
588 | 611 | remaining space is distributed among the remaining windows |
589 | 612 | according to the weights given. */ |
590 | - int available_height = height; | |
613 | + int available_size = m_vertical ? height : width; | |
591 | 614 | int last_index = -1; |
592 | 615 | int total_weight = 0; |
593 | 616 | 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_) | ||
597 | 620 | /* Always call get_sizes, to ensure that the window is |
598 | 621 | instantiated. This is a bit gross but less gross than adding |
599 | 622 | 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); | |
601 | 625 | |
602 | 626 | if (!m_applied |
603 | 627 | && cmd_win_already_exists |
@@ -607,15 +631,17 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_) | ||
607 | 631 | /* If this layout has never been applied, then it means the |
608 | 632 | user just changed the layout. In this situation, it's |
609 | 633 | 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 | |
611 | 635 | that the resizing step, below, does the right thing with |
612 | 636 | 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; | |
615 | 641 | } |
616 | 642 | |
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; | |
619 | 645 | else |
620 | 646 | { |
621 | 647 | last_index = i; |
@@ -623,54 +649,58 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_) | ||
623 | 649 | } |
624 | 650 | |
625 | 651 | /* Two adjacent boxed windows will share a border, making a bit |
626 | - more height available. */ | |
652 | + more size available. */ | |
627 | 653 | if (i > 0 |
628 | 654 | && m_splits[i - 1].layout->bottom_boxed_p () |
629 | 655 | && m_splits[i].layout->top_boxed_p ()) |
630 | 656 | info[i].share_box = true; |
631 | 657 | } |
632 | 658 | |
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 | |
634 | 660 | are given their fixed size, while others are resized according to |
635 | 661 | their weight. */ |
636 | - int used_height = 0; | |
662 | + int used_size = 0; | |
637 | 663 | for (int i = 0; i < m_splits.size (); ++i) |
638 | 664 | { |
639 | 665 | /* 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 | |
646 | 672 | 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 | |
649 | 675 | last window. */ |
650 | - if (info[i].min_height != info[i].max_height) | |
676 | + if (info[i].min_size != info[i].max_size) | |
651 | 677 | { |
652 | - used_height += info[i].height; | |
678 | + used_size += info[i].size; | |
653 | 679 | if (info[i].share_box) |
654 | - --used_height; | |
680 | + --used_size; | |
655 | 681 | } |
656 | 682 | } |
657 | 683 | |
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; | |
661 | 687 | |
662 | 688 | /* Step 3: Resize. */ |
663 | - int height_accum = 0; | |
689 | + int size_accum = 0; | |
690 | + const int maximum = m_vertical ? height : width; | |
664 | 691 | for (int i = 0; i < m_splits.size (); ++i) |
665 | 692 | { |
666 | 693 | /* If we fall off the bottom, just make allocations overlap. |
667 | 694 | 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; | |
670 | 697 | 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; | |
674 | 704 | } |
675 | 705 | |
676 | 706 | m_applied = true; |
@@ -716,6 +746,9 @@ tui_layout_split::specification (ui_file *output, int depth) | ||
716 | 746 | if (depth > 0) |
717 | 747 | fputs_unfiltered ("{", output); |
718 | 748 | |
749 | + if (!m_vertical) | |
750 | + fputs_unfiltered ("-horizontal ", output); | |
751 | + | |
719 | 752 | bool first = true; |
720 | 753 | for (auto &item : m_splits) |
721 | 754 | { |
@@ -839,8 +872,13 @@ tui_new_layout_command (const char *spec, int from_tty) | ||
839 | 872 | if (new_name[0] == '-') |
840 | 873 | error (_("Layout name cannot start with '-'")); |
841 | 874 | |
875 | + bool is_vertical = true; | |
876 | + spec = skip_spaces (spec); | |
877 | + if (check_for_argument (&spec, "-horizontal")) | |
878 | + is_vertical = false; | |
879 | + | |
842 | 880 | 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)); | |
844 | 882 | std::unordered_set<std::string> seen_windows; |
845 | 883 | while (true) |
846 | 884 | { |
@@ -850,8 +888,11 @@ tui_new_layout_command (const char *spec, int from_tty) | ||
850 | 888 | |
851 | 889 | if (spec[0] == '{') |
852 | 890 | { |
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)); | |
855 | 896 | continue; |
856 | 897 | } |
857 | 898 |
@@ -940,12 +981,12 @@ Usage: layout prev | next | LAYOUT-NAME"), | ||
940 | 981 | |
941 | 982 | add_cmd ("new-layout", class_tui, tui_new_layout_command, |
942 | 983 | _("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\ | |
944 | 985 | Create a new TUI layout. The new layout will be named NAME,\n\ |
945 | 986 | and can be accessed using \"layout NAME\".\n\ |
946 | 987 | The windows will be displayed in the specified order.\n\ |
947 | 988 | A WINDOW can also be of the form:\n\ |
948 | - { NAME WEIGHT [NAME WEIGHT]... }\n\ | |
989 | + { [-horizontal] NAME WEIGHT [NAME WEIGHT]... }\n\ | |
949 | 990 | This form indicates a sub-frame.\n\ |
950 | 991 | Each WEIGHT is an integer, which holds the relative size\n\ |
951 | 992 | to be allocated to the window."), |
@@ -58,8 +58,9 @@ public: | ||
58 | 58 | /* Change the size and location of this layout. */ |
59 | 59 | virtual void apply (int x, int y, int width, int height) = 0; |
60 | 60 | |
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; | |
63 | 64 | |
64 | 65 | /* True if the topmost item in this layout is boxed. */ |
65 | 66 | virtual bool top_boxed_p () const = 0; |
@@ -142,7 +143,7 @@ public: | ||
142 | 143 | |
143 | 144 | protected: |
144 | 145 | |
145 | - void get_sizes (int *min_height, int *max_height) override; | |
146 | + void get_sizes (bool height, int *min_value, int *max_value) override; | |
146 | 147 | |
147 | 148 | private: |
148 | 149 |
@@ -159,7 +160,12 @@ class tui_layout_split : public tui_layout_base | ||
159 | 160 | { |
160 | 161 | public: |
161 | 162 | |
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 | + } | |
163 | 169 | |
164 | 170 | DISABLE_COPY_AND_ASSIGN (tui_layout_split); |
165 | 171 |
@@ -191,7 +197,7 @@ public: | ||
191 | 197 | |
192 | 198 | protected: |
193 | 199 | |
194 | - void get_sizes (int *min_height, int *max_height) override; | |
200 | + void get_sizes (bool height, int *min_value, int *max_value) override; | |
195 | 201 | |
196 | 202 | private: |
197 | 203 |
@@ -209,6 +215,9 @@ private: | ||
209 | 215 | /* The splits. */ |
210 | 216 | std::vector<split> m_splits; |
211 | 217 | |
218 | + /* True if the windows in this split are arranged vertically. */ | |
219 | + bool m_vertical; | |
220 | + | |
212 | 221 | /* True if this layout has already been applied at least once. */ |
213 | 222 | bool m_applied = false; |
214 | 223 | }; |
@@ -952,6 +952,14 @@ tui_win_info::max_height () const | ||
952 | 952 | return tui_term_height () - 2; |
953 | 953 | } |
954 | 954 | |
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 | + | |
955 | 963 | static void |
956 | 964 | parse_scrolling_args (const char *arg, |
957 | 965 | struct tui_win_info **win_to_scroll, |