1 /* TUI window generic functions.
3 Copyright (C) 1998-2015 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_visible_with_new_height (struct tui_win_info *);
59 static void make_invisible_and_set_new_height (struct tui_win_info *,
61 static enum tui_status tui_adjust_win_heights (struct tui_win_info *,
63 static int new_height_ok (struct tui_win_info *, int);
64 static void tui_set_tab_width_command (char *, int);
65 static void tui_refresh_all_command (char *, int);
66 static void tui_set_win_height_command (char *, int);
67 static void tui_all_windows_info (char *, int);
68 static void tui_set_focus_command (char *, int);
69 static void tui_scroll_forward_command (char *, int);
70 static void tui_scroll_backward_command (char *, int);
71 static void tui_scroll_left_command (char *, int);
72 static void tui_scroll_right_command (char *, int);
73 static void parse_scrolling_args (char *,
74 struct tui_win_info **,
78 /***************************************
80 ***************************************/
81 #define WIN_HEIGHT_USAGE "Usage: winheight <win_name> [+ | -] <#lines>\n"
82 #define XDBWIN_HEIGHT_USAGE "Usage: w <#lines>\n"
83 #define FOCUS_USAGE "Usage: focus {<win> | next | prev}\n"
85 /***************************************
87 ***************************************/
90 # define ACS_LRCORNER '+'
93 # define ACS_LLCORNER '+'
96 # define ACS_ULCORNER '+'
99 # define ACS_URCORNER '+'
102 # define ACS_HLINE '-'
105 # define ACS_VLINE '|'
108 /* Possible values for tui-border-kind variable. */
109 static const char *const tui_border_kind_enums[] = {
116 /* Possible values for tui-border-mode and tui-active-border-mode. */
117 static const char *const tui_border_mode_enums[] = {
134 /* Translation table for border-mode variables.
135 The list of values must be terminated by a NULL.
136 After the NULL value, an entry defines the default. */
137 struct tui_translate tui_border_mode_translate[] = {
138 { "normal", A_NORMAL },
139 { "standout", A_STANDOUT },
140 { "reverse", A_REVERSE },
142 { "half-standout", A_DIM | A_STANDOUT },
144 { "bold-standout", A_BOLD | A_STANDOUT },
146 { "normal", A_NORMAL }
149 /* Translation tables for border-kind, one for each border
150 character (see wborder, border curses operations).
151 -1 is used to indicate the ACS because ACS characters
152 are determined at run time by curses (depends on terminal). */
153 struct tui_translate tui_border_kind_translate_vline[] = {
161 struct tui_translate tui_border_kind_translate_hline[] = {
169 struct tui_translate tui_border_kind_translate_ulcorner[] = {
177 struct tui_translate tui_border_kind_translate_urcorner[] = {
185 struct tui_translate tui_border_kind_translate_llcorner[] = {
193 struct tui_translate tui_border_kind_translate_lrcorner[] = {
202 /* Tui configuration variables controlled with set/show command. */
203 const char *tui_active_border_mode = "bold-standout";
205 show_tui_active_border_mode (struct ui_file *file,
207 struct cmd_list_element *c,
210 fprintf_filtered (file, _("\
211 The attribute mode to use for the active TUI window border is \"%s\".\n"),
215 const char *tui_border_mode = "normal";
217 show_tui_border_mode (struct ui_file *file,
219 struct cmd_list_element *c,
222 fprintf_filtered (file, _("\
223 The attribute mode to use for the TUI window borders is \"%s\".\n"),
227 const char *tui_border_kind = "acs";
229 show_tui_border_kind (struct ui_file *file,
231 struct cmd_list_element *c,
234 fprintf_filtered (file, _("The kind of border for TUI windows is \"%s\".\n"),
239 /* Tui internal configuration variables. These variables are updated
240 by tui_update_variables to reflect the tui configuration
242 chtype tui_border_vline;
243 chtype tui_border_hline;
244 chtype tui_border_ulcorner;
245 chtype tui_border_urcorner;
246 chtype tui_border_llcorner;
247 chtype tui_border_lrcorner;
249 int tui_border_attrs;
250 int tui_active_border_attrs;
252 /* Identify the item in the translation table.
253 When the item is not recognized, use the default entry. */
254 static struct tui_translate *
255 translate (const char *name, struct tui_translate *table)
259 if (name && strcmp (table->name, name) == 0)
264 /* Not found, return default entry. */
269 /* Update the tui internal configuration according to gdb settings.
270 Returns 1 if the configuration has changed and the screen should
273 tui_update_variables (void)
276 struct tui_translate *entry;
278 entry = translate (tui_border_mode, tui_border_mode_translate);
279 if (tui_border_attrs != entry->value)
281 tui_border_attrs = entry->value;
284 entry = translate (tui_active_border_mode, tui_border_mode_translate);
285 if (tui_active_border_attrs != entry->value)
287 tui_active_border_attrs = entry->value;
291 /* If one corner changes, all characters are changed.
292 Only check the first one. The ACS characters are determined at
293 run time by curses terminal management. */
294 entry = translate (tui_border_kind, tui_border_kind_translate_lrcorner);
295 if (tui_border_lrcorner != (chtype) entry->value)
297 tui_border_lrcorner = (entry->value < 0) ? ACS_LRCORNER : entry->value;
300 entry = translate (tui_border_kind, tui_border_kind_translate_llcorner);
301 tui_border_llcorner = (entry->value < 0) ? ACS_LLCORNER : entry->value;
303 entry = translate (tui_border_kind, tui_border_kind_translate_ulcorner);
304 tui_border_ulcorner = (entry->value < 0) ? ACS_ULCORNER : entry->value;
306 entry = translate (tui_border_kind, tui_border_kind_translate_urcorner);
307 tui_border_urcorner = (entry->value < 0) ? ACS_URCORNER : entry->value;
309 entry = translate (tui_border_kind, tui_border_kind_translate_hline);
310 tui_border_hline = (entry->value < 0) ? ACS_HLINE : entry->value;
312 entry = translate (tui_border_kind, tui_border_kind_translate_vline);
313 tui_border_vline = (entry->value < 0) ? ACS_VLINE : entry->value;
319 set_tui_cmd (char *args, int from_tty)
324 show_tui_cmd (char *args, int from_tty)
328 static struct cmd_list_element *tuilist;
331 tui_command (char *args, int from_tty)
333 printf_unfiltered (_("\"tui\" must be followed by the name of a "
335 help_list (tuilist, "tui ", all_commands, gdb_stdout);
338 struct cmd_list_element **
339 tui_get_cmd_list (void)
342 add_prefix_cmd ("tui", class_tui, tui_command,
343 _("Text User Interface commands."),
344 &tuilist, "tui ", 0, &cmdlist);
348 /* The set_func hook of "set tui ..." commands that affect the window
349 borders on the TUI display. */
351 tui_set_var_cmd (char *null_args, int from_tty, struct cmd_list_element *c)
353 if (tui_update_variables () && tui_active)
354 tui_rehighlight_all ();
357 /* Complete possible window names to focus on. TEXT is the complete text
358 entered so far, WORD is the word currently being completed. */
360 static VEC (char_ptr) *
361 focus_completer (struct cmd_list_element *ignore,
362 const char *text, const char *word)
364 VEC (const_char_ptr) *completion_name_vec = NULL;
365 VEC (char_ptr) *matches_vec;
368 for (win_type = SRC_WIN; win_type < MAX_MAJOR_WINDOWS; win_type++)
370 const char *completion_name = NULL;
372 /* We can't focus on an invisible window. */
373 if (tui_win_list[win_type] == NULL
374 || !tui_win_list[win_type]->generic.is_visible)
380 completion_name = "src";
383 completion_name = "asm";
386 completion_name = "regs";
389 completion_name = "cmd";
395 if (completion_name != NULL)
396 VEC_safe_push (const_char_ptr, completion_name_vec, completion_name);
399 /* If no windows are considered visible then the TUI has not yet been
400 initialized. But still "focus src" and "focus cmd" will work because
401 invoking the focus command will entail initializing the TUI which sets the
402 default layout to SRC_COMMAND. */
403 if (VEC_length (const_char_ptr, completion_name_vec) == 0)
405 VEC_safe_push (const_char_ptr, completion_name_vec, "src");
406 VEC_safe_push (const_char_ptr, completion_name_vec, "cmd");
409 VEC_safe_push (const_char_ptr, completion_name_vec, "next");
410 VEC_safe_push (const_char_ptr, completion_name_vec, "prev");
411 VEC_safe_push (const_char_ptr, completion_name_vec, NULL);
414 = complete_on_enum (VEC_address (const_char_ptr, completion_name_vec),
417 VEC_free (const_char_ptr, completion_name_vec);
422 /* Function to initialize gdb commands, for tui window
425 /* Provide a prototype to silence -Wmissing-prototypes. */
426 extern initialize_file_ftype _initialize_tui_win;
429 _initialize_tui_win (void)
431 static struct cmd_list_element *tui_setlist;
432 static struct cmd_list_element *tui_showlist;
433 struct cmd_list_element *focus_cmd;
435 /* Define the classes of commands.
436 They will appear in the help list in the reverse of this order. */
437 add_prefix_cmd ("tui", class_tui, set_tui_cmd,
438 _("TUI configuration variables"),
439 &tui_setlist, "set tui ",
440 0 /* allow-unknown */, &setlist);
441 add_prefix_cmd ("tui", class_tui, show_tui_cmd,
442 _("TUI configuration variables"),
443 &tui_showlist, "show tui ",
444 0 /* allow-unknown */, &showlist);
446 add_com ("refresh", class_tui, tui_refresh_all_command,
447 _("Refresh the terminal display.\n"));
448 add_com ("tabset", class_tui, tui_set_tab_width_command, _("\
449 Set the width (in characters) of tab stops.\n\
450 Usage: tabset <n>\n"));
451 add_com ("winheight", class_tui, tui_set_win_height_command, _("\
452 Set the height of a specified window.\n\
453 Usage: winheight <win_name> [+ | -] <#lines>\n\
455 src : the source window\n\
456 cmd : the command window\n\
457 asm : the disassembly window\n\
458 regs : the register display\n"));
459 add_com_alias ("wh", "winheight", class_tui, 0);
460 add_info ("win", tui_all_windows_info,
461 _("List of all displayed windows.\n"));
462 focus_cmd = add_com ("focus", class_tui, tui_set_focus_command, _("\
463 Set focus to named window or next/prev window.\n\
464 Usage: focus {<win> | next | prev}\n\
465 Valid Window names are:\n\
466 src : the source window\n\
467 asm : the disassembly window\n\
468 regs : the register display\n\
469 cmd : the command window\n"));
470 add_com_alias ("fs", "focus", class_tui, 0);
471 set_cmd_completer (focus_cmd, focus_completer);
472 add_com ("+", class_tui, tui_scroll_forward_command, _("\
473 Scroll window forward.\n\
474 Usage: + [win] [n]\n"));
475 add_com ("-", class_tui, tui_scroll_backward_command, _("\
476 Scroll window backward.\n\
477 Usage: - [win] [n]\n"));
478 add_com ("<", class_tui, tui_scroll_left_command, _("\
479 Scroll window text to the left.\n\
480 Usage: < [win] [n]\n"));
481 add_com (">", class_tui, tui_scroll_right_command, _("\
482 Scroll window text to the right.\n\
483 Usage: > [win] [n]\n"));
485 /* Define the tui control variables. */
486 add_setshow_enum_cmd ("border-kind", no_class, tui_border_kind_enums,
487 &tui_border_kind, _("\
488 Set the kind of border for TUI windows."), _("\
489 Show the kind of border for TUI windows."), _("\
490 This variable controls the border of TUI windows:\n\
491 space use a white space\n\
492 ascii use ascii characters + - | for the border\n\
493 acs use the Alternate Character Set"),
495 show_tui_border_kind,
496 &tui_setlist, &tui_showlist);
498 add_setshow_enum_cmd ("border-mode", no_class, tui_border_mode_enums,
499 &tui_border_mode, _("\
500 Set the attribute mode to use for the TUI window borders."), _("\
501 Show the attribute mode to use for the TUI window borders."), _("\
502 This variable controls the attributes to use for the window borders:\n\
503 normal normal display\n\
504 standout use highlight mode of terminal\n\
505 reverse use reverse video mode\n\
506 half use half bright\n\
507 half-standout use half bright and standout mode\n\
508 bold use extra bright or bold\n\
509 bold-standout use extra bright or bold with standout mode"),
511 show_tui_border_mode,
512 &tui_setlist, &tui_showlist);
514 add_setshow_enum_cmd ("active-border-mode", no_class, tui_border_mode_enums,
515 &tui_active_border_mode, _("\
516 Set the attribute mode to use for the active TUI window border."), _("\
517 Show the attribute mode to use for the active TUI window border."), _("\
518 This variable controls the attributes to use for the active window border:\n\
519 normal normal display\n\
520 standout use highlight mode of terminal\n\
521 reverse use reverse video mode\n\
522 half use half bright\n\
523 half-standout use half bright and standout mode\n\
524 bold use extra bright or bold\n\
525 bold-standout use extra bright or bold with standout mode"),
527 show_tui_active_border_mode,
528 &tui_setlist, &tui_showlist);
531 /* Update gdb's knowledge of the terminal size. */
533 tui_update_gdb_sizes (void)
539 width = TUI_CMD_WIN->generic.width;
540 height = TUI_CMD_WIN->generic.height;
544 width = tui_term_width ();
545 height = tui_term_height ();
548 set_screen_width_and_height (width, height);
552 /* Set the logical focus to win_info. */
554 tui_set_win_focus_to (struct tui_win_info *win_info)
556 if (win_info != NULL)
558 struct tui_win_info *win_with_focus = tui_win_with_focus ();
560 if (win_with_focus != NULL
561 && win_with_focus->generic.type != CMD_WIN)
562 tui_unhighlight_win (win_with_focus);
563 tui_set_win_with_focus (win_info);
564 if (win_info->generic.type != CMD_WIN)
565 tui_highlight_win (win_info);
571 tui_scroll_forward (struct tui_win_info *win_to_scroll,
574 if (win_to_scroll != TUI_CMD_WIN)
576 int _num_to_scroll = num_to_scroll;
578 if (num_to_scroll == 0)
579 _num_to_scroll = win_to_scroll->generic.height - 3;
581 /* If we are scrolling the source or disassembly window, do a
582 "psuedo" scroll since not all of the source is in memory,
583 only what is in the viewport. If win_to_scroll is the
584 command window do nothing since the term should handle
586 if (win_to_scroll == TUI_SRC_WIN)
587 tui_vertical_source_scroll (FORWARD_SCROLL, _num_to_scroll);
588 else if (win_to_scroll == TUI_DISASM_WIN)
589 tui_vertical_disassem_scroll (FORWARD_SCROLL, _num_to_scroll);
590 else if (win_to_scroll == TUI_DATA_WIN)
591 tui_vertical_data_scroll (FORWARD_SCROLL, _num_to_scroll);
596 tui_scroll_backward (struct tui_win_info *win_to_scroll,
599 if (win_to_scroll != TUI_CMD_WIN)
601 int _num_to_scroll = num_to_scroll;
603 if (num_to_scroll == 0)
604 _num_to_scroll = win_to_scroll->generic.height - 3;
606 /* If we are scrolling the source or disassembly window, do a
607 "psuedo" scroll since not all of the source is in memory,
608 only what is in the viewport. If win_to_scroll is the
609 command window do nothing since the term should handle
611 if (win_to_scroll == TUI_SRC_WIN)
612 tui_vertical_source_scroll (BACKWARD_SCROLL, _num_to_scroll);
613 else if (win_to_scroll == TUI_DISASM_WIN)
614 tui_vertical_disassem_scroll (BACKWARD_SCROLL, _num_to_scroll);
615 else if (win_to_scroll == TUI_DATA_WIN)
616 tui_vertical_data_scroll (BACKWARD_SCROLL, _num_to_scroll);
622 tui_scroll_left (struct tui_win_info *win_to_scroll,
625 if (win_to_scroll != TUI_CMD_WIN)
627 int _num_to_scroll = num_to_scroll;
629 if (_num_to_scroll == 0)
632 /* If we are scrolling the source or disassembly window, do a
633 "psuedo" scroll since not all of the source is in memory,
634 only what is in the viewport. If win_to_scroll is the command
635 window do nothing since the term should handle it. */
636 if (win_to_scroll == TUI_SRC_WIN
637 || win_to_scroll == TUI_DISASM_WIN)
638 tui_horizontal_source_scroll (win_to_scroll, LEFT_SCROLL,
645 tui_scroll_right (struct tui_win_info *win_to_scroll,
648 if (win_to_scroll != TUI_CMD_WIN)
650 int _num_to_scroll = num_to_scroll;
652 if (_num_to_scroll == 0)
655 /* If we are scrolling the source or disassembly window, do a
656 "psuedo" scroll since not all of the source is in memory,
657 only what is in the viewport. If win_to_scroll is the command
658 window do nothing since the term should handle it. */
659 if (win_to_scroll == TUI_SRC_WIN
660 || win_to_scroll == TUI_DISASM_WIN)
661 tui_horizontal_source_scroll (win_to_scroll, RIGHT_SCROLL,
667 /* Scroll a window. Arguments are passed through a va_list. */
669 tui_scroll (enum tui_scroll_direction direction,
670 struct tui_win_info *win_to_scroll,
676 tui_scroll_forward (win_to_scroll, num_to_scroll);
678 case BACKWARD_SCROLL:
679 tui_scroll_backward (win_to_scroll, num_to_scroll);
682 tui_scroll_left (win_to_scroll, num_to_scroll);
685 tui_scroll_right (win_to_scroll, num_to_scroll);
694 tui_refresh_all_win (void)
698 clearok (curscr, TRUE);
699 tui_refresh_all (tui_win_list);
700 for (type = SRC_WIN; type < MAX_MAJOR_WINDOWS; type++)
702 if (tui_win_list[type]
703 && tui_win_list[type]->generic.is_visible)
709 tui_show_source_content (tui_win_list[type]);
710 tui_check_and_display_highlight_if_needed (tui_win_list[type]);
711 tui_erase_exec_info_content (tui_win_list[type]);
712 tui_update_exec_info (tui_win_list[type]);
715 tui_refresh_data_win ();
722 tui_show_locator_content ();
726 tui_rehighlight_all (void)
730 for (type = SRC_WIN; type < MAX_MAJOR_WINDOWS; type++)
731 tui_check_and_display_highlight_if_needed (tui_win_list[type]);
734 /* Resize all the windows based on the terminal size. This function
735 gets called from within the readline sinwinch handler. */
737 tui_resize_all (void)
739 int height_diff, width_diff;
740 int screenheight, screenwidth;
742 rl_get_screen_size (&screenheight, &screenwidth);
743 width_diff = screenwidth - tui_term_width ();
744 height_diff = screenheight - tui_term_height ();
745 if (height_diff || width_diff)
747 enum tui_layout_type cur_layout = tui_current_layout ();
748 struct tui_win_info *win_with_focus = tui_win_with_focus ();
749 struct tui_win_info *first_win;
750 struct tui_win_info *second_win;
751 struct tui_gen_win_info *locator = tui_locator_win_info_ptr ();
753 int new_height, split_diff, cmd_split_diff, num_wins_displayed = 2;
755 #ifdef HAVE_RESIZE_TERM
756 resize_term (screenheight, screenwidth);
758 /* Turn keypad off while we resize. */
759 if (win_with_focus != TUI_CMD_WIN)
760 keypad (TUI_CMD_WIN->generic.handle, FALSE);
761 tui_update_gdb_sizes ();
762 tui_set_term_height_to (screenheight);
763 tui_set_term_width_to (screenwidth);
764 if (cur_layout == SRC_DISASSEM_COMMAND
765 || cur_layout == SRC_DATA_COMMAND
766 || cur_layout == DISASSEM_DATA_COMMAND)
767 num_wins_displayed++;
768 split_diff = height_diff / num_wins_displayed;
769 cmd_split_diff = split_diff;
770 if (height_diff % num_wins_displayed)
777 /* Now adjust each window. */
778 /* erase + clearok are used instead of a straightforward clear as
779 AIX 5.3 does not define clear. */
781 clearok (curscr, TRUE);
786 case DISASSEM_COMMAND:
787 first_win = (struct tui_win_info *) (tui_source_windows ())->list[0];
788 first_win->generic.width += width_diff;
789 locator->width += width_diff;
790 /* Check for invalid heights. */
791 if (height_diff == 0)
792 new_height = first_win->generic.height;
793 else if ((first_win->generic.height + split_diff) >=
794 (screenheight - MIN_CMD_WIN_HEIGHT - 1))
795 new_height = screenheight - MIN_CMD_WIN_HEIGHT - 1;
796 else if ((first_win->generic.height + split_diff) <= 0)
797 new_height = MIN_WIN_HEIGHT;
799 new_height = first_win->generic.height + split_diff;
801 locator->origin.y = new_height + 1;
802 make_invisible_and_set_new_height (first_win, new_height);
803 TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1;
804 TUI_CMD_WIN->generic.width += width_diff;
805 new_height = screenheight - TUI_CMD_WIN->generic.origin.y;
806 make_invisible_and_set_new_height (TUI_CMD_WIN, new_height);
807 make_visible_with_new_height (first_win);
808 make_visible_with_new_height (TUI_CMD_WIN);
809 if (first_win->generic.content_size <= 0)
810 tui_erase_source_content (first_win, EMPTY_SOURCE_PROMPT);
813 if (cur_layout == SRC_DISASSEM_COMMAND)
815 first_win = TUI_SRC_WIN;
816 first_win->generic.width += width_diff;
817 second_win = TUI_DISASM_WIN;
818 second_win->generic.width += width_diff;
822 first_win = TUI_DATA_WIN;
823 first_win->generic.width += width_diff;
824 second_win = (struct tui_win_info *)
825 (tui_source_windows ())->list[0];
826 second_win->generic.width += width_diff;
828 /* Change the first window's height/width. */
829 /* Check for invalid heights. */
830 if (height_diff == 0)
831 new_height = first_win->generic.height;
832 else if ((first_win->generic.height +
833 second_win->generic.height + (split_diff * 2)) >=
834 (screenheight - MIN_CMD_WIN_HEIGHT - 1))
835 new_height = (screenheight - MIN_CMD_WIN_HEIGHT - 1) / 2;
836 else if ((first_win->generic.height + split_diff) <= 0)
837 new_height = MIN_WIN_HEIGHT;
839 new_height = first_win->generic.height + split_diff;
840 make_invisible_and_set_new_height (first_win, new_height);
842 locator->width += width_diff;
844 /* Change the second window's height/width. */
845 /* Check for invalid heights. */
846 if (height_diff == 0)
847 new_height = second_win->generic.height;
848 else if ((first_win->generic.height +
849 second_win->generic.height + (split_diff * 2)) >=
850 (screenheight - MIN_CMD_WIN_HEIGHT - 1))
852 new_height = screenheight - MIN_CMD_WIN_HEIGHT - 1;
854 new_height = (new_height / 2) + 1;
858 else if ((second_win->generic.height + split_diff) <= 0)
859 new_height = MIN_WIN_HEIGHT;
861 new_height = second_win->generic.height + split_diff;
862 second_win->generic.origin.y = first_win->generic.height - 1;
863 make_invisible_and_set_new_height (second_win, new_height);
865 /* Change the command window's height/width. */
866 TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1;
867 make_invisible_and_set_new_height (TUI_CMD_WIN,
868 TUI_CMD_WIN->generic.height
870 make_visible_with_new_height (first_win);
871 make_visible_with_new_height (second_win);
872 make_visible_with_new_height (TUI_CMD_WIN);
873 if (first_win->generic.content_size <= 0)
874 tui_erase_source_content (first_win, EMPTY_SOURCE_PROMPT);
875 if (second_win->generic.content_size <= 0)
876 tui_erase_source_content (second_win, EMPTY_SOURCE_PROMPT);
879 /* Now remove all invisible windows, and their content so that
880 they get created again when called for with the new size. */
881 for (win_type = SRC_WIN; (win_type < MAX_MAJOR_WINDOWS); win_type++)
883 if (win_type != CMD_WIN
884 && (tui_win_list[win_type] != NULL)
885 && !tui_win_list[win_type]->generic.is_visible)
887 tui_free_window (tui_win_list[win_type]);
888 tui_win_list[win_type] = (struct tui_win_info *) NULL;
891 /* Turn keypad back on, unless focus is in the command
893 if (win_with_focus != TUI_CMD_WIN)
894 keypad (TUI_CMD_WIN->generic.handle, TRUE);
899 /* Token for use by TUI's asynchronous SIGWINCH handler. */
900 static struct async_signal_handler *tui_sigwinch_token;
902 /* TUI's SIGWINCH signal handler. */
904 tui_sigwinch_handler (int signal)
906 mark_async_signal_handler (tui_sigwinch_token);
907 tui_set_win_resized_to (TRUE);
910 /* Callback for asynchronously resizing TUI following a SIGWINCH signal. */
912 tui_async_resize_screen (gdb_client_data arg)
914 rl_resize_terminal ();
918 int screen_height, screen_width;
920 rl_get_screen_size (&screen_height, &screen_width);
921 set_screen_width_and_height (screen_width, screen_height);
923 /* win_resized is left set so that the next call to tui_enable()
924 resizes the TUI windows. */
928 tui_set_win_resized_to (FALSE);
930 tui_refresh_all_win ();
931 tui_update_gdb_sizes ();
932 tui_redisplay_readline ();
937 /* Initialize TUI's SIGWINCH signal handler. Note that the handler is not
938 uninstalled when we exit TUI, so the handler should not assume that TUI is
941 tui_initialize_win (void)
945 = create_async_signal_handler (tui_async_resize_screen, NULL);
948 #ifdef HAVE_SIGACTION
949 struct sigaction old_winch;
951 memset (&old_winch, 0, sizeof (old_winch));
952 old_winch.sa_handler = &tui_sigwinch_handler;
954 old_winch.sa_flags = SA_RESTART;
956 sigaction (SIGWINCH, &old_winch, NULL);
958 signal (SIGWINCH, &tui_sigwinch_handler);
965 /*************************
966 ** STATIC LOCAL FUNCTIONS
967 **************************/
971 tui_scroll_forward_command (char *arg, int from_tty)
973 int num_to_scroll = 1;
974 struct tui_win_info *win_to_scroll;
976 /* Make sure the curses mode is enabled. */
978 if (arg == (char *) NULL)
979 parse_scrolling_args (arg, &win_to_scroll, (int *) NULL);
981 parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
982 tui_scroll (FORWARD_SCROLL, win_to_scroll, num_to_scroll);
987 tui_scroll_backward_command (char *arg, int from_tty)
989 int num_to_scroll = 1;
990 struct tui_win_info *win_to_scroll;
992 /* Make sure the curses mode is enabled. */
994 if (arg == (char *) NULL)
995 parse_scrolling_args (arg, &win_to_scroll, (int *) NULL);
997 parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
998 tui_scroll (BACKWARD_SCROLL, win_to_scroll, num_to_scroll);
1003 tui_scroll_left_command (char *arg, int from_tty)
1006 struct tui_win_info *win_to_scroll;
1008 /* Make sure the curses mode is enabled. */
1010 parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
1011 tui_scroll (LEFT_SCROLL, win_to_scroll, num_to_scroll);
1016 tui_scroll_right_command (char *arg, int from_tty)
1019 struct tui_win_info *win_to_scroll;
1021 /* Make sure the curses mode is enabled. */
1023 parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
1024 tui_scroll (RIGHT_SCROLL, win_to_scroll, num_to_scroll);
1028 /* Set focus to the window named by 'arg'. */
1030 tui_set_focus (char *arg, int from_tty)
1032 if (arg != (char *) NULL)
1034 char *buf_ptr = (char *) xstrdup (arg);
1036 struct tui_win_info *win_info = (struct tui_win_info *) NULL;
1038 for (i = 0; (i < strlen (buf_ptr)); i++)
1039 buf_ptr[i] = tolower (arg[i]);
1041 if (subset_compare (buf_ptr, "next"))
1042 win_info = tui_next_win (tui_win_with_focus ());
1043 else if (subset_compare (buf_ptr, "prev"))
1044 win_info = tui_prev_win (tui_win_with_focus ());
1046 win_info = tui_partial_win_by_name (buf_ptr);
1048 if (win_info == (struct tui_win_info *) NULL
1049 || !win_info->generic.is_visible)
1050 warning (_("Invalid window specified. \n\
1051 The window name specified must be valid and visible.\n"));
1054 tui_set_win_focus_to (win_info);
1055 keypad (TUI_CMD_WIN->generic.handle, (win_info != TUI_CMD_WIN));
1058 if (TUI_DATA_WIN && TUI_DATA_WIN->generic.is_visible)
1059 tui_refresh_data_win ();
1061 printf_filtered (_("Focus set to %s window.\n"),
1062 tui_win_name (&tui_win_with_focus ()->generic));
1065 warning (_("Incorrect Number of Arguments.\n%s"), FOCUS_USAGE);
1069 tui_set_focus_command (char *arg, int from_tty)
1071 /* Make sure the curses mode is enabled. */
1073 tui_set_focus (arg, from_tty);
1078 tui_all_windows_info (char *arg, int from_tty)
1081 struct tui_win_info *win_with_focus = tui_win_with_focus ();
1083 for (type = SRC_WIN; (type < MAX_MAJOR_WINDOWS); type++)
1084 if (tui_win_list[type]
1085 && tui_win_list[type]->generic.is_visible)
1087 if (win_with_focus == tui_win_list[type])
1088 printf_filtered (" %s\t(%d lines) <has focus>\n",
1089 tui_win_name (&tui_win_list[type]->generic),
1090 tui_win_list[type]->generic.height);
1092 printf_filtered (" %s\t(%d lines)\n",
1093 tui_win_name (&tui_win_list[type]->generic),
1094 tui_win_list[type]->generic.height);
1100 tui_refresh_all_command (char *arg, int from_tty)
1102 /* Make sure the curses mode is enabled. */
1105 tui_refresh_all_win ();
1109 /* Set the tab width of the specified window. */
1111 tui_set_tab_width_command (char *arg, int from_tty)
1113 /* Make sure the curses mode is enabled. */
1115 if (arg != (char *) NULL)
1122 tui_set_default_tab_len (ts);
1123 /* We don't really change the height of any windows, but
1124 calling these 2 functions causes a complete regeneration
1125 and redisplay of the window's contents, which will take
1126 the new tab width into account. */
1127 if (tui_win_list[SRC_WIN]
1128 && tui_win_list[SRC_WIN]->generic.is_visible)
1130 make_invisible_and_set_new_height (TUI_SRC_WIN,
1131 TUI_SRC_WIN->generic.height);
1132 make_visible_with_new_height (TUI_SRC_WIN);
1134 if (tui_win_list[DISASSEM_WIN]
1135 && tui_win_list[DISASSEM_WIN]->generic.is_visible)
1137 make_invisible_and_set_new_height (TUI_DISASM_WIN,
1138 TUI_DISASM_WIN->generic.height);
1139 make_visible_with_new_height (TUI_DISASM_WIN);
1143 warning (_("Tab widths greater than 0 must be specified."));
1148 /* Set the height of the specified window. */
1150 tui_set_win_height (char *arg, int from_tty)
1152 /* Make sure the curses mode is enabled. */
1154 if (arg != (char *) NULL)
1156 char *buf = xstrdup (arg);
1157 char *buf_ptr = buf;
1158 char *wname = (char *) NULL;
1160 struct tui_win_info *win_info;
1163 buf_ptr = strchr (buf_ptr, ' ');
1164 if (buf_ptr != (char *) NULL)
1166 *buf_ptr = (char) 0;
1168 /* Validate the window name. */
1169 for (i = 0; i < strlen (wname); i++)
1170 wname[i] = tolower (wname[i]);
1171 win_info = tui_partial_win_by_name (wname);
1173 if (win_info == (struct tui_win_info *) NULL
1174 || !win_info->generic.is_visible)
1175 warning (_("Invalid window specified. \n\
1176 The window name specified must be valid and visible.\n"));
1179 /* Process the size. */
1180 while (*(++buf_ptr) == ' ')
1183 if (*buf_ptr != (char) 0)
1186 int fixed_size = TRUE;
1189 if (*buf_ptr == '+' || *buf_ptr == '-')
1191 if (*buf_ptr == '-')
1196 input_no = atoi (buf_ptr);
1202 new_height = input_no;
1204 new_height = win_info->generic.height + input_no;
1206 /* Now change the window's height, and adjust
1207 all other windows around it. */
1208 if (tui_adjust_win_heights (win_info,
1209 new_height) == TUI_FAILURE)
1210 warning (_("Invalid window height specified.\n%s"),
1213 tui_update_gdb_sizes ();
1216 warning (_("Invalid window height specified.\n%s"),
1222 printf_filtered (WIN_HEIGHT_USAGE);
1224 if (buf != (char *) NULL)
1228 printf_filtered (WIN_HEIGHT_USAGE);
1231 /* Set the height of the specified window, with va_list. */
1233 tui_set_win_height_command (char *arg, int from_tty)
1235 /* Make sure the curses mode is enabled. */
1237 tui_set_win_height (arg, from_tty);
1240 /* Function to adjust all window heights around the primary. */
1241 static enum tui_status
1242 tui_adjust_win_heights (struct tui_win_info *primary_win_info,
1245 enum tui_status status = TUI_FAILURE;
1247 if (new_height_ok (primary_win_info, new_height))
1249 status = TUI_SUCCESS;
1250 if (new_height != primary_win_info->generic.height)
1253 struct tui_win_info *win_info;
1254 struct tui_gen_win_info *locator = tui_locator_win_info_ptr ();
1255 enum tui_layout_type cur_layout = tui_current_layout ();
1257 diff = (new_height - primary_win_info->generic.height) * (-1);
1258 if (cur_layout == SRC_COMMAND
1259 || cur_layout == DISASSEM_COMMAND)
1261 struct tui_win_info *src_win_info;
1263 make_invisible_and_set_new_height (primary_win_info, new_height);
1264 if (primary_win_info->generic.type == CMD_WIN)
1266 win_info = (tui_source_windows ())->list[0];
1267 src_win_info = win_info;
1271 win_info = tui_win_list[CMD_WIN];
1272 src_win_info = primary_win_info;
1274 make_invisible_and_set_new_height (win_info,
1275 win_info->generic.height + diff);
1276 TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1;
1277 make_visible_with_new_height (win_info);
1278 make_visible_with_new_height (primary_win_info);
1279 if (src_win_info->generic.content_size <= 0)
1280 tui_erase_source_content (src_win_info, EMPTY_SOURCE_PROMPT);
1284 struct tui_win_info *first_win;
1285 struct tui_win_info *second_win;
1287 if (cur_layout == SRC_DISASSEM_COMMAND)
1289 first_win = TUI_SRC_WIN;
1290 second_win = TUI_DISASM_WIN;
1294 first_win = TUI_DATA_WIN;
1295 second_win = (tui_source_windows ())->list[0];
1297 if (primary_win_info == TUI_CMD_WIN)
1298 { /* Split the change in height accross the 1st & 2nd
1299 windows, adjusting them as well. */
1300 /* Subtract the locator. */
1301 int first_split_diff = diff / 2;
1302 int second_split_diff = first_split_diff;
1306 if (first_win->generic.height >
1307 second_win->generic.height)
1315 second_split_diff--;
1317 second_split_diff++;
1320 /* Make sure that the minimum hieghts are
1322 while ((first_win->generic.height + first_split_diff) < 3)
1325 second_split_diff--;
1327 while ((second_win->generic.height + second_split_diff) < 3)
1329 second_split_diff++;
1332 make_invisible_and_set_new_height (
1334 first_win->generic.height + first_split_diff);
1335 second_win->generic.origin.y = first_win->generic.height - 1;
1336 make_invisible_and_set_new_height (second_win,
1337 second_win->generic.height
1338 + second_split_diff);
1339 TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1;
1340 make_invisible_and_set_new_height (TUI_CMD_WIN, new_height);
1344 if ((TUI_CMD_WIN->generic.height + diff) < 1)
1345 { /* If there is no way to increase the command
1346 window take real estate from the 1st or 2nd
1348 if ((TUI_CMD_WIN->generic.height + diff) < 1)
1352 for (i = TUI_CMD_WIN->generic.height + diff;
1354 if (primary_win_info == first_win)
1355 second_win->generic.height--;
1357 first_win->generic.height--;
1360 if (primary_win_info == first_win)
1361 make_invisible_and_set_new_height (first_win, new_height);
1363 make_invisible_and_set_new_height (
1365 first_win->generic.height);
1366 second_win->generic.origin.y = first_win->generic.height - 1;
1367 if (primary_win_info == second_win)
1368 make_invisible_and_set_new_height (second_win, new_height);
1370 make_invisible_and_set_new_height (
1371 second_win, second_win->generic.height);
1372 TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1;
1373 if ((TUI_CMD_WIN->generic.height + diff) < 1)
1374 make_invisible_and_set_new_height (TUI_CMD_WIN, 1);
1376 make_invisible_and_set_new_height (TUI_CMD_WIN,
1377 TUI_CMD_WIN->generic.height + diff);
1379 make_visible_with_new_height (TUI_CMD_WIN);
1380 make_visible_with_new_height (second_win);
1381 make_visible_with_new_height (first_win);
1382 if (first_win->generic.content_size <= 0)
1383 tui_erase_source_content (first_win, EMPTY_SOURCE_PROMPT);
1384 if (second_win->generic.content_size <= 0)
1385 tui_erase_source_content (second_win, EMPTY_SOURCE_PROMPT);
1394 /* Function make the target window (and auxillary windows associated
1395 with the targer) invisible, and set the new height and
1398 make_invisible_and_set_new_height (struct tui_win_info *win_info,
1402 struct tui_gen_win_info *gen_win_info;
1404 tui_make_invisible (&win_info->generic);
1405 win_info->generic.height = height;
1407 win_info->generic.viewport_height = height - 1;
1409 win_info->generic.viewport_height = height;
1410 if (win_info != TUI_CMD_WIN)
1411 win_info->generic.viewport_height--;
1413 /* Now deal with the auxillary windows associated with win_info. */
1414 switch (win_info->generic.type)
1418 gen_win_info = win_info->detail.source_info.execution_info;
1419 tui_make_invisible (gen_win_info);
1420 gen_win_info->height = height;
1421 gen_win_info->origin.y = win_info->generic.origin.y;
1423 gen_win_info->viewport_height = height - 1;
1425 gen_win_info->viewport_height = height;
1426 if (win_info != TUI_CMD_WIN)
1427 gen_win_info->viewport_height--;
1429 if (tui_win_has_locator (win_info))
1431 gen_win_info = tui_locator_win_info_ptr ();
1432 tui_make_invisible (gen_win_info);
1433 gen_win_info->origin.y = win_info->generic.origin.y + height;
1437 /* Delete all data item windows. */
1438 for (i = 0; i < win_info->generic.content_size; i++)
1440 gen_win_info = (struct tui_gen_win_info *)
1441 &((struct tui_win_element *)
1442 win_info->generic.content[i])->which_element.data_window;
1443 tui_delete_win (gen_win_info->handle);
1444 gen_win_info->handle = (WINDOW *) NULL;
1453 /* Function to make the windows with new heights visible. This means
1454 re-creating the windows' content since the window had to be
1455 destroyed to be made invisible. */
1457 make_visible_with_new_height (struct tui_win_info *win_info)
1461 tui_make_visible (&win_info->generic);
1462 tui_check_and_display_highlight_if_needed (win_info);
1463 switch (win_info->generic.type)
1467 tui_free_win_content (win_info->detail.source_info.execution_info);
1468 tui_make_visible (win_info->detail.source_info.execution_info);
1469 if (win_info->generic.content != NULL)
1471 struct gdbarch *gdbarch = win_info->detail.source_info.gdbarch;
1472 struct tui_line_or_address line_or_addr;
1473 struct symtab_and_line cursal
1474 = get_current_source_symtab_and_line ();
1476 line_or_addr = win_info->detail.source_info.start_line_or_addr;
1477 tui_free_win_content (&win_info->generic);
1478 tui_update_source_window (win_info, gdbarch,
1479 cursal.symtab, line_or_addr, TRUE);
1481 else if (deprecated_safe_get_selected_frame () != NULL)
1483 struct tui_line_or_address line;
1484 struct symtab_and_line cursal
1485 = get_current_source_symtab_and_line ();
1486 struct frame_info *frame = deprecated_safe_get_selected_frame ();
1487 struct gdbarch *gdbarch = get_frame_arch (frame);
1489 s = find_pc_line_symtab (get_frame_pc (frame));
1490 if (win_info->generic.type == SRC_WIN)
1492 line.loa = LOA_LINE;
1493 line.u.line_no = cursal.line;
1497 line.loa = LOA_ADDRESS;
1498 find_line_pc (s, cursal.line, &line.u.addr);
1500 tui_update_source_window (win_info, gdbarch, s, line, TRUE);
1502 if (tui_win_has_locator (win_info))
1504 tui_make_visible (tui_locator_win_info_ptr ());
1505 tui_show_locator_content ();
1509 tui_display_all_data ();
1512 win_info->detail.command_info.cur_line = 0;
1513 win_info->detail.command_info.curch = 0;
1515 wresize (TUI_CMD_WIN->generic.handle,
1516 TUI_CMD_WIN->generic.height,
1517 TUI_CMD_WIN->generic.width);
1519 mvwin (TUI_CMD_WIN->generic.handle,
1520 TUI_CMD_WIN->generic.origin.y,
1521 TUI_CMD_WIN->generic.origin.x);
1522 wmove (win_info->generic.handle,
1523 win_info->detail.command_info.cur_line,
1524 win_info->detail.command_info.curch);
1533 new_height_ok (struct tui_win_info *primary_win_info,
1536 int ok = (new_height < tui_term_height ());
1541 enum tui_layout_type cur_layout = tui_current_layout ();
1543 diff = (new_height - primary_win_info->generic.height) * (-1);
1544 if (cur_layout == SRC_COMMAND || cur_layout == DISASSEM_COMMAND)
1546 ok = ((primary_win_info->generic.type == CMD_WIN
1547 && new_height <= (tui_term_height () - 4)
1548 && new_height >= MIN_CMD_WIN_HEIGHT)
1549 || (primary_win_info->generic.type != CMD_WIN
1550 && new_height <= (tui_term_height () - 2)
1551 && new_height >= MIN_WIN_HEIGHT));
1553 { /* Check the total height. */
1554 struct tui_win_info *win_info;
1556 if (primary_win_info == TUI_CMD_WIN)
1557 win_info = (tui_source_windows ())->list[0];
1559 win_info = TUI_CMD_WIN;
1561 (win_info->generic.height + diff)) <= tui_term_height ());
1566 int cur_total_height, total_height, min_height = 0;
1567 struct tui_win_info *first_win;
1568 struct tui_win_info *second_win;
1570 if (cur_layout == SRC_DISASSEM_COMMAND)
1572 first_win = TUI_SRC_WIN;
1573 second_win = TUI_DISASM_WIN;
1577 first_win = TUI_DATA_WIN;
1578 second_win = (tui_source_windows ())->list[0];
1580 /* We could simply add all the heights to obtain the same
1581 result but below is more explicit since we subtract 1 for
1582 the line that the first and second windows share, and add
1583 one for the locator. */
1584 total_height = cur_total_height =
1585 (first_win->generic.height + second_win->generic.height - 1)
1586 + TUI_CMD_WIN->generic.height + 1; /* Locator. */
1587 if (primary_win_info == TUI_CMD_WIN)
1589 /* Locator included since first & second win share a line. */
1590 ok = ((first_win->generic.height +
1591 second_win->generic.height + diff) >=
1592 (MIN_WIN_HEIGHT * 2)
1593 && new_height >= MIN_CMD_WIN_HEIGHT);
1596 total_height = new_height +
1597 (first_win->generic.height +
1598 second_win->generic.height + diff);
1599 min_height = MIN_CMD_WIN_HEIGHT;
1604 min_height = MIN_WIN_HEIGHT;
1606 /* First see if we can increase/decrease the command
1607 window. And make sure that the command window is at
1609 ok = ((TUI_CMD_WIN->generic.height + diff) > 0);
1611 { /* Looks like we have to increase/decrease one of
1612 the other windows. */
1613 if (primary_win_info == first_win)
1614 ok = (second_win->generic.height + diff) >= min_height;
1616 ok = (first_win->generic.height + diff) >= min_height;
1620 if (primary_win_info == first_win)
1621 total_height = new_height +
1622 second_win->generic.height +
1623 TUI_CMD_WIN->generic.height + diff;
1625 total_height = new_height +
1626 first_win->generic.height +
1627 TUI_CMD_WIN->generic.height + diff;
1630 /* Now make sure that the proposed total height doesn't
1631 exceed the old total height. */
1633 ok = (new_height >= min_height
1634 && total_height <= cur_total_height);
1643 parse_scrolling_args (char *arg,
1644 struct tui_win_info **win_to_scroll,
1649 *win_to_scroll = tui_win_with_focus ();
1651 /* First set up the default window to scroll, in case there is no
1653 if (arg != (char *) NULL)
1655 char *buf, *buf_ptr;
1657 /* Process the number of lines to scroll. */
1658 buf = buf_ptr = xstrdup (arg);
1659 if (isdigit (*buf_ptr))
1664 buf_ptr = strchr (buf_ptr, ' ');
1665 if (buf_ptr != (char *) NULL)
1667 *buf_ptr = (char) 0;
1669 *num_to_scroll = atoi (num_str);
1672 else if (num_to_scroll)
1673 *num_to_scroll = atoi (num_str);
1676 /* Process the window name if one is specified. */
1677 if (buf_ptr != (char *) NULL)
1682 if (*buf_ptr == ' ')
1683 while (*(++buf_ptr) == ' ')
1686 if (*buf_ptr != (char) 0)
1690 /* Validate the window name. */
1691 for (i = 0; i < strlen (wname); i++)
1692 wname[i] = tolower (wname[i]);
1697 *win_to_scroll = tui_partial_win_by_name (wname);
1699 if (*win_to_scroll == (struct tui_win_info *) NULL
1700 || !(*win_to_scroll)->generic.is_visible)
1701 error (_("Invalid window specified. \n\
1702 The window name specified must be valid and visible.\n"));
1703 else if (*win_to_scroll == TUI_CMD_WIN)
1704 *win_to_scroll = (tui_source_windows ())->list[0];