1 /* TUI layout window management.
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/>. */
23 #include "arch-utils.h"
31 #include "tui/tui-data.h"
32 #include "tui/tui-windata.h"
33 #include "tui/tui-wingeneral.h"
34 #include "tui/tui-stack.h"
35 #include "tui/tui-regs.h"
36 #include "tui/tui-win.h"
37 #include "tui/tui-winsource.h"
38 #include "tui/tui-disasm.h"
39 #include "tui/tui-layout.h"
40 #include "gdb_curses.h"
42 /*******************************
44 ********************************/
45 static void show_layout (enum tui_layout_type);
46 static tui_gen_win_info *init_and_make_win (tui_gen_win_info *,
50 static void show_source_or_disasm_and_command (enum tui_layout_type);
51 static struct tui_win_info *make_source_or_disasm_window (enum tui_win_type,
53 static struct tui_win_info *make_command_window (int, int);
54 static struct tui_win_info *make_source_window (int, int);
55 static struct tui_win_info *make_disasm_window (int, int);
56 static void make_data_window (struct tui_win_info **, int, int);
57 static void show_source_command (void);
58 static void show_disasm_command (void);
59 static void show_source_disasm_command (void);
60 static void show_data (enum tui_layout_type);
61 static enum tui_layout_type next_layout (void);
62 static enum tui_layout_type prev_layout (void);
63 static void tui_layout_command (const char *, int);
64 static void extract_display_start_addr (struct gdbarch **, CORE_ADDR *);
67 /***************************************
69 ***************************************/
71 #define LAYOUT_USAGE "Usage: layout prev | next | <layout_name> \n"
73 /* Show the screen layout defined. */
75 show_layout (enum tui_layout_type layout)
77 enum tui_layout_type cur_layout = tui_current_layout ();
79 if (layout != cur_layout)
81 /* Since the new layout may cause changes in window size, we
82 should free the content and reallocate on next display of
84 tui_clear_source_windows ();
85 if (layout == SRC_DATA_COMMAND
86 || layout == DISASSEM_DATA_COMMAND)
93 /* First make the current layout be invisible. */
94 tui_make_all_invisible ();
95 tui_make_invisible (tui_locator_win_info_ptr ());
99 /* Now show the new layout. */
101 show_source_command ();
102 tui_add_to_source_windows (TUI_SRC_WIN);
104 case DISASSEM_COMMAND:
105 show_disasm_command ();
106 tui_add_to_source_windows (TUI_DISASM_WIN);
108 case SRC_DISASSEM_COMMAND:
109 show_source_disasm_command ();
110 tui_add_to_source_windows (TUI_SRC_WIN);
111 tui_add_to_source_windows (TUI_DISASM_WIN);
121 /* Function to set the layout to SRC_COMMAND, DISASSEM_COMMAND,
122 SRC_DISASSEM_COMMAND, SRC_DATA_COMMAND, or DISASSEM_DATA_COMMAND. */
124 tui_set_layout (enum tui_layout_type layout_type)
126 enum tui_status status = TUI_SUCCESS;
128 if (layout_type != UNDEFINED_LAYOUT)
130 enum tui_layout_type cur_layout = tui_current_layout (),
131 new_layout = UNDEFINED_LAYOUT;
132 int regs_populate = FALSE;
133 struct gdbarch *gdbarch;
135 struct tui_win_info *win_with_focus = tui_win_with_focus ();
136 struct tui_layout_def *layout_def = tui_layout_def ();
138 extract_display_start_addr (&gdbarch, &addr);
140 new_layout = layout_type;
142 regs_populate = (new_layout == SRC_DATA_COMMAND
143 || new_layout == DISASSEM_DATA_COMMAND);
144 if (new_layout != cur_layout)
146 show_layout (new_layout);
148 /* Now determine where focus should be. */
149 if (win_with_focus != TUI_CMD_WIN)
154 tui_set_win_focus_to (TUI_SRC_WIN);
155 layout_def->display_mode = SRC_WIN;
157 case DISASSEM_COMMAND:
158 /* The previous layout was not showing code.
159 This can happen if there is no source
162 1. if the source file is in another dir OR
163 2. if target was compiled without -g
164 We still want to show the assembly though! */
166 tui_get_begin_asm_address (&gdbarch, &addr);
167 tui_set_win_focus_to (TUI_DISASM_WIN);
168 layout_def->display_mode = DISASSEM_WIN;
170 case SRC_DISASSEM_COMMAND:
171 /* The previous layout was not showing code.
172 This can happen if there is no source
175 1. if the source file is in another dir OR
176 2. if target was compiled without -g
177 We still want to show the assembly though! */
179 tui_get_begin_asm_address (&gdbarch, &addr);
180 if (win_with_focus == TUI_SRC_WIN)
181 tui_set_win_focus_to (TUI_SRC_WIN);
183 tui_set_win_focus_to (TUI_DISASM_WIN);
185 case SRC_DATA_COMMAND:
186 if (win_with_focus != TUI_DATA_WIN)
187 tui_set_win_focus_to (TUI_SRC_WIN);
189 tui_set_win_focus_to (TUI_DATA_WIN);
190 layout_def->display_mode = SRC_WIN;
192 case DISASSEM_DATA_COMMAND:
193 /* The previous layout was not showing code.
194 This can happen if there is no source
197 1. if the source file is in another dir OR
198 2. if target was compiled without -g
199 We still want to show the assembly though! */
201 tui_get_begin_asm_address (&gdbarch, &addr);
202 if (win_with_focus != TUI_DATA_WIN)
203 tui_set_win_focus_to (TUI_DISASM_WIN);
205 tui_set_win_focus_to (TUI_DATA_WIN);
206 layout_def->display_mode = DISASSEM_WIN;
213 * Now update the window content.
216 && (new_layout == SRC_DATA_COMMAND
217 || new_layout == DISASSEM_DATA_COMMAND))
218 TUI_DATA_WIN->display_all_data ();
220 tui_update_source_windows_with_addr (gdbarch, addr);
223 tui_show_registers (TUI_DATA_WIN->current_group);
227 status = TUI_FAILURE;
232 /* Add the specified window to the layout in a logical way. This
233 means setting up the most logical layout given the window to be
236 tui_add_win_to_layout (enum tui_win_type type)
238 enum tui_layout_type cur_layout = tui_current_layout ();
243 if (cur_layout != SRC_COMMAND
244 && cur_layout != SRC_DISASSEM_COMMAND
245 && cur_layout != SRC_DATA_COMMAND)
247 tui_clear_source_windows_detail ();
248 if (cur_layout == DISASSEM_DATA_COMMAND)
249 show_layout (SRC_DATA_COMMAND);
251 show_layout (SRC_COMMAND);
255 if (cur_layout != DISASSEM_COMMAND
256 && cur_layout != SRC_DISASSEM_COMMAND
257 && cur_layout != DISASSEM_DATA_COMMAND)
259 tui_clear_source_windows_detail ();
260 if (cur_layout == SRC_DATA_COMMAND)
261 show_layout (DISASSEM_DATA_COMMAND);
263 show_layout (DISASSEM_COMMAND);
267 if (cur_layout != SRC_DATA_COMMAND
268 && cur_layout != DISASSEM_DATA_COMMAND)
270 if (cur_layout == DISASSEM_COMMAND)
271 show_layout (DISASSEM_DATA_COMMAND);
273 show_layout (SRC_DATA_COMMAND);
282 /* Answer the height of a window. If it hasn't been created yet,
283 answer what the height of a window would be based upon its type and
286 tui_default_win_height (enum tui_win_type type,
287 enum tui_layout_type layout)
291 if (tui_win_list[type] != NULL)
292 h = tui_win_list[type]->height;
298 case DISASSEM_COMMAND:
299 if (TUI_CMD_WIN == NULL)
300 h = tui_term_height () / 2;
302 h = tui_term_height () - TUI_CMD_WIN->height;
304 case SRC_DISASSEM_COMMAND:
305 case SRC_DATA_COMMAND:
306 case DISASSEM_DATA_COMMAND:
307 if (TUI_CMD_WIN == NULL)
308 h = tui_term_height () / 3;
310 h = (tui_term_height () - TUI_CMD_WIN->height) / 2;
322 /* Answer the height of a window. If it hasn't been created yet,
323 answer what the height of a window would be based upon its type and
326 tui_default_win_viewport_height (enum tui_win_type type,
327 enum tui_layout_type layout)
331 h = tui_default_win_height (type, layout);
333 if (tui_win_list[type] == TUI_CMD_WIN)
341 /* Complete possible layout names. TEXT is the complete text entered so
342 far, WORD is the word currently being completed. */
345 layout_completer (struct cmd_list_element *ignore,
346 completion_tracker &tracker,
347 const char *text, const char *word)
349 static const char *layout_names [] =
350 { "src", "asm", "split", "regs", "next", "prev", NULL };
352 complete_on_enum (tracker, layout_names, text, word);
355 /* Function to initialize gdb commands, for tui window layout
359 _initialize_tui_layout (void)
361 struct cmd_list_element *cmd;
363 cmd = add_com ("layout", class_tui, tui_layout_command, _("\
364 Change the layout of windows.\n\
365 Usage: layout prev | next | LAYOUT-NAME\n\
367 src : Displays source and command windows.\n\
368 asm : Displays disassembly and command windows.\n\
369 split : Displays source, disassembly and command windows.\n\
370 regs : Displays register window. If existing layout\n\
371 is source/command or assembly/command, the \n\
372 register window is displayed. If the\n\
373 source/assembly/command (split) is displayed, \n\
374 the register window is displayed with \n\
375 the window that has current logical focus."));
376 set_cmd_completer (cmd, layout_completer);
380 /*************************
381 ** STATIC LOCAL FUNCTIONS
382 **************************/
385 /* Function to set the layout to SRC, ASM, SPLIT, NEXT, PREV, DATA, or
388 tui_set_layout_by_name (const char *layout_name)
390 enum tui_status status = TUI_SUCCESS;
392 if (layout_name != NULL)
395 enum tui_layout_type new_layout = UNDEFINED_LAYOUT;
396 enum tui_layout_type cur_layout = tui_current_layout ();
398 std::string copy = layout_name;
399 for (i = 0; i < copy.size (); i++)
400 copy[i] = toupper (copy[i]);
401 const char *buf_ptr = copy.c_str ();
403 /* First check for ambiguous input. */
404 if (strlen (buf_ptr) <= 1 && *buf_ptr == 'S')
406 warning (_("Ambiguous command input."));
407 status = TUI_FAILURE;
411 if (subset_compare (buf_ptr, "SRC"))
412 new_layout = SRC_COMMAND;
413 else if (subset_compare (buf_ptr, "ASM"))
414 new_layout = DISASSEM_COMMAND;
415 else if (subset_compare (buf_ptr, "SPLIT"))
416 new_layout = SRC_DISASSEM_COMMAND;
417 else if (subset_compare (buf_ptr, "REGS"))
419 if (cur_layout == SRC_COMMAND
420 || cur_layout == SRC_DATA_COMMAND)
421 new_layout = SRC_DATA_COMMAND;
423 new_layout = DISASSEM_DATA_COMMAND;
425 else if (subset_compare (buf_ptr, "NEXT"))
426 new_layout = next_layout ();
427 else if (subset_compare (buf_ptr, "PREV"))
428 new_layout = prev_layout ();
430 status = TUI_FAILURE;
432 if (status == TUI_SUCCESS)
434 /* Make sure the curses mode is enabled. */
436 tui_set_layout (new_layout);
441 status = TUI_FAILURE;
448 extract_display_start_addr (struct gdbarch **gdbarch_p, CORE_ADDR *addr_p)
450 enum tui_layout_type cur_layout = tui_current_layout ();
451 struct gdbarch *gdbarch = get_current_arch ();
454 struct symtab_and_line cursal = get_current_source_symtab_and_line ();
459 case SRC_DATA_COMMAND:
460 gdbarch = TUI_SRC_WIN->gdbarch;
461 find_line_pc (cursal.symtab,
462 TUI_SRC_WIN->start_line_or_addr.u.line_no,
466 case DISASSEM_COMMAND:
467 case SRC_DISASSEM_COMMAND:
468 case DISASSEM_DATA_COMMAND:
469 gdbarch = TUI_DISASM_WIN->gdbarch;
470 addr = TUI_DISASM_WIN->start_line_or_addr.u.addr;
477 *gdbarch_p = gdbarch;
483 tui_layout_command (const char *arg, int from_tty)
485 /* Switch to the selected layout. */
486 if (tui_set_layout_by_name (arg) != TUI_SUCCESS)
487 warning (_("Invalid layout specified.\n%s"), LAYOUT_USAGE);
490 /* Answer the previous layout to cycle to. */
491 static enum tui_layout_type
496 new_layout = tui_current_layout ();
497 if (new_layout == UNDEFINED_LAYOUT)
498 new_layout = SRC_COMMAND;
502 if (new_layout == UNDEFINED_LAYOUT)
503 new_layout = SRC_COMMAND;
506 return (enum tui_layout_type) new_layout;
510 /* Answer the next layout to cycle to. */
511 static enum tui_layout_type
516 new_layout = tui_current_layout ();
517 if (new_layout == SRC_COMMAND)
518 new_layout = DISASSEM_DATA_COMMAND;
522 if (new_layout == UNDEFINED_LAYOUT)
523 new_layout = DISASSEM_DATA_COMMAND;
526 return (enum tui_layout_type) new_layout;
531 static struct tui_win_info *
532 make_command_window (int height, int origin_y)
534 struct tui_win_info *result
535 = (struct tui_win_info *) init_and_make_win (NULL,
546 /* make_source_window().
548 static struct tui_win_info *
549 make_source_window (int height, int origin_y)
551 return make_source_or_disasm_window (SRC_WIN, height, origin_y);
552 } /* make_source_window */
555 /* make_disasm_window().
557 static struct tui_win_info *
558 make_disasm_window (int height, int origin_y)
560 return make_source_or_disasm_window (DISASSEM_WIN, height, origin_y);
561 } /* make_disasm_window */
565 make_data_window (struct tui_win_info **win_info_ptr,
566 int height, int origin_y)
569 = (struct tui_win_info *) init_and_make_win (*win_info_ptr,
580 /* Show the Source/Command layout. */
582 show_source_command (void)
584 show_source_or_disasm_and_command (SRC_COMMAND);
588 /* Show the Dissassem/Command layout. */
590 show_disasm_command (void)
592 show_source_or_disasm_and_command (DISASSEM_COMMAND);
596 /* Show the Source/Disassem/Command layout. */
598 show_source_disasm_command (void)
600 if (tui_current_layout () != SRC_DISASSEM_COMMAND)
602 int cmd_height, src_height, asm_height;
604 if (TUI_CMD_WIN != NULL)
605 cmd_height = TUI_CMD_WIN->height;
607 cmd_height = tui_term_height () / 3;
609 src_height = (tui_term_height () - cmd_height) / 2;
610 asm_height = tui_term_height () - (src_height + cmd_height);
612 if (TUI_SRC_WIN == NULL)
613 tui_win_list[SRC_WIN] = make_source_window (src_height, 0);
616 TUI_SRC_WIN->reset (TUI_SRC_WIN->type,
619 TUI_SRC_WIN->execution_info->width,
621 TUI_SRC_WIN->execution_info->reset (EXEC_INFO_WIN,
626 tui_make_visible (TUI_SRC_WIN);
627 tui_make_visible (TUI_SRC_WIN->execution_info);
628 TUI_SRC_WIN->m_has_locator = false;
631 struct tui_locator_window *locator = tui_locator_win_info_ptr ();
632 gdb_assert (locator != nullptr);
634 tui_show_source_content (TUI_SRC_WIN);
635 if (TUI_DISASM_WIN == NULL)
637 tui_win_list[DISASSEM_WIN]
638 = make_disasm_window (asm_height, src_height - 1);
639 init_and_make_win (locator,
644 (src_height + asm_height) - 1,
649 locator->reset (LOCATOR_WIN,
653 (src_height + asm_height) - 1);
654 TUI_DISASM_WIN->m_has_locator = true;
655 TUI_DISASM_WIN->reset (TUI_DISASM_WIN->type,
657 TUI_DISASM_WIN->width,
658 TUI_DISASM_WIN->execution_info->width,
660 TUI_DISASM_WIN->execution_info->reset (EXEC_INFO_WIN,
665 tui_make_visible (TUI_DISASM_WIN);
666 tui_make_visible (TUI_DISASM_WIN->execution_info);
668 TUI_SRC_WIN->m_has_locator = false;
669 TUI_DISASM_WIN->m_has_locator = true;
670 tui_make_visible (locator);
671 tui_show_locator_content ();
672 tui_show_source_content (TUI_DISASM_WIN);
674 if (TUI_CMD_WIN == NULL)
675 tui_win_list[CMD_WIN]
676 = make_command_window (cmd_height, tui_term_height () - cmd_height);
679 TUI_CMD_WIN->reset (TUI_CMD_WIN->type,
683 TUI_CMD_WIN->origin.y);
684 tui_make_visible (TUI_CMD_WIN);
686 TUI_CMD_WIN->refresh_window ();
687 tui_set_current_layout_to (SRC_DISASSEM_COMMAND);
692 /* Show the Source/Data/Command or the Dissassembly/Data/Command
695 show_data (enum tui_layout_type new_layout)
697 int total_height = (tui_term_height () - TUI_CMD_WIN->height);
698 int src_height, data_height;
699 enum tui_win_type win_type;
701 struct tui_locator_window *locator = tui_locator_win_info_ptr ();
702 gdb_assert (locator != nullptr);
704 data_height = total_height / 2;
705 src_height = total_height - data_height;
706 tui_make_all_invisible ();
707 tui_make_invisible (locator);
708 make_data_window (&tui_win_list[DATA_WIN], data_height, 0);
709 if (new_layout == SRC_DATA_COMMAND)
712 win_type = DISASSEM_WIN;
714 tui_source_window_base *base;
715 if (tui_win_list[win_type] == NULL)
717 if (win_type == SRC_WIN)
718 tui_win_list[win_type]
719 = make_source_window (src_height, data_height - 1);
721 tui_win_list[win_type]
722 = make_disasm_window (src_height, data_height - 1);
723 init_and_make_win (locator,
730 base = (tui_source_window_base *) tui_win_list[win_type];
734 base = (tui_source_window_base *) tui_win_list[win_type];
735 tui_win_list[win_type]->reset (tui_win_list[win_type]->type,
737 tui_win_list[win_type]->width,
738 base->execution_info->width,
740 base->execution_info->reset (EXEC_INFO_WIN,
745 tui_make_visible (tui_win_list[win_type]);
746 tui_make_visible (base->execution_info);
747 locator->reset (LOCATOR_WIN,
753 base->m_has_locator = true;
754 tui_make_visible (locator);
755 tui_show_locator_content ();
756 tui_add_to_source_windows
757 ((tui_source_window_base *) tui_win_list[win_type]);
758 tui_set_current_layout_to (new_layout);
762 tui_gen_win_info::reset (enum tui_win_type win_type,
763 int height_, int width_,
764 int origin_x_, int origin_y_)
768 gdb_assert (type == win_type);
774 viewport_height = h - 1;
780 origin.x = origin_x_;
781 origin.y = origin_y_;
784 /* init_and_make_win().
786 static tui_gen_win_info *
787 init_and_make_win (tui_gen_win_info *win_info,
788 enum tui_win_type win_type,
789 int height, int width,
790 int origin_x, int origin_y,
793 if (win_info == NULL)
798 win_info = new tui_source_window ();
802 win_info = new tui_disasm_window ();
806 win_info = new tui_data_window ();
810 win_info = new tui_cmd_window ();
814 win_info = new tui_exec_info_window ();
818 gdb_assert_not_reached (_("unhandled window type"));
822 win_info->reset (win_type, height, width, origin_x, origin_y);
823 tui_make_window (win_info, box_it);
829 static struct tui_win_info *
830 make_source_or_disasm_window (enum tui_win_type type,
831 int height, int origin_y)
833 struct tui_exec_info_window *execution_info
834 = (tui_exec_info_window *) init_and_make_win (nullptr,
842 /* Now create the source window. */
843 struct tui_source_window_base *result
844 = ((struct tui_source_window_base *)
845 init_and_make_win (NULL,
848 tui_term_width () - execution_info->width,
849 execution_info->width,
852 result->execution_info = execution_info;
857 /* Show the Source/Command or the Disassem layout. */
859 show_source_or_disasm_and_command (enum tui_layout_type layout_type)
861 if (tui_current_layout () != layout_type)
863 struct tui_win_info **win_info_ptr;
864 int src_height, cmd_height;
865 struct tui_locator_window *locator = tui_locator_win_info_ptr ();
866 gdb_assert (locator != nullptr);
868 if (TUI_CMD_WIN != NULL)
869 cmd_height = TUI_CMD_WIN->height;
871 cmd_height = tui_term_height () / 3;
872 src_height = tui_term_height () - cmd_height;
874 if (layout_type == SRC_COMMAND)
875 win_info_ptr = &tui_win_list[SRC_WIN];
877 win_info_ptr = &tui_win_list[DISASSEM_WIN];
879 tui_source_window_base *base;
880 if ((*win_info_ptr) == NULL)
882 if (layout_type == SRC_COMMAND)
883 *win_info_ptr = make_source_window (src_height - 1, 0);
885 *win_info_ptr = make_disasm_window (src_height - 1, 0);
886 init_and_make_win (locator,
893 base = (tui_source_window_base *) *win_info_ptr;
897 base = (tui_source_window_base *) *win_info_ptr;
898 locator->reset (LOCATOR_WIN,
903 base->m_has_locator = true;
904 (*win_info_ptr)->reset ((*win_info_ptr)->type,
906 (*win_info_ptr)->width,
907 base->execution_info->width,
909 base->execution_info->reset (EXEC_INFO_WIN,
914 tui_make_visible (*win_info_ptr);
915 tui_make_visible (base->execution_info);
918 base->m_has_locator = true;
919 tui_make_visible (locator);
920 tui_show_locator_content ();
921 tui_show_source_content (base);
923 if (TUI_CMD_WIN == NULL)
925 tui_win_list[CMD_WIN] = make_command_window (cmd_height,
927 TUI_CMD_WIN->refresh_window ();
931 TUI_CMD_WIN->reset (TUI_CMD_WIN->type,
934 TUI_CMD_WIN->origin.x,
935 TUI_CMD_WIN->origin.y);
936 tui_make_visible (TUI_CMD_WIN);
938 tui_set_current_layout_to (layout_type);