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
*,
48 int, int, int, int, int);
49 static void show_source_or_disasm_and_command (enum tui_layout_type
);
50 static struct tui_win_info
*make_source_or_disasm_window (enum tui_win_type
,
52 static struct tui_win_info
*make_command_window (int, int);
53 static struct tui_win_info
*make_source_window (int, int);
54 static struct tui_win_info
*make_disasm_window (int, int);
55 static void make_data_window (struct tui_win_info
**, int, int);
56 static void show_source_command (void);
57 static void show_disasm_command (void);
58 static void show_source_disasm_command (void);
59 static void show_data (enum tui_layout_type
);
60 static enum tui_layout_type
next_layout (void);
61 static enum tui_layout_type
prev_layout (void);
62 static void tui_layout_command (const char *, int);
63 static void extract_display_start_addr (struct gdbarch
**, CORE_ADDR
*);
66 /***************************************
68 ***************************************/
70 #define LAYOUT_USAGE "Usage: layout prev | next | <layout_name> \n"
72 /* Show the screen layout defined. */
74 show_layout (enum tui_layout_type layout
)
76 enum tui_layout_type cur_layout
= tui_current_layout ();
78 if (layout
!= cur_layout
)
80 /* Since the new layout may cause changes in window size, we
81 should free the content and reallocate on next display of
83 tui_free_all_source_wins_content ();
84 tui_clear_source_windows ();
85 if (layout
== SRC_DATA_COMMAND
86 || layout
== DISASSEM_DATA_COMMAND
)
89 tui_refresh_all (tui_win_list
);
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
;
156 layout_def
->split
= FALSE
;
158 case DISASSEM_COMMAND
:
159 /* The previous layout was not showing code.
160 This can happen if there is no source
163 1. if the source file is in another dir OR
164 2. if target was compiled without -g
165 We still want to show the assembly though! */
167 tui_get_begin_asm_address (&gdbarch
, &addr
);
168 tui_set_win_focus_to (TUI_DISASM_WIN
);
169 layout_def
->display_mode
= DISASSEM_WIN
;
170 layout_def
->split
= FALSE
;
172 case SRC_DISASSEM_COMMAND
:
173 /* The previous layout was not showing code.
174 This can happen if there is no source
177 1. if the source file is in another dir OR
178 2. if target was compiled without -g
179 We still want to show the assembly though! */
181 tui_get_begin_asm_address (&gdbarch
, &addr
);
182 if (win_with_focus
== TUI_SRC_WIN
)
183 tui_set_win_focus_to (TUI_SRC_WIN
);
185 tui_set_win_focus_to (TUI_DISASM_WIN
);
186 layout_def
->split
= TRUE
;
188 case SRC_DATA_COMMAND
:
189 if (win_with_focus
!= TUI_DATA_WIN
)
190 tui_set_win_focus_to (TUI_SRC_WIN
);
192 tui_set_win_focus_to (TUI_DATA_WIN
);
193 layout_def
->display_mode
= SRC_WIN
;
194 layout_def
->split
= FALSE
;
196 case DISASSEM_DATA_COMMAND
:
197 /* The previous layout was not showing code.
198 This can happen if there is no source
201 1. if the source file is in another dir OR
202 2. if target was compiled without -g
203 We still want to show the assembly though! */
205 tui_get_begin_asm_address (&gdbarch
, &addr
);
206 if (win_with_focus
!= TUI_DATA_WIN
)
207 tui_set_win_focus_to (TUI_DISASM_WIN
);
209 tui_set_win_focus_to (TUI_DATA_WIN
);
210 layout_def
->display_mode
= DISASSEM_WIN
;
211 layout_def
->split
= FALSE
;
218 * Now update the window content.
221 && (new_layout
== SRC_DATA_COMMAND
222 || new_layout
== DISASSEM_DATA_COMMAND
))
223 tui_display_all_data ();
225 tui_update_source_windows_with_addr (gdbarch
, addr
);
228 tui_show_registers (TUI_DATA_WIN
->current_group
);
232 status
= TUI_FAILURE
;
237 /* Add the specified window to the layout in a logical way. This
238 means setting up the most logical layout given the window to be
241 tui_add_win_to_layout (enum tui_win_type type
)
243 enum tui_layout_type cur_layout
= tui_current_layout ();
248 if (cur_layout
!= SRC_COMMAND
249 && cur_layout
!= SRC_DISASSEM_COMMAND
250 && cur_layout
!= SRC_DATA_COMMAND
)
252 tui_clear_source_windows_detail ();
253 if (cur_layout
== DISASSEM_DATA_COMMAND
)
254 show_layout (SRC_DATA_COMMAND
);
256 show_layout (SRC_COMMAND
);
260 if (cur_layout
!= DISASSEM_COMMAND
261 && cur_layout
!= SRC_DISASSEM_COMMAND
262 && cur_layout
!= DISASSEM_DATA_COMMAND
)
264 tui_clear_source_windows_detail ();
265 if (cur_layout
== SRC_DATA_COMMAND
)
266 show_layout (DISASSEM_DATA_COMMAND
);
268 show_layout (DISASSEM_COMMAND
);
272 if (cur_layout
!= SRC_DATA_COMMAND
273 && cur_layout
!= DISASSEM_DATA_COMMAND
)
275 if (cur_layout
== DISASSEM_COMMAND
)
276 show_layout (DISASSEM_DATA_COMMAND
);
278 show_layout (SRC_DATA_COMMAND
);
287 /* Answer the height of a window. If it hasn't been created yet,
288 answer what the height of a window would be based upon its type and
291 tui_default_win_height (enum tui_win_type type
,
292 enum tui_layout_type layout
)
296 if (tui_win_list
[type
] != NULL
)
297 h
= tui_win_list
[type
]->height
;
303 case DISASSEM_COMMAND
:
304 if (TUI_CMD_WIN
== NULL
)
305 h
= tui_term_height () / 2;
307 h
= tui_term_height () - TUI_CMD_WIN
->height
;
309 case SRC_DISASSEM_COMMAND
:
310 case SRC_DATA_COMMAND
:
311 case DISASSEM_DATA_COMMAND
:
312 if (TUI_CMD_WIN
== NULL
)
313 h
= tui_term_height () / 3;
315 h
= (tui_term_height () - TUI_CMD_WIN
->height
) / 2;
327 /* Answer the height of a window. If it hasn't been created yet,
328 answer what the height of a window would be based upon its type and
331 tui_default_win_viewport_height (enum tui_win_type type
,
332 enum tui_layout_type layout
)
336 h
= tui_default_win_height (type
, layout
);
338 if (tui_win_list
[type
] == TUI_CMD_WIN
)
346 /* Complete possible layout names. TEXT is the complete text entered so
347 far, WORD is the word currently being completed. */
350 layout_completer (struct cmd_list_element
*ignore
,
351 completion_tracker
&tracker
,
352 const char *text
, const char *word
)
354 static const char *layout_names
[] =
355 { "src", "asm", "split", "regs", "next", "prev", NULL
};
357 complete_on_enum (tracker
, layout_names
, text
, word
);
360 /* Function to initialize gdb commands, for tui window layout
364 _initialize_tui_layout (void)
366 struct cmd_list_element
*cmd
;
368 cmd
= add_com ("layout", class_tui
, tui_layout_command
, _("\
369 Change the layout of windows.\n\
370 Usage: layout prev | next | LAYOUT-NAME\n\
372 src : Displays source and command windows.\n\
373 asm : Displays disassembly and command windows.\n\
374 split : Displays source, disassembly and command windows.\n\
375 regs : Displays register window. If existing layout\n\
376 is source/command or assembly/command, the \n\
377 register window is displayed. If the\n\
378 source/assembly/command (split) is displayed, \n\
379 the register window is displayed with \n\
380 the window that has current logical focus."));
381 set_cmd_completer (cmd
, layout_completer
);
385 /*************************
386 ** STATIC LOCAL FUNCTIONS
387 **************************/
390 /* Function to set the layout to SRC, ASM, SPLIT, NEXT, PREV, DATA, or
393 tui_set_layout_by_name (const char *layout_name
)
395 enum tui_status status
= TUI_SUCCESS
;
397 if (layout_name
!= NULL
)
400 enum tui_layout_type new_layout
= UNDEFINED_LAYOUT
;
401 enum tui_layout_type cur_layout
= tui_current_layout ();
403 std::string copy
= layout_name
;
404 for (i
= 0; i
< copy
.size (); i
++)
405 copy
[i
] = toupper (copy
[i
]);
406 const char *buf_ptr
= copy
.c_str ();
408 /* First check for ambiguous input. */
409 if (strlen (buf_ptr
) <= 1 && *buf_ptr
== 'S')
411 warning (_("Ambiguous command input."));
412 status
= TUI_FAILURE
;
416 if (subset_compare (buf_ptr
, "SRC"))
417 new_layout
= SRC_COMMAND
;
418 else if (subset_compare (buf_ptr
, "ASM"))
419 new_layout
= DISASSEM_COMMAND
;
420 else if (subset_compare (buf_ptr
, "SPLIT"))
421 new_layout
= SRC_DISASSEM_COMMAND
;
422 else if (subset_compare (buf_ptr
, "REGS"))
424 if (cur_layout
== SRC_COMMAND
425 || cur_layout
== SRC_DATA_COMMAND
)
426 new_layout
= SRC_DATA_COMMAND
;
428 new_layout
= DISASSEM_DATA_COMMAND
;
430 else if (subset_compare (buf_ptr
, "NEXT"))
431 new_layout
= next_layout ();
432 else if (subset_compare (buf_ptr
, "PREV"))
433 new_layout
= prev_layout ();
435 status
= TUI_FAILURE
;
437 if (status
== TUI_SUCCESS
)
439 /* Make sure the curses mode is enabled. */
441 tui_set_layout (new_layout
);
446 status
= TUI_FAILURE
;
453 extract_display_start_addr (struct gdbarch
**gdbarch_p
, CORE_ADDR
*addr_p
)
455 enum tui_layout_type cur_layout
= tui_current_layout ();
456 struct gdbarch
*gdbarch
= get_current_arch ();
459 struct symtab_and_line cursal
= get_current_source_symtab_and_line ();
464 case SRC_DATA_COMMAND
:
465 gdbarch
= TUI_SRC_WIN
->gdbarch
;
466 find_line_pc (cursal
.symtab
,
467 TUI_SRC_WIN
->start_line_or_addr
.u
.line_no
,
471 case DISASSEM_COMMAND
:
472 case SRC_DISASSEM_COMMAND
:
473 case DISASSEM_DATA_COMMAND
:
474 gdbarch
= TUI_DISASM_WIN
->gdbarch
;
475 addr
= TUI_DISASM_WIN
->start_line_or_addr
.u
.addr
;
482 *gdbarch_p
= gdbarch
;
488 tui_layout_command (const char *arg
, int from_tty
)
490 /* Switch to the selected layout. */
491 if (tui_set_layout_by_name (arg
) != TUI_SUCCESS
)
492 warning (_("Invalid layout specified.\n%s"), LAYOUT_USAGE
);
495 /* Answer the previous layout to cycle to. */
496 static enum tui_layout_type
501 new_layout
= tui_current_layout ();
502 if (new_layout
== UNDEFINED_LAYOUT
)
503 new_layout
= SRC_COMMAND
;
507 if (new_layout
== UNDEFINED_LAYOUT
)
508 new_layout
= SRC_COMMAND
;
511 return (enum tui_layout_type
) new_layout
;
515 /* Answer the next layout to cycle to. */
516 static enum tui_layout_type
521 new_layout
= tui_current_layout ();
522 if (new_layout
== SRC_COMMAND
)
523 new_layout
= DISASSEM_DATA_COMMAND
;
527 if (new_layout
== UNDEFINED_LAYOUT
)
528 new_layout
= DISASSEM_DATA_COMMAND
;
531 return (enum tui_layout_type
) new_layout
;
536 static struct tui_win_info
*
537 make_command_window (int height
, int origin_y
)
539 struct tui_win_info
*result
540 = (struct tui_win_info
*) init_and_make_win (NULL
,
551 /* make_source_window().
553 static struct tui_win_info
*
554 make_source_window (int height
, int origin_y
)
556 return make_source_or_disasm_window (SRC_WIN
, height
, origin_y
);
557 } /* make_source_window */
560 /* make_disasm_window().
562 static struct tui_win_info
*
563 make_disasm_window (int height
, int origin_y
)
565 return make_source_or_disasm_window (DISASSEM_WIN
, height
, origin_y
);
566 } /* make_disasm_window */
570 make_data_window (struct tui_win_info
**win_info_ptr
,
571 int height
, int origin_y
)
574 = (struct tui_win_info
*) init_and_make_win (*win_info_ptr
,
585 /* Show the Source/Command layout. */
587 show_source_command (void)
589 show_source_or_disasm_and_command (SRC_COMMAND
);
593 /* Show the Dissassem/Command layout. */
595 show_disasm_command (void)
597 show_source_or_disasm_and_command (DISASSEM_COMMAND
);
601 /* Show the Source/Disassem/Command layout. */
603 show_source_disasm_command (void)
605 if (tui_current_layout () != SRC_DISASSEM_COMMAND
)
607 int cmd_height
, src_height
, asm_height
;
609 if (TUI_CMD_WIN
!= NULL
)
610 cmd_height
= TUI_CMD_WIN
->height
;
612 cmd_height
= tui_term_height () / 3;
614 src_height
= (tui_term_height () - cmd_height
) / 2;
615 asm_height
= tui_term_height () - (src_height
+ cmd_height
);
617 if (TUI_SRC_WIN
== NULL
)
618 tui_win_list
[SRC_WIN
] = make_source_window (src_height
, 0);
621 TUI_SRC_WIN
->reset (TUI_SRC_WIN
->type
,
624 TUI_SRC_WIN
->execution_info
->width
,
626 TUI_SRC_WIN
->execution_info
->reset (EXEC_INFO_WIN
,
631 tui_make_visible (TUI_SRC_WIN
);
632 tui_make_visible (TUI_SRC_WIN
->execution_info
);
633 TUI_SRC_WIN
->m_has_locator
= false;
636 struct tui_gen_win_info
*locator
= tui_locator_win_info_ptr ();
638 tui_show_source_content (TUI_SRC_WIN
);
639 if (TUI_DISASM_WIN
== NULL
)
641 tui_win_list
[DISASSEM_WIN
]
642 = make_disasm_window (asm_height
, src_height
- 1);
644 = init_and_make_win (locator
,
649 (src_height
+ asm_height
) - 1,
654 locator
->reset (LOCATOR_WIN
,
658 (src_height
+ asm_height
) - 1);
659 TUI_DISASM_WIN
->m_has_locator
= true;
660 TUI_DISASM_WIN
->reset (TUI_DISASM_WIN
->type
,
662 TUI_DISASM_WIN
->width
,
663 TUI_DISASM_WIN
->execution_info
->width
,
665 TUI_DISASM_WIN
->execution_info
->reset (EXEC_INFO_WIN
,
670 tui_make_visible (TUI_DISASM_WIN
);
671 tui_make_visible (TUI_DISASM_WIN
->execution_info
);
673 TUI_SRC_WIN
->m_has_locator
= false;
674 TUI_DISASM_WIN
->m_has_locator
= true;
675 tui_make_visible (locator
);
676 tui_show_locator_content ();
677 tui_show_source_content (TUI_DISASM_WIN
);
679 if (TUI_CMD_WIN
== NULL
)
680 tui_win_list
[CMD_WIN
]
681 = make_command_window (cmd_height
, tui_term_height () - cmd_height
);
684 TUI_CMD_WIN
->reset (TUI_CMD_WIN
->type
,
688 TUI_CMD_WIN
->origin
.y
);
689 tui_make_visible (TUI_CMD_WIN
);
691 TUI_CMD_WIN
->refresh_window ();
692 tui_set_current_layout_to (SRC_DISASSEM_COMMAND
);
697 /* Show the Source/Data/Command or the Dissassembly/Data/Command
700 show_data (enum tui_layout_type new_layout
)
702 int total_height
= (tui_term_height () - TUI_CMD_WIN
->height
);
703 int src_height
, data_height
;
704 enum tui_win_type win_type
;
705 struct tui_gen_win_info
*locator
= tui_locator_win_info_ptr ();
708 data_height
= total_height
/ 2;
709 src_height
= total_height
- data_height
;
710 tui_make_all_invisible ();
711 tui_make_invisible (locator
);
712 make_data_window (&tui_win_list
[DATA_WIN
], data_height
, 0);
713 if (new_layout
== SRC_DATA_COMMAND
)
716 win_type
= DISASSEM_WIN
;
718 tui_source_window_base
*base
;
719 if (tui_win_list
[win_type
] == NULL
)
721 if (win_type
== SRC_WIN
)
722 tui_win_list
[win_type
]
723 = make_source_window (src_height
, data_height
- 1);
725 tui_win_list
[win_type
]
726 = make_disasm_window (src_height
, data_height
- 1);
728 = init_and_make_win (locator
,
735 base
= (tui_source_window_base
*) tui_win_list
[win_type
];
739 base
= (tui_source_window_base
*) tui_win_list
[win_type
];
740 tui_win_list
[win_type
]->reset (tui_win_list
[win_type
]->type
,
742 tui_win_list
[win_type
]->width
,
743 base
->execution_info
->width
,
745 base
->execution_info
->reset (EXEC_INFO_WIN
,
750 tui_make_visible (tui_win_list
[win_type
]);
751 tui_make_visible (base
->execution_info
);
752 locator
->reset (LOCATOR_WIN
,
758 base
->m_has_locator
= true;
759 tui_make_visible (locator
);
760 tui_show_locator_content ();
761 tui_add_to_source_windows
762 ((tui_source_window_base
*) tui_win_list
[win_type
]);
763 tui_set_current_layout_to (new_layout
);
767 tui_gen_win_info::reset (enum tui_win_type win_type
,
768 int height_
, int width_
,
769 int origin_x_
, int origin_y_
)
773 gdb_assert (type
== win_type
);
779 viewport_height
= h
- 1;
785 origin
.x
= origin_x_
;
786 origin
.y
= origin_y_
;
789 /* init_and_make_win().
791 static tui_gen_win_info
*
792 init_and_make_win (tui_gen_win_info
*win_info
,
793 enum tui_win_type win_type
,
794 int height
, int width
,
795 int origin_x
, int origin_y
,
798 if (win_info
== NULL
)
800 if (tui_win_is_auxillary (win_type
))
801 win_info
= new tui_gen_win_info (win_type
);
803 win_info
= tui_alloc_win_info (win_type
);
806 win_info
->reset (win_type
, height
, width
, origin_x
, origin_y
);
807 tui_make_window (win_info
, box_it
);
813 static struct tui_win_info
*
814 make_source_or_disasm_window (enum tui_win_type type
,
815 int height
, int origin_y
)
817 struct tui_gen_win_info
*execution_info
818 = init_and_make_win (nullptr,
826 /* Now create the source window. */
827 struct tui_source_window_base
*result
828 = ((struct tui_source_window_base
*)
829 init_and_make_win (NULL
,
832 tui_term_width () - execution_info
->width
,
833 execution_info
->width
,
836 result
->execution_info
= execution_info
;
841 /* Show the Source/Command or the Disassem layout. */
843 show_source_or_disasm_and_command (enum tui_layout_type layout_type
)
845 if (tui_current_layout () != layout_type
)
847 struct tui_win_info
**win_info_ptr
;
848 int src_height
, cmd_height
;
849 struct tui_gen_win_info
*locator
= tui_locator_win_info_ptr ();
851 if (TUI_CMD_WIN
!= NULL
)
852 cmd_height
= TUI_CMD_WIN
->height
;
854 cmd_height
= tui_term_height () / 3;
855 src_height
= tui_term_height () - cmd_height
;
857 if (layout_type
== SRC_COMMAND
)
858 win_info_ptr
= &tui_win_list
[SRC_WIN
];
860 win_info_ptr
= &tui_win_list
[DISASSEM_WIN
];
862 tui_source_window_base
*base
;
863 if ((*win_info_ptr
) == NULL
)
865 if (layout_type
== SRC_COMMAND
)
866 *win_info_ptr
= make_source_window (src_height
- 1, 0);
868 *win_info_ptr
= make_disasm_window (src_height
- 1, 0);
870 = init_and_make_win (locator
,
877 base
= (tui_source_window_base
*) *win_info_ptr
;
881 base
= (tui_source_window_base
*) *win_info_ptr
;
882 locator
->reset (LOCATOR_WIN
,
887 base
->m_has_locator
= true;
888 (*win_info_ptr
)->reset ((*win_info_ptr
)->type
,
890 (*win_info_ptr
)->width
,
891 base
->execution_info
->width
,
893 base
->execution_info
->reset (EXEC_INFO_WIN
,
898 tui_make_visible (*win_info_ptr
);
899 tui_make_visible (base
->execution_info
);
902 base
->m_has_locator
= true;
903 tui_make_visible (locator
);
904 tui_show_locator_content ();
905 tui_show_source_content (*win_info_ptr
);
907 if (TUI_CMD_WIN
== NULL
)
909 tui_win_list
[CMD_WIN
] = make_command_window (cmd_height
,
911 TUI_CMD_WIN
->refresh_window ();
915 TUI_CMD_WIN
->reset (TUI_CMD_WIN
->type
,
918 TUI_CMD_WIN
->origin
.x
,
919 TUI_CMD_WIN
->origin
.y
);
920 tui_make_visible (TUI_CMD_WIN
);
922 tui_set_current_layout_to (layout_type
);