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"
33 #include "cli/cli-style.h"
36 #include "event-loop.h"
40 #include "tui/tui-io.h"
41 #include "tui/tui-command.h"
42 #include "tui/tui-data.h"
43 #include "tui/tui-layout.h"
44 #include "tui/tui-wingeneral.h"
45 #include "tui/tui-stack.h"
46 #include "tui/tui-regs.h"
47 #include "tui/tui-disasm.h"
48 #include "tui/tui-source.h"
49 #include "tui/tui-winsource.h"
50 #include "tui/tui-win.h"
52 #include "gdb_curses.h"
54 #include "readline/readline.h"
55 #include "gdbsupport/gdb_string_view.h"
59 static enum tui_status
tui_adjust_win_heights (struct tui_win_info
*,
61 static int new_height_ok (struct tui_win_info
*, int);
62 static void tui_set_tab_width_command (const char *, int);
63 static void tui_refresh_all_command (const char *, int);
64 static void tui_all_windows_info (const char *, int);
65 static void tui_scroll_forward_command (const char *, int);
66 static void tui_scroll_backward_command (const char *, int);
67 static void tui_scroll_left_command (const char *, int);
68 static void tui_scroll_right_command (const char *, int);
69 static void parse_scrolling_args (const char *,
70 struct tui_win_info
**,
74 #define WIN_HEIGHT_USAGE "Usage: winheight WINDOW-NAME [+ | -] NUM-LINES\n"
75 #define FOCUS_USAGE "Usage: focus [WINDOW-NAME | next | prev]\n"
78 # define ACS_LRCORNER '+'
81 # define ACS_LLCORNER '+'
84 # define ACS_ULCORNER '+'
87 # define ACS_URCORNER '+'
90 # define ACS_HLINE '-'
93 # define ACS_VLINE '|'
96 /* Possible values for tui-border-kind variable. */
97 static const char *const tui_border_kind_enums
[] = {
104 /* Possible values for tui-border-mode and tui-active-border-mode. */
105 static const char *const tui_border_mode_enums
[] = {
122 /* Translation table for border-mode variables.
123 The list of values must be terminated by a NULL.
124 After the NULL value, an entry defines the default. */
125 struct tui_translate tui_border_mode_translate
[] = {
126 { "normal", A_NORMAL
},
127 { "standout", A_STANDOUT
},
128 { "reverse", A_REVERSE
},
130 { "half-standout", A_DIM
| A_STANDOUT
},
132 { "bold-standout", A_BOLD
| A_STANDOUT
},
134 { "normal", A_NORMAL
}
137 /* Translation tables for border-kind, one for each border
138 character (see wborder, border curses operations).
139 -1 is used to indicate the ACS because ACS characters
140 are determined at run time by curses (depends on terminal). */
141 struct tui_translate tui_border_kind_translate_vline
[] = {
149 struct tui_translate tui_border_kind_translate_hline
[] = {
157 struct tui_translate tui_border_kind_translate_ulcorner
[] = {
165 struct tui_translate tui_border_kind_translate_urcorner
[] = {
173 struct tui_translate tui_border_kind_translate_llcorner
[] = {
181 struct tui_translate tui_border_kind_translate_lrcorner
[] = {
190 /* Tui configuration variables controlled with set/show command. */
191 const char *tui_active_border_mode
= "bold-standout";
193 show_tui_active_border_mode (struct ui_file
*file
,
195 struct cmd_list_element
*c
,
198 fprintf_filtered (file
, _("\
199 The attribute mode to use for the active TUI window border is \"%s\".\n"),
203 const char *tui_border_mode
= "normal";
205 show_tui_border_mode (struct ui_file
*file
,
207 struct cmd_list_element
*c
,
210 fprintf_filtered (file
, _("\
211 The attribute mode to use for the TUI window borders is \"%s\".\n"),
215 const char *tui_border_kind
= "acs";
217 show_tui_border_kind (struct ui_file
*file
,
219 struct cmd_list_element
*c
,
222 fprintf_filtered (file
, _("The kind of border for TUI windows is \"%s\".\n"),
227 /* Tui internal configuration variables. These variables are updated
228 by tui_update_variables to reflect the tui configuration
230 chtype tui_border_vline
;
231 chtype tui_border_hline
;
232 chtype tui_border_ulcorner
;
233 chtype tui_border_urcorner
;
234 chtype tui_border_llcorner
;
235 chtype tui_border_lrcorner
;
237 int tui_border_attrs
;
238 int tui_active_border_attrs
;
240 /* Identify the item in the translation table.
241 When the item is not recognized, use the default entry. */
242 static struct tui_translate
*
243 translate (const char *name
, struct tui_translate
*table
)
247 if (name
&& strcmp (table
->name
, name
) == 0)
252 /* Not found, return default entry. */
257 /* Update the tui internal configuration according to gdb settings.
258 Returns 1 if the configuration has changed and the screen should
261 tui_update_variables (void)
264 struct tui_translate
*entry
;
266 entry
= translate (tui_border_mode
, tui_border_mode_translate
);
267 if (tui_border_attrs
!= entry
->value
)
269 tui_border_attrs
= entry
->value
;
272 entry
= translate (tui_active_border_mode
, tui_border_mode_translate
);
273 if (tui_active_border_attrs
!= entry
->value
)
275 tui_active_border_attrs
= entry
->value
;
279 /* If one corner changes, all characters are changed.
280 Only check the first one. The ACS characters are determined at
281 run time by curses terminal management. */
282 entry
= translate (tui_border_kind
, tui_border_kind_translate_lrcorner
);
283 if (tui_border_lrcorner
!= (chtype
) entry
->value
)
285 tui_border_lrcorner
= (entry
->value
< 0) ? ACS_LRCORNER
: entry
->value
;
288 entry
= translate (tui_border_kind
, tui_border_kind_translate_llcorner
);
289 tui_border_llcorner
= (entry
->value
< 0) ? ACS_LLCORNER
: entry
->value
;
291 entry
= translate (tui_border_kind
, tui_border_kind_translate_ulcorner
);
292 tui_border_ulcorner
= (entry
->value
< 0) ? ACS_ULCORNER
: entry
->value
;
294 entry
= translate (tui_border_kind
, tui_border_kind_translate_urcorner
);
295 tui_border_urcorner
= (entry
->value
< 0) ? ACS_URCORNER
: entry
->value
;
297 entry
= translate (tui_border_kind
, tui_border_kind_translate_hline
);
298 tui_border_hline
= (entry
->value
< 0) ? ACS_HLINE
: entry
->value
;
300 entry
= translate (tui_border_kind
, tui_border_kind_translate_vline
);
301 tui_border_vline
= (entry
->value
< 0) ? ACS_VLINE
: entry
->value
;
307 set_tui_cmd (const char *args
, int from_tty
)
312 show_tui_cmd (const char *args
, int from_tty
)
316 static struct cmd_list_element
*tuilist
;
319 tui_command (const char *args
, int from_tty
)
321 printf_unfiltered (_("\"tui\" must be followed by the name of a "
323 help_list (tuilist
, "tui ", all_commands
, gdb_stdout
);
326 struct cmd_list_element
**
327 tui_get_cmd_list (void)
330 add_prefix_cmd ("tui", class_tui
, tui_command
,
331 _("Text User Interface commands."),
332 &tuilist
, "tui ", 0, &cmdlist
);
336 /* The set_func hook of "set tui ..." commands that affect the window
337 borders on the TUI display. */
340 tui_set_var_cmd (const char *null_args
,
341 int from_tty
, struct cmd_list_element
*c
)
343 if (tui_update_variables () && tui_active
)
344 tui_rehighlight_all ();
349 /* True if TUI resizes should print a message. This is used by the
352 static bool resize_message
;
355 show_tui_resize_message (struct ui_file
*file
, int from_tty
,
356 struct cmd_list_element
*c
, const char *value
)
358 fprintf_filtered (file
, _("TUI resize messaging is %s.\n"), value
);
363 /* Generic window name completion function. Complete window name pointed
364 to by TEXT and WORD. If INCLUDE_NEXT_PREV_P is true then the special
365 window names 'next' and 'prev' will also be considered as possible
366 completions of the window name. */
369 window_name_completer (completion_tracker
&tracker
,
370 int include_next_prev_p
,
371 const char *text
, const char *word
)
373 std::vector
<const char *> completion_name_vec
;
375 for (tui_win_info
*win_info
: all_tui_windows ())
377 const char *completion_name
= NULL
;
379 /* We can't focus on an invisible window. */
380 if (!win_info
->is_visible ())
383 completion_name
= win_info
->name ();
384 gdb_assert (completion_name
!= NULL
);
385 completion_name_vec
.push_back (completion_name
);
388 /* If no windows are considered visible then the TUI has not yet been
389 initialized. But still "focus src" and "focus cmd" will work because
390 invoking the focus command will entail initializing the TUI which sets the
391 default layout to SRC_COMMAND. */
392 if (completion_name_vec
.empty ())
394 completion_name_vec
.push_back (SRC_NAME
);
395 completion_name_vec
.push_back (CMD_NAME
);
398 if (include_next_prev_p
)
400 completion_name_vec
.push_back ("next");
401 completion_name_vec
.push_back ("prev");
405 completion_name_vec
.push_back (NULL
);
406 complete_on_enum (tracker
, completion_name_vec
.data (), text
, word
);
409 /* Complete possible window names to focus on. TEXT is the complete text
410 entered so far, WORD is the word currently being completed. */
413 focus_completer (struct cmd_list_element
*ignore
,
414 completion_tracker
&tracker
,
415 const char *text
, const char *word
)
417 window_name_completer (tracker
, 1, text
, word
);
420 /* Complete possible window names for winheight command. TEXT is the
421 complete text entered so far, WORD is the word currently being
425 winheight_completer (struct cmd_list_element
*ignore
,
426 completion_tracker
&tracker
,
427 const char *text
, const char *word
)
429 /* The first word is the window name. That we can complete. Subsequent
430 words can't be completed. */
434 window_name_completer (tracker
, 0, text
, word
);
437 /* Update gdb's knowledge of the terminal size. */
439 tui_update_gdb_sizes (void)
445 width
= TUI_CMD_WIN
->width
;
446 height
= TUI_CMD_WIN
->height
;
450 width
= tui_term_width ();
451 height
= tui_term_height ();
454 set_screen_width_and_height (width
, height
);
458 /* Set the logical focus to win_info. */
460 tui_set_win_focus_to (struct tui_win_info
*win_info
)
462 if (win_info
!= NULL
)
464 struct tui_win_info
*win_with_focus
= tui_win_with_focus ();
466 tui_unhighlight_win (win_with_focus
);
467 tui_set_win_with_focus (win_info
);
468 tui_highlight_win (win_info
);
474 tui_win_info::forward_scroll (int num_to_scroll
)
476 if (num_to_scroll
== 0)
477 num_to_scroll
= height
- 3;
479 do_scroll_vertical (num_to_scroll
);
483 tui_win_info::backward_scroll (int num_to_scroll
)
485 if (num_to_scroll
== 0)
486 num_to_scroll
= height
- 3;
488 do_scroll_vertical (-num_to_scroll
);
493 tui_win_info::left_scroll (int num_to_scroll
)
495 if (num_to_scroll
== 0)
498 do_scroll_horizontal (num_to_scroll
);
503 tui_win_info::right_scroll (int num_to_scroll
)
505 if (num_to_scroll
== 0)
508 do_scroll_horizontal (-num_to_scroll
);
513 tui_refresh_all_win (void)
515 clearok (curscr
, TRUE
);
520 tui_rehighlight_all (void)
522 for (tui_win_info
*win_info
: all_tui_windows ())
523 win_info
->check_and_display_highlight_if_needed ();
526 /* Resize all the windows based on the terminal size. This function
527 gets called from within the readline SIGWINCH handler. */
529 tui_resize_all (void)
531 int height_diff
, width_diff
;
532 int screenheight
, screenwidth
;
534 rl_get_screen_size (&screenheight
, &screenwidth
);
535 width_diff
= screenwidth
- tui_term_width ();
536 height_diff
= screenheight
- tui_term_height ();
537 if (height_diff
|| width_diff
)
539 enum tui_layout_type cur_layout
= tui_current_layout ();
540 struct tui_win_info
*win_with_focus
= tui_win_with_focus ();
541 struct tui_win_info
*first_win
;
542 struct tui_win_info
*second_win
;
543 tui_source_window_base
*src_win
;
544 struct tui_locator_window
*locator
= tui_locator_win_info_ptr ();
545 int new_height
, split_diff
, cmd_split_diff
, num_wins_displayed
= 2;
547 #ifdef HAVE_RESIZE_TERM
548 resize_term (screenheight
, screenwidth
);
550 /* Turn keypad off while we resize. */
551 if (win_with_focus
!= TUI_CMD_WIN
)
552 keypad (TUI_CMD_WIN
->handle
.get (), FALSE
);
553 tui_update_gdb_sizes ();
554 tui_set_term_height_to (screenheight
);
555 tui_set_term_width_to (screenwidth
);
556 if (cur_layout
== SRC_DISASSEM_COMMAND
557 || cur_layout
== SRC_DATA_COMMAND
558 || cur_layout
== DISASSEM_DATA_COMMAND
)
559 num_wins_displayed
++;
560 split_diff
= height_diff
/ num_wins_displayed
;
561 cmd_split_diff
= split_diff
;
562 if (height_diff
% num_wins_displayed
)
569 /* Now adjust each window. */
570 /* erase + clearok are used instead of a straightforward clear as
571 AIX 5.3 does not define clear. */
573 clearok (curscr
, TRUE
);
577 case DISASSEM_COMMAND
:
578 src_win
= *(tui_source_windows ().begin ());
579 /* Check for invalid heights. */
580 if (height_diff
== 0)
581 new_height
= src_win
->height
;
582 else if ((src_win
->height
+ split_diff
) >=
583 (screenheight
- MIN_CMD_WIN_HEIGHT
- 1))
584 new_height
= screenheight
- MIN_CMD_WIN_HEIGHT
- 1;
585 else if ((src_win
->height
+ split_diff
) <= 0)
586 new_height
= MIN_WIN_HEIGHT
;
588 new_height
= src_win
->height
+ split_diff
;
590 src_win
->resize (new_height
, screenwidth
, 0, 0);
592 locator
->resize (1, screenwidth
, 0, new_height
);
594 new_height
= screenheight
- (new_height
+ 1);
595 TUI_CMD_WIN
->resize (new_height
, screenwidth
,
596 0, locator
->origin
.y
+ 1);
599 if (cur_layout
== SRC_DISASSEM_COMMAND
)
601 src_win
= TUI_SRC_WIN
;
603 second_win
= TUI_DISASM_WIN
;
607 first_win
= TUI_DATA_WIN
;
608 src_win
= *(tui_source_windows ().begin ());
609 second_win
= src_win
;
611 /* Change the first window's height/width. */
612 /* Check for invalid heights. */
613 if (height_diff
== 0)
614 new_height
= first_win
->height
;
615 else if ((first_win
->height
+
616 second_win
->height
+ (split_diff
* 2)) >=
617 (screenheight
- MIN_CMD_WIN_HEIGHT
- 1))
618 new_height
= (screenheight
- MIN_CMD_WIN_HEIGHT
- 1) / 2;
619 else if ((first_win
->height
+ split_diff
) <= 0)
620 new_height
= MIN_WIN_HEIGHT
;
622 new_height
= first_win
->height
+ split_diff
;
624 first_win
->resize (new_height
, screenwidth
, 0, 0);
626 /* Change the second window's height/width. */
627 /* Check for invalid heights. */
628 if (height_diff
== 0)
629 new_height
= second_win
->height
;
630 else if ((first_win
->height
+
631 second_win
->height
+ (split_diff
* 2)) >=
632 (screenheight
- MIN_CMD_WIN_HEIGHT
- 1))
634 new_height
= screenheight
- MIN_CMD_WIN_HEIGHT
- 1;
636 new_height
= (new_height
/ 2) + 1;
640 else if ((second_win
->height
+ split_diff
) <= 0)
641 new_height
= MIN_WIN_HEIGHT
;
643 new_height
= second_win
->height
+ split_diff
;
645 second_win
->resize (new_height
, screenwidth
,
646 0, first_win
->height
- 1);
648 locator
->resize (1, screenwidth
,
649 0, second_win
->origin
.y
+ new_height
);
651 /* Change the command window's height/width. */
652 new_height
= screenheight
- (locator
->origin
.y
+ 1);
653 TUI_CMD_WIN
->resize (new_height
, screenwidth
,
654 0, locator
->origin
.y
+ 1);
658 tui_delete_invisible_windows ();
659 /* Turn keypad back on, unless focus is in the command
661 if (win_with_focus
!= TUI_CMD_WIN
)
662 keypad (TUI_CMD_WIN
->handle
.get (), TRUE
);
667 /* Token for use by TUI's asynchronous SIGWINCH handler. */
668 static struct async_signal_handler
*tui_sigwinch_token
;
670 /* TUI's SIGWINCH signal handler. */
672 tui_sigwinch_handler (int signal
)
674 mark_async_signal_handler (tui_sigwinch_token
);
675 tui_set_win_resized_to (true);
678 /* Callback for asynchronously resizing TUI following a SIGWINCH signal. */
680 tui_async_resize_screen (gdb_client_data arg
)
682 rl_resize_terminal ();
686 int screen_height
, screen_width
;
688 rl_get_screen_size (&screen_height
, &screen_width
);
689 set_screen_width_and_height (screen_width
, screen_height
);
691 /* win_resized is left set so that the next call to tui_enable()
692 resizes the TUI windows. */
696 tui_set_win_resized_to (false);
698 tui_refresh_all_win ();
699 tui_update_gdb_sizes ();
703 printf_unfiltered ("@@ resize done %d, size = %dx%d\n", count
,
704 tui_term_width (), tui_term_height ());
707 tui_redisplay_readline ();
712 /* Initialize TUI's SIGWINCH signal handler. Note that the handler is not
713 uninstalled when we exit TUI, so the handler should not assume that TUI is
716 tui_initialize_win (void)
720 = create_async_signal_handler (tui_async_resize_screen
, NULL
);
723 #ifdef HAVE_SIGACTION
724 struct sigaction old_winch
;
726 memset (&old_winch
, 0, sizeof (old_winch
));
727 old_winch
.sa_handler
= &tui_sigwinch_handler
;
729 old_winch
.sa_flags
= SA_RESTART
;
731 sigaction (SIGWINCH
, &old_winch
, NULL
);
733 signal (SIGWINCH
, &tui_sigwinch_handler
);
741 tui_scroll_forward_command (const char *arg
, int from_tty
)
743 int num_to_scroll
= 1;
744 struct tui_win_info
*win_to_scroll
;
746 /* Make sure the curses mode is enabled. */
749 parse_scrolling_args (arg
, &win_to_scroll
, NULL
);
751 parse_scrolling_args (arg
, &win_to_scroll
, &num_to_scroll
);
752 win_to_scroll
->forward_scroll (num_to_scroll
);
757 tui_scroll_backward_command (const char *arg
, int from_tty
)
759 int num_to_scroll
= 1;
760 struct tui_win_info
*win_to_scroll
;
762 /* Make sure the curses mode is enabled. */
765 parse_scrolling_args (arg
, &win_to_scroll
, NULL
);
767 parse_scrolling_args (arg
, &win_to_scroll
, &num_to_scroll
);
768 win_to_scroll
->backward_scroll (num_to_scroll
);
773 tui_scroll_left_command (const char *arg
, int from_tty
)
776 struct tui_win_info
*win_to_scroll
;
778 /* Make sure the curses mode is enabled. */
780 parse_scrolling_args (arg
, &win_to_scroll
, &num_to_scroll
);
781 win_to_scroll
->left_scroll (num_to_scroll
);
786 tui_scroll_right_command (const char *arg
, int from_tty
)
789 struct tui_win_info
*win_to_scroll
;
791 /* Make sure the curses mode is enabled. */
793 parse_scrolling_args (arg
, &win_to_scroll
, &num_to_scroll
);
794 win_to_scroll
->right_scroll (num_to_scroll
);
798 /* Answer the window represented by name. */
799 static struct tui_win_info
*
800 tui_partial_win_by_name (gdb::string_view name
)
804 for (tui_win_info
*item
: all_tui_windows ())
806 const char *cur_name
= item
->name ();
808 if (startswith (cur_name
, name
))
816 /* Set focus to the window named by 'arg'. */
818 tui_set_focus_command (const char *arg
, int from_tty
)
824 struct tui_win_info
*win_info
= NULL
;
826 if (subset_compare (arg
, "next"))
827 win_info
= tui_next_win (tui_win_with_focus ());
828 else if (subset_compare (arg
, "prev"))
829 win_info
= tui_prev_win (tui_win_with_focus ());
831 win_info
= tui_partial_win_by_name (arg
);
833 if (win_info
== NULL
)
834 error (_("Unrecognized window name \"%s\""), arg
);
835 if (!win_info
->is_visible ())
836 error (_("Window \"%s\" is not visible"), arg
);
838 tui_set_win_focus_to (win_info
);
839 keypad (TUI_CMD_WIN
->handle
.get (), win_info
!= TUI_CMD_WIN
);
840 printf_filtered (_("Focus set to %s window.\n"),
841 tui_win_with_focus ()->name ());
844 error (_("Incorrect Number of Arguments.\n%s"), FOCUS_USAGE
);
848 tui_all_windows_info (const char *arg
, int from_tty
)
850 struct tui_win_info
*win_with_focus
= tui_win_with_focus ();
851 struct ui_out
*uiout
= current_uiout
;
853 ui_out_emit_table
table_emitter (uiout
, 3, -1, "tui-windows");
854 uiout
->table_header (10, ui_left
, "name", "Name");
855 uiout
->table_header (5, ui_right
, "lines", "Lines");
856 uiout
->table_header (10, ui_left
, "focus", "Focus");
857 uiout
->table_body ();
859 for (tui_win_info
*win_info
: all_tui_windows ())
860 if (win_info
->is_visible ())
862 ui_out_emit_tuple
tuple_emitter (uiout
, nullptr);
864 uiout
->field_string ("name", win_info
->name ());
865 uiout
->field_signed ("lines", win_info
->height
);
866 if (win_with_focus
== win_info
)
867 uiout
->field_string ("focus", _("(has focus)"));
869 uiout
->field_skip ("focus");
876 tui_refresh_all_command (const char *arg
, int from_tty
)
878 /* Make sure the curses mode is enabled. */
881 tui_refresh_all_win ();
884 /* The tab width that should be used by the TUI. */
886 unsigned int tui_tab_width
= DEFAULT_TAB_LEN
;
888 /* The tab width as set by the user. */
890 static unsigned int internal_tab_width
= DEFAULT_TAB_LEN
;
892 /* After the tab width is set, call this to update the relevant
898 for (tui_win_info
*win_info
: all_tui_windows ())
900 if (win_info
->is_visible ())
901 win_info
->update_tab_width ();
905 /* Callback for "set tui tab-width". */
908 tui_set_tab_width (const char *ignore
,
909 int from_tty
, struct cmd_list_element
*c
)
911 if (internal_tab_width
== 0)
913 internal_tab_width
= tui_tab_width
;
914 error (_("Tab width must not be 0"));
917 tui_tab_width
= internal_tab_width
;
921 /* Callback for "show tui tab-width". */
924 tui_show_tab_width (struct ui_file
*file
, int from_tty
,
925 struct cmd_list_element
*c
, const char *value
)
927 fprintf_filtered (gdb_stdout
, _("TUI tab width is %s spaces.\n"), value
);
933 bool compact_source
= false;
935 /* Callback for "set tui compact-source". */
938 tui_set_compact_source (const char *ignore
, int from_tty
,
939 struct cmd_list_element
*c
)
941 if (TUI_SRC_WIN
!= nullptr)
942 TUI_SRC_WIN
->refill ();
945 /* Callback for "show tui compact-source". */
948 tui_show_compact_source (struct ui_file
*file
, int from_tty
,
949 struct cmd_list_element
*c
, const char *value
)
951 printf_filtered (_("TUI source window compactness is %s.\n"), value
);
954 /* Set the tab width of the specified window. */
956 tui_set_tab_width_command (const char *arg
, int from_tty
)
958 /* Make sure the curses mode is enabled. */
966 warning (_("Tab widths greater than 0 must be specified."));
969 internal_tab_width
= ts
;
978 /* Set the height of the specified window. */
980 tui_set_win_height_command (const char *arg
, int from_tty
)
982 /* Make sure the curses mode is enabled. */
986 const char *buf
= arg
;
987 const char *buf_ptr
= buf
;
989 struct tui_win_info
*win_info
;
991 buf_ptr
= strchr (buf_ptr
, ' ');
994 /* Validate the window name. */
995 gdb::string_view
wname (buf
, buf_ptr
- buf
);
996 win_info
= tui_partial_win_by_name (wname
);
998 if (win_info
== NULL
)
999 error (_("Unrecognized window name \"%s\""), arg
);
1000 if (!win_info
->is_visible ())
1001 error (_("Window \"%s\" is not visible"), arg
);
1003 /* Process the size. */
1004 buf_ptr
= skip_spaces (buf_ptr
);
1006 if (*buf_ptr
!= '\0')
1008 bool negate
= false;
1009 bool fixed_size
= true;
1012 if (*buf_ptr
== '+' || *buf_ptr
== '-')
1014 if (*buf_ptr
== '-')
1019 input_no
= atoi (buf_ptr
);
1025 new_height
= input_no
;
1027 new_height
= win_info
->height
+ input_no
;
1029 /* Now change the window's height, and adjust
1030 all other windows around it. */
1031 if (tui_adjust_win_heights (win_info
,
1032 new_height
) == TUI_FAILURE
)
1033 warning (_("Invalid window height specified.\n%s"),
1036 tui_update_gdb_sizes ();
1039 warning (_("Invalid window height specified.\n%s"),
1044 printf_filtered (WIN_HEIGHT_USAGE
);
1047 printf_filtered (WIN_HEIGHT_USAGE
);
1050 /* Function to adjust all window heights around the primary. */
1051 static enum tui_status
1052 tui_adjust_win_heights (struct tui_win_info
*primary_win_info
,
1055 enum tui_status status
= TUI_FAILURE
;
1057 if (new_height_ok (primary_win_info
, new_height
))
1059 status
= TUI_SUCCESS
;
1060 if (new_height
!= primary_win_info
->height
)
1063 struct tui_win_info
*win_info
;
1064 struct tui_locator_window
*locator
= tui_locator_win_info_ptr ();
1065 enum tui_layout_type cur_layout
= tui_current_layout ();
1066 int width
= tui_term_width ();
1068 diff
= (new_height
- primary_win_info
->height
) * (-1);
1069 if (cur_layout
== SRC_COMMAND
1070 || cur_layout
== DISASSEM_COMMAND
)
1072 struct tui_win_info
*src_win_info
;
1074 primary_win_info
->resize (new_height
, width
,
1075 0, primary_win_info
->origin
.y
);
1076 if (primary_win_info
->type
== CMD_WIN
)
1078 win_info
= *(tui_source_windows ().begin ());
1079 src_win_info
= win_info
;
1083 win_info
= tui_win_list
[CMD_WIN
];
1084 src_win_info
= primary_win_info
;
1086 win_info
->resize (win_info
->height
+ diff
, width
,
1087 0, win_info
->origin
.y
);
1088 TUI_CMD_WIN
->origin
.y
= locator
->origin
.y
+ 1;
1089 if ((src_win_info
->type
== SRC_WIN
1090 || src_win_info
->type
== DISASSEM_WIN
))
1092 tui_source_window_base
*src_base
1093 = (tui_source_window_base
*) src_win_info
;
1094 if (src_base
->content
.empty ())
1095 src_base
->erase_source_content ();
1100 struct tui_win_info
*first_win
;
1101 struct tui_source_window_base
*second_win
;
1102 tui_source_window_base
*src1
;
1104 if (cur_layout
== SRC_DISASSEM_COMMAND
)
1108 second_win
= TUI_DISASM_WIN
;
1113 first_win
= TUI_DATA_WIN
;
1114 second_win
= *(tui_source_windows ().begin ());
1116 if (primary_win_info
== TUI_CMD_WIN
)
1117 { /* Split the change in height across the 1st & 2nd
1118 windows, adjusting them as well. */
1119 /* Subtract the locator. */
1120 int first_split_diff
= diff
/ 2;
1121 int second_split_diff
= first_split_diff
;
1125 if (first_win
->height
>
1134 second_split_diff
--;
1136 second_split_diff
++;
1139 /* Make sure that the minimum heights are
1141 while ((first_win
->height
+ first_split_diff
) < 3)
1144 second_split_diff
--;
1146 while ((second_win
->height
+ second_split_diff
) < 3)
1148 second_split_diff
++;
1151 first_win
->resize (first_win
->height
+ first_split_diff
,
1153 0, first_win
->origin
.y
);
1154 second_win
->resize (second_win
->height
+ second_split_diff
,
1156 0, first_win
->height
- 1);
1157 locator
->resize (1, width
,
1158 0, (second_win
->origin
.y
1159 + second_win
->height
+ 1));
1161 TUI_CMD_WIN
->resize (new_height
, width
,
1162 0, locator
->origin
.y
+ 1);
1166 if ((TUI_CMD_WIN
->height
+ diff
) < 1)
1167 { /* If there is no way to increase the command
1168 window take real estate from the 1st or 2nd
1170 if ((TUI_CMD_WIN
->height
+ diff
) < 1)
1174 for (i
= TUI_CMD_WIN
->height
+ diff
;
1176 if (primary_win_info
== first_win
)
1177 second_win
->height
--;
1179 first_win
->height
--;
1182 if (primary_win_info
== first_win
)
1183 first_win
->resize (new_height
, width
, 0, 0);
1185 first_win
->resize (first_win
->height
, width
, 0, 0);
1186 second_win
->origin
.y
= first_win
->height
- 1;
1187 if (primary_win_info
== second_win
)
1188 second_win
->resize (new_height
, width
,
1189 0, first_win
->height
- 1);
1191 second_win
->resize (second_win
->height
, width
,
1192 0, first_win
->height
- 1);
1193 locator
->resize (1, width
,
1194 0, (second_win
->origin
.y
1195 + second_win
->height
+ 1));
1196 TUI_CMD_WIN
->origin
.y
= locator
->origin
.y
+ 1;
1197 if ((TUI_CMD_WIN
->height
+ diff
) < 1)
1198 TUI_CMD_WIN
->resize (1, width
, 0, locator
->origin
.y
+ 1);
1200 TUI_CMD_WIN
->resize (TUI_CMD_WIN
->height
+ diff
, width
,
1201 0, locator
->origin
.y
+ 1);
1203 if (src1
!= nullptr && src1
->content
.empty ())
1204 src1
->erase_source_content ();
1205 if (second_win
->content
.empty ())
1206 second_win
->erase_source_content ();
1214 /* See tui-data.h. */
1217 tui_win_info::max_height () const
1219 return tui_term_height () - 2;
1223 new_height_ok (struct tui_win_info
*primary_win_info
,
1226 int ok
= (new_height
< tui_term_height ());
1231 enum tui_layout_type cur_layout
= tui_current_layout ();
1233 diff
= (new_height
- primary_win_info
->height
) * (-1);
1234 if (cur_layout
== SRC_COMMAND
|| cur_layout
== DISASSEM_COMMAND
)
1236 ok
= (new_height
<= primary_win_info
->max_height ()
1237 && new_height
>= MIN_CMD_WIN_HEIGHT
);
1239 { /* Check the total height. */
1240 struct tui_win_info
*win_info
;
1242 if (primary_win_info
== TUI_CMD_WIN
)
1243 win_info
= *(tui_source_windows ().begin ());
1245 win_info
= TUI_CMD_WIN
;
1247 (win_info
->height
+ diff
)) <= tui_term_height ());
1252 int cur_total_height
, total_height
, min_height
= 0;
1253 struct tui_win_info
*first_win
;
1254 struct tui_win_info
*second_win
;
1256 if (cur_layout
== SRC_DISASSEM_COMMAND
)
1258 first_win
= TUI_SRC_WIN
;
1259 second_win
= TUI_DISASM_WIN
;
1263 first_win
= TUI_DATA_WIN
;
1264 second_win
= *(tui_source_windows ().begin ());
1266 /* We could simply add all the heights to obtain the same
1267 result but below is more explicit since we subtract 1 for
1268 the line that the first and second windows share, and add
1269 one for the locator. */
1270 total_height
= cur_total_height
=
1271 (first_win
->height
+ second_win
->height
- 1)
1272 + TUI_CMD_WIN
->height
+ 1; /* Locator. */
1273 if (primary_win_info
== TUI_CMD_WIN
)
1275 /* Locator included since first & second win share a line. */
1276 ok
= ((first_win
->height
+
1277 second_win
->height
+ diff
) >=
1278 (MIN_WIN_HEIGHT
* 2)
1279 && new_height
>= MIN_CMD_WIN_HEIGHT
);
1282 total_height
= new_height
+
1283 (first_win
->height
+
1284 second_win
->height
+ diff
);
1285 min_height
= MIN_CMD_WIN_HEIGHT
;
1290 min_height
= MIN_WIN_HEIGHT
;
1292 /* First see if we can increase/decrease the command
1293 window. And make sure that the command window is at
1295 ok
= ((TUI_CMD_WIN
->height
+ diff
) > 0);
1297 { /* Looks like we have to increase/decrease one of
1298 the other windows. */
1299 if (primary_win_info
== first_win
)
1300 ok
= (second_win
->height
+ diff
) >= min_height
;
1302 ok
= (first_win
->height
+ diff
) >= min_height
;
1306 if (primary_win_info
== first_win
)
1307 total_height
= new_height
+
1308 second_win
->height
+
1309 TUI_CMD_WIN
->height
+ diff
;
1311 total_height
= new_height
+
1313 TUI_CMD_WIN
->height
+ diff
;
1316 /* Now make sure that the proposed total height doesn't
1317 exceed the old total height. */
1319 ok
= (new_height
>= min_height
1320 && total_height
<= cur_total_height
);
1329 parse_scrolling_args (const char *arg
,
1330 struct tui_win_info
**win_to_scroll
,
1335 *win_to_scroll
= tui_win_with_focus ();
1337 /* First set up the default window to scroll, in case there is no
1343 /* Process the number of lines to scroll. */
1344 std::string copy
= arg
;
1346 if (isdigit (*buf_ptr
))
1351 buf_ptr
= strchr (buf_ptr
, ' ');
1352 if (buf_ptr
!= NULL
)
1356 *num_to_scroll
= atoi (num_str
);
1359 else if (num_to_scroll
)
1360 *num_to_scroll
= atoi (num_str
);
1363 /* Process the window name if one is specified. */
1364 if (buf_ptr
!= NULL
)
1368 wname
= skip_spaces (buf_ptr
);
1372 *win_to_scroll
= tui_partial_win_by_name (wname
);
1374 if (*win_to_scroll
== NULL
)
1375 error (_("Unrecognized window `%s'"), wname
);
1376 if (!(*win_to_scroll
)->is_visible ())
1377 error (_("Window is not visible"));
1378 else if (*win_to_scroll
== TUI_CMD_WIN
)
1379 *win_to_scroll
= *(tui_source_windows ().begin ());
1385 /* Function to initialize gdb commands, for tui window
1389 _initialize_tui_win (void)
1391 static struct cmd_list_element
*tui_setlist
;
1392 static struct cmd_list_element
*tui_showlist
;
1393 struct cmd_list_element
*cmd
;
1395 /* Define the classes of commands.
1396 They will appear in the help list in the reverse of this order. */
1397 add_prefix_cmd ("tui", class_tui
, set_tui_cmd
,
1398 _("TUI configuration variables."),
1399 &tui_setlist
, "set tui ",
1400 0 /* allow-unknown */, &setlist
);
1401 add_prefix_cmd ("tui", class_tui
, show_tui_cmd
,
1402 _("TUI configuration variables."),
1403 &tui_showlist
, "show tui ",
1404 0 /* allow-unknown */, &showlist
);
1406 add_com ("refresh", class_tui
, tui_refresh_all_command
,
1407 _("Refresh the terminal display."));
1409 cmd
= add_com ("tabset", class_tui
, tui_set_tab_width_command
, _("\
1410 Set the width (in characters) of tab stops.\n\
1412 deprecate_cmd (cmd
, "set tui tab-width");
1414 cmd
= add_com ("winheight", class_tui
, tui_set_win_height_command
, _("\
1415 Set or modify the height of a specified window.\n"
1417 "Window names are:\n\
1418 src : the source window\n\
1419 cmd : the command window\n\
1420 asm : the disassembly window\n\
1421 regs : the register display"));
1422 add_com_alias ("wh", "winheight", class_tui
, 0);
1423 set_cmd_completer (cmd
, winheight_completer
);
1424 add_info ("win", tui_all_windows_info
,
1425 _("List of all displayed windows."));
1426 cmd
= add_com ("focus", class_tui
, tui_set_focus_command
, _("\
1427 Set focus to named window or next/prev window.\n"
1429 "Valid Window names are:\n\
1430 src : the source window\n\
1431 asm : the disassembly window\n\
1432 regs : the register display\n\
1433 cmd : the command window"));
1434 add_com_alias ("fs", "focus", class_tui
, 0);
1435 set_cmd_completer (cmd
, focus_completer
);
1436 add_com ("+", class_tui
, tui_scroll_forward_command
, _("\
1437 Scroll window forward.\n\
1438 Usage: + [WIN] [N]"));
1439 add_com ("-", class_tui
, tui_scroll_backward_command
, _("\
1440 Scroll window backward.\n\
1441 Usage: - [WIN] [N]"));
1442 add_com ("<", class_tui
, tui_scroll_left_command
, _("\
1443 Scroll window text to the left.\n\
1444 Usage: < [WIN] [N]"));
1445 add_com (">", class_tui
, tui_scroll_right_command
, _("\
1446 Scroll window text to the right.\n\
1447 Usage: > [WIN] [N]"));
1449 /* Define the tui control variables. */
1450 add_setshow_enum_cmd ("border-kind", no_class
, tui_border_kind_enums
,
1451 &tui_border_kind
, _("\
1452 Set the kind of border for TUI windows."), _("\
1453 Show the kind of border for TUI windows."), _("\
1454 This variable controls the border of TUI windows:\n\
1455 space use a white space\n\
1456 ascii use ascii characters + - | for the border\n\
1457 acs use the Alternate Character Set"),
1459 show_tui_border_kind
,
1460 &tui_setlist
, &tui_showlist
);
1462 add_setshow_enum_cmd ("border-mode", no_class
, tui_border_mode_enums
,
1463 &tui_border_mode
, _("\
1464 Set the attribute mode to use for the TUI window borders."), _("\
1465 Show the attribute mode to use for the TUI window borders."), _("\
1466 This variable controls the attributes to use for the window borders:\n\
1467 normal normal display\n\
1468 standout use highlight mode of terminal\n\
1469 reverse use reverse video mode\n\
1470 half use half bright\n\
1471 half-standout use half bright and standout mode\n\
1472 bold use extra bright or bold\n\
1473 bold-standout use extra bright or bold with standout mode"),
1475 show_tui_border_mode
,
1476 &tui_setlist
, &tui_showlist
);
1478 add_setshow_enum_cmd ("active-border-mode", no_class
, tui_border_mode_enums
,
1479 &tui_active_border_mode
, _("\
1480 Set the attribute mode to use for the active TUI window border."), _("\
1481 Show the attribute mode to use for the active TUI window border."), _("\
1482 This variable controls the attributes to use for the active window border:\n\
1483 normal normal display\n\
1484 standout use highlight mode of terminal\n\
1485 reverse use reverse video mode\n\
1486 half use half bright\n\
1487 half-standout use half bright and standout mode\n\
1488 bold use extra bright or bold\n\
1489 bold-standout use extra bright or bold with standout mode"),
1491 show_tui_active_border_mode
,
1492 &tui_setlist
, &tui_showlist
);
1494 add_setshow_zuinteger_cmd ("tab-width", no_class
,
1495 &internal_tab_width
, _("\
1496 Set the tab width, in characters, for the TUI."), _("\
1497 Show the tab witdh, in characters, for the TUI."), _("\
1498 This variable controls how many spaces are used to display a tab character."),
1499 tui_set_tab_width
, tui_show_tab_width
,
1500 &tui_setlist
, &tui_showlist
);
1502 add_setshow_boolean_cmd ("tui-resize-message", class_maintenance
,
1503 &resize_message
, _("\
1504 Set TUI resize messaging."), _("\
1505 Show TUI resize messaging."), _("\
1506 When enabled GDB will print a message when the terminal is resized."),
1508 show_tui_resize_message
,
1509 &maintenance_set_cmdlist
,
1510 &maintenance_show_cmdlist
);
1512 add_setshow_boolean_cmd ("compact-source", class_tui
,
1513 &compact_source
, _("\
1514 Set whether the TUI source window is compact."), _("\
1515 Show whether the TUI source window is compact."), _("\
1516 This variable controls whether the TUI source window is shown\n\
1517 in a compact form. The compact form puts the source closer to\n\
1518 the line numbers and uses less horizontal space."),
1519 tui_set_compact_source
, tui_show_compact_source
,
1520 &tui_setlist
, &tui_showlist
);
1522 tui_border_style
.changed
.attach (tui_rehighlight_all
);
1523 tui_active_border_style
.changed
.attach (tui_rehighlight_all
);