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_free_all_source_wins_content ();
85 tui_clear_source_windows ();
86 if (layout
== SRC_DATA_COMMAND
87 || layout
== DISASSEM_DATA_COMMAND
)
90 tui_refresh_all (tui_win_list
);
94 /* First make the current layout be invisible. */
95 tui_make_all_invisible ();
96 tui_make_invisible (tui_locator_win_info_ptr ());
100 /* Now show the new layout. */
102 show_source_command ();
103 tui_add_to_source_windows (TUI_SRC_WIN
);
105 case DISASSEM_COMMAND
:
106 show_disasm_command ();
107 tui_add_to_source_windows (TUI_DISASM_WIN
);
109 case SRC_DISASSEM_COMMAND
:
110 show_source_disasm_command ();
111 tui_add_to_source_windows (TUI_SRC_WIN
);
112 tui_add_to_source_windows (TUI_DISASM_WIN
);
122 /* Function to set the layout to SRC_COMMAND, DISASSEM_COMMAND,
123 SRC_DISASSEM_COMMAND, SRC_DATA_COMMAND, or DISASSEM_DATA_COMMAND. */
125 tui_set_layout (enum tui_layout_type layout_type
)
127 enum tui_status status
= TUI_SUCCESS
;
129 if (layout_type
!= UNDEFINED_LAYOUT
)
131 enum tui_layout_type cur_layout
= tui_current_layout (),
132 new_layout
= UNDEFINED_LAYOUT
;
133 int regs_populate
= FALSE
;
134 struct gdbarch
*gdbarch
;
136 struct tui_win_info
*win_with_focus
= tui_win_with_focus ();
137 struct tui_layout_def
*layout_def
= tui_layout_def ();
139 extract_display_start_addr (&gdbarch
, &addr
);
141 new_layout
= layout_type
;
143 regs_populate
= (new_layout
== SRC_DATA_COMMAND
144 || new_layout
== DISASSEM_DATA_COMMAND
);
145 if (new_layout
!= cur_layout
)
147 show_layout (new_layout
);
149 /* Now determine where focus should be. */
150 if (win_with_focus
!= TUI_CMD_WIN
)
155 tui_set_win_focus_to (TUI_SRC_WIN
);
156 layout_def
->display_mode
= SRC_WIN
;
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
;
171 case SRC_DISASSEM_COMMAND
:
172 /* The previous layout was not showing code.
173 This can happen if there is no source
176 1. if the source file is in another dir OR
177 2. if target was compiled without -g
178 We still want to show the assembly though! */
180 tui_get_begin_asm_address (&gdbarch
, &addr
);
181 if (win_with_focus
== TUI_SRC_WIN
)
182 tui_set_win_focus_to (TUI_SRC_WIN
);
184 tui_set_win_focus_to (TUI_DISASM_WIN
);
186 case SRC_DATA_COMMAND
:
187 if (win_with_focus
!= TUI_DATA_WIN
)
188 tui_set_win_focus_to (TUI_SRC_WIN
);
190 tui_set_win_focus_to (TUI_DATA_WIN
);
191 layout_def
->display_mode
= SRC_WIN
;
193 case DISASSEM_DATA_COMMAND
:
194 /* The previous layout was not showing code.
195 This can happen if there is no source
198 1. if the source file is in another dir OR
199 2. if target was compiled without -g
200 We still want to show the assembly though! */
202 tui_get_begin_asm_address (&gdbarch
, &addr
);
203 if (win_with_focus
!= TUI_DATA_WIN
)
204 tui_set_win_focus_to (TUI_DISASM_WIN
);
206 tui_set_win_focus_to (TUI_DATA_WIN
);
207 layout_def
->display_mode
= DISASSEM_WIN
;
214 * Now update the window content.
217 && (new_layout
== SRC_DATA_COMMAND
218 || new_layout
== DISASSEM_DATA_COMMAND
))
219 tui_display_all_data ();
221 tui_update_source_windows_with_addr (gdbarch
, addr
);
224 tui_show_registers (TUI_DATA_WIN
->current_group
);
228 status
= TUI_FAILURE
;
233 /* Add the specified window to the layout in a logical way. This
234 means setting up the most logical layout given the window to be
237 tui_add_win_to_layout (enum tui_win_type type
)
239 enum tui_layout_type cur_layout
= tui_current_layout ();
244 if (cur_layout
!= SRC_COMMAND
245 && cur_layout
!= SRC_DISASSEM_COMMAND
246 && cur_layout
!= SRC_DATA_COMMAND
)
248 tui_clear_source_windows_detail ();
249 if (cur_layout
== DISASSEM_DATA_COMMAND
)
250 show_layout (SRC_DATA_COMMAND
);
252 show_layout (SRC_COMMAND
);
256 if (cur_layout
!= DISASSEM_COMMAND
257 && cur_layout
!= SRC_DISASSEM_COMMAND
258 && cur_layout
!= DISASSEM_DATA_COMMAND
)
260 tui_clear_source_windows_detail ();
261 if (cur_layout
== SRC_DATA_COMMAND
)
262 show_layout (DISASSEM_DATA_COMMAND
);
264 show_layout (DISASSEM_COMMAND
);
268 if (cur_layout
!= SRC_DATA_COMMAND
269 && cur_layout
!= DISASSEM_DATA_COMMAND
)
271 if (cur_layout
== DISASSEM_COMMAND
)
272 show_layout (DISASSEM_DATA_COMMAND
);
274 show_layout (SRC_DATA_COMMAND
);
283 /* Answer the height of a window. If it hasn't been created yet,
284 answer what the height of a window would be based upon its type and
287 tui_default_win_height (enum tui_win_type type
,
288 enum tui_layout_type layout
)
292 if (tui_win_list
[type
] != NULL
)
293 h
= tui_win_list
[type
]->height
;
299 case DISASSEM_COMMAND
:
300 if (TUI_CMD_WIN
== NULL
)
301 h
= tui_term_height () / 2;
303 h
= tui_term_height () - TUI_CMD_WIN
->height
;
305 case SRC_DISASSEM_COMMAND
:
306 case SRC_DATA_COMMAND
:
307 case DISASSEM_DATA_COMMAND
:
308 if (TUI_CMD_WIN
== NULL
)
309 h
= tui_term_height () / 3;
311 h
= (tui_term_height () - TUI_CMD_WIN
->height
) / 2;
323 /* Answer the height of a window. If it hasn't been created yet,
324 answer what the height of a window would be based upon its type and
327 tui_default_win_viewport_height (enum tui_win_type type
,
328 enum tui_layout_type layout
)
332 h
= tui_default_win_height (type
, layout
);
334 if (tui_win_list
[type
] == TUI_CMD_WIN
)
342 /* Complete possible layout names. TEXT is the complete text entered so
343 far, WORD is the word currently being completed. */
346 layout_completer (struct cmd_list_element
*ignore
,
347 completion_tracker
&tracker
,
348 const char *text
, const char *word
)
350 static const char *layout_names
[] =
351 { "src", "asm", "split", "regs", "next", "prev", NULL
};
353 complete_on_enum (tracker
, layout_names
, text
, word
);
356 /* Function to initialize gdb commands, for tui window layout
360 _initialize_tui_layout (void)
362 struct cmd_list_element
*cmd
;
364 cmd
= add_com ("layout", class_tui
, tui_layout_command
, _("\
365 Change the layout of windows.\n\
366 Usage: layout prev | next | LAYOUT-NAME\n\
368 src : Displays source and command windows.\n\
369 asm : Displays disassembly and command windows.\n\
370 split : Displays source, disassembly and command windows.\n\
371 regs : Displays register window. If existing layout\n\
372 is source/command or assembly/command, the \n\
373 register window is displayed. If the\n\
374 source/assembly/command (split) is displayed, \n\
375 the register window is displayed with \n\
376 the window that has current logical focus."));
377 set_cmd_completer (cmd
, layout_completer
);
381 /*************************
382 ** STATIC LOCAL FUNCTIONS
383 **************************/
386 /* Function to set the layout to SRC, ASM, SPLIT, NEXT, PREV, DATA, or
389 tui_set_layout_by_name (const char *layout_name
)
391 enum tui_status status
= TUI_SUCCESS
;
393 if (layout_name
!= NULL
)
396 enum tui_layout_type new_layout
= UNDEFINED_LAYOUT
;
397 enum tui_layout_type cur_layout
= tui_current_layout ();
399 std::string copy
= layout_name
;
400 for (i
= 0; i
< copy
.size (); i
++)
401 copy
[i
] = toupper (copy
[i
]);
402 const char *buf_ptr
= copy
.c_str ();
404 /* First check for ambiguous input. */
405 if (strlen (buf_ptr
) <= 1 && *buf_ptr
== 'S')
407 warning (_("Ambiguous command input."));
408 status
= TUI_FAILURE
;
412 if (subset_compare (buf_ptr
, "SRC"))
413 new_layout
= SRC_COMMAND
;
414 else if (subset_compare (buf_ptr
, "ASM"))
415 new_layout
= DISASSEM_COMMAND
;
416 else if (subset_compare (buf_ptr
, "SPLIT"))
417 new_layout
= SRC_DISASSEM_COMMAND
;
418 else if (subset_compare (buf_ptr
, "REGS"))
420 if (cur_layout
== SRC_COMMAND
421 || cur_layout
== SRC_DATA_COMMAND
)
422 new_layout
= SRC_DATA_COMMAND
;
424 new_layout
= DISASSEM_DATA_COMMAND
;
426 else if (subset_compare (buf_ptr
, "NEXT"))
427 new_layout
= next_layout ();
428 else if (subset_compare (buf_ptr
, "PREV"))
429 new_layout
= prev_layout ();
431 status
= TUI_FAILURE
;
433 if (status
== TUI_SUCCESS
)
435 /* Make sure the curses mode is enabled. */
437 tui_set_layout (new_layout
);
442 status
= TUI_FAILURE
;
449 extract_display_start_addr (struct gdbarch
**gdbarch_p
, CORE_ADDR
*addr_p
)
451 enum tui_layout_type cur_layout
= tui_current_layout ();
452 struct gdbarch
*gdbarch
= get_current_arch ();
455 struct symtab_and_line cursal
= get_current_source_symtab_and_line ();
460 case SRC_DATA_COMMAND
:
461 gdbarch
= TUI_SRC_WIN
->gdbarch
;
462 find_line_pc (cursal
.symtab
,
463 TUI_SRC_WIN
->start_line_or_addr
.u
.line_no
,
467 case DISASSEM_COMMAND
:
468 case SRC_DISASSEM_COMMAND
:
469 case DISASSEM_DATA_COMMAND
:
470 gdbarch
= TUI_DISASM_WIN
->gdbarch
;
471 addr
= TUI_DISASM_WIN
->start_line_or_addr
.u
.addr
;
478 *gdbarch_p
= gdbarch
;
484 tui_layout_command (const char *arg
, int from_tty
)
486 /* Switch to the selected layout. */
487 if (tui_set_layout_by_name (arg
) != TUI_SUCCESS
)
488 warning (_("Invalid layout specified.\n%s"), LAYOUT_USAGE
);
491 /* Answer the previous layout to cycle to. */
492 static enum tui_layout_type
497 new_layout
= tui_current_layout ();
498 if (new_layout
== UNDEFINED_LAYOUT
)
499 new_layout
= SRC_COMMAND
;
503 if (new_layout
== UNDEFINED_LAYOUT
)
504 new_layout
= SRC_COMMAND
;
507 return (enum tui_layout_type
) new_layout
;
511 /* Answer the next layout to cycle to. */
512 static enum tui_layout_type
517 new_layout
= tui_current_layout ();
518 if (new_layout
== SRC_COMMAND
)
519 new_layout
= DISASSEM_DATA_COMMAND
;
523 if (new_layout
== UNDEFINED_LAYOUT
)
524 new_layout
= DISASSEM_DATA_COMMAND
;
527 return (enum tui_layout_type
) new_layout
;
532 static struct tui_win_info
*
533 make_command_window (int height
, int origin_y
)
535 struct tui_win_info
*result
536 = (struct tui_win_info
*) init_and_make_win (NULL
,
547 /* make_source_window().
549 static struct tui_win_info
*
550 make_source_window (int height
, int origin_y
)
552 return make_source_or_disasm_window (SRC_WIN
, height
, origin_y
);
553 } /* make_source_window */
556 /* make_disasm_window().
558 static struct tui_win_info
*
559 make_disasm_window (int height
, int origin_y
)
561 return make_source_or_disasm_window (DISASSEM_WIN
, height
, origin_y
);
562 } /* make_disasm_window */
566 make_data_window (struct tui_win_info
**win_info_ptr
,
567 int height
, int origin_y
)
570 = (struct tui_win_info
*) init_and_make_win (*win_info_ptr
,
581 /* Show the Source/Command layout. */
583 show_source_command (void)
585 show_source_or_disasm_and_command (SRC_COMMAND
);
589 /* Show the Dissassem/Command layout. */
591 show_disasm_command (void)
593 show_source_or_disasm_and_command (DISASSEM_COMMAND
);
597 /* Show the Source/Disassem/Command layout. */
599 show_source_disasm_command (void)
601 if (tui_current_layout () != SRC_DISASSEM_COMMAND
)
603 int cmd_height
, src_height
, asm_height
;
605 if (TUI_CMD_WIN
!= NULL
)
606 cmd_height
= TUI_CMD_WIN
->height
;
608 cmd_height
= tui_term_height () / 3;
610 src_height
= (tui_term_height () - cmd_height
) / 2;
611 asm_height
= tui_term_height () - (src_height
+ cmd_height
);
613 if (TUI_SRC_WIN
== NULL
)
614 tui_win_list
[SRC_WIN
] = make_source_window (src_height
, 0);
617 TUI_SRC_WIN
->reset (TUI_SRC_WIN
->type
,
620 TUI_SRC_WIN
->execution_info
->width
,
622 TUI_SRC_WIN
->execution_info
->reset (EXEC_INFO_WIN
,
627 tui_make_visible (TUI_SRC_WIN
);
628 tui_make_visible (TUI_SRC_WIN
->execution_info
);
629 TUI_SRC_WIN
->m_has_locator
= false;
632 struct tui_locator_window
*locator
= tui_locator_win_info_ptr ();
633 gdb_assert (locator
!= nullptr);
635 tui_show_source_content (TUI_SRC_WIN
);
636 if (TUI_DISASM_WIN
== NULL
)
638 tui_win_list
[DISASSEM_WIN
]
639 = make_disasm_window (asm_height
, src_height
- 1);
640 init_and_make_win (locator
,
645 (src_height
+ asm_height
) - 1,
650 locator
->reset (LOCATOR_WIN
,
654 (src_height
+ asm_height
) - 1);
655 TUI_DISASM_WIN
->m_has_locator
= true;
656 TUI_DISASM_WIN
->reset (TUI_DISASM_WIN
->type
,
658 TUI_DISASM_WIN
->width
,
659 TUI_DISASM_WIN
->execution_info
->width
,
661 TUI_DISASM_WIN
->execution_info
->reset (EXEC_INFO_WIN
,
666 tui_make_visible (TUI_DISASM_WIN
);
667 tui_make_visible (TUI_DISASM_WIN
->execution_info
);
669 TUI_SRC_WIN
->m_has_locator
= false;
670 TUI_DISASM_WIN
->m_has_locator
= true;
671 tui_make_visible (locator
);
672 tui_show_locator_content ();
673 tui_show_source_content (TUI_DISASM_WIN
);
675 if (TUI_CMD_WIN
== NULL
)
676 tui_win_list
[CMD_WIN
]
677 = make_command_window (cmd_height
, tui_term_height () - cmd_height
);
680 TUI_CMD_WIN
->reset (TUI_CMD_WIN
->type
,
684 TUI_CMD_WIN
->origin
.y
);
685 tui_make_visible (TUI_CMD_WIN
);
687 TUI_CMD_WIN
->refresh_window ();
688 tui_set_current_layout_to (SRC_DISASSEM_COMMAND
);
693 /* Show the Source/Data/Command or the Dissassembly/Data/Command
696 show_data (enum tui_layout_type new_layout
)
698 int total_height
= (tui_term_height () - TUI_CMD_WIN
->height
);
699 int src_height
, data_height
;
700 enum tui_win_type win_type
;
702 struct tui_locator_window
*locator
= tui_locator_win_info_ptr ();
703 gdb_assert (locator
!= nullptr);
705 data_height
= total_height
/ 2;
706 src_height
= total_height
- data_height
;
707 tui_make_all_invisible ();
708 tui_make_invisible (locator
);
709 make_data_window (&tui_win_list
[DATA_WIN
], data_height
, 0);
710 if (new_layout
== SRC_DATA_COMMAND
)
713 win_type
= DISASSEM_WIN
;
715 tui_source_window_base
*base
;
716 if (tui_win_list
[win_type
] == NULL
)
718 if (win_type
== SRC_WIN
)
719 tui_win_list
[win_type
]
720 = make_source_window (src_height
, data_height
- 1);
722 tui_win_list
[win_type
]
723 = make_disasm_window (src_height
, data_height
- 1);
724 init_and_make_win (locator
,
731 base
= (tui_source_window_base
*) tui_win_list
[win_type
];
735 base
= (tui_source_window_base
*) tui_win_list
[win_type
];
736 tui_win_list
[win_type
]->reset (tui_win_list
[win_type
]->type
,
738 tui_win_list
[win_type
]->width
,
739 base
->execution_info
->width
,
741 base
->execution_info
->reset (EXEC_INFO_WIN
,
746 tui_make_visible (tui_win_list
[win_type
]);
747 tui_make_visible (base
->execution_info
);
748 locator
->reset (LOCATOR_WIN
,
754 base
->m_has_locator
= true;
755 tui_make_visible (locator
);
756 tui_show_locator_content ();
757 tui_add_to_source_windows
758 ((tui_source_window_base
*) tui_win_list
[win_type
]);
759 tui_set_current_layout_to (new_layout
);
763 tui_gen_win_info::reset (enum tui_win_type win_type
,
764 int height_
, int width_
,
765 int origin_x_
, int origin_y_
)
769 gdb_assert (type
== win_type
);
775 viewport_height
= h
- 1;
781 origin
.x
= origin_x_
;
782 origin
.y
= origin_y_
;
785 /* init_and_make_win().
787 static tui_gen_win_info
*
788 init_and_make_win (tui_gen_win_info
*win_info
,
789 enum tui_win_type win_type
,
790 int height
, int width
,
791 int origin_x
, int origin_y
,
794 if (win_info
== NULL
)
799 win_info
= new tui_source_window ();
803 win_info
= new tui_disasm_window ();
807 win_info
= new tui_data_window ();
811 win_info
= new tui_cmd_window ();
815 win_info
= new tui_exec_info_window ();
819 gdb_assert (tui_win_is_auxiliary (win_type
));
820 win_info
= new tui_gen_win_info (win_type
);
825 win_info
->reset (win_type
, height
, width
, origin_x
, origin_y
);
826 tui_make_window (win_info
, box_it
);
832 static struct tui_win_info
*
833 make_source_or_disasm_window (enum tui_win_type type
,
834 int height
, int origin_y
)
836 struct tui_exec_info_window
*execution_info
837 = (tui_exec_info_window
*) init_and_make_win (nullptr,
845 /* Now create the source window. */
846 struct tui_source_window_base
*result
847 = ((struct tui_source_window_base
*)
848 init_and_make_win (NULL
,
851 tui_term_width () - execution_info
->width
,
852 execution_info
->width
,
855 result
->execution_info
= execution_info
;
860 /* Show the Source/Command or the Disassem layout. */
862 show_source_or_disasm_and_command (enum tui_layout_type layout_type
)
864 if (tui_current_layout () != layout_type
)
866 struct tui_win_info
**win_info_ptr
;
867 int src_height
, cmd_height
;
868 struct tui_locator_window
*locator
= tui_locator_win_info_ptr ();
869 gdb_assert (locator
!= nullptr);
871 if (TUI_CMD_WIN
!= NULL
)
872 cmd_height
= TUI_CMD_WIN
->height
;
874 cmd_height
= tui_term_height () / 3;
875 src_height
= tui_term_height () - cmd_height
;
877 if (layout_type
== SRC_COMMAND
)
878 win_info_ptr
= &tui_win_list
[SRC_WIN
];
880 win_info_ptr
= &tui_win_list
[DISASSEM_WIN
];
882 tui_source_window_base
*base
;
883 if ((*win_info_ptr
) == NULL
)
885 if (layout_type
== SRC_COMMAND
)
886 *win_info_ptr
= make_source_window (src_height
- 1, 0);
888 *win_info_ptr
= make_disasm_window (src_height
- 1, 0);
889 init_and_make_win (locator
,
896 base
= (tui_source_window_base
*) *win_info_ptr
;
900 base
= (tui_source_window_base
*) *win_info_ptr
;
901 locator
->reset (LOCATOR_WIN
,
906 base
->m_has_locator
= true;
907 (*win_info_ptr
)->reset ((*win_info_ptr
)->type
,
909 (*win_info_ptr
)->width
,
910 base
->execution_info
->width
,
912 base
->execution_info
->reset (EXEC_INFO_WIN
,
917 tui_make_visible (*win_info_ptr
);
918 tui_make_visible (base
->execution_info
);
921 base
->m_has_locator
= true;
922 tui_make_visible (locator
);
923 tui_show_locator_content ();
924 tui_show_source_content (base
);
926 if (TUI_CMD_WIN
== NULL
)
928 tui_win_list
[CMD_WIN
] = make_command_window (cmd_height
,
930 TUI_CMD_WIN
->refresh_window ();
934 TUI_CMD_WIN
->reset (TUI_CMD_WIN
->type
,
937 TUI_CMD_WIN
->origin
.x
,
938 TUI_CMD_WIN
->origin
.y
);
939 tui_make_visible (TUI_CMD_WIN
);
941 tui_set_current_layout_to (layout_type
);