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-command.h"
32 #include "tui/tui-data.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 "tui/tui-source.h"
41 #include "gdb_curses.h"
43 static void show_layout (enum tui_layout_type
);
44 static void show_source_or_disasm_and_command (enum tui_layout_type
);
45 static void show_source_command (void);
46 static void show_disasm_command (void);
47 static void show_source_disasm_command (void);
48 static void show_data (enum tui_layout_type
);
49 static enum tui_layout_type
next_layout (void);
50 static enum tui_layout_type
prev_layout (void);
51 static void tui_layout_command (const char *, int);
52 static void extract_display_start_addr (struct gdbarch
**, CORE_ADDR
*);
55 static enum tui_layout_type current_layout
= UNDEFINED_LAYOUT
;
57 /* Accessor for the current layout. */
59 tui_current_layout (void)
61 return current_layout
;
65 /* Show the screen layout defined. */
67 show_layout (enum tui_layout_type layout
)
69 enum tui_layout_type cur_layout
= tui_current_layout ();
71 if (layout
!= cur_layout
)
73 tui_make_all_invisible ();
76 case SRC_DATA_COMMAND
:
77 case DISASSEM_DATA_COMMAND
:
80 /* Now show the new layout. */
82 show_source_command ();
84 case DISASSEM_COMMAND
:
85 show_disasm_command ();
87 case SRC_DISASSEM_COMMAND
:
88 show_source_disasm_command ();
94 tui_delete_invisible_windows ();
99 /* Function to set the layout to SRC_COMMAND, DISASSEM_COMMAND,
100 SRC_DISASSEM_COMMAND, SRC_DATA_COMMAND, or DISASSEM_DATA_COMMAND. */
102 tui_set_layout (enum tui_layout_type layout_type
)
104 gdb_assert (layout_type
!= UNDEFINED_LAYOUT
);
106 enum tui_layout_type cur_layout
= tui_current_layout ();
107 struct gdbarch
*gdbarch
;
109 struct tui_win_info
*win_with_focus
= tui_win_with_focus ();
111 extract_display_start_addr (&gdbarch
, &addr
);
113 enum tui_layout_type new_layout
= layout_type
;
115 if (new_layout
!= cur_layout
)
117 show_layout (new_layout
);
119 /* Now determine where focus should be. */
120 if (win_with_focus
!= TUI_CMD_WIN
)
125 tui_set_win_focus_to (TUI_SRC_WIN
);
127 case DISASSEM_COMMAND
:
128 /* The previous layout was not showing code.
129 This can happen if there is no source
132 1. if the source file is in another dir OR
133 2. if target was compiled without -g
134 We still want to show the assembly though! */
136 tui_get_begin_asm_address (&gdbarch
, &addr
);
137 tui_set_win_focus_to (TUI_DISASM_WIN
);
139 case SRC_DISASSEM_COMMAND
:
140 /* The previous layout was not showing code.
141 This can happen if there is no source
144 1. if the source file is in another dir OR
145 2. if target was compiled without -g
146 We still want to show the assembly though! */
148 tui_get_begin_asm_address (&gdbarch
, &addr
);
149 if (win_with_focus
== TUI_SRC_WIN
)
150 tui_set_win_focus_to (TUI_SRC_WIN
);
152 tui_set_win_focus_to (TUI_DISASM_WIN
);
154 case SRC_DATA_COMMAND
:
155 if (win_with_focus
!= TUI_DATA_WIN
)
156 tui_set_win_focus_to (TUI_SRC_WIN
);
158 tui_set_win_focus_to (TUI_DATA_WIN
);
160 case DISASSEM_DATA_COMMAND
:
161 /* The previous layout was not showing code.
162 This can happen if there is no source
165 1. if the source file is in another dir OR
166 2. if target was compiled without -g
167 We still want to show the assembly though! */
169 tui_get_begin_asm_address (&gdbarch
, &addr
);
170 if (win_with_focus
!= TUI_DATA_WIN
)
171 tui_set_win_focus_to (TUI_DISASM_WIN
);
173 tui_set_win_focus_to (TUI_DATA_WIN
);
180 * Now update the window content.
182 tui_update_source_windows_with_addr (gdbarch
, addr
);
183 if (new_layout
== SRC_DATA_COMMAND
184 || new_layout
== DISASSEM_DATA_COMMAND
)
185 TUI_DATA_WIN
->show_registers (TUI_DATA_WIN
->get_current_group ());
189 /* Add the specified window to the layout in a logical way. This
190 means setting up the most logical layout given the window to be
193 tui_add_win_to_layout (enum tui_win_type type
)
195 enum tui_layout_type cur_layout
= tui_current_layout ();
200 if (cur_layout
!= SRC_COMMAND
201 && cur_layout
!= SRC_DISASSEM_COMMAND
202 && cur_layout
!= SRC_DATA_COMMAND
)
204 if (cur_layout
== DISASSEM_DATA_COMMAND
)
205 show_layout (SRC_DATA_COMMAND
);
207 show_layout (SRC_COMMAND
);
211 if (cur_layout
!= DISASSEM_COMMAND
212 && cur_layout
!= SRC_DISASSEM_COMMAND
213 && cur_layout
!= DISASSEM_DATA_COMMAND
)
215 if (cur_layout
== SRC_DATA_COMMAND
)
216 show_layout (DISASSEM_DATA_COMMAND
);
218 show_layout (DISASSEM_COMMAND
);
222 if (cur_layout
!= SRC_DATA_COMMAND
223 && cur_layout
!= DISASSEM_DATA_COMMAND
)
225 if (cur_layout
== DISASSEM_COMMAND
)
226 show_layout (DISASSEM_DATA_COMMAND
);
228 show_layout (SRC_DATA_COMMAND
);
236 /* Complete possible layout names. TEXT is the complete text entered so
237 far, WORD is the word currently being completed. */
240 layout_completer (struct cmd_list_element
*ignore
,
241 completion_tracker
&tracker
,
242 const char *text
, const char *word
)
244 static const char *layout_names
[] =
245 { "src", "asm", "split", "regs", "next", "prev", NULL
};
247 complete_on_enum (tracker
, layout_names
, text
, word
);
250 /* Function to set the layout to SRC, ASM, SPLIT, NEXT, PREV, DATA, or
253 tui_layout_command (const char *layout_name
, int from_tty
)
255 enum tui_layout_type new_layout
= UNDEFINED_LAYOUT
;
256 enum tui_layout_type cur_layout
= tui_current_layout ();
258 if (layout_name
== NULL
|| *layout_name
== '\0')
259 error (_("Usage: layout prev | next | LAYOUT-NAME"));
261 /* First check for ambiguous input. */
262 if (strcmp (layout_name
, "s") == 0)
263 error (_("Ambiguous command input."));
265 if (subset_compare (layout_name
, "src"))
266 new_layout
= SRC_COMMAND
;
267 else if (subset_compare (layout_name
, "asm"))
268 new_layout
= DISASSEM_COMMAND
;
269 else if (subset_compare (layout_name
, "split"))
270 new_layout
= SRC_DISASSEM_COMMAND
;
271 else if (subset_compare (layout_name
, "regs"))
273 if (cur_layout
== SRC_COMMAND
274 || cur_layout
== SRC_DATA_COMMAND
)
275 new_layout
= SRC_DATA_COMMAND
;
277 new_layout
= DISASSEM_DATA_COMMAND
;
279 else if (subset_compare (layout_name
, "next"))
280 new_layout
= next_layout ();
281 else if (subset_compare (layout_name
, "prev"))
282 new_layout
= prev_layout ();
284 error (_("Unrecognized layout: %s"), layout_name
);
286 /* Make sure the curses mode is enabled. */
288 tui_set_layout (new_layout
);
293 extract_display_start_addr (struct gdbarch
**gdbarch_p
, CORE_ADDR
*addr_p
)
295 enum tui_layout_type cur_layout
= tui_current_layout ();
296 struct gdbarch
*gdbarch
= get_current_arch ();
299 struct symtab_and_line cursal
= get_current_source_symtab_and_line ();
304 case SRC_DATA_COMMAND
:
305 gdbarch
= TUI_SRC_WIN
->gdbarch
;
306 find_line_pc (cursal
.symtab
,
307 TUI_SRC_WIN
->start_line_or_addr
.u
.line_no
,
311 case DISASSEM_COMMAND
:
312 case SRC_DISASSEM_COMMAND
:
313 case DISASSEM_DATA_COMMAND
:
314 gdbarch
= TUI_DISASM_WIN
->gdbarch
;
315 addr
= TUI_DISASM_WIN
->start_line_or_addr
.u
.addr
;
322 *gdbarch_p
= gdbarch
;
327 /* Answer the previous layout to cycle to. */
328 static enum tui_layout_type
333 new_layout
= tui_current_layout ();
334 if (new_layout
== UNDEFINED_LAYOUT
)
335 new_layout
= SRC_COMMAND
;
339 if (new_layout
== UNDEFINED_LAYOUT
)
340 new_layout
= SRC_COMMAND
;
343 return (enum tui_layout_type
) new_layout
;
347 /* Answer the next layout to cycle to. */
348 static enum tui_layout_type
353 new_layout
= tui_current_layout ();
354 if (new_layout
== SRC_COMMAND
)
355 new_layout
= DISASSEM_DATA_COMMAND
;
359 if (new_layout
== UNDEFINED_LAYOUT
)
360 new_layout
= DISASSEM_DATA_COMMAND
;
363 return (enum tui_layout_type
) new_layout
;
366 /* Show the Source/Command layout. */
368 show_source_command (void)
370 show_source_or_disasm_and_command (SRC_COMMAND
);
374 /* Show the Dissassem/Command layout. */
376 show_disasm_command (void)
378 show_source_or_disasm_and_command (DISASSEM_COMMAND
);
382 /* Show the Source/Disassem/Command layout. */
384 show_source_disasm_command (void)
386 int cmd_height
, src_height
, asm_height
;
388 if (TUI_CMD_WIN
!= NULL
)
389 cmd_height
= TUI_CMD_WIN
->height
;
391 cmd_height
= tui_term_height () / 3;
393 src_height
= (tui_term_height () - cmd_height
) / 2;
394 asm_height
= tui_term_height () - (src_height
+ cmd_height
);
396 if (TUI_SRC_WIN
== NULL
)
397 tui_win_list
[SRC_WIN
] = new tui_source_window ();
398 TUI_SRC_WIN
->resize (src_height
,
403 struct tui_locator_window
*locator
= tui_locator_win_info_ptr ();
404 gdb_assert (locator
!= nullptr);
406 if (TUI_DISASM_WIN
== NULL
)
407 tui_win_list
[DISASSEM_WIN
] = new tui_disasm_window ();
408 TUI_DISASM_WIN
->resize (asm_height
,
412 locator
->resize (1, tui_term_width (),
413 0, (src_height
+ asm_height
) - 1);
415 if (TUI_CMD_WIN
== NULL
)
416 tui_win_list
[CMD_WIN
] = new tui_cmd_window ();
417 TUI_CMD_WIN
->resize (cmd_height
,
420 tui_term_height () - cmd_height
);
421 current_layout
= SRC_DISASSEM_COMMAND
;
425 /* Show the Source/Data/Command or the Dissassembly/Data/Command
428 show_data (enum tui_layout_type new_layout
)
430 int total_height
= (tui_term_height () - TUI_CMD_WIN
->height
);
431 int src_height
, data_height
;
432 enum tui_win_type win_type
;
434 struct tui_locator_window
*locator
= tui_locator_win_info_ptr ();
435 gdb_assert (locator
!= nullptr);
437 data_height
= total_height
/ 2;
438 src_height
= total_height
- data_height
;
439 if (tui_win_list
[DATA_WIN
] == nullptr)
440 tui_win_list
[DATA_WIN
] = new tui_data_window ();
441 tui_win_list
[DATA_WIN
]->resize (data_height
, tui_term_width (), 0, 0);
443 if (new_layout
== SRC_DATA_COMMAND
)
446 win_type
= DISASSEM_WIN
;
448 if (tui_win_list
[win_type
] == NULL
)
450 if (win_type
== SRC_WIN
)
451 tui_win_list
[win_type
] = new tui_source_window ();
453 tui_win_list
[win_type
] = new tui_disasm_window ();
456 tui_win_list
[win_type
]->resize (src_height
,
460 locator
->resize (1, tui_term_width (),
461 0, total_height
- 1);
462 TUI_CMD_WIN
->resize (TUI_CMD_WIN
->height
, tui_term_width (),
465 current_layout
= new_layout
;
469 tui_gen_win_info::resize (int height_
, int width_
,
470 int origin_x_
, int origin_y_
)
472 if (width
== width_
&& height
== height_
473 && origin
.x
== origin_x_
&& origin
.y
== origin_y_
474 && handle
!= nullptr)
480 viewport_height
= height
- 2;
483 origin
.x
= origin_x_
;
484 origin
.y
= origin_y_
;
486 if (handle
!= nullptr)
489 wresize (handle
.get (), height
, width
);
490 mvwin (handle
.get (), origin
.y
, origin
.x
);
491 wmove (handle
.get (), 0, 0);
493 handle
.reset (nullptr);
497 if (handle
== nullptr)
503 /* Show the Source/Command or the Disassem layout. */
505 show_source_or_disasm_and_command (enum tui_layout_type layout_type
)
507 struct tui_source_window_base
*win_info
;
508 int src_height
, cmd_height
;
509 struct tui_locator_window
*locator
= tui_locator_win_info_ptr ();
510 gdb_assert (locator
!= nullptr);
512 if (TUI_CMD_WIN
!= NULL
)
513 cmd_height
= TUI_CMD_WIN
->height
;
515 cmd_height
= tui_term_height () / 3;
516 src_height
= tui_term_height () - cmd_height
;
518 if (layout_type
== SRC_COMMAND
)
520 if (tui_win_list
[SRC_WIN
] == nullptr)
521 tui_win_list
[SRC_WIN
] = new tui_source_window ();
522 win_info
= TUI_SRC_WIN
;
526 if (tui_win_list
[DISASSEM_WIN
] == nullptr)
527 tui_win_list
[DISASSEM_WIN
] = new tui_disasm_window ();
528 win_info
= TUI_DISASM_WIN
;
531 locator
->resize (1, tui_term_width (),
533 win_info
->resize (src_height
- 1,
538 if (TUI_CMD_WIN
== NULL
)
539 tui_win_list
[CMD_WIN
] = new tui_cmd_window ();
540 TUI_CMD_WIN
->resize (cmd_height
,
544 current_layout
= layout_type
;
549 /* Function to initialize gdb commands, for tui window layout
553 _initialize_tui_layout (void)
555 struct cmd_list_element
*cmd
;
557 cmd
= add_com ("layout", class_tui
, tui_layout_command
, _("\
558 Change the layout of windows.\n\
559 Usage: layout prev | next | LAYOUT-NAME\n\
561 src : Displays source and command windows.\n\
562 asm : Displays disassembly and command windows.\n\
563 split : Displays source, disassembly and command windows.\n\
564 regs : Displays register window. If existing layout\n\
565 is source/command or assembly/command, the \n\
566 register window is displayed. If the\n\
567 source/assembly/command (split) is displayed, \n\
568 the register window is displayed with \n\
569 the window that has current logical focus."));
570 set_cmd_completer (cmd
, layout_completer
);