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 current_layout = layout;
95 tui_delete_invisible_windows ();
100 /* Function to set the layout to SRC_COMMAND, DISASSEM_COMMAND,
101 SRC_DISASSEM_COMMAND, SRC_DATA_COMMAND, or DISASSEM_DATA_COMMAND. */
103 tui_set_layout (enum tui_layout_type layout_type)
105 gdb_assert (layout_type != UNDEFINED_LAYOUT);
107 enum tui_layout_type cur_layout = tui_current_layout ();
108 struct gdbarch *gdbarch;
110 struct tui_win_info *win_with_focus = tui_win_with_focus ();
112 extract_display_start_addr (&gdbarch, &addr);
114 enum tui_layout_type new_layout = layout_type;
116 if (new_layout != cur_layout)
118 show_layout (new_layout);
120 /* Now determine where focus should be. */
121 if (win_with_focus != TUI_CMD_WIN)
126 tui_set_win_focus_to (TUI_SRC_WIN);
128 case DISASSEM_COMMAND:
129 /* The previous layout was not showing code.
130 This can happen if there is no source
133 1. if the source file is in another dir OR
134 2. if target was compiled without -g
135 We still want to show the assembly though! */
137 tui_get_begin_asm_address (&gdbarch, &addr);
138 tui_set_win_focus_to (TUI_DISASM_WIN);
140 case SRC_DISASSEM_COMMAND:
141 /* The previous layout was not showing code.
142 This can happen if there is no source
145 1. if the source file is in another dir OR
146 2. if target was compiled without -g
147 We still want to show the assembly though! */
149 tui_get_begin_asm_address (&gdbarch, &addr);
150 if (win_with_focus == TUI_SRC_WIN)
151 tui_set_win_focus_to (TUI_SRC_WIN);
153 tui_set_win_focus_to (TUI_DISASM_WIN);
155 case SRC_DATA_COMMAND:
156 if (win_with_focus != TUI_DATA_WIN)
157 tui_set_win_focus_to (TUI_SRC_WIN);
159 tui_set_win_focus_to (TUI_DATA_WIN);
161 case DISASSEM_DATA_COMMAND:
162 /* The previous layout was not showing code.
163 This can happen if there is no source
166 1. if the source file is in another dir OR
167 2. if target was compiled without -g
168 We still want to show the assembly though! */
170 tui_get_begin_asm_address (&gdbarch, &addr);
171 if (win_with_focus != TUI_DATA_WIN)
172 tui_set_win_focus_to (TUI_DISASM_WIN);
174 tui_set_win_focus_to (TUI_DATA_WIN);
181 * Now update the window content.
183 tui_update_source_windows_with_addr (gdbarch, addr);
184 if (new_layout == SRC_DATA_COMMAND
185 || new_layout == DISASSEM_DATA_COMMAND)
186 TUI_DATA_WIN->show_registers (TUI_DATA_WIN->get_current_group ());
190 /* Add the specified window to the layout in a logical way. This
191 means setting up the most logical layout given the window to be
194 tui_add_win_to_layout (enum tui_win_type type)
196 enum tui_layout_type cur_layout = tui_current_layout ();
201 if (cur_layout != SRC_COMMAND
202 && cur_layout != SRC_DISASSEM_COMMAND
203 && cur_layout != SRC_DATA_COMMAND)
205 if (cur_layout == DISASSEM_DATA_COMMAND)
206 show_layout (SRC_DATA_COMMAND);
208 show_layout (SRC_COMMAND);
212 if (cur_layout != DISASSEM_COMMAND
213 && cur_layout != SRC_DISASSEM_COMMAND
214 && cur_layout != DISASSEM_DATA_COMMAND)
216 if (cur_layout == SRC_DATA_COMMAND)
217 show_layout (DISASSEM_DATA_COMMAND);
219 show_layout (DISASSEM_COMMAND);
223 if (cur_layout != SRC_DATA_COMMAND
224 && cur_layout != DISASSEM_DATA_COMMAND)
226 if (cur_layout == DISASSEM_COMMAND)
227 show_layout (DISASSEM_DATA_COMMAND);
229 show_layout (SRC_DATA_COMMAND);
237 /* Complete possible layout names. TEXT is the complete text entered so
238 far, WORD is the word currently being completed. */
241 layout_completer (struct cmd_list_element *ignore,
242 completion_tracker &tracker,
243 const char *text, const char *word)
245 static const char *layout_names [] =
246 { "src", "asm", "split", "regs", "next", "prev", NULL };
248 complete_on_enum (tracker, layout_names, text, word);
251 /* Function to set the layout to SRC, ASM, SPLIT, NEXT, PREV, DATA, or
254 tui_layout_command (const char *layout_name, int from_tty)
256 enum tui_layout_type new_layout = UNDEFINED_LAYOUT;
257 enum tui_layout_type cur_layout = tui_current_layout ();
259 if (layout_name == NULL || *layout_name == '\0')
260 error (_("Usage: layout prev | next | LAYOUT-NAME"));
262 /* First check for ambiguous input. */
263 if (strcmp (layout_name, "s") == 0)
264 error (_("Ambiguous command input."));
266 if (subset_compare (layout_name, "src"))
267 new_layout = SRC_COMMAND;
268 else if (subset_compare (layout_name, "asm"))
269 new_layout = DISASSEM_COMMAND;
270 else if (subset_compare (layout_name, "split"))
271 new_layout = SRC_DISASSEM_COMMAND;
272 else if (subset_compare (layout_name, "regs"))
274 if (cur_layout == SRC_COMMAND
275 || cur_layout == SRC_DATA_COMMAND)
276 new_layout = SRC_DATA_COMMAND;
278 new_layout = DISASSEM_DATA_COMMAND;
280 else if (subset_compare (layout_name, "next"))
281 new_layout = next_layout ();
282 else if (subset_compare (layout_name, "prev"))
283 new_layout = prev_layout ();
285 error (_("Unrecognized layout: %s"), layout_name);
287 /* Make sure the curses mode is enabled. */
289 tui_set_layout (new_layout);
294 extract_display_start_addr (struct gdbarch **gdbarch_p, CORE_ADDR *addr_p)
296 enum tui_layout_type cur_layout = tui_current_layout ();
297 struct gdbarch *gdbarch = get_current_arch ();
300 struct symtab_and_line cursal = get_current_source_symtab_and_line ();
305 case SRC_DATA_COMMAND:
306 gdbarch = TUI_SRC_WIN->gdbarch;
307 find_line_pc (cursal.symtab,
308 TUI_SRC_WIN->start_line_or_addr.u.line_no,
312 case DISASSEM_COMMAND:
313 case SRC_DISASSEM_COMMAND:
314 case DISASSEM_DATA_COMMAND:
315 gdbarch = TUI_DISASM_WIN->gdbarch;
316 addr = TUI_DISASM_WIN->start_line_or_addr.u.addr;
323 *gdbarch_p = gdbarch;
328 /* Answer the previous layout to cycle to. */
329 static enum tui_layout_type
334 new_layout = tui_current_layout ();
335 if (new_layout == UNDEFINED_LAYOUT)
336 new_layout = SRC_COMMAND;
340 if (new_layout == UNDEFINED_LAYOUT)
341 new_layout = SRC_COMMAND;
344 return (enum tui_layout_type) new_layout;
348 /* Answer the next layout to cycle to. */
349 static enum tui_layout_type
354 new_layout = tui_current_layout ();
355 if (new_layout == SRC_COMMAND)
356 new_layout = DISASSEM_DATA_COMMAND;
360 if (new_layout == UNDEFINED_LAYOUT)
361 new_layout = DISASSEM_DATA_COMMAND;
364 return (enum tui_layout_type) new_layout;
367 /* Show the Source/Command layout. */
369 show_source_command (void)
371 show_source_or_disasm_and_command (SRC_COMMAND);
375 /* Show the Dissassem/Command layout. */
377 show_disasm_command (void)
379 show_source_or_disasm_and_command (DISASSEM_COMMAND);
383 /* Show the Source/Disassem/Command layout. */
385 show_source_disasm_command (void)
387 int cmd_height, src_height, asm_height;
389 if (TUI_CMD_WIN != NULL)
390 cmd_height = TUI_CMD_WIN->height;
392 cmd_height = tui_term_height () / 3;
394 src_height = (tui_term_height () - cmd_height) / 2;
395 asm_height = tui_term_height () - (src_height + cmd_height);
397 if (TUI_SRC_WIN == NULL)
398 tui_win_list[SRC_WIN] = new tui_source_window ();
399 TUI_SRC_WIN->resize (src_height,
404 struct tui_locator_window *locator = tui_locator_win_info_ptr ();
405 gdb_assert (locator != nullptr);
407 if (TUI_DISASM_WIN == NULL)
408 tui_win_list[DISASSEM_WIN] = new tui_disasm_window ();
409 TUI_DISASM_WIN->resize (asm_height,
413 locator->resize (1, tui_term_width (),
414 0, (src_height + asm_height) - 1);
416 if (TUI_CMD_WIN == NULL)
417 tui_win_list[CMD_WIN] = new tui_cmd_window ();
418 TUI_CMD_WIN->resize (cmd_height,
421 tui_term_height () - cmd_height);
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 (),
467 tui_gen_win_info::resize (int height_, int width_,
468 int origin_x_, int origin_y_)
470 if (width == width_ && height == height_
471 && x == origin_x_ && y == origin_y_
472 && handle != nullptr)
478 viewport_height = height - 2;
484 if (handle != nullptr)
487 wresize (handle.get (), height, width);
488 mvwin (handle.get (), y, x);
489 wmove (handle.get (), 0, 0);
491 handle.reset (nullptr);
495 if (handle == nullptr)
501 /* Show the Source/Command or the Disassem layout. */
503 show_source_or_disasm_and_command (enum tui_layout_type layout_type)
505 struct tui_source_window_base *win_info;
506 int src_height, cmd_height;
507 struct tui_locator_window *locator = tui_locator_win_info_ptr ();
508 gdb_assert (locator != nullptr);
510 if (TUI_CMD_WIN != NULL)
511 cmd_height = TUI_CMD_WIN->height;
513 cmd_height = tui_term_height () / 3;
514 src_height = tui_term_height () - cmd_height;
516 if (layout_type == SRC_COMMAND)
518 if (tui_win_list[SRC_WIN] == nullptr)
519 tui_win_list[SRC_WIN] = new tui_source_window ();
520 win_info = TUI_SRC_WIN;
524 if (tui_win_list[DISASSEM_WIN] == nullptr)
525 tui_win_list[DISASSEM_WIN] = new tui_disasm_window ();
526 win_info = TUI_DISASM_WIN;
529 locator->resize (1, tui_term_width (),
531 win_info->resize (src_height - 1,
536 if (TUI_CMD_WIN == NULL)
537 tui_win_list[CMD_WIN] = new tui_cmd_window ();
538 TUI_CMD_WIN->resize (cmd_height,
546 /* Function to initialize gdb commands, for tui window layout
550 _initialize_tui_layout (void)
552 struct cmd_list_element *cmd;
554 cmd = add_com ("layout", class_tui, tui_layout_command, _("\
555 Change the layout of windows.\n\
556 Usage: layout prev | next | LAYOUT-NAME\n\
558 src : Displays source and command windows.\n\
559 asm : Displays disassembly and command windows.\n\
560 split : Displays source, disassembly and command windows.\n\
561 regs : Displays register window. If existing layout\n\
562 is source/command or assembly/command, the \n\
563 register window is displayed. If the\n\
564 source/assembly/command (split) is displayed, \n\
565 the register window is displayed with \n\
566 the window that has current logical focus."));
567 set_cmd_completer (cmd, layout_completer);