1 /* TUI window generic functions.
3 Copyright (C) 1998-2019 Free Software Foundation, Inc.
5 Contributed by Hewlett-Packard Company.
7 This file is part of GDB.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
22 /* This module contains procedures for handling tui window functions
23 like resize, scrolling, scrolling, changing focus, etc.
25 Author: Susan B. Macchia */
30 #include "breakpoint.h"
32 #include "cli/cli-cmds.h"
35 #include "event-loop.h"
39 #include "tui/tui-io.h"
40 #include "tui/tui-command.h"
41 #include "tui/tui-data.h"
42 #include "tui/tui-layout.h"
43 #include "tui/tui-wingeneral.h"
44 #include "tui/tui-stack.h"
45 #include "tui/tui-regs.h"
46 #include "tui/tui-disasm.h"
47 #include "tui/tui-source.h"
48 #include "tui/tui-winsource.h"
49 #include "tui/tui-win.h"
51 #include "gdb_curses.h"
53 #include "readline/readline.h"
54 #include "gdbsupport/gdb_string_view.h"
58 static enum tui_status
tui_adjust_win_heights (struct tui_win_info
*,
60 static int new_height_ok (struct tui_win_info
*, int);
61 static void tui_set_tab_width_command (const char *, int);
62 static void tui_refresh_all_command (const char *, int);
63 static void tui_all_windows_info (const char *, int);
64 static void tui_scroll_forward_command (const char *, int);
65 static void tui_scroll_backward_command (const char *, int);
66 static void tui_scroll_left_command (const char *, int);
67 static void tui_scroll_right_command (const char *, int);
68 static void parse_scrolling_args (const char *,
69 struct tui_win_info
**,
73 #define WIN_HEIGHT_USAGE "Usage: winheight WINDOW-NAME [+ | -] NUM-LINES\n"
74 #define FOCUS_USAGE "Usage: focus [WINDOW-NAME | next | prev]\n"
77 # define ACS_LRCORNER '+'
80 # define ACS_LLCORNER '+'
83 # define ACS_ULCORNER '+'
86 # define ACS_URCORNER '+'
89 # define ACS_HLINE '-'
92 # define ACS_VLINE '|'
95 /* Possible values for tui-border-kind variable. */
96 static const char *const tui_border_kind_enums
[] = {
103 /* Possible values for tui-border-mode and tui-active-border-mode. */
104 static const char *const tui_border_mode_enums
[] = {
121 /* Translation table for border-mode variables.
122 The list of values must be terminated by a NULL.
123 After the NULL value, an entry defines the default. */
124 struct tui_translate tui_border_mode_translate
[] = {
125 { "normal", A_NORMAL
},
126 { "standout", A_STANDOUT
},
127 { "reverse", A_REVERSE
},
129 { "half-standout", A_DIM
| A_STANDOUT
},
131 { "bold-standout", A_BOLD
| A_STANDOUT
},
133 { "normal", A_NORMAL
}
136 /* Translation tables for border-kind, one for each border
137 character (see wborder, border curses operations).
138 -1 is used to indicate the ACS because ACS characters
139 are determined at run time by curses (depends on terminal). */
140 struct tui_translate tui_border_kind_translate_vline
[] = {
148 struct tui_translate tui_border_kind_translate_hline
[] = {
156 struct tui_translate tui_border_kind_translate_ulcorner
[] = {
164 struct tui_translate tui_border_kind_translate_urcorner
[] = {
172 struct tui_translate tui_border_kind_translate_llcorner
[] = {
180 struct tui_translate tui_border_kind_translate_lrcorner
[] = {
189 /* Tui configuration variables controlled with set/show command. */
190 const char *tui_active_border_mode
= "bold-standout";
192 show_tui_active_border_mode (struct ui_file
*file
,
194 struct cmd_list_element
*c
,
197 fprintf_filtered (file
, _("\
198 The attribute mode to use for the active TUI window border is \"%s\".\n"),
202 const char *tui_border_mode
= "normal";
204 show_tui_border_mode (struct ui_file
*file
,
206 struct cmd_list_element
*c
,
209 fprintf_filtered (file
, _("\
210 The attribute mode to use for the TUI window borders is \"%s\".\n"),
214 const char *tui_border_kind
= "acs";
216 show_tui_border_kind (struct ui_file
*file
,
218 struct cmd_list_element
*c
,
221 fprintf_filtered (file
, _("The kind of border for TUI windows is \"%s\".\n"),
226 /* Tui internal configuration variables. These variables are updated
227 by tui_update_variables to reflect the tui configuration
229 chtype tui_border_vline
;
230 chtype tui_border_hline
;
231 chtype tui_border_ulcorner
;
232 chtype tui_border_urcorner
;
233 chtype tui_border_llcorner
;
234 chtype tui_border_lrcorner
;
236 int tui_border_attrs
;
237 int tui_active_border_attrs
;
239 /* Identify the item in the translation table.
240 When the item is not recognized, use the default entry. */
241 static struct tui_translate
*
242 translate (const char *name
, struct tui_translate
*table
)
246 if (name
&& strcmp (table
->name
, name
) == 0)
251 /* Not found, return default entry. */
256 /* Update the tui internal configuration according to gdb settings.
257 Returns 1 if the configuration has changed and the screen should
260 tui_update_variables (void)
263 struct tui_translate
*entry
;
265 entry
= translate (tui_border_mode
, tui_border_mode_translate
);
266 if (tui_border_attrs
!= entry
->value
)
268 tui_border_attrs
= entry
->value
;
271 entry
= translate (tui_active_border_mode
, tui_border_mode_translate
);
272 if (tui_active_border_attrs
!= entry
->value
)
274 tui_active_border_attrs
= entry
->value
;
278 /* If one corner changes, all characters are changed.
279 Only check the first one. The ACS characters are determined at
280 run time by curses terminal management. */
281 entry
= translate (tui_border_kind
, tui_border_kind_translate_lrcorner
);
282 if (tui_border_lrcorner
!= (chtype
) entry
->value
)
284 tui_border_lrcorner
= (entry
->value
< 0) ? ACS_LRCORNER
: entry
->value
;
287 entry
= translate (tui_border_kind
, tui_border_kind_translate_llcorner
);
288 tui_border_llcorner
= (entry
->value
< 0) ? ACS_LLCORNER
: entry
->value
;
290 entry
= translate (tui_border_kind
, tui_border_kind_translate_ulcorner
);
291 tui_border_ulcorner
= (entry
->value
< 0) ? ACS_ULCORNER
: entry
->value
;
293 entry
= translate (tui_border_kind
, tui_border_kind_translate_urcorner
);
294 tui_border_urcorner
= (entry
->value
< 0) ? ACS_URCORNER
: entry
->value
;
296 entry
= translate (tui_border_kind
, tui_border_kind_translate_hline
);
297 tui_border_hline
= (entry
->value
< 0) ? ACS_HLINE
: entry
->value
;
299 entry
= translate (tui_border_kind
, tui_border_kind_translate_vline
);
300 tui_border_vline
= (entry
->value
< 0) ? ACS_VLINE
: entry
->value
;
306 set_tui_cmd (const char *args
, int from_tty
)
311 show_tui_cmd (const char *args
, int from_tty
)
315 static struct cmd_list_element
*tuilist
;
318 tui_command (const char *args
, int from_tty
)
320 printf_unfiltered (_("\"tui\" must be followed by the name of a "
322 help_list (tuilist
, "tui ", all_commands
, gdb_stdout
);
325 struct cmd_list_element
**
326 tui_get_cmd_list (void)
329 add_prefix_cmd ("tui", class_tui
, tui_command
,
330 _("Text User Interface commands."),
331 &tuilist
, "tui ", 0, &cmdlist
);
335 /* The set_func hook of "set tui ..." commands that affect the window
336 borders on the TUI display. */
339 tui_set_var_cmd (const char *null_args
,
340 int from_tty
, struct cmd_list_element
*c
)
342 if (tui_update_variables () && tui_active
)
343 tui_rehighlight_all ();
348 /* True if TUI resizes should print a message. This is used by the
351 static bool resize_message
;
354 show_tui_resize_message (struct ui_file
*file
, int from_tty
,
355 struct cmd_list_element
*c
, const char *value
)
357 fprintf_filtered (file
, _("TUI resize messaging is %s.\n"), value
);
362 /* Generic window name completion function. Complete window name pointed
363 to by TEXT and WORD. If INCLUDE_NEXT_PREV_P is true then the special
364 window names 'next' and 'prev' will also be considered as possible
365 completions of the window name. */
368 window_name_completer (completion_tracker
&tracker
,
369 int include_next_prev_p
,
370 const char *text
, const char *word
)
372 std::vector
<const char *> completion_name_vec
;
374 for (tui_win_info
*win_info
: all_tui_windows ())
376 const char *completion_name
= NULL
;
378 /* We can't focus on an invisible window. */
379 if (!win_info
->is_visible ())
382 completion_name
= win_info
->name ();
383 gdb_assert (completion_name
!= NULL
);
384 completion_name_vec
.push_back (completion_name
);
387 /* If no windows are considered visible then the TUI has not yet been
388 initialized. But still "focus src" and "focus cmd" will work because
389 invoking the focus command will entail initializing the TUI which sets the
390 default layout to SRC_COMMAND. */
391 if (completion_name_vec
.empty ())
393 completion_name_vec
.push_back (SRC_NAME
);
394 completion_name_vec
.push_back (CMD_NAME
);
397 if (include_next_prev_p
)
399 completion_name_vec
.push_back ("next");
400 completion_name_vec
.push_back ("prev");
404 completion_name_vec
.push_back (NULL
);
405 complete_on_enum (tracker
, completion_name_vec
.data (), text
, word
);
408 /* Complete possible window names to focus on. TEXT is the complete text
409 entered so far, WORD is the word currently being completed. */
412 focus_completer (struct cmd_list_element
*ignore
,
413 completion_tracker
&tracker
,
414 const char *text
, const char *word
)
416 window_name_completer (tracker
, 1, text
, word
);
419 /* Complete possible window names for winheight command. TEXT is the
420 complete text entered so far, WORD is the word currently being
424 winheight_completer (struct cmd_list_element
*ignore
,
425 completion_tracker
&tracker
,
426 const char *text
, const char *word
)
428 /* The first word is the window name. That we can complete. Subsequent
429 words can't be completed. */
433 window_name_completer (tracker
, 0, text
, word
);
436 /* Update gdb's knowledge of the terminal size. */
438 tui_update_gdb_sizes (void)
444 width
= TUI_CMD_WIN
->width
;
445 height
= TUI_CMD_WIN
->height
;
449 width
= tui_term_width ();
450 height
= tui_term_height ();
453 set_screen_width_and_height (width
, height
);
457 /* Set the logical focus to win_info. */
459 tui_set_win_focus_to (struct tui_win_info
*win_info
)
461 if (win_info
!= NULL
)
463 struct tui_win_info
*win_with_focus
= tui_win_with_focus ();
465 tui_unhighlight_win (win_with_focus
);
466 tui_set_win_with_focus (win_info
);
467 tui_highlight_win (win_info
);
473 tui_win_info::forward_scroll (int num_to_scroll
)
475 if (num_to_scroll
== 0)
476 num_to_scroll
= height
- 3;
478 do_scroll_vertical (num_to_scroll
);
482 tui_win_info::backward_scroll (int num_to_scroll
)
484 if (num_to_scroll
== 0)
485 num_to_scroll
= height
- 3;
487 do_scroll_vertical (-num_to_scroll
);
492 tui_win_info::left_scroll (int num_to_scroll
)
494 if (num_to_scroll
== 0)
497 do_scroll_horizontal (num_to_scroll
);
502 tui_win_info::right_scroll (int num_to_scroll
)
504 if (num_to_scroll
== 0)
507 do_scroll_horizontal (-num_to_scroll
);
512 tui_refresh_all_win (void)
514 clearok (curscr
, TRUE
);
519 tui_rehighlight_all (void)
521 for (tui_win_info
*win_info
: all_tui_windows ())
522 win_info
->check_and_display_highlight_if_needed ();
525 /* Resize all the windows based on the terminal size. This function
526 gets called from within the readline SIGWINCH handler. */
528 tui_resize_all (void)
530 int height_diff
, width_diff
;
531 int screenheight
, screenwidth
;
533 rl_get_screen_size (&screenheight
, &screenwidth
);
534 width_diff
= screenwidth
- tui_term_width ();
535 height_diff
= screenheight
- tui_term_height ();
536 if (height_diff
|| width_diff
)
538 enum tui_layout_type cur_layout
= tui_current_layout ();
539 struct tui_win_info
*win_with_focus
= tui_win_with_focus ();
540 struct tui_win_info
*first_win
;
541 struct tui_win_info
*second_win
;
542 tui_source_window_base
*src_win
;
543 struct tui_locator_window
*locator
= tui_locator_win_info_ptr ();
544 int new_height
, split_diff
, cmd_split_diff
, num_wins_displayed
= 2;
546 #ifdef HAVE_RESIZE_TERM
547 resize_term (screenheight
, screenwidth
);
549 /* Turn keypad off while we resize. */
550 if (win_with_focus
!= TUI_CMD_WIN
)
551 keypad (TUI_CMD_WIN
->handle
.get (), FALSE
);
552 tui_update_gdb_sizes ();
553 tui_set_term_height_to (screenheight
);
554 tui_set_term_width_to (screenwidth
);
555 if (cur_layout
== SRC_DISASSEM_COMMAND
556 || cur_layout
== SRC_DATA_COMMAND
557 || cur_layout
== DISASSEM_DATA_COMMAND
)
558 num_wins_displayed
++;
559 split_diff
= height_diff
/ num_wins_displayed
;
560 cmd_split_diff
= split_diff
;
561 if (height_diff
% num_wins_displayed
)
568 /* Now adjust each window. */
569 /* erase + clearok are used instead of a straightforward clear as
570 AIX 5.3 does not define clear. */
572 clearok (curscr
, TRUE
);
576 case DISASSEM_COMMAND
:
577 src_win
= *(tui_source_windows ().begin ());
578 /* Check for invalid heights. */
579 if (height_diff
== 0)
580 new_height
= src_win
->height
;
581 else if ((src_win
->height
+ split_diff
) >=
582 (screenheight
- MIN_CMD_WIN_HEIGHT
- 1))
583 new_height
= screenheight
- MIN_CMD_WIN_HEIGHT
- 1;
584 else if ((src_win
->height
+ split_diff
) <= 0)
585 new_height
= MIN_WIN_HEIGHT
;
587 new_height
= src_win
->height
+ split_diff
;
589 src_win
->resize (new_height
, screenwidth
, 0, 0);
591 locator
->resize (1, screenwidth
, 0, new_height
);
593 new_height
= screenheight
- (new_height
+ 1);
594 TUI_CMD_WIN
->resize (new_height
, screenwidth
,
595 0, locator
->origin
.y
+ 1);
598 if (cur_layout
== SRC_DISASSEM_COMMAND
)
600 src_win
= TUI_SRC_WIN
;
602 second_win
= TUI_DISASM_WIN
;
606 first_win
= TUI_DATA_WIN
;
607 src_win
= *(tui_source_windows ().begin ());
608 second_win
= src_win
;
610 /* Change the first window's height/width. */
611 /* Check for invalid heights. */
612 if (height_diff
== 0)
613 new_height
= first_win
->height
;
614 else if ((first_win
->height
+
615 second_win
->height
+ (split_diff
* 2)) >=
616 (screenheight
- MIN_CMD_WIN_HEIGHT
- 1))
617 new_height
= (screenheight
- MIN_CMD_WIN_HEIGHT
- 1) / 2;
618 else if ((first_win
->height
+ split_diff
) <= 0)
619 new_height
= MIN_WIN_HEIGHT
;
621 new_height
= first_win
->height
+ split_diff
;
623 first_win
->resize (new_height
, screenwidth
, 0, 0);
625 /* Change the second window's height/width. */
626 /* Check for invalid heights. */
627 if (height_diff
== 0)
628 new_height
= second_win
->height
;
629 else if ((first_win
->height
+
630 second_win
->height
+ (split_diff
* 2)) >=
631 (screenheight
- MIN_CMD_WIN_HEIGHT
- 1))
633 new_height
= screenheight
- MIN_CMD_WIN_HEIGHT
- 1;
635 new_height
= (new_height
/ 2) + 1;
639 else if ((second_win
->height
+ split_diff
) <= 0)
640 new_height
= MIN_WIN_HEIGHT
;
642 new_height
= second_win
->height
+ split_diff
;
644 second_win
->resize (new_height
, screenwidth
,
645 0, first_win
->height
- 1);
647 locator
->resize (1, screenwidth
,
648 0, second_win
->origin
.y
+ new_height
);
650 /* Change the command window's height/width. */
651 new_height
= screenheight
- (locator
->origin
.y
+ 1);
652 TUI_CMD_WIN
->resize (new_height
, screenwidth
,
653 0, locator
->origin
.y
+ 1);
657 tui_delete_invisible_windows ();
658 /* Turn keypad back on, unless focus is in the command
660 if (win_with_focus
!= TUI_CMD_WIN
)
661 keypad (TUI_CMD_WIN
->handle
.get (), TRUE
);
666 /* Token for use by TUI's asynchronous SIGWINCH handler. */
667 static struct async_signal_handler
*tui_sigwinch_token
;
669 /* TUI's SIGWINCH signal handler. */
671 tui_sigwinch_handler (int signal
)
673 mark_async_signal_handler (tui_sigwinch_token
);
674 tui_set_win_resized_to (true);
677 /* Callback for asynchronously resizing TUI following a SIGWINCH signal. */
679 tui_async_resize_screen (gdb_client_data arg
)
681 rl_resize_terminal ();
685 int screen_height
, screen_width
;
687 rl_get_screen_size (&screen_height
, &screen_width
);
688 set_screen_width_and_height (screen_width
, screen_height
);
690 /* win_resized is left set so that the next call to tui_enable()
691 resizes the TUI windows. */
695 tui_set_win_resized_to (false);
697 tui_refresh_all_win ();
698 tui_update_gdb_sizes ();
702 printf_unfiltered ("@@ resize done %d, size = %dx%d\n", count
,
703 tui_term_width (), tui_term_height ());
706 tui_redisplay_readline ();
711 /* Initialize TUI's SIGWINCH signal handler. Note that the handler is not
712 uninstalled when we exit TUI, so the handler should not assume that TUI is
715 tui_initialize_win (void)
719 = create_async_signal_handler (tui_async_resize_screen
, NULL
);
722 #ifdef HAVE_SIGACTION
723 struct sigaction old_winch
;
725 memset (&old_winch
, 0, sizeof (old_winch
));
726 old_winch
.sa_handler
= &tui_sigwinch_handler
;
728 old_winch
.sa_flags
= SA_RESTART
;
730 sigaction (SIGWINCH
, &old_winch
, NULL
);
732 signal (SIGWINCH
, &tui_sigwinch_handler
);
740 tui_scroll_forward_command (const char *arg
, int from_tty
)
742 int num_to_scroll
= 1;
743 struct tui_win_info
*win_to_scroll
;
745 /* Make sure the curses mode is enabled. */
748 parse_scrolling_args (arg
, &win_to_scroll
, NULL
);
750 parse_scrolling_args (arg
, &win_to_scroll
, &num_to_scroll
);
751 win_to_scroll
->forward_scroll (num_to_scroll
);
756 tui_scroll_backward_command (const char *arg
, int from_tty
)
758 int num_to_scroll
= 1;
759 struct tui_win_info
*win_to_scroll
;
761 /* Make sure the curses mode is enabled. */
764 parse_scrolling_args (arg
, &win_to_scroll
, NULL
);
766 parse_scrolling_args (arg
, &win_to_scroll
, &num_to_scroll
);
767 win_to_scroll
->backward_scroll (num_to_scroll
);
772 tui_scroll_left_command (const char *arg
, int from_tty
)
775 struct tui_win_info
*win_to_scroll
;
777 /* Make sure the curses mode is enabled. */
779 parse_scrolling_args (arg
, &win_to_scroll
, &num_to_scroll
);
780 win_to_scroll
->left_scroll (num_to_scroll
);
785 tui_scroll_right_command (const char *arg
, int from_tty
)
788 struct tui_win_info
*win_to_scroll
;
790 /* Make sure the curses mode is enabled. */
792 parse_scrolling_args (arg
, &win_to_scroll
, &num_to_scroll
);
793 win_to_scroll
->right_scroll (num_to_scroll
);
797 /* Answer the window represented by name. */
798 static struct tui_win_info
*
799 tui_partial_win_by_name (gdb::string_view name
)
803 for (tui_win_info
*item
: all_tui_windows ())
805 const char *cur_name
= item
->name ();
807 if (startswith (cur_name
, name
))
815 /* Set focus to the window named by 'arg'. */
817 tui_set_focus_command (const char *arg
, int from_tty
)
823 struct tui_win_info
*win_info
= NULL
;
825 if (subset_compare (arg
, "next"))
826 win_info
= tui_next_win (tui_win_with_focus ());
827 else if (subset_compare (arg
, "prev"))
828 win_info
= tui_prev_win (tui_win_with_focus ());
830 win_info
= tui_partial_win_by_name (arg
);
832 if (win_info
== NULL
)
833 error (_("Unrecognized window name \"%s\""), arg
);
834 if (!win_info
->is_visible ())
835 error (_("Window \"%s\" is not visible"), arg
);
837 tui_set_win_focus_to (win_info
);
838 keypad (TUI_CMD_WIN
->handle
.get (), win_info
!= TUI_CMD_WIN
);
839 printf_filtered (_("Focus set to %s window.\n"),
840 tui_win_with_focus ()->name ());
843 error (_("Incorrect Number of Arguments.\n%s"), FOCUS_USAGE
);
847 tui_all_windows_info (const char *arg
, int from_tty
)
849 struct tui_win_info
*win_with_focus
= tui_win_with_focus ();
850 struct ui_out
*uiout
= current_uiout
;
852 ui_out_emit_table
table_emitter (uiout
, 3, -1, "tui-windows");
853 uiout
->table_header (10, ui_left
, "name", "Name");
854 uiout
->table_header (5, ui_right
, "lines", "Lines");
855 uiout
->table_header (10, ui_left
, "focus", "Focus");
856 uiout
->table_body ();
858 for (tui_win_info
*win_info
: all_tui_windows ())
859 if (win_info
->is_visible ())
861 ui_out_emit_tuple
tuple_emitter (uiout
, nullptr);
863 uiout
->field_string ("name", win_info
->name ());
864 uiout
->field_signed ("lines", win_info
->height
);
865 if (win_with_focus
== win_info
)
866 uiout
->field_string ("focus", _("(has focus)"));
868 uiout
->field_skip ("focus");
875 tui_refresh_all_command (const char *arg
, int from_tty
)
877 /* Make sure the curses mode is enabled. */
880 tui_refresh_all_win ();
883 /* The tab width that should be used by the TUI. */
885 unsigned int tui_tab_width
= DEFAULT_TAB_LEN
;
887 /* The tab width as set by the user. */
889 static unsigned int internal_tab_width
= DEFAULT_TAB_LEN
;
891 /* After the tab width is set, call this to update the relevant
897 for (tui_win_info
*win_info
: all_tui_windows ())
899 if (win_info
->is_visible ())
900 win_info
->update_tab_width ();
904 /* Callback for "set tui tab-width". */
907 tui_set_tab_width (const char *ignore
,
908 int from_tty
, struct cmd_list_element
*c
)
910 if (internal_tab_width
== 0)
912 internal_tab_width
= tui_tab_width
;
913 error (_("Tab width must not be 0"));
916 tui_tab_width
= internal_tab_width
;
920 /* Callback for "show tui tab-width". */
923 tui_show_tab_width (struct ui_file
*file
, int from_tty
,
924 struct cmd_list_element
*c
, const char *value
)
926 fprintf_filtered (gdb_stdout
, _("TUI tab width is %s spaces.\n"), value
);
932 bool compact_source
= false;
934 /* Callback for "set tui compact-source". */
937 tui_set_compact_source (const char *ignore
, int from_tty
,
938 struct cmd_list_element
*c
)
940 if (TUI_SRC_WIN
!= nullptr)
941 TUI_SRC_WIN
->refill ();
944 /* Callback for "show tui compact-source". */
947 tui_show_compact_source (struct ui_file
*file
, int from_tty
,
948 struct cmd_list_element
*c
, const char *value
)
950 printf_filtered (_("TUI source window compactness is %s.\n"), value
);
953 /* Set the tab width of the specified window. */
955 tui_set_tab_width_command (const char *arg
, int from_tty
)
957 /* Make sure the curses mode is enabled. */
965 warning (_("Tab widths greater than 0 must be specified."));
968 internal_tab_width
= ts
;
977 /* Set the height of the specified window. */
979 tui_set_win_height_command (const char *arg
, int from_tty
)
981 /* Make sure the curses mode is enabled. */
985 const char *buf
= arg
;
986 const char *buf_ptr
= buf
;
988 struct tui_win_info
*win_info
;
990 buf_ptr
= strchr (buf_ptr
, ' ');
993 /* Validate the window name. */
994 gdb::string_view
wname (buf
, buf_ptr
- buf
);
995 win_info
= tui_partial_win_by_name (wname
);
997 if (win_info
== NULL
)
998 error (_("Unrecognized window name \"%s\""), arg
);
999 if (!win_info
->is_visible ())
1000 error (_("Window \"%s\" is not visible"), arg
);
1002 /* Process the size. */
1003 buf_ptr
= skip_spaces (buf_ptr
);
1005 if (*buf_ptr
!= '\0')
1007 bool negate
= false;
1008 bool fixed_size
= true;
1011 if (*buf_ptr
== '+' || *buf_ptr
== '-')
1013 if (*buf_ptr
== '-')
1018 input_no
= atoi (buf_ptr
);
1024 new_height
= input_no
;
1026 new_height
= win_info
->height
+ input_no
;
1028 /* Now change the window's height, and adjust
1029 all other windows around it. */
1030 if (tui_adjust_win_heights (win_info
,
1031 new_height
) == TUI_FAILURE
)
1032 warning (_("Invalid window height specified.\n%s"),
1035 tui_update_gdb_sizes ();
1038 warning (_("Invalid window height specified.\n%s"),
1043 printf_filtered (WIN_HEIGHT_USAGE
);
1046 printf_filtered (WIN_HEIGHT_USAGE
);
1049 /* Function to adjust all window heights around the primary. */
1050 static enum tui_status
1051 tui_adjust_win_heights (struct tui_win_info
*primary_win_info
,
1054 enum tui_status status
= TUI_FAILURE
;
1056 if (new_height_ok (primary_win_info
, new_height
))
1058 status
= TUI_SUCCESS
;
1059 if (new_height
!= primary_win_info
->height
)
1062 struct tui_win_info
*win_info
;
1063 struct tui_locator_window
*locator
= tui_locator_win_info_ptr ();
1064 enum tui_layout_type cur_layout
= tui_current_layout ();
1065 int width
= tui_term_width ();
1067 diff
= (new_height
- primary_win_info
->height
) * (-1);
1068 if (cur_layout
== SRC_COMMAND
1069 || cur_layout
== DISASSEM_COMMAND
)
1071 struct tui_win_info
*src_win_info
;
1073 primary_win_info
->resize (new_height
, width
,
1074 0, primary_win_info
->origin
.y
);
1075 if (primary_win_info
->type
== CMD_WIN
)
1077 win_info
= *(tui_source_windows ().begin ());
1078 src_win_info
= win_info
;
1082 win_info
= tui_win_list
[CMD_WIN
];
1083 src_win_info
= primary_win_info
;
1085 win_info
->resize (win_info
->height
+ diff
, width
,
1086 0, win_info
->origin
.y
);
1087 TUI_CMD_WIN
->origin
.y
= locator
->origin
.y
+ 1;
1088 if ((src_win_info
->type
== SRC_WIN
1089 || src_win_info
->type
== DISASSEM_WIN
))
1091 tui_source_window_base
*src_base
1092 = (tui_source_window_base
*) src_win_info
;
1093 if (src_base
->content
.empty ())
1094 src_base
->erase_source_content ();
1099 struct tui_win_info
*first_win
;
1100 struct tui_source_window_base
*second_win
;
1101 tui_source_window_base
*src1
;
1103 if (cur_layout
== SRC_DISASSEM_COMMAND
)
1107 second_win
= TUI_DISASM_WIN
;
1112 first_win
= TUI_DATA_WIN
;
1113 second_win
= *(tui_source_windows ().begin ());
1115 if (primary_win_info
== TUI_CMD_WIN
)
1116 { /* Split the change in height across the 1st & 2nd
1117 windows, adjusting them as well. */
1118 /* Subtract the locator. */
1119 int first_split_diff
= diff
/ 2;
1120 int second_split_diff
= first_split_diff
;
1124 if (first_win
->height
>
1133 second_split_diff
--;
1135 second_split_diff
++;
1138 /* Make sure that the minimum heights are
1140 while ((first_win
->height
+ first_split_diff
) < 3)
1143 second_split_diff
--;
1145 while ((second_win
->height
+ second_split_diff
) < 3)
1147 second_split_diff
++;
1150 first_win
->resize (first_win
->height
+ first_split_diff
,
1152 0, first_win
->origin
.y
);
1153 second_win
->resize (second_win
->height
+ second_split_diff
,
1155 0, first_win
->height
- 1);
1156 locator
->resize (1, width
,
1157 0, (second_win
->origin
.y
1158 + second_win
->height
+ 1));
1160 TUI_CMD_WIN
->resize (new_height
, width
,
1161 0, locator
->origin
.y
+ 1);
1165 if ((TUI_CMD_WIN
->height
+ diff
) < 1)
1166 { /* If there is no way to increase the command
1167 window take real estate from the 1st or 2nd
1169 if ((TUI_CMD_WIN
->height
+ diff
) < 1)
1173 for (i
= TUI_CMD_WIN
->height
+ diff
;
1175 if (primary_win_info
== first_win
)
1176 second_win
->height
--;
1178 first_win
->height
--;
1181 if (primary_win_info
== first_win
)
1182 first_win
->resize (new_height
, width
, 0, 0);
1184 first_win
->resize (first_win
->height
, width
, 0, 0);
1185 second_win
->origin
.y
= first_win
->height
- 1;
1186 if (primary_win_info
== second_win
)
1187 second_win
->resize (new_height
, width
,
1188 0, first_win
->height
- 1);
1190 second_win
->resize (second_win
->height
, width
,
1191 0, first_win
->height
- 1);
1192 locator
->resize (1, width
,
1193 0, (second_win
->origin
.y
1194 + second_win
->height
+ 1));
1195 TUI_CMD_WIN
->origin
.y
= locator
->origin
.y
+ 1;
1196 if ((TUI_CMD_WIN
->height
+ diff
) < 1)
1197 TUI_CMD_WIN
->resize (1, width
, 0, locator
->origin
.y
+ 1);
1199 TUI_CMD_WIN
->resize (TUI_CMD_WIN
->height
+ diff
, width
,
1200 0, locator
->origin
.y
+ 1);
1202 if (src1
!= nullptr && src1
->content
.empty ())
1203 src1
->erase_source_content ();
1204 if (second_win
->content
.empty ())
1205 second_win
->erase_source_content ();
1213 /* See tui-data.h. */
1216 tui_win_info::max_height () const
1218 return tui_term_height () - 2;
1222 new_height_ok (struct tui_win_info
*primary_win_info
,
1225 int ok
= (new_height
< tui_term_height ());
1230 enum tui_layout_type cur_layout
= tui_current_layout ();
1232 diff
= (new_height
- primary_win_info
->height
) * (-1);
1233 if (cur_layout
== SRC_COMMAND
|| cur_layout
== DISASSEM_COMMAND
)
1235 ok
= (new_height
<= primary_win_info
->max_height ()
1236 && new_height
>= MIN_CMD_WIN_HEIGHT
);
1238 { /* Check the total height. */
1239 struct tui_win_info
*win_info
;
1241 if (primary_win_info
== TUI_CMD_WIN
)
1242 win_info
= *(tui_source_windows ().begin ());
1244 win_info
= TUI_CMD_WIN
;
1246 (win_info
->height
+ diff
)) <= tui_term_height ());
1251 int cur_total_height
, total_height
, min_height
= 0;
1252 struct tui_win_info
*first_win
;
1253 struct tui_win_info
*second_win
;
1255 if (cur_layout
== SRC_DISASSEM_COMMAND
)
1257 first_win
= TUI_SRC_WIN
;
1258 second_win
= TUI_DISASM_WIN
;
1262 first_win
= TUI_DATA_WIN
;
1263 second_win
= *(tui_source_windows ().begin ());
1265 /* We could simply add all the heights to obtain the same
1266 result but below is more explicit since we subtract 1 for
1267 the line that the first and second windows share, and add
1268 one for the locator. */
1269 total_height
= cur_total_height
=
1270 (first_win
->height
+ second_win
->height
- 1)
1271 + TUI_CMD_WIN
->height
+ 1; /* Locator. */
1272 if (primary_win_info
== TUI_CMD_WIN
)
1274 /* Locator included since first & second win share a line. */
1275 ok
= ((first_win
->height
+
1276 second_win
->height
+ diff
) >=
1277 (MIN_WIN_HEIGHT
* 2)
1278 && new_height
>= MIN_CMD_WIN_HEIGHT
);
1281 total_height
= new_height
+
1282 (first_win
->height
+
1283 second_win
->height
+ diff
);
1284 min_height
= MIN_CMD_WIN_HEIGHT
;
1289 min_height
= MIN_WIN_HEIGHT
;
1291 /* First see if we can increase/decrease the command
1292 window. And make sure that the command window is at
1294 ok
= ((TUI_CMD_WIN
->height
+ diff
) > 0);
1296 { /* Looks like we have to increase/decrease one of
1297 the other windows. */
1298 if (primary_win_info
== first_win
)
1299 ok
= (second_win
->height
+ diff
) >= min_height
;
1301 ok
= (first_win
->height
+ diff
) >= min_height
;
1305 if (primary_win_info
== first_win
)
1306 total_height
= new_height
+
1307 second_win
->height
+
1308 TUI_CMD_WIN
->height
+ diff
;
1310 total_height
= new_height
+
1312 TUI_CMD_WIN
->height
+ diff
;
1315 /* Now make sure that the proposed total height doesn't
1316 exceed the old total height. */
1318 ok
= (new_height
>= min_height
1319 && total_height
<= cur_total_height
);
1328 parse_scrolling_args (const char *arg
,
1329 struct tui_win_info
**win_to_scroll
,
1334 *win_to_scroll
= tui_win_with_focus ();
1336 /* First set up the default window to scroll, in case there is no
1342 /* Process the number of lines to scroll. */
1343 std::string copy
= arg
;
1345 if (isdigit (*buf_ptr
))
1350 buf_ptr
= strchr (buf_ptr
, ' ');
1351 if (buf_ptr
!= NULL
)
1355 *num_to_scroll
= atoi (num_str
);
1358 else if (num_to_scroll
)
1359 *num_to_scroll
= atoi (num_str
);
1362 /* Process the window name if one is specified. */
1363 if (buf_ptr
!= NULL
)
1367 wname
= skip_spaces (buf_ptr
);
1371 *win_to_scroll
= tui_partial_win_by_name (wname
);
1373 if (*win_to_scroll
== NULL
)
1374 error (_("Unrecognized window `%s'"), wname
);
1375 if (!(*win_to_scroll
)->is_visible ())
1376 error (_("Window is not visible"));
1377 else if (*win_to_scroll
== TUI_CMD_WIN
)
1378 *win_to_scroll
= *(tui_source_windows ().begin ());
1384 /* Function to initialize gdb commands, for tui window
1388 _initialize_tui_win (void)
1390 static struct cmd_list_element
*tui_setlist
;
1391 static struct cmd_list_element
*tui_showlist
;
1392 struct cmd_list_element
*cmd
;
1394 /* Define the classes of commands.
1395 They will appear in the help list in the reverse of this order. */
1396 add_prefix_cmd ("tui", class_tui
, set_tui_cmd
,
1397 _("TUI configuration variables."),
1398 &tui_setlist
, "set tui ",
1399 0 /* allow-unknown */, &setlist
);
1400 add_prefix_cmd ("tui", class_tui
, show_tui_cmd
,
1401 _("TUI configuration variables."),
1402 &tui_showlist
, "show tui ",
1403 0 /* allow-unknown */, &showlist
);
1405 add_com ("refresh", class_tui
, tui_refresh_all_command
,
1406 _("Refresh the terminal display."));
1408 cmd
= add_com ("tabset", class_tui
, tui_set_tab_width_command
, _("\
1409 Set the width (in characters) of tab stops.\n\
1411 deprecate_cmd (cmd
, "set tui tab-width");
1413 cmd
= add_com ("winheight", class_tui
, tui_set_win_height_command
, _("\
1414 Set or modify the height of a specified window.\n"
1416 "Window names are:\n\
1417 src : the source window\n\
1418 cmd : the command window\n\
1419 asm : the disassembly window\n\
1420 regs : the register display"));
1421 add_com_alias ("wh", "winheight", class_tui
, 0);
1422 set_cmd_completer (cmd
, winheight_completer
);
1423 add_info ("win", tui_all_windows_info
,
1424 _("List of all displayed windows."));
1425 cmd
= add_com ("focus", class_tui
, tui_set_focus_command
, _("\
1426 Set focus to named window or next/prev window.\n"
1428 "Valid Window names are:\n\
1429 src : the source window\n\
1430 asm : the disassembly window\n\
1431 regs : the register display\n\
1432 cmd : the command window"));
1433 add_com_alias ("fs", "focus", class_tui
, 0);
1434 set_cmd_completer (cmd
, focus_completer
);
1435 add_com ("+", class_tui
, tui_scroll_forward_command
, _("\
1436 Scroll window forward.\n\
1437 Usage: + [WIN] [N]"));
1438 add_com ("-", class_tui
, tui_scroll_backward_command
, _("\
1439 Scroll window backward.\n\
1440 Usage: - [WIN] [N]"));
1441 add_com ("<", class_tui
, tui_scroll_left_command
, _("\
1442 Scroll window text to the left.\n\
1443 Usage: < [WIN] [N]"));
1444 add_com (">", class_tui
, tui_scroll_right_command
, _("\
1445 Scroll window text to the right.\n\
1446 Usage: > [WIN] [N]"));
1448 /* Define the tui control variables. */
1449 add_setshow_enum_cmd ("border-kind", no_class
, tui_border_kind_enums
,
1450 &tui_border_kind
, _("\
1451 Set the kind of border for TUI windows."), _("\
1452 Show the kind of border for TUI windows."), _("\
1453 This variable controls the border of TUI windows:\n\
1454 space use a white space\n\
1455 ascii use ascii characters + - | for the border\n\
1456 acs use the Alternate Character Set"),
1458 show_tui_border_kind
,
1459 &tui_setlist
, &tui_showlist
);
1461 add_setshow_enum_cmd ("border-mode", no_class
, tui_border_mode_enums
,
1462 &tui_border_mode
, _("\
1463 Set the attribute mode to use for the TUI window borders."), _("\
1464 Show the attribute mode to use for the TUI window borders."), _("\
1465 This variable controls the attributes to use for the window borders:\n\
1466 normal normal display\n\
1467 standout use highlight mode of terminal\n\
1468 reverse use reverse video mode\n\
1469 half use half bright\n\
1470 half-standout use half bright and standout mode\n\
1471 bold use extra bright or bold\n\
1472 bold-standout use extra bright or bold with standout mode"),
1474 show_tui_border_mode
,
1475 &tui_setlist
, &tui_showlist
);
1477 add_setshow_enum_cmd ("active-border-mode", no_class
, tui_border_mode_enums
,
1478 &tui_active_border_mode
, _("\
1479 Set the attribute mode to use for the active TUI window border."), _("\
1480 Show the attribute mode to use for the active TUI window border."), _("\
1481 This variable controls the attributes to use for the active window border:\n\
1482 normal normal display\n\
1483 standout use highlight mode of terminal\n\
1484 reverse use reverse video mode\n\
1485 half use half bright\n\
1486 half-standout use half bright and standout mode\n\
1487 bold use extra bright or bold\n\
1488 bold-standout use extra bright or bold with standout mode"),
1490 show_tui_active_border_mode
,
1491 &tui_setlist
, &tui_showlist
);
1493 add_setshow_zuinteger_cmd ("tab-width", no_class
,
1494 &internal_tab_width
, _("\
1495 Set the tab width, in characters, for the TUI."), _("\
1496 Show the tab witdh, in characters, for the TUI."), _("\
1497 This variable controls how many spaces are used to display a tab character."),
1498 tui_set_tab_width
, tui_show_tab_width
,
1499 &tui_setlist
, &tui_showlist
);
1501 add_setshow_boolean_cmd ("tui-resize-message", class_maintenance
,
1502 &resize_message
, _("\
1503 Set TUI resize messaging."), _("\
1504 Show TUI resize messaging."), _("\
1505 When enabled GDB will print a message when the terminal is resized."),
1507 show_tui_resize_message
,
1508 &maintenance_set_cmdlist
,
1509 &maintenance_show_cmdlist
);
1511 add_setshow_boolean_cmd ("compact-source", class_tui
,
1512 &compact_source
, _("\
1513 Set whether the TUI source window is compact."), _("\
1514 Show whether the TUI source window is compact."), _("\
1515 This variable controls whether the TUI source window is shown\n\
1516 in a compact form. The compact form puts the source closer to\n\
1517 the line numbers and uses less horizontal space."),
1518 tui_set_compact_source
, tui_show_compact_source
,
1519 &tui_setlist
, &tui_showlist
);