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
)
852 printf_filtered (_("The TUI is not active.\n"));
856 struct tui_win_info
*win_with_focus
= tui_win_with_focus ();
857 struct ui_out
*uiout
= current_uiout
;
859 ui_out_emit_table
table_emitter (uiout
, 3, -1, "tui-windows");
860 uiout
->table_header (10, ui_left
, "name", "Name");
861 uiout
->table_header (5, ui_right
, "lines", "Lines");
862 uiout
->table_header (10, ui_left
, "focus", "Focus");
863 uiout
->table_body ();
865 for (tui_win_info
*win_info
: all_tui_windows ())
866 if (win_info
->is_visible ())
868 ui_out_emit_tuple
tuple_emitter (uiout
, nullptr);
870 uiout
->field_string ("name", win_info
->name ());
871 uiout
->field_signed ("lines", win_info
->height
);
872 if (win_with_focus
== win_info
)
873 uiout
->field_string ("focus", _("(has focus)"));
875 uiout
->field_skip ("focus");
882 tui_refresh_all_command (const char *arg
, int from_tty
)
884 /* Make sure the curses mode is enabled. */
887 tui_refresh_all_win ();
890 /* The tab width that should be used by the TUI. */
892 unsigned int tui_tab_width
= DEFAULT_TAB_LEN
;
894 /* The tab width as set by the user. */
896 static unsigned int internal_tab_width
= DEFAULT_TAB_LEN
;
898 /* After the tab width is set, call this to update the relevant
904 for (tui_win_info
*win_info
: all_tui_windows ())
906 if (win_info
->is_visible ())
907 win_info
->update_tab_width ();
911 /* Callback for "set tui tab-width". */
914 tui_set_tab_width (const char *ignore
,
915 int from_tty
, struct cmd_list_element
*c
)
917 if (internal_tab_width
== 0)
919 internal_tab_width
= tui_tab_width
;
920 error (_("Tab width must not be 0"));
923 tui_tab_width
= internal_tab_width
;
927 /* Callback for "show tui tab-width". */
930 tui_show_tab_width (struct ui_file
*file
, int from_tty
,
931 struct cmd_list_element
*c
, const char *value
)
933 fprintf_filtered (gdb_stdout
, _("TUI tab width is %s spaces.\n"), value
);
939 bool compact_source
= false;
941 /* Callback for "set tui compact-source". */
944 tui_set_compact_source (const char *ignore
, int from_tty
,
945 struct cmd_list_element
*c
)
947 if (TUI_SRC_WIN
!= nullptr)
948 TUI_SRC_WIN
->refill ();
951 /* Callback for "show tui compact-source". */
954 tui_show_compact_source (struct ui_file
*file
, int from_tty
,
955 struct cmd_list_element
*c
, const char *value
)
957 printf_filtered (_("TUI source window compactness is %s.\n"), value
);
960 /* Set the tab width of the specified window. */
962 tui_set_tab_width_command (const char *arg
, int from_tty
)
964 /* Make sure the curses mode is enabled. */
972 warning (_("Tab widths greater than 0 must be specified."));
975 internal_tab_width
= ts
;
984 /* Set the height of the specified window. */
986 tui_set_win_height_command (const char *arg
, int from_tty
)
988 /* Make sure the curses mode is enabled. */
992 const char *buf
= arg
;
993 const char *buf_ptr
= buf
;
995 struct tui_win_info
*win_info
;
997 buf_ptr
= strchr (buf_ptr
, ' ');
1000 /* Validate the window name. */
1001 gdb::string_view
wname (buf
, buf_ptr
- buf
);
1002 win_info
= tui_partial_win_by_name (wname
);
1004 if (win_info
== NULL
)
1005 error (_("Unrecognized window name \"%s\""), arg
);
1006 if (!win_info
->is_visible ())
1007 error (_("Window \"%s\" is not visible"), arg
);
1009 /* Process the size. */
1010 buf_ptr
= skip_spaces (buf_ptr
);
1012 if (*buf_ptr
!= '\0')
1014 bool negate
= false;
1015 bool fixed_size
= true;
1018 if (*buf_ptr
== '+' || *buf_ptr
== '-')
1020 if (*buf_ptr
== '-')
1025 input_no
= atoi (buf_ptr
);
1031 new_height
= input_no
;
1033 new_height
= win_info
->height
+ input_no
;
1035 /* Now change the window's height, and adjust
1036 all other windows around it. */
1037 if (tui_adjust_win_heights (win_info
,
1038 new_height
) == TUI_FAILURE
)
1039 warning (_("Invalid window height specified.\n%s"),
1042 tui_update_gdb_sizes ();
1045 warning (_("Invalid window height specified.\n%s"),
1050 printf_filtered (WIN_HEIGHT_USAGE
);
1053 printf_filtered (WIN_HEIGHT_USAGE
);
1056 /* Function to adjust all window heights around the primary. */
1057 static enum tui_status
1058 tui_adjust_win_heights (struct tui_win_info
*primary_win_info
,
1061 enum tui_status status
= TUI_FAILURE
;
1063 if (new_height_ok (primary_win_info
, new_height
))
1065 status
= TUI_SUCCESS
;
1066 if (new_height
!= primary_win_info
->height
)
1069 struct tui_win_info
*win_info
;
1070 struct tui_locator_window
*locator
= tui_locator_win_info_ptr ();
1071 enum tui_layout_type cur_layout
= tui_current_layout ();
1072 int width
= tui_term_width ();
1074 diff
= (new_height
- primary_win_info
->height
) * (-1);
1075 if (cur_layout
== SRC_COMMAND
1076 || cur_layout
== DISASSEM_COMMAND
)
1078 struct tui_win_info
*src_win_info
;
1080 primary_win_info
->resize (new_height
, width
,
1081 0, primary_win_info
->origin
.y
);
1082 if (primary_win_info
->type
== CMD_WIN
)
1084 win_info
= *(tui_source_windows ().begin ());
1085 src_win_info
= win_info
;
1089 win_info
= tui_win_list
[CMD_WIN
];
1090 src_win_info
= primary_win_info
;
1092 win_info
->resize (win_info
->height
+ diff
, width
,
1093 0, win_info
->origin
.y
);
1094 TUI_CMD_WIN
->origin
.y
= locator
->origin
.y
+ 1;
1095 if ((src_win_info
->type
== SRC_WIN
1096 || src_win_info
->type
== DISASSEM_WIN
))
1098 tui_source_window_base
*src_base
1099 = (tui_source_window_base
*) src_win_info
;
1100 if (src_base
->content
.empty ())
1101 src_base
->erase_source_content ();
1106 struct tui_win_info
*first_win
;
1107 struct tui_source_window_base
*second_win
;
1108 tui_source_window_base
*src1
;
1110 if (cur_layout
== SRC_DISASSEM_COMMAND
)
1114 second_win
= TUI_DISASM_WIN
;
1119 first_win
= TUI_DATA_WIN
;
1120 second_win
= *(tui_source_windows ().begin ());
1122 if (primary_win_info
== TUI_CMD_WIN
)
1123 { /* Split the change in height across the 1st & 2nd
1124 windows, adjusting them as well. */
1125 /* Subtract the locator. */
1126 int first_split_diff
= diff
/ 2;
1127 int second_split_diff
= first_split_diff
;
1131 if (first_win
->height
>
1140 second_split_diff
--;
1142 second_split_diff
++;
1145 /* Make sure that the minimum heights are
1147 while ((first_win
->height
+ first_split_diff
) < 3)
1150 second_split_diff
--;
1152 while ((second_win
->height
+ second_split_diff
) < 3)
1154 second_split_diff
++;
1157 first_win
->resize (first_win
->height
+ first_split_diff
,
1159 0, first_win
->origin
.y
);
1160 second_win
->resize (second_win
->height
+ second_split_diff
,
1162 0, first_win
->height
- 1);
1163 locator
->resize (1, width
,
1164 0, (second_win
->origin
.y
1165 + second_win
->height
+ 1));
1167 TUI_CMD_WIN
->resize (new_height
, width
,
1168 0, locator
->origin
.y
+ 1);
1172 if ((TUI_CMD_WIN
->height
+ diff
) < 1)
1173 { /* If there is no way to increase the command
1174 window take real estate from the 1st or 2nd
1176 if ((TUI_CMD_WIN
->height
+ diff
) < 1)
1180 for (i
= TUI_CMD_WIN
->height
+ diff
;
1182 if (primary_win_info
== first_win
)
1183 second_win
->height
--;
1185 first_win
->height
--;
1188 if (primary_win_info
== first_win
)
1189 first_win
->resize (new_height
, width
, 0, 0);
1191 first_win
->resize (first_win
->height
, width
, 0, 0);
1192 second_win
->origin
.y
= first_win
->height
- 1;
1193 if (primary_win_info
== second_win
)
1194 second_win
->resize (new_height
, width
,
1195 0, first_win
->height
- 1);
1197 second_win
->resize (second_win
->height
, width
,
1198 0, first_win
->height
- 1);
1199 locator
->resize (1, width
,
1200 0, (second_win
->origin
.y
1201 + second_win
->height
+ 1));
1202 TUI_CMD_WIN
->origin
.y
= locator
->origin
.y
+ 1;
1203 if ((TUI_CMD_WIN
->height
+ diff
) < 1)
1204 TUI_CMD_WIN
->resize (1, width
, 0, locator
->origin
.y
+ 1);
1206 TUI_CMD_WIN
->resize (TUI_CMD_WIN
->height
+ diff
, width
,
1207 0, locator
->origin
.y
+ 1);
1209 if (src1
!= nullptr && src1
->content
.empty ())
1210 src1
->erase_source_content ();
1211 if (second_win
->content
.empty ())
1212 second_win
->erase_source_content ();
1220 /* See tui-data.h. */
1223 tui_win_info::max_height () const
1225 return tui_term_height () - 2;
1229 new_height_ok (struct tui_win_info
*primary_win_info
,
1232 int ok
= (new_height
< tui_term_height ());
1237 enum tui_layout_type cur_layout
= tui_current_layout ();
1239 diff
= (new_height
- primary_win_info
->height
) * (-1);
1240 if (cur_layout
== SRC_COMMAND
|| cur_layout
== DISASSEM_COMMAND
)
1242 ok
= (new_height
<= primary_win_info
->max_height ()
1243 && new_height
>= MIN_CMD_WIN_HEIGHT
);
1245 { /* Check the total height. */
1246 struct tui_win_info
*win_info
;
1248 if (primary_win_info
== TUI_CMD_WIN
)
1249 win_info
= *(tui_source_windows ().begin ());
1251 win_info
= TUI_CMD_WIN
;
1253 (win_info
->height
+ diff
)) <= tui_term_height ());
1258 int cur_total_height
, total_height
, min_height
= 0;
1259 struct tui_win_info
*first_win
;
1260 struct tui_win_info
*second_win
;
1262 if (cur_layout
== SRC_DISASSEM_COMMAND
)
1264 first_win
= TUI_SRC_WIN
;
1265 second_win
= TUI_DISASM_WIN
;
1269 first_win
= TUI_DATA_WIN
;
1270 second_win
= *(tui_source_windows ().begin ());
1272 /* We could simply add all the heights to obtain the same
1273 result but below is more explicit since we subtract 1 for
1274 the line that the first and second windows share, and add
1275 one for the locator. */
1276 total_height
= cur_total_height
=
1277 (first_win
->height
+ second_win
->height
- 1)
1278 + TUI_CMD_WIN
->height
+ 1; /* Locator. */
1279 if (primary_win_info
== TUI_CMD_WIN
)
1281 /* Locator included since first & second win share a line. */
1282 ok
= ((first_win
->height
+
1283 second_win
->height
+ diff
) >=
1284 (MIN_WIN_HEIGHT
* 2)
1285 && new_height
>= MIN_CMD_WIN_HEIGHT
);
1288 total_height
= new_height
+
1289 (first_win
->height
+
1290 second_win
->height
+ diff
);
1291 min_height
= MIN_CMD_WIN_HEIGHT
;
1296 min_height
= MIN_WIN_HEIGHT
;
1298 /* First see if we can increase/decrease the command
1299 window. And make sure that the command window is at
1301 ok
= ((TUI_CMD_WIN
->height
+ diff
) > 0);
1303 { /* Looks like we have to increase/decrease one of
1304 the other windows. */
1305 if (primary_win_info
== first_win
)
1306 ok
= (second_win
->height
+ diff
) >= min_height
;
1308 ok
= (first_win
->height
+ diff
) >= min_height
;
1312 if (primary_win_info
== first_win
)
1313 total_height
= new_height
+
1314 second_win
->height
+
1315 TUI_CMD_WIN
->height
+ diff
;
1317 total_height
= new_height
+
1319 TUI_CMD_WIN
->height
+ diff
;
1322 /* Now make sure that the proposed total height doesn't
1323 exceed the old total height. */
1325 ok
= (new_height
>= min_height
1326 && total_height
<= cur_total_height
);
1335 parse_scrolling_args (const char *arg
,
1336 struct tui_win_info
**win_to_scroll
,
1341 *win_to_scroll
= tui_win_with_focus ();
1343 /* First set up the default window to scroll, in case there is no
1349 /* Process the number of lines to scroll. */
1350 std::string copy
= arg
;
1352 if (isdigit (*buf_ptr
))
1357 buf_ptr
= strchr (buf_ptr
, ' ');
1358 if (buf_ptr
!= NULL
)
1362 *num_to_scroll
= atoi (num_str
);
1365 else if (num_to_scroll
)
1366 *num_to_scroll
= atoi (num_str
);
1369 /* Process the window name if one is specified. */
1370 if (buf_ptr
!= NULL
)
1374 wname
= skip_spaces (buf_ptr
);
1378 *win_to_scroll
= tui_partial_win_by_name (wname
);
1380 if (*win_to_scroll
== NULL
)
1381 error (_("Unrecognized window `%s'"), wname
);
1382 if (!(*win_to_scroll
)->is_visible ())
1383 error (_("Window is not visible"));
1384 else if (*win_to_scroll
== TUI_CMD_WIN
)
1385 *win_to_scroll
= *(tui_source_windows ().begin ());
1391 /* Function to initialize gdb commands, for tui window
1395 _initialize_tui_win (void)
1397 static struct cmd_list_element
*tui_setlist
;
1398 static struct cmd_list_element
*tui_showlist
;
1399 struct cmd_list_element
*cmd
;
1401 /* Define the classes of commands.
1402 They will appear in the help list in the reverse of this order. */
1403 add_prefix_cmd ("tui", class_tui
, set_tui_cmd
,
1404 _("TUI configuration variables."),
1405 &tui_setlist
, "set tui ",
1406 0 /* allow-unknown */, &setlist
);
1407 add_prefix_cmd ("tui", class_tui
, show_tui_cmd
,
1408 _("TUI configuration variables."),
1409 &tui_showlist
, "show tui ",
1410 0 /* allow-unknown */, &showlist
);
1412 add_com ("refresh", class_tui
, tui_refresh_all_command
,
1413 _("Refresh the terminal display."));
1415 cmd
= add_com ("tabset", class_tui
, tui_set_tab_width_command
, _("\
1416 Set the width (in characters) of tab stops.\n\
1418 deprecate_cmd (cmd
, "set tui tab-width");
1420 cmd
= add_com ("winheight", class_tui
, tui_set_win_height_command
, _("\
1421 Set or modify the height of a specified window.\n"
1423 "Window names are:\n\
1424 src : the source window\n\
1425 cmd : the command window\n\
1426 asm : the disassembly window\n\
1427 regs : the register display"));
1428 add_com_alias ("wh", "winheight", class_tui
, 0);
1429 set_cmd_completer (cmd
, winheight_completer
);
1430 add_info ("win", tui_all_windows_info
,
1431 _("List of all displayed windows."));
1432 cmd
= add_com ("focus", class_tui
, tui_set_focus_command
, _("\
1433 Set focus to named window or next/prev window.\n"
1435 "Valid Window names are:\n\
1436 src : the source window\n\
1437 asm : the disassembly window\n\
1438 regs : the register display\n\
1439 cmd : the command window"));
1440 add_com_alias ("fs", "focus", class_tui
, 0);
1441 set_cmd_completer (cmd
, focus_completer
);
1442 add_com ("+", class_tui
, tui_scroll_forward_command
, _("\
1443 Scroll window forward.\n\
1444 Usage: + [WIN] [N]"));
1445 add_com ("-", class_tui
, tui_scroll_backward_command
, _("\
1446 Scroll window backward.\n\
1447 Usage: - [WIN] [N]"));
1448 add_com ("<", class_tui
, tui_scroll_left_command
, _("\
1449 Scroll window text to the left.\n\
1450 Usage: < [WIN] [N]"));
1451 add_com (">", class_tui
, tui_scroll_right_command
, _("\
1452 Scroll window text to the right.\n\
1453 Usage: > [WIN] [N]"));
1455 /* Define the tui control variables. */
1456 add_setshow_enum_cmd ("border-kind", no_class
, tui_border_kind_enums
,
1457 &tui_border_kind
, _("\
1458 Set the kind of border for TUI windows."), _("\
1459 Show the kind of border for TUI windows."), _("\
1460 This variable controls the border of TUI windows:\n\
1461 space use a white space\n\
1462 ascii use ascii characters + - | for the border\n\
1463 acs use the Alternate Character Set"),
1465 show_tui_border_kind
,
1466 &tui_setlist
, &tui_showlist
);
1468 add_setshow_enum_cmd ("border-mode", no_class
, tui_border_mode_enums
,
1469 &tui_border_mode
, _("\
1470 Set the attribute mode to use for the TUI window borders."), _("\
1471 Show the attribute mode to use for the TUI window borders."), _("\
1472 This variable controls the attributes to use for the window borders:\n\
1473 normal normal display\n\
1474 standout use highlight mode of terminal\n\
1475 reverse use reverse video mode\n\
1476 half use half bright\n\
1477 half-standout use half bright and standout mode\n\
1478 bold use extra bright or bold\n\
1479 bold-standout use extra bright or bold with standout mode"),
1481 show_tui_border_mode
,
1482 &tui_setlist
, &tui_showlist
);
1484 add_setshow_enum_cmd ("active-border-mode", no_class
, tui_border_mode_enums
,
1485 &tui_active_border_mode
, _("\
1486 Set the attribute mode to use for the active TUI window border."), _("\
1487 Show the attribute mode to use for the active TUI window border."), _("\
1488 This variable controls the attributes to use for the active window border:\n\
1489 normal normal display\n\
1490 standout use highlight mode of terminal\n\
1491 reverse use reverse video mode\n\
1492 half use half bright\n\
1493 half-standout use half bright and standout mode\n\
1494 bold use extra bright or bold\n\
1495 bold-standout use extra bright or bold with standout mode"),
1497 show_tui_active_border_mode
,
1498 &tui_setlist
, &tui_showlist
);
1500 add_setshow_zuinteger_cmd ("tab-width", no_class
,
1501 &internal_tab_width
, _("\
1502 Set the tab width, in characters, for the TUI."), _("\
1503 Show the tab witdh, in characters, for the TUI."), _("\
1504 This variable controls how many spaces are used to display a tab character."),
1505 tui_set_tab_width
, tui_show_tab_width
,
1506 &tui_setlist
, &tui_showlist
);
1508 add_setshow_boolean_cmd ("tui-resize-message", class_maintenance
,
1509 &resize_message
, _("\
1510 Set TUI resize messaging."), _("\
1511 Show TUI resize messaging."), _("\
1512 When enabled GDB will print a message when the terminal is resized."),
1514 show_tui_resize_message
,
1515 &maintenance_set_cmdlist
,
1516 &maintenance_show_cmdlist
);
1518 add_setshow_boolean_cmd ("compact-source", class_tui
,
1519 &compact_source
, _("\
1520 Set whether the TUI source window is compact."), _("\
1521 Show whether the TUI source window is compact."), _("\
1522 This variable controls whether the TUI source window is shown\n\
1523 in a compact form. The compact form puts the source closer to\n\
1524 the line numbers and uses less horizontal space."),
1525 tui_set_compact_source
, tui_show_compact_source
,
1526 &tui_setlist
, &tui_showlist
);
1528 tui_border_style
.changed
.attach (tui_rehighlight_all
);
1529 tui_active_border_style
.changed
.attach (tui_rehighlight_all
);