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-data.h"
40 #include "tui/tui-wingeneral.h"
41 #include "tui/tui-stack.h"
42 #include "tui/tui-regs.h"
43 #include "tui/tui-disasm.h"
44 #include "tui/tui-source.h"
45 #include "tui/tui-winsource.h"
46 #include "tui/tui-windata.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_set_focus_command (const char *, int);
67 static void tui_scroll_forward_command (const char *, int);
68 static void tui_scroll_backward_command (const char *, int);
69 static void tui_scroll_left_command (const char *, int);
70 static void tui_scroll_right_command (const char *, int);
71 static void parse_scrolling_args (const char *,
72 struct tui_win_info
**,
76 /***************************************
78 ***************************************/
79 #define WIN_HEIGHT_USAGE "Usage: winheight WINDOW-NAME [+ | -] NUM-LINES\n"
80 #define FOCUS_USAGE "Usage: focus [WINDOW-NAME | next | prev]\n"
82 /***************************************
84 ***************************************/
87 # define ACS_LRCORNER '+'
90 # define ACS_LLCORNER '+'
93 # define ACS_ULCORNER '+'
96 # define ACS_URCORNER '+'
99 # define ACS_HLINE '-'
102 # define ACS_VLINE '|'
105 /* Possible values for tui-border-kind variable. */
106 static const char *const tui_border_kind_enums
[] = {
113 /* Possible values for tui-border-mode and tui-active-border-mode. */
114 static const char *const tui_border_mode_enums
[] = {
131 /* Translation table for border-mode variables.
132 The list of values must be terminated by a NULL.
133 After the NULL value, an entry defines the default. */
134 struct tui_translate tui_border_mode_translate
[] = {
135 { "normal", A_NORMAL
},
136 { "standout", A_STANDOUT
},
137 { "reverse", A_REVERSE
},
139 { "half-standout", A_DIM
| A_STANDOUT
},
141 { "bold-standout", A_BOLD
| A_STANDOUT
},
143 { "normal", A_NORMAL
}
146 /* Translation tables for border-kind, one for each border
147 character (see wborder, border curses operations).
148 -1 is used to indicate the ACS because ACS characters
149 are determined at run time by curses (depends on terminal). */
150 struct tui_translate tui_border_kind_translate_vline
[] = {
158 struct tui_translate tui_border_kind_translate_hline
[] = {
166 struct tui_translate tui_border_kind_translate_ulcorner
[] = {
174 struct tui_translate tui_border_kind_translate_urcorner
[] = {
182 struct tui_translate tui_border_kind_translate_llcorner
[] = {
190 struct tui_translate tui_border_kind_translate_lrcorner
[] = {
199 /* Tui configuration variables controlled with set/show command. */
200 const char *tui_active_border_mode
= "bold-standout";
202 show_tui_active_border_mode (struct ui_file
*file
,
204 struct cmd_list_element
*c
,
207 fprintf_filtered (file
, _("\
208 The attribute mode to use for the active TUI window border is \"%s\".\n"),
212 const char *tui_border_mode
= "normal";
214 show_tui_border_mode (struct ui_file
*file
,
216 struct cmd_list_element
*c
,
219 fprintf_filtered (file
, _("\
220 The attribute mode to use for the TUI window borders is \"%s\".\n"),
224 const char *tui_border_kind
= "acs";
226 show_tui_border_kind (struct ui_file
*file
,
228 struct cmd_list_element
*c
,
231 fprintf_filtered (file
, _("The kind of border for TUI windows is \"%s\".\n"),
236 /* Tui internal configuration variables. These variables are updated
237 by tui_update_variables to reflect the tui configuration
239 chtype tui_border_vline
;
240 chtype tui_border_hline
;
241 chtype tui_border_ulcorner
;
242 chtype tui_border_urcorner
;
243 chtype tui_border_llcorner
;
244 chtype tui_border_lrcorner
;
246 int tui_border_attrs
;
247 int tui_active_border_attrs
;
249 /* Identify the item in the translation table.
250 When the item is not recognized, use the default entry. */
251 static struct tui_translate
*
252 translate (const char *name
, struct tui_translate
*table
)
256 if (name
&& strcmp (table
->name
, name
) == 0)
261 /* Not found, return default entry. */
266 /* Update the tui internal configuration according to gdb settings.
267 Returns 1 if the configuration has changed and the screen should
270 tui_update_variables (void)
273 struct tui_translate
*entry
;
275 entry
= translate (tui_border_mode
, tui_border_mode_translate
);
276 if (tui_border_attrs
!= entry
->value
)
278 tui_border_attrs
= entry
->value
;
281 entry
= translate (tui_active_border_mode
, tui_border_mode_translate
);
282 if (tui_active_border_attrs
!= entry
->value
)
284 tui_active_border_attrs
= entry
->value
;
288 /* If one corner changes, all characters are changed.
289 Only check the first one. The ACS characters are determined at
290 run time by curses terminal management. */
291 entry
= translate (tui_border_kind
, tui_border_kind_translate_lrcorner
);
292 if (tui_border_lrcorner
!= (chtype
) entry
->value
)
294 tui_border_lrcorner
= (entry
->value
< 0) ? ACS_LRCORNER
: entry
->value
;
297 entry
= translate (tui_border_kind
, tui_border_kind_translate_llcorner
);
298 tui_border_llcorner
= (entry
->value
< 0) ? ACS_LLCORNER
: entry
->value
;
300 entry
= translate (tui_border_kind
, tui_border_kind_translate_ulcorner
);
301 tui_border_ulcorner
= (entry
->value
< 0) ? ACS_ULCORNER
: entry
->value
;
303 entry
= translate (tui_border_kind
, tui_border_kind_translate_urcorner
);
304 tui_border_urcorner
= (entry
->value
< 0) ? ACS_URCORNER
: entry
->value
;
306 entry
= translate (tui_border_kind
, tui_border_kind_translate_hline
);
307 tui_border_hline
= (entry
->value
< 0) ? ACS_HLINE
: entry
->value
;
309 entry
= translate (tui_border_kind
, tui_border_kind_translate_vline
);
310 tui_border_vline
= (entry
->value
< 0) ? ACS_VLINE
: entry
->value
;
316 set_tui_cmd (const char *args
, int from_tty
)
321 show_tui_cmd (const char *args
, int from_tty
)
325 static struct cmd_list_element
*tuilist
;
328 tui_command (const char *args
, int from_tty
)
330 printf_unfiltered (_("\"tui\" must be followed by the name of a "
332 help_list (tuilist
, "tui ", all_commands
, gdb_stdout
);
335 struct cmd_list_element
**
336 tui_get_cmd_list (void)
339 add_prefix_cmd ("tui", class_tui
, tui_command
,
340 _("Text User Interface commands."),
341 &tuilist
, "tui ", 0, &cmdlist
);
345 /* The set_func hook of "set tui ..." commands that affect the window
346 borders on the TUI display. */
348 tui_set_var_cmd (const char *null_args
,
349 int from_tty
, struct cmd_list_element
*c
)
351 if (tui_update_variables () && tui_active
)
352 tui_rehighlight_all ();
355 /* Generic window name completion function. Complete window name pointed
356 to by TEXT and WORD. If INCLUDE_NEXT_PREV_P is true then the special
357 window names 'next' and 'prev' will also be considered as possible
358 completions of the window name. */
361 window_name_completer (completion_tracker
&tracker
,
362 int include_next_prev_p
,
363 const char *text
, const char *word
)
365 std::vector
<const char *> completion_name_vec
;
367 for (tui_win_info
*win_info
: all_tui_windows ())
369 const char *completion_name
= NULL
;
371 /* We can't focus on an invisible window. */
372 if (!win_info
->is_visible
)
375 completion_name
= win_info
->name ();
376 gdb_assert (completion_name
!= NULL
);
377 completion_name_vec
.push_back (completion_name
);
380 /* If no windows are considered visible then the TUI has not yet been
381 initialized. But still "focus src" and "focus cmd" will work because
382 invoking the focus command will entail initializing the TUI which sets the
383 default layout to SRC_COMMAND. */
384 if (completion_name_vec
.empty ())
386 completion_name_vec
.push_back (SRC_NAME
);
387 completion_name_vec
.push_back (CMD_NAME
);
390 if (include_next_prev_p
)
392 completion_name_vec
.push_back ("next");
393 completion_name_vec
.push_back ("prev");
397 completion_name_vec
.push_back (NULL
);
398 complete_on_enum (tracker
, completion_name_vec
.data (), text
, word
);
401 /* Complete possible window names to focus on. TEXT is the complete text
402 entered so far, WORD is the word currently being completed. */
405 focus_completer (struct cmd_list_element
*ignore
,
406 completion_tracker
&tracker
,
407 const char *text
, const char *word
)
409 window_name_completer (tracker
, 1, text
, word
);
412 /* Complete possible window names for winheight command. TEXT is the
413 complete text entered so far, WORD is the word currently being
417 winheight_completer (struct cmd_list_element
*ignore
,
418 completion_tracker
&tracker
,
419 const char *text
, const char *word
)
421 /* The first word is the window name. That we can complete. Subsequent
422 words can't be completed. */
426 window_name_completer (tracker
, 0, text
, word
);
429 /* Update gdb's knowledge of the terminal size. */
431 tui_update_gdb_sizes (void)
437 width
= TUI_CMD_WIN
->width
;
438 height
= TUI_CMD_WIN
->height
;
442 width
= tui_term_width ();
443 height
= tui_term_height ();
446 set_screen_width_and_height (width
, height
);
450 /* Set the logical focus to win_info. */
452 tui_set_win_focus_to (struct tui_win_info
*win_info
)
454 if (win_info
!= NULL
)
456 struct tui_win_info
*win_with_focus
= tui_win_with_focus ();
458 tui_unhighlight_win (win_with_focus
);
459 tui_set_win_with_focus (win_info
);
460 tui_highlight_win (win_info
);
466 tui_win_info::forward_scroll (int num_to_scroll
)
468 if (num_to_scroll
== 0)
469 num_to_scroll
= height
- 3;
471 do_scroll_vertical (num_to_scroll
);
475 tui_win_info::backward_scroll (int num_to_scroll
)
477 if (num_to_scroll
== 0)
478 num_to_scroll
= height
- 3;
480 do_scroll_vertical (-num_to_scroll
);
485 tui_win_info::left_scroll (int num_to_scroll
)
487 if (num_to_scroll
== 0)
490 do_scroll_horizontal (num_to_scroll
);
495 tui_win_info::right_scroll (int num_to_scroll
)
497 if (num_to_scroll
== 0)
500 do_scroll_horizontal (-num_to_scroll
);
504 /* See tui-data.h. */
507 tui_source_window_base::refresh_all ()
509 tui_show_source_content (this);
510 tui_check_and_display_highlight_if_needed (this);
511 tui_erase_exec_info_content (this);
512 tui_update_exec_info (this);
516 tui_refresh_all_win (void)
518 clearok (curscr
, TRUE
);
520 for (tui_win_info
*win_info
: all_tui_windows ())
522 if (win_info
->is_visible
)
523 win_info
->refresh_all ();
525 tui_show_locator_content ();
529 tui_rehighlight_all (void)
531 for (tui_win_info
*win_info
: all_tui_windows ())
532 tui_check_and_display_highlight_if_needed (win_info
);
535 /* Resize all the windows based on the terminal size. This function
536 gets called from within the readline SIGWINCH handler. */
538 tui_resize_all (void)
540 int height_diff
, width_diff
;
541 int screenheight
, screenwidth
;
543 rl_get_screen_size (&screenheight
, &screenwidth
);
544 width_diff
= screenwidth
- tui_term_width ();
545 height_diff
= screenheight
- tui_term_height ();
546 if (height_diff
|| width_diff
)
548 enum tui_layout_type cur_layout
= tui_current_layout ();
549 struct tui_win_info
*win_with_focus
= tui_win_with_focus ();
550 struct tui_win_info
*first_win
;
551 struct tui_win_info
*second_win
;
552 tui_source_window_base
*src_win
;
553 struct tui_locator_window
*locator
= tui_locator_win_info_ptr ();
555 int new_height
, split_diff
, cmd_split_diff
, num_wins_displayed
= 2;
557 #ifdef HAVE_RESIZE_TERM
558 resize_term (screenheight
, screenwidth
);
560 /* Turn keypad off while we resize. */
561 if (win_with_focus
!= TUI_CMD_WIN
)
562 keypad (TUI_CMD_WIN
->handle
, FALSE
);
563 tui_update_gdb_sizes ();
564 tui_set_term_height_to (screenheight
);
565 tui_set_term_width_to (screenwidth
);
566 if (cur_layout
== SRC_DISASSEM_COMMAND
567 || cur_layout
== SRC_DATA_COMMAND
568 || cur_layout
== DISASSEM_DATA_COMMAND
)
569 num_wins_displayed
++;
570 split_diff
= height_diff
/ num_wins_displayed
;
571 cmd_split_diff
= split_diff
;
572 if (height_diff
% num_wins_displayed
)
579 /* Now adjust each window. */
580 /* erase + clearok are used instead of a straightforward clear as
581 AIX 5.3 does not define clear. */
583 clearok (curscr
, TRUE
);
588 case DISASSEM_COMMAND
:
589 src_win
= tui_source_windows ()[0];
591 first_win
->width
+= width_diff
;
592 locator
->width
+= width_diff
;
593 /* Check for invalid heights. */
594 if (height_diff
== 0)
595 new_height
= first_win
->height
;
596 else if ((first_win
->height
+ split_diff
) >=
597 (screenheight
- MIN_CMD_WIN_HEIGHT
- 1))
598 new_height
= screenheight
- MIN_CMD_WIN_HEIGHT
- 1;
599 else if ((first_win
->height
+ split_diff
) <= 0)
600 new_height
= MIN_WIN_HEIGHT
;
602 new_height
= first_win
->height
+ split_diff
;
604 locator
->origin
.y
= new_height
+ 1;
605 make_invisible_and_set_new_height (first_win
, new_height
);
606 TUI_CMD_WIN
->origin
.y
= locator
->origin
.y
+ 1;
607 TUI_CMD_WIN
->width
+= width_diff
;
608 new_height
= screenheight
- TUI_CMD_WIN
->origin
.y
;
609 make_invisible_and_set_new_height (TUI_CMD_WIN
, new_height
);
610 first_win
->make_visible_with_new_height ();
611 TUI_CMD_WIN
->make_visible_with_new_height ();
612 if (src_win
->content
.empty ())
613 tui_erase_source_content (src_win
);
616 if (cur_layout
== SRC_DISASSEM_COMMAND
)
618 src_win
= TUI_SRC_WIN
;
620 first_win
->width
+= width_diff
;
621 second_win
= TUI_DISASM_WIN
;
622 second_win
->width
+= width_diff
;
626 first_win
= TUI_DATA_WIN
;
627 first_win
->width
+= width_diff
;
628 src_win
= tui_source_windows ()[0];
629 second_win
= src_win
;
630 second_win
->width
+= width_diff
;
632 /* Change the first window's height/width. */
633 /* Check for invalid heights. */
634 if (height_diff
== 0)
635 new_height
= first_win
->height
;
636 else if ((first_win
->height
+
637 second_win
->height
+ (split_diff
* 2)) >=
638 (screenheight
- MIN_CMD_WIN_HEIGHT
- 1))
639 new_height
= (screenheight
- MIN_CMD_WIN_HEIGHT
- 1) / 2;
640 else if ((first_win
->height
+ split_diff
) <= 0)
641 new_height
= MIN_WIN_HEIGHT
;
643 new_height
= first_win
->height
+ split_diff
;
644 make_invisible_and_set_new_height (first_win
, new_height
);
646 locator
->width
+= width_diff
;
648 /* Change the second window's height/width. */
649 /* Check for invalid heights. */
650 if (height_diff
== 0)
651 new_height
= second_win
->height
;
652 else if ((first_win
->height
+
653 second_win
->height
+ (split_diff
* 2)) >=
654 (screenheight
- MIN_CMD_WIN_HEIGHT
- 1))
656 new_height
= screenheight
- MIN_CMD_WIN_HEIGHT
- 1;
658 new_height
= (new_height
/ 2) + 1;
662 else if ((second_win
->height
+ split_diff
) <= 0)
663 new_height
= MIN_WIN_HEIGHT
;
665 new_height
= second_win
->height
+ split_diff
;
666 second_win
->origin
.y
= first_win
->height
- 1;
667 make_invisible_and_set_new_height (second_win
, new_height
);
669 /* Change the command window's height/width. */
670 TUI_CMD_WIN
->origin
.y
= locator
->origin
.y
+ 1;
671 make_invisible_and_set_new_height (TUI_CMD_WIN
,
674 first_win
->make_visible_with_new_height ();
675 second_win
->make_visible_with_new_height ();
676 TUI_CMD_WIN
->make_visible_with_new_height ();
677 if (src_win
->content
.empty ())
678 tui_erase_source_content (src_win
);
681 /* Now remove all invisible windows, and their content so that
682 they get created again when called for with the new size. */
683 for (win_type
= SRC_WIN
; (win_type
< MAX_MAJOR_WINDOWS
); win_type
++)
685 if (win_type
!= CMD_WIN
686 && (tui_win_list
[win_type
] != NULL
)
687 && !tui_win_list
[win_type
]->is_visible
)
689 delete tui_win_list
[win_type
];
690 tui_win_list
[win_type
] = NULL
;
693 /* Turn keypad back on, unless focus is in the command
695 if (win_with_focus
!= TUI_CMD_WIN
)
696 keypad (TUI_CMD_WIN
->handle
, TRUE
);
701 /* Token for use by TUI's asynchronous SIGWINCH handler. */
702 static struct async_signal_handler
*tui_sigwinch_token
;
704 /* TUI's SIGWINCH signal handler. */
706 tui_sigwinch_handler (int signal
)
708 mark_async_signal_handler (tui_sigwinch_token
);
709 tui_set_win_resized_to (TRUE
);
712 /* Callback for asynchronously resizing TUI following a SIGWINCH signal. */
714 tui_async_resize_screen (gdb_client_data arg
)
716 rl_resize_terminal ();
720 int screen_height
, screen_width
;
722 rl_get_screen_size (&screen_height
, &screen_width
);
723 set_screen_width_and_height (screen_width
, screen_height
);
725 /* win_resized is left set so that the next call to tui_enable()
726 resizes the TUI windows. */
730 tui_set_win_resized_to (FALSE
);
732 tui_refresh_all_win ();
733 tui_update_gdb_sizes ();
734 tui_redisplay_readline ();
739 /* Initialize TUI's SIGWINCH signal handler. Note that the handler is not
740 uninstalled when we exit TUI, so the handler should not assume that TUI is
743 tui_initialize_win (void)
747 = create_async_signal_handler (tui_async_resize_screen
, NULL
);
750 #ifdef HAVE_SIGACTION
751 struct sigaction old_winch
;
753 memset (&old_winch
, 0, sizeof (old_winch
));
754 old_winch
.sa_handler
= &tui_sigwinch_handler
;
756 old_winch
.sa_flags
= SA_RESTART
;
758 sigaction (SIGWINCH
, &old_winch
, NULL
);
760 signal (SIGWINCH
, &tui_sigwinch_handler
);
767 /*************************
768 ** STATIC LOCAL FUNCTIONS
769 **************************/
773 tui_scroll_forward_command (const char *arg
, int from_tty
)
775 int num_to_scroll
= 1;
776 struct tui_win_info
*win_to_scroll
;
778 /* Make sure the curses mode is enabled. */
781 parse_scrolling_args (arg
, &win_to_scroll
, NULL
);
783 parse_scrolling_args (arg
, &win_to_scroll
, &num_to_scroll
);
784 win_to_scroll
->forward_scroll (num_to_scroll
);
789 tui_scroll_backward_command (const char *arg
, int from_tty
)
791 int num_to_scroll
= 1;
792 struct tui_win_info
*win_to_scroll
;
794 /* Make sure the curses mode is enabled. */
797 parse_scrolling_args (arg
, &win_to_scroll
, NULL
);
799 parse_scrolling_args (arg
, &win_to_scroll
, &num_to_scroll
);
800 win_to_scroll
->backward_scroll (num_to_scroll
);
805 tui_scroll_left_command (const char *arg
, int from_tty
)
808 struct tui_win_info
*win_to_scroll
;
810 /* Make sure the curses mode is enabled. */
812 parse_scrolling_args (arg
, &win_to_scroll
, &num_to_scroll
);
813 win_to_scroll
->left_scroll (num_to_scroll
);
818 tui_scroll_right_command (const char *arg
, int from_tty
)
821 struct tui_win_info
*win_to_scroll
;
823 /* Make sure the curses mode is enabled. */
825 parse_scrolling_args (arg
, &win_to_scroll
, &num_to_scroll
);
826 win_to_scroll
->right_scroll (num_to_scroll
);
830 /* Set focus to the window named by 'arg'. */
832 tui_set_focus (const char *arg
, int from_tty
)
836 char *buf_ptr
= xstrdup (arg
);
838 struct tui_win_info
*win_info
= NULL
;
840 for (i
= 0; (i
< strlen (buf_ptr
)); i
++)
841 buf_ptr
[i
] = tolower (arg
[i
]);
843 if (subset_compare (buf_ptr
, "next"))
844 win_info
= tui_next_win (tui_win_with_focus ());
845 else if (subset_compare (buf_ptr
, "prev"))
846 win_info
= tui_prev_win (tui_win_with_focus ());
848 win_info
= tui_partial_win_by_name (buf_ptr
);
850 if (win_info
== NULL
|| !win_info
->is_visible
)
851 warning (_("Invalid window specified. \n\
852 The window name specified must be valid and visible.\n"));
855 tui_set_win_focus_to (win_info
);
856 keypad (TUI_CMD_WIN
->handle
, (win_info
!= TUI_CMD_WIN
));
859 if (TUI_DATA_WIN
&& TUI_DATA_WIN
->is_visible
)
860 TUI_DATA_WIN
->refresh_all ();
862 printf_filtered (_("Focus set to %s window.\n"),
863 tui_win_with_focus ()->name ());
866 warning (_("Incorrect Number of Arguments.\n%s"), FOCUS_USAGE
);
870 tui_set_focus_command (const char *arg
, int from_tty
)
872 /* Make sure the curses mode is enabled. */
874 tui_set_focus (arg
, from_tty
);
879 tui_all_windows_info (const char *arg
, int from_tty
)
881 struct tui_win_info
*win_with_focus
= tui_win_with_focus ();
883 for (tui_win_info
*win_info
: all_tui_windows ())
884 if (win_info
->is_visible
)
886 if (win_with_focus
== win_info
)
887 printf_filtered (" %s\t(%d lines) <has focus>\n",
891 printf_filtered (" %s\t(%d lines)\n",
899 tui_refresh_all_command (const char *arg
, int from_tty
)
901 /* Make sure the curses mode is enabled. */
904 tui_refresh_all_win ();
907 /* The tab width that should be used by the TUI. */
909 unsigned int tui_tab_width
= DEFAULT_TAB_LEN
;
911 /* The tab width as set by the user. */
913 static unsigned int internal_tab_width
= DEFAULT_TAB_LEN
;
915 /* See tui-data.h. */
918 tui_source_window_base::update_tab_width ()
920 /* We don't really change the height of any windows, but
921 calling these 2 functions causes a complete regeneration
922 and redisplay of the window's contents, which will take
923 the new tab width into account. */
924 make_invisible_and_set_new_height (this, height
);
925 make_visible_with_new_height ();
928 /* After the tab width is set, call this to update the relevant
934 for (tui_win_info
*win_info
: all_tui_windows ())
936 if (win_info
->is_visible
)
937 win_info
->update_tab_width ();
941 /* Callback for "set tui tab-width". */
944 tui_set_tab_width (const char *ignore
,
945 int from_tty
, struct cmd_list_element
*c
)
947 if (internal_tab_width
== 0)
949 internal_tab_width
= tui_tab_width
;
950 error (_("Tab width must not be 0"));
953 tui_tab_width
= internal_tab_width
;
957 /* Callback for "show tui tab-width". */
960 tui_show_tab_width (struct ui_file
*file
, int from_tty
,
961 struct cmd_list_element
*c
, const char *value
)
963 fprintf_filtered (gdb_stdout
, _("TUI tab width is %s spaces.\n"), value
);
967 /* Set the tab width of the specified window. */
969 tui_set_tab_width_command (const char *arg
, int from_tty
)
971 /* Make sure the curses mode is enabled. */
979 warning (_("Tab widths greater than 0 must be specified."));
982 internal_tab_width
= ts
;
991 /* Set the height of the specified window. */
993 tui_set_win_height_command (const char *arg
, int from_tty
)
995 /* Make sure the curses mode is enabled. */
999 std::string copy
= arg
;
1000 char *buf
= ©
[0];
1001 char *buf_ptr
= buf
;
1004 struct tui_win_info
*win_info
;
1007 buf_ptr
= strchr (buf_ptr
, ' ');
1008 if (buf_ptr
!= NULL
)
1010 *buf_ptr
= (char) 0;
1012 /* Validate the window name. */
1013 for (i
= 0; i
< strlen (wname
); i
++)
1014 wname
[i
] = tolower (wname
[i
]);
1015 win_info
= tui_partial_win_by_name (wname
);
1017 if (win_info
== NULL
|| !win_info
->is_visible
)
1018 warning (_("Invalid window specified. \n\
1019 The window name specified must be valid and visible.\n"));
1022 /* Process the size. */
1023 while (*(++buf_ptr
) == ' ')
1026 if (*buf_ptr
!= (char) 0)
1029 int fixed_size
= TRUE
;
1032 if (*buf_ptr
== '+' || *buf_ptr
== '-')
1034 if (*buf_ptr
== '-')
1039 input_no
= atoi (buf_ptr
);
1045 new_height
= input_no
;
1047 new_height
= win_info
->height
+ input_no
;
1049 /* Now change the window's height, and adjust
1050 all other windows around it. */
1051 if (tui_adjust_win_heights (win_info
,
1052 new_height
) == TUI_FAILURE
)
1053 warning (_("Invalid window height specified.\n%s"),
1056 tui_update_gdb_sizes ();
1059 warning (_("Invalid window height specified.\n%s"),
1065 printf_filtered (WIN_HEIGHT_USAGE
);
1068 printf_filtered (WIN_HEIGHT_USAGE
);
1071 /* Function to adjust all window heights around the primary. */
1072 static enum tui_status
1073 tui_adjust_win_heights (struct tui_win_info
*primary_win_info
,
1076 enum tui_status status
= TUI_FAILURE
;
1078 if (new_height_ok (primary_win_info
, new_height
))
1080 status
= TUI_SUCCESS
;
1081 if (new_height
!= primary_win_info
->height
)
1084 struct tui_win_info
*win_info
;
1085 struct tui_locator_window
*locator
= tui_locator_win_info_ptr ();
1086 enum tui_layout_type cur_layout
= tui_current_layout ();
1088 diff
= (new_height
- primary_win_info
->height
) * (-1);
1089 if (cur_layout
== SRC_COMMAND
1090 || cur_layout
== DISASSEM_COMMAND
)
1092 struct tui_win_info
*src_win_info
;
1094 make_invisible_and_set_new_height (primary_win_info
, new_height
);
1095 if (primary_win_info
->type
== CMD_WIN
)
1097 win_info
= tui_source_windows ()[0];
1098 src_win_info
= win_info
;
1102 win_info
= tui_win_list
[CMD_WIN
];
1103 src_win_info
= primary_win_info
;
1105 make_invisible_and_set_new_height (win_info
,
1106 win_info
->height
+ diff
);
1107 TUI_CMD_WIN
->origin
.y
= locator
->origin
.y
+ 1;
1108 win_info
->make_visible_with_new_height ();
1109 primary_win_info
->make_visible_with_new_height ();
1110 if ((src_win_info
->type
== SRC_WIN
1111 || src_win_info
->type
== DISASSEM_WIN
))
1113 tui_source_window_base
*src_base
1114 = (tui_source_window_base
*) src_win_info
;
1115 if (src_base
->content
.empty ())
1116 tui_erase_source_content (src_base
);
1121 struct tui_win_info
*first_win
;
1122 struct tui_source_window_base
*second_win
;
1123 tui_source_window_base
*src1
;
1125 if (cur_layout
== SRC_DISASSEM_COMMAND
)
1129 second_win
= TUI_DISASM_WIN
;
1134 first_win
= TUI_DATA_WIN
;
1135 second_win
= tui_source_windows ()[0];
1137 if (primary_win_info
== TUI_CMD_WIN
)
1138 { /* Split the change in height accross the 1st & 2nd
1139 windows, adjusting them as well. */
1140 /* Subtract the locator. */
1141 int first_split_diff
= diff
/ 2;
1142 int second_split_diff
= first_split_diff
;
1146 if (first_win
->height
>
1155 second_split_diff
--;
1157 second_split_diff
++;
1160 /* Make sure that the minimum hieghts are
1162 while ((first_win
->height
+ first_split_diff
) < 3)
1165 second_split_diff
--;
1167 while ((second_win
->height
+ second_split_diff
) < 3)
1169 second_split_diff
++;
1172 make_invisible_and_set_new_height (
1174 first_win
->height
+ first_split_diff
);
1175 second_win
->origin
.y
= first_win
->height
- 1;
1176 make_invisible_and_set_new_height (second_win
,
1178 + second_split_diff
);
1179 TUI_CMD_WIN
->origin
.y
= locator
->origin
.y
+ 1;
1180 make_invisible_and_set_new_height (TUI_CMD_WIN
, new_height
);
1184 if ((TUI_CMD_WIN
->height
+ diff
) < 1)
1185 { /* If there is no way to increase the command
1186 window take real estate from the 1st or 2nd
1188 if ((TUI_CMD_WIN
->height
+ diff
) < 1)
1192 for (i
= TUI_CMD_WIN
->height
+ diff
;
1194 if (primary_win_info
== first_win
)
1195 second_win
->height
--;
1197 first_win
->height
--;
1200 if (primary_win_info
== first_win
)
1201 make_invisible_and_set_new_height (first_win
, new_height
);
1203 make_invisible_and_set_new_height (
1206 second_win
->origin
.y
= first_win
->height
- 1;
1207 if (primary_win_info
== second_win
)
1208 make_invisible_and_set_new_height (second_win
, new_height
);
1210 make_invisible_and_set_new_height (
1211 second_win
, second_win
->height
);
1212 TUI_CMD_WIN
->origin
.y
= locator
->origin
.y
+ 1;
1213 if ((TUI_CMD_WIN
->height
+ diff
) < 1)
1214 make_invisible_and_set_new_height (TUI_CMD_WIN
, 1);
1216 make_invisible_and_set_new_height (TUI_CMD_WIN
,
1217 TUI_CMD_WIN
->height
+ diff
);
1219 TUI_CMD_WIN
->make_visible_with_new_height ();
1220 second_win
->make_visible_with_new_height ();
1221 first_win
->make_visible_with_new_height ();
1222 if (src1
!= nullptr && src1
->content
.empty ())
1223 tui_erase_source_content (src1
);
1224 if (second_win
->content
.empty ())
1225 tui_erase_source_content (second_win
);
1234 /* See tui-data.h. */
1237 tui_source_window_base::set_new_height (int height
)
1239 tui_make_invisible (execution_info
);
1240 execution_info
->height
= height
;
1241 execution_info
->origin
.y
= origin
.y
;
1243 execution_info
->viewport_height
= height
- 1;
1245 execution_info
->viewport_height
= height
;
1246 execution_info
->viewport_height
--;
1250 tui_locator_window
*gen_win_info
= tui_locator_win_info_ptr ();
1251 tui_make_invisible (gen_win_info
);
1252 gen_win_info
->origin
.y
= origin
.y
+ height
;
1256 /* See tui-data.h. */
1259 tui_data_window::set_new_height (int height
)
1261 /* Delete all data item windows. */
1262 for (auto &&win
: regs_content
)
1264 tui_delete_win (win
->handle
);
1269 /* Function make the target window (and auxiliary windows associated
1270 with the targer) invisible, and set the new height and
1273 make_invisible_and_set_new_height (struct tui_win_info
*win_info
,
1276 tui_make_invisible (win_info
);
1277 win_info
->height
= height
;
1279 win_info
->viewport_height
= height
- 1;
1281 win_info
->viewport_height
= height
;
1282 if (win_info
!= TUI_CMD_WIN
)
1283 win_info
->viewport_height
--;
1285 /* Now deal with the auxiliary windows associated with win_info. */
1286 win_info
->set_new_height (height
);
1290 /* See tui-data.h. */
1293 tui_win_info::make_visible_with_new_height ()
1295 make_visible (true);
1296 tui_check_and_display_highlight_if_needed (this);
1297 do_make_visible_with_new_height ();
1300 /* See tui-data.h. */
1303 tui_source_window_base::do_make_visible_with_new_height ()
1305 tui_make_visible (execution_info
);
1306 if (!content
.empty ())
1308 struct tui_line_or_address line_or_addr
;
1309 struct symtab_and_line cursal
1310 = get_current_source_symtab_and_line ();
1312 line_or_addr
= start_line_or_addr
;
1313 tui_update_source_window (this, gdbarch
,
1314 cursal
.symtab
, line_or_addr
, TRUE
);
1316 else if (deprecated_safe_get_selected_frame () != NULL
)
1318 struct tui_line_or_address line
;
1319 struct symtab_and_line cursal
1320 = get_current_source_symtab_and_line ();
1321 struct frame_info
*frame
= deprecated_safe_get_selected_frame ();
1322 struct gdbarch
*gdbarch
= get_frame_arch (frame
);
1324 struct symtab
*s
= find_pc_line_symtab (get_frame_pc (frame
));
1325 if (type
== SRC_WIN
)
1327 line
.loa
= LOA_LINE
;
1328 line
.u
.line_no
= cursal
.line
;
1332 line
.loa
= LOA_ADDRESS
;
1333 find_line_pc (s
, cursal
.line
, &line
.u
.addr
);
1335 tui_update_source_window (this, gdbarch
, s
, line
, TRUE
);
1339 tui_make_visible (tui_locator_win_info_ptr ());
1340 tui_show_locator_content ();
1344 /* See tui-data.h. */
1347 tui_data_window::do_make_visible_with_new_height ()
1349 display_all_data ();
1352 /* See tui-data.h. */
1355 tui_cmd_window::do_make_visible_with_new_height ()
1358 wresize (handle
, height
, width
);
1360 mvwin (handle
, origin
.y
, origin
.x
);
1361 wmove (handle
, 0, 0);
1364 /* See tui-data.h. */
1367 tui_win_info::max_height () const
1369 return tui_term_height () - 2;
1372 /* See tui-data.h. */
1375 tui_cmd_window::max_height () const
1377 return tui_term_height () - 4;
1381 new_height_ok (struct tui_win_info
*primary_win_info
,
1384 int ok
= (new_height
< tui_term_height ());
1389 enum tui_layout_type cur_layout
= tui_current_layout ();
1391 diff
= (new_height
- primary_win_info
->height
) * (-1);
1392 if (cur_layout
== SRC_COMMAND
|| cur_layout
== DISASSEM_COMMAND
)
1394 ok
= (new_height
<= primary_win_info
->max_height ()
1395 && new_height
>= MIN_CMD_WIN_HEIGHT
);
1397 { /* Check the total height. */
1398 struct tui_win_info
*win_info
;
1400 if (primary_win_info
== TUI_CMD_WIN
)
1401 win_info
= tui_source_windows ()[0];
1403 win_info
= TUI_CMD_WIN
;
1405 (win_info
->height
+ diff
)) <= tui_term_height ());
1410 int cur_total_height
, total_height
, min_height
= 0;
1411 struct tui_win_info
*first_win
;
1412 struct tui_win_info
*second_win
;
1414 if (cur_layout
== SRC_DISASSEM_COMMAND
)
1416 first_win
= TUI_SRC_WIN
;
1417 second_win
= TUI_DISASM_WIN
;
1421 first_win
= TUI_DATA_WIN
;
1422 second_win
= tui_source_windows ()[0];
1424 /* We could simply add all the heights to obtain the same
1425 result but below is more explicit since we subtract 1 for
1426 the line that the first and second windows share, and add
1427 one for the locator. */
1428 total_height
= cur_total_height
=
1429 (first_win
->height
+ second_win
->height
- 1)
1430 + TUI_CMD_WIN
->height
+ 1; /* Locator. */
1431 if (primary_win_info
== TUI_CMD_WIN
)
1433 /* Locator included since first & second win share a line. */
1434 ok
= ((first_win
->height
+
1435 second_win
->height
+ diff
) >=
1436 (MIN_WIN_HEIGHT
* 2)
1437 && new_height
>= MIN_CMD_WIN_HEIGHT
);
1440 total_height
= new_height
+
1441 (first_win
->height
+
1442 second_win
->height
+ diff
);
1443 min_height
= MIN_CMD_WIN_HEIGHT
;
1448 min_height
= MIN_WIN_HEIGHT
;
1450 /* First see if we can increase/decrease the command
1451 window. And make sure that the command window is at
1453 ok
= ((TUI_CMD_WIN
->height
+ diff
) > 0);
1455 { /* Looks like we have to increase/decrease one of
1456 the other windows. */
1457 if (primary_win_info
== first_win
)
1458 ok
= (second_win
->height
+ diff
) >= min_height
;
1460 ok
= (first_win
->height
+ diff
) >= min_height
;
1464 if (primary_win_info
== first_win
)
1465 total_height
= new_height
+
1466 second_win
->height
+
1467 TUI_CMD_WIN
->height
+ diff
;
1469 total_height
= new_height
+
1471 TUI_CMD_WIN
->height
+ diff
;
1474 /* Now make sure that the proposed total height doesn't
1475 exceed the old total height. */
1477 ok
= (new_height
>= min_height
1478 && total_height
<= cur_total_height
);
1487 parse_scrolling_args (const char *arg
,
1488 struct tui_win_info
**win_to_scroll
,
1493 *win_to_scroll
= tui_win_with_focus ();
1495 /* First set up the default window to scroll, in case there is no
1501 /* Process the number of lines to scroll. */
1502 std::string copy
= arg
;
1504 if (isdigit (*buf_ptr
))
1509 buf_ptr
= strchr (buf_ptr
, ' ');
1510 if (buf_ptr
!= NULL
)
1512 *buf_ptr
= (char) 0;
1514 *num_to_scroll
= atoi (num_str
);
1517 else if (num_to_scroll
)
1518 *num_to_scroll
= atoi (num_str
);
1521 /* Process the window name if one is specified. */
1522 if (buf_ptr
!= NULL
)
1526 if (*buf_ptr
== ' ')
1527 while (*(++buf_ptr
) == ' ')
1530 if (*buf_ptr
!= (char) 0)
1532 /* Validate the window name. */
1533 for (char *p
= buf_ptr
; *p
!= '\0'; p
++)
1541 *win_to_scroll
= tui_partial_win_by_name (wname
);
1543 if (*win_to_scroll
== NULL
1544 || !(*win_to_scroll
)->is_visible
)
1545 error (_("Invalid window specified. \n\
1546 The window name specified must be valid and visible.\n"));
1547 else if (*win_to_scroll
== TUI_CMD_WIN
)
1548 *win_to_scroll
= tui_source_windows ()[0];
1553 /* Function to initialize gdb commands, for tui window
1557 _initialize_tui_win (void)
1559 static struct cmd_list_element
*tui_setlist
;
1560 static struct cmd_list_element
*tui_showlist
;
1561 struct cmd_list_element
*cmd
;
1563 /* Define the classes of commands.
1564 They will appear in the help list in the reverse of this order. */
1565 add_prefix_cmd ("tui", class_tui
, set_tui_cmd
,
1566 _("TUI configuration variables"),
1567 &tui_setlist
, "set tui ",
1568 0 /* allow-unknown */, &setlist
);
1569 add_prefix_cmd ("tui", class_tui
, show_tui_cmd
,
1570 _("TUI configuration variables"),
1571 &tui_showlist
, "show tui ",
1572 0 /* allow-unknown */, &showlist
);
1574 add_com ("refresh", class_tui
, tui_refresh_all_command
,
1575 _("Refresh the terminal display."));
1577 cmd
= add_com ("tabset", class_tui
, tui_set_tab_width_command
, _("\
1578 Set the width (in characters) of tab stops.\n\
1580 deprecate_cmd (cmd
, "set tui tab-width");
1582 cmd
= add_com ("winheight", class_tui
, tui_set_win_height_command
, _("\
1583 Set or modify the height of a specified window.\n"
1585 "Window names are:\n\
1586 src : the source window\n\
1587 cmd : the command window\n\
1588 asm : the disassembly window\n\
1589 regs : the register display"));
1590 add_com_alias ("wh", "winheight", class_tui
, 0);
1591 set_cmd_completer (cmd
, winheight_completer
);
1592 add_info ("win", tui_all_windows_info
,
1593 _("List of all displayed windows."));
1594 cmd
= add_com ("focus", class_tui
, tui_set_focus_command
, _("\
1595 Set focus to named window or next/prev window.\n"
1597 "Valid Window names are:\n\
1598 src : the source window\n\
1599 asm : the disassembly window\n\
1600 regs : the register display\n\
1601 cmd : the command window"));
1602 add_com_alias ("fs", "focus", class_tui
, 0);
1603 set_cmd_completer (cmd
, focus_completer
);
1604 add_com ("+", class_tui
, tui_scroll_forward_command
, _("\
1605 Scroll window forward.\n\
1606 Usage: + [WIN] [N]"));
1607 add_com ("-", class_tui
, tui_scroll_backward_command
, _("\
1608 Scroll window backward.\n\
1609 Usage: - [WIN] [N]"));
1610 add_com ("<", class_tui
, tui_scroll_left_command
, _("\
1611 Scroll window text to the left.\n\
1612 Usage: < [WIN] [N]"));
1613 add_com (">", class_tui
, tui_scroll_right_command
, _("\
1614 Scroll window text to the right.\n\
1615 Usage: > [WIN] [N]"));
1617 /* Define the tui control variables. */
1618 add_setshow_enum_cmd ("border-kind", no_class
, tui_border_kind_enums
,
1619 &tui_border_kind
, _("\
1620 Set the kind of border for TUI windows."), _("\
1621 Show the kind of border for TUI windows."), _("\
1622 This variable controls the border of TUI windows:\n\
1623 space use a white space\n\
1624 ascii use ascii characters + - | for the border\n\
1625 acs use the Alternate Character Set"),
1627 show_tui_border_kind
,
1628 &tui_setlist
, &tui_showlist
);
1630 add_setshow_enum_cmd ("border-mode", no_class
, tui_border_mode_enums
,
1631 &tui_border_mode
, _("\
1632 Set the attribute mode to use for the TUI window borders."), _("\
1633 Show the attribute mode to use for the TUI window borders."), _("\
1634 This variable controls the attributes to use for the window borders:\n\
1635 normal normal display\n\
1636 standout use highlight mode of terminal\n\
1637 reverse use reverse video mode\n\
1638 half use half bright\n\
1639 half-standout use half bright and standout mode\n\
1640 bold use extra bright or bold\n\
1641 bold-standout use extra bright or bold with standout mode"),
1643 show_tui_border_mode
,
1644 &tui_setlist
, &tui_showlist
);
1646 add_setshow_enum_cmd ("active-border-mode", no_class
, tui_border_mode_enums
,
1647 &tui_active_border_mode
, _("\
1648 Set the attribute mode to use for the active TUI window border."), _("\
1649 Show the attribute mode to use for the active TUI window border."), _("\
1650 This variable controls the attributes to use for the active window border:\n\
1651 normal normal display\n\
1652 standout use highlight mode of terminal\n\
1653 reverse use reverse video mode\n\
1654 half use half bright\n\
1655 half-standout use half bright and standout mode\n\
1656 bold use extra bright or bold\n\
1657 bold-standout use extra bright or bold with standout mode"),
1659 show_tui_active_border_mode
,
1660 &tui_setlist
, &tui_showlist
);
1662 add_setshow_zuinteger_cmd ("tab-width", no_class
,
1663 &internal_tab_width
, _("\
1664 Set the tab width, in characters, for the TUI."), _("\
1665 Show the tab witdh, in characters, for the TUI"), _("\
1666 This variable controls how many spaces are used to display a tab character."),
1667 tui_set_tab_width
, tui_show_tab_width
,
1668 &tui_setlist
, &tui_showlist
);