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"
38 #include "tui/tui-io.h"
39 #include "tui/tui-command.h"
40 #include "tui/tui-data.h"
41 #include "tui/tui-wingeneral.h"
42 #include "tui/tui-stack.h"
43 #include "tui/tui-regs.h"
44 #include "tui/tui-disasm.h"
45 #include "tui/tui-source.h"
46 #include "tui/tui-winsource.h"
47 #include "tui/tui-win.h"
49 #include "gdb_curses.h"
51 #include "readline/readline.h"
55 /*******************************
57 ********************************/
58 static void make_invisible_and_set_new_height (struct tui_win_info
*,
60 static enum tui_status
tui_adjust_win_heights (struct tui_win_info
*,
62 static int new_height_ok (struct tui_win_info
*, int);
63 static void tui_set_tab_width_command (const char *, int);
64 static void tui_refresh_all_command (const char *, int);
65 static void tui_all_windows_info (const char *, int);
66 static void tui_scroll_forward_command (const char *, int);
67 static void tui_scroll_backward_command (const char *, int);
68 static void tui_scroll_left_command (const char *, int);
69 static void tui_scroll_right_command (const char *, int);
70 static void parse_scrolling_args (const char *,
71 struct tui_win_info
**,
75 /***************************************
77 ***************************************/
78 #define WIN_HEIGHT_USAGE "Usage: winheight WINDOW-NAME [+ | -] NUM-LINES\n"
79 #define FOCUS_USAGE "Usage: focus [WINDOW-NAME | next | prev]\n"
81 /***************************************
83 ***************************************/
86 # define ACS_LRCORNER '+'
89 # define ACS_LLCORNER '+'
92 # define ACS_ULCORNER '+'
95 # define ACS_URCORNER '+'
98 # define ACS_HLINE '-'
101 # define ACS_VLINE '|'
104 /* Possible values for tui-border-kind variable. */
105 static const char *const tui_border_kind_enums
[] = {
112 /* Possible values for tui-border-mode and tui-active-border-mode. */
113 static const char *const tui_border_mode_enums
[] = {
130 /* Translation table for border-mode variables.
131 The list of values must be terminated by a NULL.
132 After the NULL value, an entry defines the default. */
133 struct tui_translate tui_border_mode_translate
[] = {
134 { "normal", A_NORMAL
},
135 { "standout", A_STANDOUT
},
136 { "reverse", A_REVERSE
},
138 { "half-standout", A_DIM
| A_STANDOUT
},
140 { "bold-standout", A_BOLD
| A_STANDOUT
},
142 { "normal", A_NORMAL
}
145 /* Translation tables for border-kind, one for each border
146 character (see wborder, border curses operations).
147 -1 is used to indicate the ACS because ACS characters
148 are determined at run time by curses (depends on terminal). */
149 struct tui_translate tui_border_kind_translate_vline
[] = {
157 struct tui_translate tui_border_kind_translate_hline
[] = {
165 struct tui_translate tui_border_kind_translate_ulcorner
[] = {
173 struct tui_translate tui_border_kind_translate_urcorner
[] = {
181 struct tui_translate tui_border_kind_translate_llcorner
[] = {
189 struct tui_translate tui_border_kind_translate_lrcorner
[] = {
198 /* Tui configuration variables controlled with set/show command. */
199 const char *tui_active_border_mode
= "bold-standout";
201 show_tui_active_border_mode (struct ui_file
*file
,
203 struct cmd_list_element
*c
,
206 fprintf_filtered (file
, _("\
207 The attribute mode to use for the active TUI window border is \"%s\".\n"),
211 const char *tui_border_mode
= "normal";
213 show_tui_border_mode (struct ui_file
*file
,
215 struct cmd_list_element
*c
,
218 fprintf_filtered (file
, _("\
219 The attribute mode to use for the TUI window borders is \"%s\".\n"),
223 const char *tui_border_kind
= "acs";
225 show_tui_border_kind (struct ui_file
*file
,
227 struct cmd_list_element
*c
,
230 fprintf_filtered (file
, _("The kind of border for TUI windows is \"%s\".\n"),
235 /* Tui internal configuration variables. These variables are updated
236 by tui_update_variables to reflect the tui configuration
238 chtype tui_border_vline
;
239 chtype tui_border_hline
;
240 chtype tui_border_ulcorner
;
241 chtype tui_border_urcorner
;
242 chtype tui_border_llcorner
;
243 chtype tui_border_lrcorner
;
245 int tui_border_attrs
;
246 int tui_active_border_attrs
;
248 /* Identify the item in the translation table.
249 When the item is not recognized, use the default entry. */
250 static struct tui_translate
*
251 translate (const char *name
, struct tui_translate
*table
)
255 if (name
&& strcmp (table
->name
, name
) == 0)
260 /* Not found, return default entry. */
265 /* Update the tui internal configuration according to gdb settings.
266 Returns 1 if the configuration has changed and the screen should
269 tui_update_variables (void)
272 struct tui_translate
*entry
;
274 entry
= translate (tui_border_mode
, tui_border_mode_translate
);
275 if (tui_border_attrs
!= entry
->value
)
277 tui_border_attrs
= entry
->value
;
280 entry
= translate (tui_active_border_mode
, tui_border_mode_translate
);
281 if (tui_active_border_attrs
!= entry
->value
)
283 tui_active_border_attrs
= entry
->value
;
287 /* If one corner changes, all characters are changed.
288 Only check the first one. The ACS characters are determined at
289 run time by curses terminal management. */
290 entry
= translate (tui_border_kind
, tui_border_kind_translate_lrcorner
);
291 if (tui_border_lrcorner
!= (chtype
) entry
->value
)
293 tui_border_lrcorner
= (entry
->value
< 0) ? ACS_LRCORNER
: entry
->value
;
296 entry
= translate (tui_border_kind
, tui_border_kind_translate_llcorner
);
297 tui_border_llcorner
= (entry
->value
< 0) ? ACS_LLCORNER
: entry
->value
;
299 entry
= translate (tui_border_kind
, tui_border_kind_translate_ulcorner
);
300 tui_border_ulcorner
= (entry
->value
< 0) ? ACS_ULCORNER
: entry
->value
;
302 entry
= translate (tui_border_kind
, tui_border_kind_translate_urcorner
);
303 tui_border_urcorner
= (entry
->value
< 0) ? ACS_URCORNER
: entry
->value
;
305 entry
= translate (tui_border_kind
, tui_border_kind_translate_hline
);
306 tui_border_hline
= (entry
->value
< 0) ? ACS_HLINE
: entry
->value
;
308 entry
= translate (tui_border_kind
, tui_border_kind_translate_vline
);
309 tui_border_vline
= (entry
->value
< 0) ? ACS_VLINE
: entry
->value
;
315 set_tui_cmd (const char *args
, int from_tty
)
320 show_tui_cmd (const char *args
, int from_tty
)
324 static struct cmd_list_element
*tuilist
;
327 tui_command (const char *args
, int from_tty
)
329 printf_unfiltered (_("\"tui\" must be followed by the name of a "
331 help_list (tuilist
, "tui ", all_commands
, gdb_stdout
);
334 struct cmd_list_element
**
335 tui_get_cmd_list (void)
338 add_prefix_cmd ("tui", class_tui
, tui_command
,
339 _("Text User Interface commands."),
340 &tuilist
, "tui ", 0, &cmdlist
);
344 /* The set_func hook of "set tui ..." commands that affect the window
345 borders on the TUI display. */
347 tui_set_var_cmd (const char *null_args
,
348 int from_tty
, struct cmd_list_element
*c
)
350 if (tui_update_variables () && tui_active
)
351 tui_rehighlight_all ();
354 /* Generic window name completion function. Complete window name pointed
355 to by TEXT and WORD. If INCLUDE_NEXT_PREV_P is true then the special
356 window names 'next' and 'prev' will also be considered as possible
357 completions of the window name. */
360 window_name_completer (completion_tracker
&tracker
,
361 int include_next_prev_p
,
362 const char *text
, const char *word
)
364 std::vector
<const char *> completion_name_vec
;
366 for (tui_win_info
*win_info
: all_tui_windows ())
368 const char *completion_name
= NULL
;
370 /* We can't focus on an invisible window. */
371 if (!win_info
->is_visible
)
374 completion_name
= win_info
->name ();
375 gdb_assert (completion_name
!= NULL
);
376 completion_name_vec
.push_back (completion_name
);
379 /* If no windows are considered visible then the TUI has not yet been
380 initialized. But still "focus src" and "focus cmd" will work because
381 invoking the focus command will entail initializing the TUI which sets the
382 default layout to SRC_COMMAND. */
383 if (completion_name_vec
.empty ())
385 completion_name_vec
.push_back (SRC_NAME
);
386 completion_name_vec
.push_back (CMD_NAME
);
389 if (include_next_prev_p
)
391 completion_name_vec
.push_back ("next");
392 completion_name_vec
.push_back ("prev");
396 completion_name_vec
.push_back (NULL
);
397 complete_on_enum (tracker
, completion_name_vec
.data (), text
, word
);
400 /* Complete possible window names to focus on. TEXT is the complete text
401 entered so far, WORD is the word currently being completed. */
404 focus_completer (struct cmd_list_element
*ignore
,
405 completion_tracker
&tracker
,
406 const char *text
, const char *word
)
408 window_name_completer (tracker
, 1, text
, word
);
411 /* Complete possible window names for winheight command. TEXT is the
412 complete text entered so far, WORD is the word currently being
416 winheight_completer (struct cmd_list_element
*ignore
,
417 completion_tracker
&tracker
,
418 const char *text
, const char *word
)
420 /* The first word is the window name. That we can complete. Subsequent
421 words can't be completed. */
425 window_name_completer (tracker
, 0, text
, word
);
428 /* Update gdb's knowledge of the terminal size. */
430 tui_update_gdb_sizes (void)
436 width
= TUI_CMD_WIN
->width
;
437 height
= TUI_CMD_WIN
->height
;
441 width
= tui_term_width ();
442 height
= tui_term_height ();
445 set_screen_width_and_height (width
, height
);
449 /* Set the logical focus to win_info. */
451 tui_set_win_focus_to (struct tui_win_info
*win_info
)
453 if (win_info
!= NULL
)
455 struct tui_win_info
*win_with_focus
= tui_win_with_focus ();
457 tui_unhighlight_win (win_with_focus
);
458 tui_set_win_with_focus (win_info
);
459 tui_highlight_win (win_info
);
465 tui_win_info::forward_scroll (int num_to_scroll
)
467 if (num_to_scroll
== 0)
468 num_to_scroll
= height
- 3;
470 do_scroll_vertical (num_to_scroll
);
474 tui_win_info::backward_scroll (int num_to_scroll
)
476 if (num_to_scroll
== 0)
477 num_to_scroll
= height
- 3;
479 do_scroll_vertical (-num_to_scroll
);
484 tui_win_info::left_scroll (int num_to_scroll
)
486 if (num_to_scroll
== 0)
489 do_scroll_horizontal (num_to_scroll
);
494 tui_win_info::right_scroll (int num_to_scroll
)
496 if (num_to_scroll
== 0)
499 do_scroll_horizontal (-num_to_scroll
);
503 /* See tui-data.h. */
506 tui_source_window_base::refresh_all ()
508 tui_show_source_content (this);
509 tui_check_and_display_highlight_if_needed (this);
510 tui_erase_exec_info_content (this);
511 tui_update_exec_info (this);
515 tui_refresh_all_win (void)
517 clearok (curscr
, TRUE
);
519 for (tui_win_info
*win_info
: all_tui_windows ())
521 if (win_info
->is_visible
)
522 win_info
->refresh_all ();
524 tui_show_locator_content ();
528 tui_rehighlight_all (void)
530 for (tui_win_info
*win_info
: all_tui_windows ())
531 tui_check_and_display_highlight_if_needed (win_info
);
534 /* Resize all the windows based on the terminal size. This function
535 gets called from within the readline SIGWINCH handler. */
537 tui_resize_all (void)
539 int height_diff
, width_diff
;
540 int screenheight
, screenwidth
;
542 rl_get_screen_size (&screenheight
, &screenwidth
);
543 width_diff
= screenwidth
- tui_term_width ();
544 height_diff
= screenheight
- tui_term_height ();
545 if (height_diff
|| width_diff
)
547 enum tui_layout_type cur_layout
= tui_current_layout ();
548 struct tui_win_info
*win_with_focus
= tui_win_with_focus ();
549 struct tui_win_info
*first_win
;
550 struct tui_win_info
*second_win
;
551 tui_source_window_base
*src_win
;
552 struct tui_locator_window
*locator
= tui_locator_win_info_ptr ();
554 int new_height
, split_diff
, cmd_split_diff
, num_wins_displayed
= 2;
556 #ifdef HAVE_RESIZE_TERM
557 resize_term (screenheight
, screenwidth
);
559 /* Turn keypad off while we resize. */
560 if (win_with_focus
!= TUI_CMD_WIN
)
561 keypad (TUI_CMD_WIN
->handle
, FALSE
);
562 tui_update_gdb_sizes ();
563 tui_set_term_height_to (screenheight
);
564 tui_set_term_width_to (screenwidth
);
565 if (cur_layout
== SRC_DISASSEM_COMMAND
566 || cur_layout
== SRC_DATA_COMMAND
567 || cur_layout
== DISASSEM_DATA_COMMAND
)
568 num_wins_displayed
++;
569 split_diff
= height_diff
/ num_wins_displayed
;
570 cmd_split_diff
= split_diff
;
571 if (height_diff
% num_wins_displayed
)
578 /* Now adjust each window. */
579 /* erase + clearok are used instead of a straightforward clear as
580 AIX 5.3 does not define clear. */
582 clearok (curscr
, TRUE
);
587 case DISASSEM_COMMAND
:
588 src_win
= tui_source_windows ()[0];
590 first_win
->width
+= width_diff
;
591 locator
->width
+= width_diff
;
592 /* Check for invalid heights. */
593 if (height_diff
== 0)
594 new_height
= first_win
->height
;
595 else if ((first_win
->height
+ split_diff
) >=
596 (screenheight
- MIN_CMD_WIN_HEIGHT
- 1))
597 new_height
= screenheight
- MIN_CMD_WIN_HEIGHT
- 1;
598 else if ((first_win
->height
+ split_diff
) <= 0)
599 new_height
= MIN_WIN_HEIGHT
;
601 new_height
= first_win
->height
+ split_diff
;
603 locator
->origin
.y
= new_height
+ 1;
604 make_invisible_and_set_new_height (first_win
, new_height
);
605 TUI_CMD_WIN
->origin
.y
= locator
->origin
.y
+ 1;
606 TUI_CMD_WIN
->width
+= width_diff
;
607 new_height
= screenheight
- TUI_CMD_WIN
->origin
.y
;
608 make_invisible_and_set_new_height (TUI_CMD_WIN
, new_height
);
609 first_win
->make_visible_with_new_height ();
610 TUI_CMD_WIN
->make_visible_with_new_height ();
611 if (src_win
->content
.empty ())
612 tui_erase_source_content (src_win
);
615 if (cur_layout
== SRC_DISASSEM_COMMAND
)
617 src_win
= TUI_SRC_WIN
;
619 first_win
->width
+= width_diff
;
620 second_win
= TUI_DISASM_WIN
;
621 second_win
->width
+= width_diff
;
625 first_win
= TUI_DATA_WIN
;
626 first_win
->width
+= width_diff
;
627 src_win
= tui_source_windows ()[0];
628 second_win
= src_win
;
629 second_win
->width
+= width_diff
;
631 /* Change the first window's height/width. */
632 /* Check for invalid heights. */
633 if (height_diff
== 0)
634 new_height
= first_win
->height
;
635 else if ((first_win
->height
+
636 second_win
->height
+ (split_diff
* 2)) >=
637 (screenheight
- MIN_CMD_WIN_HEIGHT
- 1))
638 new_height
= (screenheight
- MIN_CMD_WIN_HEIGHT
- 1) / 2;
639 else if ((first_win
->height
+ split_diff
) <= 0)
640 new_height
= MIN_WIN_HEIGHT
;
642 new_height
= first_win
->height
+ split_diff
;
643 make_invisible_and_set_new_height (first_win
, new_height
);
645 locator
->width
+= width_diff
;
647 /* Change the second window's height/width. */
648 /* Check for invalid heights. */
649 if (height_diff
== 0)
650 new_height
= second_win
->height
;
651 else if ((first_win
->height
+
652 second_win
->height
+ (split_diff
* 2)) >=
653 (screenheight
- MIN_CMD_WIN_HEIGHT
- 1))
655 new_height
= screenheight
- MIN_CMD_WIN_HEIGHT
- 1;
657 new_height
= (new_height
/ 2) + 1;
661 else if ((second_win
->height
+ split_diff
) <= 0)
662 new_height
= MIN_WIN_HEIGHT
;
664 new_height
= second_win
->height
+ split_diff
;
665 second_win
->origin
.y
= first_win
->height
- 1;
666 make_invisible_and_set_new_height (second_win
, new_height
);
668 /* Change the command window's height/width. */
669 TUI_CMD_WIN
->origin
.y
= locator
->origin
.y
+ 1;
670 make_invisible_and_set_new_height (TUI_CMD_WIN
,
673 first_win
->make_visible_with_new_height ();
674 second_win
->make_visible_with_new_height ();
675 TUI_CMD_WIN
->make_visible_with_new_height ();
676 if (src_win
->content
.empty ())
677 tui_erase_source_content (src_win
);
680 /* Now remove all invisible windows, and their content so that
681 they get created again when called for with the new size. */
682 for (win_type
= SRC_WIN
; (win_type
< MAX_MAJOR_WINDOWS
); win_type
++)
684 if (win_type
!= CMD_WIN
685 && (tui_win_list
[win_type
] != NULL
)
686 && !tui_win_list
[win_type
]->is_visible
)
688 delete tui_win_list
[win_type
];
689 tui_win_list
[win_type
] = NULL
;
692 /* Turn keypad back on, unless focus is in the command
694 if (win_with_focus
!= TUI_CMD_WIN
)
695 keypad (TUI_CMD_WIN
->handle
, TRUE
);
700 /* Token for use by TUI's asynchronous SIGWINCH handler. */
701 static struct async_signal_handler
*tui_sigwinch_token
;
703 /* TUI's SIGWINCH signal handler. */
705 tui_sigwinch_handler (int signal
)
707 mark_async_signal_handler (tui_sigwinch_token
);
708 tui_set_win_resized_to (TRUE
);
711 /* Callback for asynchronously resizing TUI following a SIGWINCH signal. */
713 tui_async_resize_screen (gdb_client_data arg
)
715 rl_resize_terminal ();
719 int screen_height
, screen_width
;
721 rl_get_screen_size (&screen_height
, &screen_width
);
722 set_screen_width_and_height (screen_width
, screen_height
);
724 /* win_resized is left set so that the next call to tui_enable()
725 resizes the TUI windows. */
729 tui_set_win_resized_to (FALSE
);
731 tui_refresh_all_win ();
732 tui_update_gdb_sizes ();
733 tui_redisplay_readline ();
738 /* Initialize TUI's SIGWINCH signal handler. Note that the handler is not
739 uninstalled when we exit TUI, so the handler should not assume that TUI is
742 tui_initialize_win (void)
746 = create_async_signal_handler (tui_async_resize_screen
, NULL
);
749 #ifdef HAVE_SIGACTION
750 struct sigaction old_winch
;
752 memset (&old_winch
, 0, sizeof (old_winch
));
753 old_winch
.sa_handler
= &tui_sigwinch_handler
;
755 old_winch
.sa_flags
= SA_RESTART
;
757 sigaction (SIGWINCH
, &old_winch
, NULL
);
759 signal (SIGWINCH
, &tui_sigwinch_handler
);
766 /*************************
767 ** STATIC LOCAL FUNCTIONS
768 **************************/
772 tui_scroll_forward_command (const char *arg
, int from_tty
)
774 int num_to_scroll
= 1;
775 struct tui_win_info
*win_to_scroll
;
777 /* Make sure the curses mode is enabled. */
780 parse_scrolling_args (arg
, &win_to_scroll
, NULL
);
782 parse_scrolling_args (arg
, &win_to_scroll
, &num_to_scroll
);
783 win_to_scroll
->forward_scroll (num_to_scroll
);
788 tui_scroll_backward_command (const char *arg
, int from_tty
)
790 int num_to_scroll
= 1;
791 struct tui_win_info
*win_to_scroll
;
793 /* Make sure the curses mode is enabled. */
796 parse_scrolling_args (arg
, &win_to_scroll
, NULL
);
798 parse_scrolling_args (arg
, &win_to_scroll
, &num_to_scroll
);
799 win_to_scroll
->backward_scroll (num_to_scroll
);
804 tui_scroll_left_command (const char *arg
, int from_tty
)
807 struct tui_win_info
*win_to_scroll
;
809 /* Make sure the curses mode is enabled. */
811 parse_scrolling_args (arg
, &win_to_scroll
, &num_to_scroll
);
812 win_to_scroll
->left_scroll (num_to_scroll
);
817 tui_scroll_right_command (const char *arg
, int from_tty
)
820 struct tui_win_info
*win_to_scroll
;
822 /* Make sure the curses mode is enabled. */
824 parse_scrolling_args (arg
, &win_to_scroll
, &num_to_scroll
);
825 win_to_scroll
->right_scroll (num_to_scroll
);
829 /* Set focus to the window named by 'arg'. */
831 tui_set_focus_command (const char *arg
, int from_tty
)
837 char *buf_ptr
= xstrdup (arg
);
839 struct tui_win_info
*win_info
= NULL
;
841 for (i
= 0; (i
< strlen (buf_ptr
)); i
++)
842 buf_ptr
[i
] = tolower (arg
[i
]);
844 if (subset_compare (buf_ptr
, "next"))
845 win_info
= tui_next_win (tui_win_with_focus ());
846 else if (subset_compare (buf_ptr
, "prev"))
847 win_info
= tui_prev_win (tui_win_with_focus ());
849 win_info
= tui_partial_win_by_name (buf_ptr
);
851 if (win_info
== NULL
|| !win_info
->is_visible
)
852 warning (_("Invalid window specified. \n\
853 The window name specified must be valid and visible.\n"));
856 tui_set_win_focus_to (win_info
);
857 keypad (TUI_CMD_WIN
->handle
, (win_info
!= TUI_CMD_WIN
));
861 printf_filtered (_("Focus set to %s window.\n"),
862 tui_win_with_focus ()->name ());
865 warning (_("Incorrect Number of Arguments.\n%s"), FOCUS_USAGE
);
869 tui_all_windows_info (const char *arg
, int from_tty
)
871 struct tui_win_info
*win_with_focus
= tui_win_with_focus ();
873 for (tui_win_info
*win_info
: all_tui_windows ())
874 if (win_info
->is_visible
)
876 if (win_with_focus
== win_info
)
877 printf_filtered (" %s\t(%d lines) <has focus>\n",
881 printf_filtered (" %s\t(%d lines)\n",
889 tui_refresh_all_command (const char *arg
, int from_tty
)
891 /* Make sure the curses mode is enabled. */
894 tui_refresh_all_win ();
897 /* The tab width that should be used by the TUI. */
899 unsigned int tui_tab_width
= DEFAULT_TAB_LEN
;
901 /* The tab width as set by the user. */
903 static unsigned int internal_tab_width
= DEFAULT_TAB_LEN
;
905 /* See tui-data.h. */
908 tui_source_window_base::update_tab_width ()
910 /* We don't really change the height of any windows, but
911 calling these 2 functions causes a complete regeneration
912 and redisplay of the window's contents, which will take
913 the new tab width into account. */
914 make_invisible_and_set_new_height (this, height
);
915 make_visible_with_new_height ();
918 /* After the tab width is set, call this to update the relevant
924 for (tui_win_info
*win_info
: all_tui_windows ())
926 if (win_info
->is_visible
)
927 win_info
->update_tab_width ();
931 /* Callback for "set tui tab-width". */
934 tui_set_tab_width (const char *ignore
,
935 int from_tty
, struct cmd_list_element
*c
)
937 if (internal_tab_width
== 0)
939 internal_tab_width
= tui_tab_width
;
940 error (_("Tab width must not be 0"));
943 tui_tab_width
= internal_tab_width
;
947 /* Callback for "show tui tab-width". */
950 tui_show_tab_width (struct ui_file
*file
, int from_tty
,
951 struct cmd_list_element
*c
, const char *value
)
953 fprintf_filtered (gdb_stdout
, _("TUI tab width is %s spaces.\n"), value
);
957 /* Set the tab width of the specified window. */
959 tui_set_tab_width_command (const char *arg
, int from_tty
)
961 /* Make sure the curses mode is enabled. */
969 warning (_("Tab widths greater than 0 must be specified."));
972 internal_tab_width
= ts
;
981 /* Set the height of the specified window. */
983 tui_set_win_height_command (const char *arg
, int from_tty
)
985 /* Make sure the curses mode is enabled. */
989 std::string copy
= arg
;
990 char *buf
= ©
[0];
994 struct tui_win_info
*win_info
;
997 buf_ptr
= strchr (buf_ptr
, ' ');
1000 *buf_ptr
= (char) 0;
1002 /* Validate the window name. */
1003 for (i
= 0; i
< strlen (wname
); i
++)
1004 wname
[i
] = tolower (wname
[i
]);
1005 win_info
= tui_partial_win_by_name (wname
);
1007 if (win_info
== NULL
|| !win_info
->is_visible
)
1008 warning (_("Invalid window specified. \n\
1009 The window name specified must be valid and visible.\n"));
1012 /* Process the size. */
1013 while (*(++buf_ptr
) == ' ')
1016 if (*buf_ptr
!= (char) 0)
1019 int fixed_size
= TRUE
;
1022 if (*buf_ptr
== '+' || *buf_ptr
== '-')
1024 if (*buf_ptr
== '-')
1029 input_no
= atoi (buf_ptr
);
1035 new_height
= input_no
;
1037 new_height
= win_info
->height
+ input_no
;
1039 /* Now change the window's height, and adjust
1040 all other windows around it. */
1041 if (tui_adjust_win_heights (win_info
,
1042 new_height
) == TUI_FAILURE
)
1043 warning (_("Invalid window height specified.\n%s"),
1046 tui_update_gdb_sizes ();
1049 warning (_("Invalid window height specified.\n%s"),
1055 printf_filtered (WIN_HEIGHT_USAGE
);
1058 printf_filtered (WIN_HEIGHT_USAGE
);
1061 /* Function to adjust all window heights around the primary. */
1062 static enum tui_status
1063 tui_adjust_win_heights (struct tui_win_info
*primary_win_info
,
1066 enum tui_status status
= TUI_FAILURE
;
1068 if (new_height_ok (primary_win_info
, new_height
))
1070 status
= TUI_SUCCESS
;
1071 if (new_height
!= primary_win_info
->height
)
1074 struct tui_win_info
*win_info
;
1075 struct tui_locator_window
*locator
= tui_locator_win_info_ptr ();
1076 enum tui_layout_type cur_layout
= tui_current_layout ();
1078 diff
= (new_height
- primary_win_info
->height
) * (-1);
1079 if (cur_layout
== SRC_COMMAND
1080 || cur_layout
== DISASSEM_COMMAND
)
1082 struct tui_win_info
*src_win_info
;
1084 make_invisible_and_set_new_height (primary_win_info
, new_height
);
1085 if (primary_win_info
->type
== CMD_WIN
)
1087 win_info
= tui_source_windows ()[0];
1088 src_win_info
= win_info
;
1092 win_info
= tui_win_list
[CMD_WIN
];
1093 src_win_info
= primary_win_info
;
1095 make_invisible_and_set_new_height (win_info
,
1096 win_info
->height
+ diff
);
1097 TUI_CMD_WIN
->origin
.y
= locator
->origin
.y
+ 1;
1098 win_info
->make_visible_with_new_height ();
1099 primary_win_info
->make_visible_with_new_height ();
1100 if ((src_win_info
->type
== SRC_WIN
1101 || src_win_info
->type
== DISASSEM_WIN
))
1103 tui_source_window_base
*src_base
1104 = (tui_source_window_base
*) src_win_info
;
1105 if (src_base
->content
.empty ())
1106 tui_erase_source_content (src_base
);
1111 struct tui_win_info
*first_win
;
1112 struct tui_source_window_base
*second_win
;
1113 tui_source_window_base
*src1
;
1115 if (cur_layout
== SRC_DISASSEM_COMMAND
)
1119 second_win
= TUI_DISASM_WIN
;
1124 first_win
= TUI_DATA_WIN
;
1125 second_win
= tui_source_windows ()[0];
1127 if (primary_win_info
== TUI_CMD_WIN
)
1128 { /* Split the change in height accross the 1st & 2nd
1129 windows, adjusting them as well. */
1130 /* Subtract the locator. */
1131 int first_split_diff
= diff
/ 2;
1132 int second_split_diff
= first_split_diff
;
1136 if (first_win
->height
>
1145 second_split_diff
--;
1147 second_split_diff
++;
1150 /* Make sure that the minimum hieghts are
1152 while ((first_win
->height
+ first_split_diff
) < 3)
1155 second_split_diff
--;
1157 while ((second_win
->height
+ second_split_diff
) < 3)
1159 second_split_diff
++;
1162 make_invisible_and_set_new_height (
1164 first_win
->height
+ first_split_diff
);
1165 second_win
->origin
.y
= first_win
->height
- 1;
1166 make_invisible_and_set_new_height (second_win
,
1168 + second_split_diff
);
1169 TUI_CMD_WIN
->origin
.y
= locator
->origin
.y
+ 1;
1170 make_invisible_and_set_new_height (TUI_CMD_WIN
, new_height
);
1174 if ((TUI_CMD_WIN
->height
+ diff
) < 1)
1175 { /* If there is no way to increase the command
1176 window take real estate from the 1st or 2nd
1178 if ((TUI_CMD_WIN
->height
+ diff
) < 1)
1182 for (i
= TUI_CMD_WIN
->height
+ diff
;
1184 if (primary_win_info
== first_win
)
1185 second_win
->height
--;
1187 first_win
->height
--;
1190 if (primary_win_info
== first_win
)
1191 make_invisible_and_set_new_height (first_win
, new_height
);
1193 make_invisible_and_set_new_height (
1196 second_win
->origin
.y
= first_win
->height
- 1;
1197 if (primary_win_info
== second_win
)
1198 make_invisible_and_set_new_height (second_win
, new_height
);
1200 make_invisible_and_set_new_height (
1201 second_win
, second_win
->height
);
1202 TUI_CMD_WIN
->origin
.y
= locator
->origin
.y
+ 1;
1203 if ((TUI_CMD_WIN
->height
+ diff
) < 1)
1204 make_invisible_and_set_new_height (TUI_CMD_WIN
, 1);
1206 make_invisible_and_set_new_height (TUI_CMD_WIN
,
1207 TUI_CMD_WIN
->height
+ diff
);
1209 TUI_CMD_WIN
->make_visible_with_new_height ();
1210 second_win
->make_visible_with_new_height ();
1211 first_win
->make_visible_with_new_height ();
1212 if (src1
!= nullptr && src1
->content
.empty ())
1213 tui_erase_source_content (src1
);
1214 if (second_win
->content
.empty ())
1215 tui_erase_source_content (second_win
);
1224 /* See tui-data.h. */
1227 tui_source_window_base::set_new_height (int height
)
1229 execution_info
->make_visible (false);
1230 execution_info
->height
= height
;
1231 execution_info
->origin
.y
= origin
.y
;
1233 execution_info
->viewport_height
= height
- 1;
1235 execution_info
->viewport_height
= height
;
1236 execution_info
->viewport_height
--;
1240 tui_locator_window
*gen_win_info
= tui_locator_win_info_ptr ();
1241 gen_win_info
->make_visible (false);
1242 gen_win_info
->origin
.y
= origin
.y
+ height
;
1246 /* Function make the target window (and auxiliary windows associated
1247 with the targer) invisible, and set the new height and
1250 make_invisible_and_set_new_height (struct tui_win_info
*win_info
,
1253 win_info
->make_visible (false);
1254 win_info
->height
= height
;
1256 win_info
->viewport_height
= height
- 1;
1258 win_info
->viewport_height
= height
;
1259 if (win_info
!= TUI_CMD_WIN
)
1260 win_info
->viewport_height
--;
1262 /* Now deal with the auxiliary windows associated with win_info. */
1263 win_info
->set_new_height (height
);
1267 /* See tui-data.h. */
1270 tui_win_info::make_visible_with_new_height ()
1272 make_visible (true);
1273 tui_check_and_display_highlight_if_needed (this);
1274 do_make_visible_with_new_height ();
1277 /* See tui-data.h. */
1280 tui_source_window_base::do_make_visible_with_new_height ()
1282 execution_info
->make_visible (true);
1283 if (!content
.empty ())
1285 struct tui_line_or_address line_or_addr
;
1286 struct symtab_and_line cursal
1287 = get_current_source_symtab_and_line ();
1289 line_or_addr
= start_line_or_addr
;
1290 tui_update_source_window (this, gdbarch
,
1291 cursal
.symtab
, line_or_addr
, TRUE
);
1293 else if (deprecated_safe_get_selected_frame () != NULL
)
1295 struct tui_line_or_address line
;
1296 struct symtab_and_line cursal
1297 = get_current_source_symtab_and_line ();
1298 struct frame_info
*frame
= deprecated_safe_get_selected_frame ();
1299 struct gdbarch
*gdbarch
= get_frame_arch (frame
);
1301 struct symtab
*s
= find_pc_line_symtab (get_frame_pc (frame
));
1302 if (type
== SRC_WIN
)
1304 line
.loa
= LOA_LINE
;
1305 line
.u
.line_no
= cursal
.line
;
1309 line
.loa
= LOA_ADDRESS
;
1310 find_line_pc (s
, cursal
.line
, &line
.u
.addr
);
1312 tui_update_source_window (this, gdbarch
, s
, line
, TRUE
);
1316 tui_locator_win_info_ptr ()->make_visible (true);
1317 tui_show_locator_content ();
1321 /* See tui-data.h. */
1324 tui_win_info::max_height () const
1326 return tui_term_height () - 2;
1330 new_height_ok (struct tui_win_info
*primary_win_info
,
1333 int ok
= (new_height
< tui_term_height ());
1338 enum tui_layout_type cur_layout
= tui_current_layout ();
1340 diff
= (new_height
- primary_win_info
->height
) * (-1);
1341 if (cur_layout
== SRC_COMMAND
|| cur_layout
== DISASSEM_COMMAND
)
1343 ok
= (new_height
<= primary_win_info
->max_height ()
1344 && new_height
>= MIN_CMD_WIN_HEIGHT
);
1346 { /* Check the total height. */
1347 struct tui_win_info
*win_info
;
1349 if (primary_win_info
== TUI_CMD_WIN
)
1350 win_info
= tui_source_windows ()[0];
1352 win_info
= TUI_CMD_WIN
;
1354 (win_info
->height
+ diff
)) <= tui_term_height ());
1359 int cur_total_height
, total_height
, min_height
= 0;
1360 struct tui_win_info
*first_win
;
1361 struct tui_win_info
*second_win
;
1363 if (cur_layout
== SRC_DISASSEM_COMMAND
)
1365 first_win
= TUI_SRC_WIN
;
1366 second_win
= TUI_DISASM_WIN
;
1370 first_win
= TUI_DATA_WIN
;
1371 second_win
= tui_source_windows ()[0];
1373 /* We could simply add all the heights to obtain the same
1374 result but below is more explicit since we subtract 1 for
1375 the line that the first and second windows share, and add
1376 one for the locator. */
1377 total_height
= cur_total_height
=
1378 (first_win
->height
+ second_win
->height
- 1)
1379 + TUI_CMD_WIN
->height
+ 1; /* Locator. */
1380 if (primary_win_info
== TUI_CMD_WIN
)
1382 /* Locator included since first & second win share a line. */
1383 ok
= ((first_win
->height
+
1384 second_win
->height
+ diff
) >=
1385 (MIN_WIN_HEIGHT
* 2)
1386 && new_height
>= MIN_CMD_WIN_HEIGHT
);
1389 total_height
= new_height
+
1390 (first_win
->height
+
1391 second_win
->height
+ diff
);
1392 min_height
= MIN_CMD_WIN_HEIGHT
;
1397 min_height
= MIN_WIN_HEIGHT
;
1399 /* First see if we can increase/decrease the command
1400 window. And make sure that the command window is at
1402 ok
= ((TUI_CMD_WIN
->height
+ diff
) > 0);
1404 { /* Looks like we have to increase/decrease one of
1405 the other windows. */
1406 if (primary_win_info
== first_win
)
1407 ok
= (second_win
->height
+ diff
) >= min_height
;
1409 ok
= (first_win
->height
+ diff
) >= min_height
;
1413 if (primary_win_info
== first_win
)
1414 total_height
= new_height
+
1415 second_win
->height
+
1416 TUI_CMD_WIN
->height
+ diff
;
1418 total_height
= new_height
+
1420 TUI_CMD_WIN
->height
+ diff
;
1423 /* Now make sure that the proposed total height doesn't
1424 exceed the old total height. */
1426 ok
= (new_height
>= min_height
1427 && total_height
<= cur_total_height
);
1436 parse_scrolling_args (const char *arg
,
1437 struct tui_win_info
**win_to_scroll
,
1442 *win_to_scroll
= tui_win_with_focus ();
1444 /* First set up the default window to scroll, in case there is no
1450 /* Process the number of lines to scroll. */
1451 std::string copy
= arg
;
1453 if (isdigit (*buf_ptr
))
1458 buf_ptr
= strchr (buf_ptr
, ' ');
1459 if (buf_ptr
!= NULL
)
1461 *buf_ptr
= (char) 0;
1463 *num_to_scroll
= atoi (num_str
);
1466 else if (num_to_scroll
)
1467 *num_to_scroll
= atoi (num_str
);
1470 /* Process the window name if one is specified. */
1471 if (buf_ptr
!= NULL
)
1475 if (*buf_ptr
== ' ')
1476 while (*(++buf_ptr
) == ' ')
1479 if (*buf_ptr
!= (char) 0)
1481 /* Validate the window name. */
1482 for (char *p
= buf_ptr
; *p
!= '\0'; p
++)
1490 *win_to_scroll
= tui_partial_win_by_name (wname
);
1492 if (*win_to_scroll
== NULL
1493 || !(*win_to_scroll
)->is_visible
)
1494 error (_("Invalid window specified. \n\
1495 The window name specified must be valid and visible.\n"));
1496 else if (*win_to_scroll
== TUI_CMD_WIN
)
1497 *win_to_scroll
= tui_source_windows ()[0];
1502 /* Function to initialize gdb commands, for tui window
1506 _initialize_tui_win (void)
1508 static struct cmd_list_element
*tui_setlist
;
1509 static struct cmd_list_element
*tui_showlist
;
1510 struct cmd_list_element
*cmd
;
1512 /* Define the classes of commands.
1513 They will appear in the help list in the reverse of this order. */
1514 add_prefix_cmd ("tui", class_tui
, set_tui_cmd
,
1515 _("TUI configuration variables"),
1516 &tui_setlist
, "set tui ",
1517 0 /* allow-unknown */, &setlist
);
1518 add_prefix_cmd ("tui", class_tui
, show_tui_cmd
,
1519 _("TUI configuration variables"),
1520 &tui_showlist
, "show tui ",
1521 0 /* allow-unknown */, &showlist
);
1523 add_com ("refresh", class_tui
, tui_refresh_all_command
,
1524 _("Refresh the terminal display."));
1526 cmd
= add_com ("tabset", class_tui
, tui_set_tab_width_command
, _("\
1527 Set the width (in characters) of tab stops.\n\
1529 deprecate_cmd (cmd
, "set tui tab-width");
1531 cmd
= add_com ("winheight", class_tui
, tui_set_win_height_command
, _("\
1532 Set or modify the height of a specified window.\n"
1534 "Window names are:\n\
1535 src : the source window\n\
1536 cmd : the command window\n\
1537 asm : the disassembly window\n\
1538 regs : the register display"));
1539 add_com_alias ("wh", "winheight", class_tui
, 0);
1540 set_cmd_completer (cmd
, winheight_completer
);
1541 add_info ("win", tui_all_windows_info
,
1542 _("List of all displayed windows."));
1543 cmd
= add_com ("focus", class_tui
, tui_set_focus_command
, _("\
1544 Set focus to named window or next/prev window.\n"
1546 "Valid Window names are:\n\
1547 src : the source window\n\
1548 asm : the disassembly window\n\
1549 regs : the register display\n\
1550 cmd : the command window"));
1551 add_com_alias ("fs", "focus", class_tui
, 0);
1552 set_cmd_completer (cmd
, focus_completer
);
1553 add_com ("+", class_tui
, tui_scroll_forward_command
, _("\
1554 Scroll window forward.\n\
1555 Usage: + [WIN] [N]"));
1556 add_com ("-", class_tui
, tui_scroll_backward_command
, _("\
1557 Scroll window backward.\n\
1558 Usage: - [WIN] [N]"));
1559 add_com ("<", class_tui
, tui_scroll_left_command
, _("\
1560 Scroll window text to the left.\n\
1561 Usage: < [WIN] [N]"));
1562 add_com (">", class_tui
, tui_scroll_right_command
, _("\
1563 Scroll window text to the right.\n\
1564 Usage: > [WIN] [N]"));
1566 /* Define the tui control variables. */
1567 add_setshow_enum_cmd ("border-kind", no_class
, tui_border_kind_enums
,
1568 &tui_border_kind
, _("\
1569 Set the kind of border for TUI windows."), _("\
1570 Show the kind of border for TUI windows."), _("\
1571 This variable controls the border of TUI windows:\n\
1572 space use a white space\n\
1573 ascii use ascii characters + - | for the border\n\
1574 acs use the Alternate Character Set"),
1576 show_tui_border_kind
,
1577 &tui_setlist
, &tui_showlist
);
1579 add_setshow_enum_cmd ("border-mode", no_class
, tui_border_mode_enums
,
1580 &tui_border_mode
, _("\
1581 Set the attribute mode to use for the TUI window borders."), _("\
1582 Show the attribute mode to use for the TUI window borders."), _("\
1583 This variable controls the attributes to use for the window borders:\n\
1584 normal normal display\n\
1585 standout use highlight mode of terminal\n\
1586 reverse use reverse video mode\n\
1587 half use half bright\n\
1588 half-standout use half bright and standout mode\n\
1589 bold use extra bright or bold\n\
1590 bold-standout use extra bright or bold with standout mode"),
1592 show_tui_border_mode
,
1593 &tui_setlist
, &tui_showlist
);
1595 add_setshow_enum_cmd ("active-border-mode", no_class
, tui_border_mode_enums
,
1596 &tui_active_border_mode
, _("\
1597 Set the attribute mode to use for the active TUI window border."), _("\
1598 Show the attribute mode to use for the active TUI window border."), _("\
1599 This variable controls the attributes to use for the active window border:\n\
1600 normal normal display\n\
1601 standout use highlight mode of terminal\n\
1602 reverse use reverse video mode\n\
1603 half use half bright\n\
1604 half-standout use half bright and standout mode\n\
1605 bold use extra bright or bold\n\
1606 bold-standout use extra bright or bold with standout mode"),
1608 show_tui_active_border_mode
,
1609 &tui_setlist
, &tui_showlist
);
1611 add_setshow_zuinteger_cmd ("tab-width", no_class
,
1612 &internal_tab_width
, _("\
1613 Set the tab width, in characters, for the TUI."), _("\
1614 Show the tab witdh, in characters, for the TUI"), _("\
1615 This variable controls how many spaces are used to display a tab character."),
1616 tui_set_tab_width
, tui_show_tab_width
,
1617 &tui_setlist
, &tui_showlist
);