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)
377 completion_name = tui_win_name (&tui_win_list [win_type]->generic);
378 gdb_assert (completion_name != NULL);
379 VEC_safe_push (const_char_ptr, completion_name_vec, completion_name);
382 /* If no windows are considered visible then the TUI has not yet been
383 initialized. But still "focus src" and "focus cmd" will work because
384 invoking the focus command will entail initializing the TUI which sets the
385 default layout to SRC_COMMAND. */
386 if (VEC_length (const_char_ptr, completion_name_vec) == 0)
388 VEC_safe_push (const_char_ptr, completion_name_vec, SRC_NAME);
389 VEC_safe_push (const_char_ptr, completion_name_vec, CMD_NAME);
392 VEC_safe_push (const_char_ptr, completion_name_vec, "next");
393 VEC_safe_push (const_char_ptr, completion_name_vec, "prev");
394 VEC_safe_push (const_char_ptr, completion_name_vec, NULL);
397 = complete_on_enum (VEC_address (const_char_ptr, completion_name_vec),
400 VEC_free (const_char_ptr, completion_name_vec);
405 /* Function to initialize gdb commands, for tui window
408 /* Provide a prototype to silence -Wmissing-prototypes. */
409 extern initialize_file_ftype _initialize_tui_win;
412 _initialize_tui_win (void)
414 static struct cmd_list_element *tui_setlist;
415 static struct cmd_list_element *tui_showlist;
416 struct cmd_list_element *focus_cmd;
418 /* Define the classes of commands.
419 They will appear in the help list in the reverse of this order. */
420 add_prefix_cmd ("tui", class_tui, set_tui_cmd,
421 _("TUI configuration variables"),
422 &tui_setlist, "set tui ",
423 0 /* allow-unknown */, &setlist);
424 add_prefix_cmd ("tui", class_tui, show_tui_cmd,
425 _("TUI configuration variables"),
426 &tui_showlist, "show tui ",
427 0 /* allow-unknown */, &showlist);
429 add_com ("refresh", class_tui, tui_refresh_all_command,
430 _("Refresh the terminal display.\n"));
431 add_com ("tabset", class_tui, tui_set_tab_width_command, _("\
432 Set the width (in characters) of tab stops.\n\
433 Usage: tabset <n>\n"));
434 add_com ("winheight", class_tui, tui_set_win_height_command, _("\
435 Set the height of a specified window.\n\
436 Usage: winheight <win_name> [+ | -] <#lines>\n\
438 src : the source window\n\
439 cmd : the command window\n\
440 asm : the disassembly window\n\
441 regs : the register display\n"));
442 add_com_alias ("wh", "winheight", class_tui, 0);
443 add_info ("win", tui_all_windows_info,
444 _("List of all displayed windows.\n"));
445 focus_cmd = add_com ("focus", class_tui, tui_set_focus_command, _("\
446 Set focus to named window or next/prev window.\n\
447 Usage: focus {<win> | next | prev}\n\
448 Valid Window names are:\n\
449 src : the source window\n\
450 asm : the disassembly window\n\
451 regs : the register display\n\
452 cmd : the command window\n"));
453 add_com_alias ("fs", "focus", class_tui, 0);
454 set_cmd_completer (focus_cmd, focus_completer);
455 add_com ("+", class_tui, tui_scroll_forward_command, _("\
456 Scroll window forward.\n\
457 Usage: + [win] [n]\n"));
458 add_com ("-", class_tui, tui_scroll_backward_command, _("\
459 Scroll window backward.\n\
460 Usage: - [win] [n]\n"));
461 add_com ("<", class_tui, tui_scroll_left_command, _("\
462 Scroll window text to the left.\n\
463 Usage: < [win] [n]\n"));
464 add_com (">", class_tui, tui_scroll_right_command, _("\
465 Scroll window text to the right.\n\
466 Usage: > [win] [n]\n"));
468 /* Define the tui control variables. */
469 add_setshow_enum_cmd ("border-kind", no_class, tui_border_kind_enums,
470 &tui_border_kind, _("\
471 Set the kind of border for TUI windows."), _("\
472 Show the kind of border for TUI windows."), _("\
473 This variable controls the border of TUI windows:\n\
474 space use a white space\n\
475 ascii use ascii characters + - | for the border\n\
476 acs use the Alternate Character Set"),
478 show_tui_border_kind,
479 &tui_setlist, &tui_showlist);
481 add_setshow_enum_cmd ("border-mode", no_class, tui_border_mode_enums,
482 &tui_border_mode, _("\
483 Set the attribute mode to use for the TUI window borders."), _("\
484 Show the attribute mode to use for the TUI window borders."), _("\
485 This variable controls the attributes to use for the window borders:\n\
486 normal normal display\n\
487 standout use highlight mode of terminal\n\
488 reverse use reverse video mode\n\
489 half use half bright\n\
490 half-standout use half bright and standout mode\n\
491 bold use extra bright or bold\n\
492 bold-standout use extra bright or bold with standout mode"),
494 show_tui_border_mode,
495 &tui_setlist, &tui_showlist);
497 add_setshow_enum_cmd ("active-border-mode", no_class, tui_border_mode_enums,
498 &tui_active_border_mode, _("\
499 Set the attribute mode to use for the active TUI window border."), _("\
500 Show the attribute mode to use for the active TUI window border."), _("\
501 This variable controls the attributes to use for the active window border:\n\
502 normal normal display\n\
503 standout use highlight mode of terminal\n\
504 reverse use reverse video mode\n\
505 half use half bright\n\
506 half-standout use half bright and standout mode\n\
507 bold use extra bright or bold\n\
508 bold-standout use extra bright or bold with standout mode"),
510 show_tui_active_border_mode,
511 &tui_setlist, &tui_showlist);
514 /* Update gdb's knowledge of the terminal size. */
516 tui_update_gdb_sizes (void)
522 width = TUI_CMD_WIN->generic.width;
523 height = TUI_CMD_WIN->generic.height;
527 width = tui_term_width ();
528 height = tui_term_height ();
531 set_screen_width_and_height (width, height);
535 /* Set the logical focus to win_info. */
537 tui_set_win_focus_to (struct tui_win_info *win_info)
539 if (win_info != NULL)
541 struct tui_win_info *win_with_focus = tui_win_with_focus ();
543 if (win_with_focus != NULL
544 && win_with_focus->generic.type != CMD_WIN)
545 tui_unhighlight_win (win_with_focus);
546 tui_set_win_with_focus (win_info);
547 if (win_info->generic.type != CMD_WIN)
548 tui_highlight_win (win_info);
554 tui_scroll_forward (struct tui_win_info *win_to_scroll,
557 if (win_to_scroll != TUI_CMD_WIN)
559 int _num_to_scroll = num_to_scroll;
561 if (num_to_scroll == 0)
562 _num_to_scroll = win_to_scroll->generic.height - 3;
564 /* If we are scrolling the source or disassembly window, do a
565 "psuedo" scroll since not all of the source is in memory,
566 only what is in the viewport. If win_to_scroll is the
567 command window do nothing since the term should handle
569 if (win_to_scroll == TUI_SRC_WIN)
570 tui_vertical_source_scroll (FORWARD_SCROLL, _num_to_scroll);
571 else if (win_to_scroll == TUI_DISASM_WIN)
572 tui_vertical_disassem_scroll (FORWARD_SCROLL, _num_to_scroll);
573 else if (win_to_scroll == TUI_DATA_WIN)
574 tui_vertical_data_scroll (FORWARD_SCROLL, _num_to_scroll);
579 tui_scroll_backward (struct tui_win_info *win_to_scroll,
582 if (win_to_scroll != TUI_CMD_WIN)
584 int _num_to_scroll = num_to_scroll;
586 if (num_to_scroll == 0)
587 _num_to_scroll = win_to_scroll->generic.height - 3;
589 /* If we are scrolling the source or disassembly window, do a
590 "psuedo" scroll since not all of the source is in memory,
591 only what is in the viewport. If win_to_scroll is the
592 command window do nothing since the term should handle
594 if (win_to_scroll == TUI_SRC_WIN)
595 tui_vertical_source_scroll (BACKWARD_SCROLL, _num_to_scroll);
596 else if (win_to_scroll == TUI_DISASM_WIN)
597 tui_vertical_disassem_scroll (BACKWARD_SCROLL, _num_to_scroll);
598 else if (win_to_scroll == TUI_DATA_WIN)
599 tui_vertical_data_scroll (BACKWARD_SCROLL, _num_to_scroll);
605 tui_scroll_left (struct tui_win_info *win_to_scroll,
608 if (win_to_scroll != TUI_CMD_WIN)
610 int _num_to_scroll = num_to_scroll;
612 if (_num_to_scroll == 0)
615 /* If we are scrolling the source or disassembly window, do a
616 "psuedo" scroll since not all of the source is in memory,
617 only what is in the viewport. If win_to_scroll is the command
618 window do nothing since the term should handle it. */
619 if (win_to_scroll == TUI_SRC_WIN
620 || win_to_scroll == TUI_DISASM_WIN)
621 tui_horizontal_source_scroll (win_to_scroll, LEFT_SCROLL,
628 tui_scroll_right (struct tui_win_info *win_to_scroll,
631 if (win_to_scroll != TUI_CMD_WIN)
633 int _num_to_scroll = num_to_scroll;
635 if (_num_to_scroll == 0)
638 /* If we are scrolling the source or disassembly window, do a
639 "psuedo" scroll since not all of the source is in memory,
640 only what is in the viewport. If win_to_scroll is the command
641 window do nothing since the term should handle it. */
642 if (win_to_scroll == TUI_SRC_WIN
643 || win_to_scroll == TUI_DISASM_WIN)
644 tui_horizontal_source_scroll (win_to_scroll, RIGHT_SCROLL,
650 /* Scroll a window. Arguments are passed through a va_list. */
652 tui_scroll (enum tui_scroll_direction direction,
653 struct tui_win_info *win_to_scroll,
659 tui_scroll_forward (win_to_scroll, num_to_scroll);
661 case BACKWARD_SCROLL:
662 tui_scroll_backward (win_to_scroll, num_to_scroll);
665 tui_scroll_left (win_to_scroll, num_to_scroll);
668 tui_scroll_right (win_to_scroll, num_to_scroll);
677 tui_refresh_all_win (void)
681 clearok (curscr, TRUE);
682 tui_refresh_all (tui_win_list);
683 for (type = SRC_WIN; type < MAX_MAJOR_WINDOWS; type++)
685 if (tui_win_list[type]
686 && tui_win_list[type]->generic.is_visible)
692 tui_show_source_content (tui_win_list[type]);
693 tui_check_and_display_highlight_if_needed (tui_win_list[type]);
694 tui_erase_exec_info_content (tui_win_list[type]);
695 tui_update_exec_info (tui_win_list[type]);
698 tui_refresh_data_win ();
705 tui_show_locator_content ();
709 tui_rehighlight_all (void)
713 for (type = SRC_WIN; type < MAX_MAJOR_WINDOWS; type++)
714 tui_check_and_display_highlight_if_needed (tui_win_list[type]);
717 /* Resize all the windows based on the terminal size. This function
718 gets called from within the readline sinwinch handler. */
720 tui_resize_all (void)
722 int height_diff, width_diff;
723 int screenheight, screenwidth;
725 rl_get_screen_size (&screenheight, &screenwidth);
726 width_diff = screenwidth - tui_term_width ();
727 height_diff = screenheight - tui_term_height ();
728 if (height_diff || width_diff)
730 enum tui_layout_type cur_layout = tui_current_layout ();
731 struct tui_win_info *win_with_focus = tui_win_with_focus ();
732 struct tui_win_info *first_win;
733 struct tui_win_info *second_win;
734 struct tui_gen_win_info *locator = tui_locator_win_info_ptr ();
736 int new_height, split_diff, cmd_split_diff, num_wins_displayed = 2;
738 #ifdef HAVE_RESIZE_TERM
739 resize_term (screenheight, screenwidth);
741 /* Turn keypad off while we resize. */
742 if (win_with_focus != TUI_CMD_WIN)
743 keypad (TUI_CMD_WIN->generic.handle, FALSE);
744 tui_update_gdb_sizes ();
745 tui_set_term_height_to (screenheight);
746 tui_set_term_width_to (screenwidth);
747 if (cur_layout == SRC_DISASSEM_COMMAND
748 || cur_layout == SRC_DATA_COMMAND
749 || cur_layout == DISASSEM_DATA_COMMAND)
750 num_wins_displayed++;
751 split_diff = height_diff / num_wins_displayed;
752 cmd_split_diff = split_diff;
753 if (height_diff % num_wins_displayed)
760 /* Now adjust each window. */
761 /* erase + clearok are used instead of a straightforward clear as
762 AIX 5.3 does not define clear. */
764 clearok (curscr, TRUE);
769 case DISASSEM_COMMAND:
770 first_win = (struct tui_win_info *) (tui_source_windows ())->list[0];
771 first_win->generic.width += width_diff;
772 locator->width += width_diff;
773 /* Check for invalid heights. */
774 if (height_diff == 0)
775 new_height = first_win->generic.height;
776 else if ((first_win->generic.height + split_diff) >=
777 (screenheight - MIN_CMD_WIN_HEIGHT - 1))
778 new_height = screenheight - MIN_CMD_WIN_HEIGHT - 1;
779 else if ((first_win->generic.height + split_diff) <= 0)
780 new_height = MIN_WIN_HEIGHT;
782 new_height = first_win->generic.height + split_diff;
784 locator->origin.y = new_height + 1;
785 make_invisible_and_set_new_height (first_win, new_height);
786 TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1;
787 TUI_CMD_WIN->generic.width += width_diff;
788 new_height = screenheight - TUI_CMD_WIN->generic.origin.y;
789 make_invisible_and_set_new_height (TUI_CMD_WIN, new_height);
790 make_visible_with_new_height (first_win);
791 make_visible_with_new_height (TUI_CMD_WIN);
792 if (first_win->generic.content_size <= 0)
793 tui_erase_source_content (first_win, EMPTY_SOURCE_PROMPT);
796 if (cur_layout == SRC_DISASSEM_COMMAND)
798 first_win = TUI_SRC_WIN;
799 first_win->generic.width += width_diff;
800 second_win = TUI_DISASM_WIN;
801 second_win->generic.width += width_diff;
805 first_win = TUI_DATA_WIN;
806 first_win->generic.width += width_diff;
807 second_win = (struct tui_win_info *)
808 (tui_source_windows ())->list[0];
809 second_win->generic.width += width_diff;
811 /* Change the first window's height/width. */
812 /* Check for invalid heights. */
813 if (height_diff == 0)
814 new_height = first_win->generic.height;
815 else if ((first_win->generic.height +
816 second_win->generic.height + (split_diff * 2)) >=
817 (screenheight - MIN_CMD_WIN_HEIGHT - 1))
818 new_height = (screenheight - MIN_CMD_WIN_HEIGHT - 1) / 2;
819 else if ((first_win->generic.height + split_diff) <= 0)
820 new_height = MIN_WIN_HEIGHT;
822 new_height = first_win->generic.height + split_diff;
823 make_invisible_and_set_new_height (first_win, new_height);
825 locator->width += width_diff;
827 /* Change the second window's height/width. */
828 /* Check for invalid heights. */
829 if (height_diff == 0)
830 new_height = second_win->generic.height;
831 else if ((first_win->generic.height +
832 second_win->generic.height + (split_diff * 2)) >=
833 (screenheight - MIN_CMD_WIN_HEIGHT - 1))
835 new_height = screenheight - MIN_CMD_WIN_HEIGHT - 1;
837 new_height = (new_height / 2) + 1;
841 else if ((second_win->generic.height + split_diff) <= 0)
842 new_height = MIN_WIN_HEIGHT;
844 new_height = second_win->generic.height + split_diff;
845 second_win->generic.origin.y = first_win->generic.height - 1;
846 make_invisible_and_set_new_height (second_win, new_height);
848 /* Change the command window's height/width. */
849 TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1;
850 make_invisible_and_set_new_height (TUI_CMD_WIN,
851 TUI_CMD_WIN->generic.height
853 make_visible_with_new_height (first_win);
854 make_visible_with_new_height (second_win);
855 make_visible_with_new_height (TUI_CMD_WIN);
856 if (first_win->generic.content_size <= 0)
857 tui_erase_source_content (first_win, EMPTY_SOURCE_PROMPT);
858 if (second_win->generic.content_size <= 0)
859 tui_erase_source_content (second_win, EMPTY_SOURCE_PROMPT);
862 /* Now remove all invisible windows, and their content so that
863 they get created again when called for with the new size. */
864 for (win_type = SRC_WIN; (win_type < MAX_MAJOR_WINDOWS); win_type++)
866 if (win_type != CMD_WIN
867 && (tui_win_list[win_type] != NULL)
868 && !tui_win_list[win_type]->generic.is_visible)
870 tui_free_window (tui_win_list[win_type]);
871 tui_win_list[win_type] = (struct tui_win_info *) NULL;
874 /* Turn keypad back on, unless focus is in the command
876 if (win_with_focus != TUI_CMD_WIN)
877 keypad (TUI_CMD_WIN->generic.handle, TRUE);
882 /* Token for use by TUI's asynchronous SIGWINCH handler. */
883 static struct async_signal_handler *tui_sigwinch_token;
885 /* TUI's SIGWINCH signal handler. */
887 tui_sigwinch_handler (int signal)
889 mark_async_signal_handler (tui_sigwinch_token);
890 tui_set_win_resized_to (TRUE);
893 /* Callback for asynchronously resizing TUI following a SIGWINCH signal. */
895 tui_async_resize_screen (gdb_client_data arg)
897 rl_resize_terminal ();
901 int screen_height, screen_width;
903 rl_get_screen_size (&screen_height, &screen_width);
904 set_screen_width_and_height (screen_width, screen_height);
906 /* win_resized is left set so that the next call to tui_enable()
907 resizes the TUI windows. */
911 tui_set_win_resized_to (FALSE);
913 tui_refresh_all_win ();
914 tui_update_gdb_sizes ();
915 tui_redisplay_readline ();
920 /* Initialize TUI's SIGWINCH signal handler. Note that the handler is not
921 uninstalled when we exit TUI, so the handler should not assume that TUI is
924 tui_initialize_win (void)
928 = create_async_signal_handler (tui_async_resize_screen, NULL);
931 #ifdef HAVE_SIGACTION
932 struct sigaction old_winch;
934 memset (&old_winch, 0, sizeof (old_winch));
935 old_winch.sa_handler = &tui_sigwinch_handler;
937 old_winch.sa_flags = SA_RESTART;
939 sigaction (SIGWINCH, &old_winch, NULL);
941 signal (SIGWINCH, &tui_sigwinch_handler);
948 /*************************
949 ** STATIC LOCAL FUNCTIONS
950 **************************/
954 tui_scroll_forward_command (char *arg, int from_tty)
956 int num_to_scroll = 1;
957 struct tui_win_info *win_to_scroll;
959 /* Make sure the curses mode is enabled. */
961 if (arg == (char *) NULL)
962 parse_scrolling_args (arg, &win_to_scroll, (int *) NULL);
964 parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
965 tui_scroll (FORWARD_SCROLL, win_to_scroll, num_to_scroll);
970 tui_scroll_backward_command (char *arg, int from_tty)
972 int num_to_scroll = 1;
973 struct tui_win_info *win_to_scroll;
975 /* Make sure the curses mode is enabled. */
977 if (arg == (char *) NULL)
978 parse_scrolling_args (arg, &win_to_scroll, (int *) NULL);
980 parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
981 tui_scroll (BACKWARD_SCROLL, win_to_scroll, num_to_scroll);
986 tui_scroll_left_command (char *arg, int from_tty)
989 struct tui_win_info *win_to_scroll;
991 /* Make sure the curses mode is enabled. */
993 parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
994 tui_scroll (LEFT_SCROLL, win_to_scroll, num_to_scroll);
999 tui_scroll_right_command (char *arg, int from_tty)
1002 struct tui_win_info *win_to_scroll;
1004 /* Make sure the curses mode is enabled. */
1006 parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
1007 tui_scroll (RIGHT_SCROLL, win_to_scroll, num_to_scroll);
1011 /* Set focus to the window named by 'arg'. */
1013 tui_set_focus (char *arg, int from_tty)
1015 if (arg != (char *) NULL)
1017 char *buf_ptr = (char *) xstrdup (arg);
1019 struct tui_win_info *win_info = (struct tui_win_info *) NULL;
1021 for (i = 0; (i < strlen (buf_ptr)); i++)
1022 buf_ptr[i] = tolower (arg[i]);
1024 if (subset_compare (buf_ptr, "next"))
1025 win_info = tui_next_win (tui_win_with_focus ());
1026 else if (subset_compare (buf_ptr, "prev"))
1027 win_info = tui_prev_win (tui_win_with_focus ());
1029 win_info = tui_partial_win_by_name (buf_ptr);
1031 if (win_info == (struct tui_win_info *) NULL
1032 || !win_info->generic.is_visible)
1033 warning (_("Invalid window specified. \n\
1034 The window name specified must be valid and visible.\n"));
1037 tui_set_win_focus_to (win_info);
1038 keypad (TUI_CMD_WIN->generic.handle, (win_info != TUI_CMD_WIN));
1041 if (TUI_DATA_WIN && TUI_DATA_WIN->generic.is_visible)
1042 tui_refresh_data_win ();
1044 printf_filtered (_("Focus set to %s window.\n"),
1045 tui_win_name (&tui_win_with_focus ()->generic));
1048 warning (_("Incorrect Number of Arguments.\n%s"), FOCUS_USAGE);
1052 tui_set_focus_command (char *arg, int from_tty)
1054 /* Make sure the curses mode is enabled. */
1056 tui_set_focus (arg, from_tty);
1061 tui_all_windows_info (char *arg, int from_tty)
1064 struct tui_win_info *win_with_focus = tui_win_with_focus ();
1066 for (type = SRC_WIN; (type < MAX_MAJOR_WINDOWS); type++)
1067 if (tui_win_list[type]
1068 && tui_win_list[type]->generic.is_visible)
1070 if (win_with_focus == tui_win_list[type])
1071 printf_filtered (" %s\t(%d lines) <has focus>\n",
1072 tui_win_name (&tui_win_list[type]->generic),
1073 tui_win_list[type]->generic.height);
1075 printf_filtered (" %s\t(%d lines)\n",
1076 tui_win_name (&tui_win_list[type]->generic),
1077 tui_win_list[type]->generic.height);
1083 tui_refresh_all_command (char *arg, int from_tty)
1085 /* Make sure the curses mode is enabled. */
1088 tui_refresh_all_win ();
1092 /* Set the tab width of the specified window. */
1094 tui_set_tab_width_command (char *arg, int from_tty)
1096 /* Make sure the curses mode is enabled. */
1098 if (arg != (char *) NULL)
1105 tui_set_default_tab_len (ts);
1106 /* We don't really change the height of any windows, but
1107 calling these 2 functions causes a complete regeneration
1108 and redisplay of the window's contents, which will take
1109 the new tab width into account. */
1110 if (tui_win_list[SRC_WIN]
1111 && tui_win_list[SRC_WIN]->generic.is_visible)
1113 make_invisible_and_set_new_height (TUI_SRC_WIN,
1114 TUI_SRC_WIN->generic.height);
1115 make_visible_with_new_height (TUI_SRC_WIN);
1117 if (tui_win_list[DISASSEM_WIN]
1118 && tui_win_list[DISASSEM_WIN]->generic.is_visible)
1120 make_invisible_and_set_new_height (TUI_DISASM_WIN,
1121 TUI_DISASM_WIN->generic.height);
1122 make_visible_with_new_height (TUI_DISASM_WIN);
1126 warning (_("Tab widths greater than 0 must be specified."));
1131 /* Set the height of the specified window. */
1133 tui_set_win_height (char *arg, int from_tty)
1135 /* Make sure the curses mode is enabled. */
1137 if (arg != (char *) NULL)
1139 char *buf = xstrdup (arg);
1140 char *buf_ptr = buf;
1141 char *wname = (char *) NULL;
1143 struct tui_win_info *win_info;
1146 buf_ptr = strchr (buf_ptr, ' ');
1147 if (buf_ptr != (char *) NULL)
1149 *buf_ptr = (char) 0;
1151 /* Validate the window name. */
1152 for (i = 0; i < strlen (wname); i++)
1153 wname[i] = tolower (wname[i]);
1154 win_info = tui_partial_win_by_name (wname);
1156 if (win_info == (struct tui_win_info *) NULL
1157 || !win_info->generic.is_visible)
1158 warning (_("Invalid window specified. \n\
1159 The window name specified must be valid and visible.\n"));
1162 /* Process the size. */
1163 while (*(++buf_ptr) == ' ')
1166 if (*buf_ptr != (char) 0)
1169 int fixed_size = TRUE;
1172 if (*buf_ptr == '+' || *buf_ptr == '-')
1174 if (*buf_ptr == '-')
1179 input_no = atoi (buf_ptr);
1185 new_height = input_no;
1187 new_height = win_info->generic.height + input_no;
1189 /* Now change the window's height, and adjust
1190 all other windows around it. */
1191 if (tui_adjust_win_heights (win_info,
1192 new_height) == TUI_FAILURE)
1193 warning (_("Invalid window height specified.\n%s"),
1196 tui_update_gdb_sizes ();
1199 warning (_("Invalid window height specified.\n%s"),
1205 printf_filtered (WIN_HEIGHT_USAGE);
1207 if (buf != (char *) NULL)
1211 printf_filtered (WIN_HEIGHT_USAGE);
1214 /* Set the height of the specified window, with va_list. */
1216 tui_set_win_height_command (char *arg, int from_tty)
1218 /* Make sure the curses mode is enabled. */
1220 tui_set_win_height (arg, from_tty);
1223 /* Function to adjust all window heights around the primary. */
1224 static enum tui_status
1225 tui_adjust_win_heights (struct tui_win_info *primary_win_info,
1228 enum tui_status status = TUI_FAILURE;
1230 if (new_height_ok (primary_win_info, new_height))
1232 status = TUI_SUCCESS;
1233 if (new_height != primary_win_info->generic.height)
1236 struct tui_win_info *win_info;
1237 struct tui_gen_win_info *locator = tui_locator_win_info_ptr ();
1238 enum tui_layout_type cur_layout = tui_current_layout ();
1240 diff = (new_height - primary_win_info->generic.height) * (-1);
1241 if (cur_layout == SRC_COMMAND
1242 || cur_layout == DISASSEM_COMMAND)
1244 struct tui_win_info *src_win_info;
1246 make_invisible_and_set_new_height (primary_win_info, new_height);
1247 if (primary_win_info->generic.type == CMD_WIN)
1249 win_info = (tui_source_windows ())->list[0];
1250 src_win_info = win_info;
1254 win_info = tui_win_list[CMD_WIN];
1255 src_win_info = primary_win_info;
1257 make_invisible_and_set_new_height (win_info,
1258 win_info->generic.height + diff);
1259 TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1;
1260 make_visible_with_new_height (win_info);
1261 make_visible_with_new_height (primary_win_info);
1262 if (src_win_info->generic.content_size <= 0)
1263 tui_erase_source_content (src_win_info, EMPTY_SOURCE_PROMPT);
1267 struct tui_win_info *first_win;
1268 struct tui_win_info *second_win;
1270 if (cur_layout == SRC_DISASSEM_COMMAND)
1272 first_win = TUI_SRC_WIN;
1273 second_win = TUI_DISASM_WIN;
1277 first_win = TUI_DATA_WIN;
1278 second_win = (tui_source_windows ())->list[0];
1280 if (primary_win_info == TUI_CMD_WIN)
1281 { /* Split the change in height accross the 1st & 2nd
1282 windows, adjusting them as well. */
1283 /* Subtract the locator. */
1284 int first_split_diff = diff / 2;
1285 int second_split_diff = first_split_diff;
1289 if (first_win->generic.height >
1290 second_win->generic.height)
1298 second_split_diff--;
1300 second_split_diff++;
1303 /* Make sure that the minimum hieghts are
1305 while ((first_win->generic.height + first_split_diff) < 3)
1308 second_split_diff--;
1310 while ((second_win->generic.height + second_split_diff) < 3)
1312 second_split_diff++;
1315 make_invisible_and_set_new_height (
1317 first_win->generic.height + first_split_diff);
1318 second_win->generic.origin.y = first_win->generic.height - 1;
1319 make_invisible_and_set_new_height (second_win,
1320 second_win->generic.height
1321 + second_split_diff);
1322 TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1;
1323 make_invisible_and_set_new_height (TUI_CMD_WIN, new_height);
1327 if ((TUI_CMD_WIN->generic.height + diff) < 1)
1328 { /* If there is no way to increase the command
1329 window take real estate from the 1st or 2nd
1331 if ((TUI_CMD_WIN->generic.height + diff) < 1)
1335 for (i = TUI_CMD_WIN->generic.height + diff;
1337 if (primary_win_info == first_win)
1338 second_win->generic.height--;
1340 first_win->generic.height--;
1343 if (primary_win_info == first_win)
1344 make_invisible_and_set_new_height (first_win, new_height);
1346 make_invisible_and_set_new_height (
1348 first_win->generic.height);
1349 second_win->generic.origin.y = first_win->generic.height - 1;
1350 if (primary_win_info == second_win)
1351 make_invisible_and_set_new_height (second_win, new_height);
1353 make_invisible_and_set_new_height (
1354 second_win, second_win->generic.height);
1355 TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1;
1356 if ((TUI_CMD_WIN->generic.height + diff) < 1)
1357 make_invisible_and_set_new_height (TUI_CMD_WIN, 1);
1359 make_invisible_and_set_new_height (TUI_CMD_WIN,
1360 TUI_CMD_WIN->generic.height + diff);
1362 make_visible_with_new_height (TUI_CMD_WIN);
1363 make_visible_with_new_height (second_win);
1364 make_visible_with_new_height (first_win);
1365 if (first_win->generic.content_size <= 0)
1366 tui_erase_source_content (first_win, EMPTY_SOURCE_PROMPT);
1367 if (second_win->generic.content_size <= 0)
1368 tui_erase_source_content (second_win, EMPTY_SOURCE_PROMPT);
1377 /* Function make the target window (and auxillary windows associated
1378 with the targer) invisible, and set the new height and
1381 make_invisible_and_set_new_height (struct tui_win_info *win_info,
1385 struct tui_gen_win_info *gen_win_info;
1387 tui_make_invisible (&win_info->generic);
1388 win_info->generic.height = height;
1390 win_info->generic.viewport_height = height - 1;
1392 win_info->generic.viewport_height = height;
1393 if (win_info != TUI_CMD_WIN)
1394 win_info->generic.viewport_height--;
1396 /* Now deal with the auxillary windows associated with win_info. */
1397 switch (win_info->generic.type)
1401 gen_win_info = win_info->detail.source_info.execution_info;
1402 tui_make_invisible (gen_win_info);
1403 gen_win_info->height = height;
1404 gen_win_info->origin.y = win_info->generic.origin.y;
1406 gen_win_info->viewport_height = height - 1;
1408 gen_win_info->viewport_height = height;
1409 if (win_info != TUI_CMD_WIN)
1410 gen_win_info->viewport_height--;
1412 if (tui_win_has_locator (win_info))
1414 gen_win_info = tui_locator_win_info_ptr ();
1415 tui_make_invisible (gen_win_info);
1416 gen_win_info->origin.y = win_info->generic.origin.y + height;
1420 /* Delete all data item windows. */
1421 for (i = 0; i < win_info->generic.content_size; i++)
1423 gen_win_info = (struct tui_gen_win_info *)
1424 &((struct tui_win_element *)
1425 win_info->generic.content[i])->which_element.data_window;
1426 tui_delete_win (gen_win_info->handle);
1427 gen_win_info->handle = (WINDOW *) NULL;
1436 /* Function to make the windows with new heights visible. This means
1437 re-creating the windows' content since the window had to be
1438 destroyed to be made invisible. */
1440 make_visible_with_new_height (struct tui_win_info *win_info)
1444 tui_make_visible (&win_info->generic);
1445 tui_check_and_display_highlight_if_needed (win_info);
1446 switch (win_info->generic.type)
1450 tui_free_win_content (win_info->detail.source_info.execution_info);
1451 tui_make_visible (win_info->detail.source_info.execution_info);
1452 if (win_info->generic.content != NULL)
1454 struct gdbarch *gdbarch = win_info->detail.source_info.gdbarch;
1455 struct tui_line_or_address line_or_addr;
1456 struct symtab_and_line cursal
1457 = get_current_source_symtab_and_line ();
1459 line_or_addr = win_info->detail.source_info.start_line_or_addr;
1460 tui_free_win_content (&win_info->generic);
1461 tui_update_source_window (win_info, gdbarch,
1462 cursal.symtab, line_or_addr, TRUE);
1464 else if (deprecated_safe_get_selected_frame () != NULL)
1466 struct tui_line_or_address line;
1467 struct symtab_and_line cursal
1468 = get_current_source_symtab_and_line ();
1469 struct frame_info *frame = deprecated_safe_get_selected_frame ();
1470 struct gdbarch *gdbarch = get_frame_arch (frame);
1472 s = find_pc_line_symtab (get_frame_pc (frame));
1473 if (win_info->generic.type == SRC_WIN)
1475 line.loa = LOA_LINE;
1476 line.u.line_no = cursal.line;
1480 line.loa = LOA_ADDRESS;
1481 find_line_pc (s, cursal.line, &line.u.addr);
1483 tui_update_source_window (win_info, gdbarch, s, line, TRUE);
1485 if (tui_win_has_locator (win_info))
1487 tui_make_visible (tui_locator_win_info_ptr ());
1488 tui_show_locator_content ();
1492 tui_display_all_data ();
1495 win_info->detail.command_info.cur_line = 0;
1496 win_info->detail.command_info.curch = 0;
1498 wresize (TUI_CMD_WIN->generic.handle,
1499 TUI_CMD_WIN->generic.height,
1500 TUI_CMD_WIN->generic.width);
1502 mvwin (TUI_CMD_WIN->generic.handle,
1503 TUI_CMD_WIN->generic.origin.y,
1504 TUI_CMD_WIN->generic.origin.x);
1505 wmove (win_info->generic.handle,
1506 win_info->detail.command_info.cur_line,
1507 win_info->detail.command_info.curch);
1516 new_height_ok (struct tui_win_info *primary_win_info,
1519 int ok = (new_height < tui_term_height ());
1524 enum tui_layout_type cur_layout = tui_current_layout ();
1526 diff = (new_height - primary_win_info->generic.height) * (-1);
1527 if (cur_layout == SRC_COMMAND || cur_layout == DISASSEM_COMMAND)
1529 ok = ((primary_win_info->generic.type == CMD_WIN
1530 && new_height <= (tui_term_height () - 4)
1531 && new_height >= MIN_CMD_WIN_HEIGHT)
1532 || (primary_win_info->generic.type != CMD_WIN
1533 && new_height <= (tui_term_height () - 2)
1534 && new_height >= MIN_WIN_HEIGHT));
1536 { /* Check the total height. */
1537 struct tui_win_info *win_info;
1539 if (primary_win_info == TUI_CMD_WIN)
1540 win_info = (tui_source_windows ())->list[0];
1542 win_info = TUI_CMD_WIN;
1544 (win_info->generic.height + diff)) <= tui_term_height ());
1549 int cur_total_height, total_height, min_height = 0;
1550 struct tui_win_info *first_win;
1551 struct tui_win_info *second_win;
1553 if (cur_layout == SRC_DISASSEM_COMMAND)
1555 first_win = TUI_SRC_WIN;
1556 second_win = TUI_DISASM_WIN;
1560 first_win = TUI_DATA_WIN;
1561 second_win = (tui_source_windows ())->list[0];
1563 /* We could simply add all the heights to obtain the same
1564 result but below is more explicit since we subtract 1 for
1565 the line that the first and second windows share, and add
1566 one for the locator. */
1567 total_height = cur_total_height =
1568 (first_win->generic.height + second_win->generic.height - 1)
1569 + TUI_CMD_WIN->generic.height + 1; /* Locator. */
1570 if (primary_win_info == TUI_CMD_WIN)
1572 /* Locator included since first & second win share a line. */
1573 ok = ((first_win->generic.height +
1574 second_win->generic.height + diff) >=
1575 (MIN_WIN_HEIGHT * 2)
1576 && new_height >= MIN_CMD_WIN_HEIGHT);
1579 total_height = new_height +
1580 (first_win->generic.height +
1581 second_win->generic.height + diff);
1582 min_height = MIN_CMD_WIN_HEIGHT;
1587 min_height = MIN_WIN_HEIGHT;
1589 /* First see if we can increase/decrease the command
1590 window. And make sure that the command window is at
1592 ok = ((TUI_CMD_WIN->generic.height + diff) > 0);
1594 { /* Looks like we have to increase/decrease one of
1595 the other windows. */
1596 if (primary_win_info == first_win)
1597 ok = (second_win->generic.height + diff) >= min_height;
1599 ok = (first_win->generic.height + diff) >= min_height;
1603 if (primary_win_info == first_win)
1604 total_height = new_height +
1605 second_win->generic.height +
1606 TUI_CMD_WIN->generic.height + diff;
1608 total_height = new_height +
1609 first_win->generic.height +
1610 TUI_CMD_WIN->generic.height + diff;
1613 /* Now make sure that the proposed total height doesn't
1614 exceed the old total height. */
1616 ok = (new_height >= min_height
1617 && total_height <= cur_total_height);
1626 parse_scrolling_args (char *arg,
1627 struct tui_win_info **win_to_scroll,
1632 *win_to_scroll = tui_win_with_focus ();
1634 /* First set up the default window to scroll, in case there is no
1636 if (arg != (char *) NULL)
1638 char *buf, *buf_ptr;
1640 /* Process the number of lines to scroll. */
1641 buf = buf_ptr = xstrdup (arg);
1642 if (isdigit (*buf_ptr))
1647 buf_ptr = strchr (buf_ptr, ' ');
1648 if (buf_ptr != (char *) NULL)
1650 *buf_ptr = (char) 0;
1652 *num_to_scroll = atoi (num_str);
1655 else if (num_to_scroll)
1656 *num_to_scroll = atoi (num_str);
1659 /* Process the window name if one is specified. */
1660 if (buf_ptr != (char *) NULL)
1665 if (*buf_ptr == ' ')
1666 while (*(++buf_ptr) == ' ')
1669 if (*buf_ptr != (char) 0)
1673 /* Validate the window name. */
1674 for (i = 0; i < strlen (wname); i++)
1675 wname[i] = tolower (wname[i]);
1680 *win_to_scroll = tui_partial_win_by_name (wname);
1682 if (*win_to_scroll == (struct tui_win_info *) NULL
1683 || !(*win_to_scroll)->generic.is_visible)
1684 error (_("Invalid window specified. \n\
1685 The window name specified must be valid and visible.\n"));
1686 else if (*win_to_scroll == TUI_CMD_WIN)
1687 *win_to_scroll = (tui_source_windows ())->list[0];