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 /*******************************
45 ********************************/
46 static void show_layout (enum tui_layout_type);
47 static void show_source_or_disasm_and_command (enum tui_layout_type);
48 static void show_source_command (void);
49 static void show_disasm_command (void);
50 static void show_source_disasm_command (void);
51 static void show_data (enum tui_layout_type);
52 static enum tui_layout_type next_layout (void);
53 static enum tui_layout_type prev_layout (void);
54 static void tui_layout_command (const char *, int);
55 static void extract_display_start_addr (struct gdbarch **, CORE_ADDR *);
58 static enum tui_layout_type current_layout = UNDEFINED_LAYOUT;
60 /* Accessor for the current layout. */
62 tui_current_layout (void)
64 return current_layout;
67 /***************************************
69 ***************************************/
71 /* Show the screen layout defined. */
73 show_layout (enum tui_layout_type layout)
75 enum tui_layout_type cur_layout = tui_current_layout ();
77 if (layout != cur_layout)
79 /* First make the current layout be invisible. */
80 tui_make_all_invisible ();
81 tui_locator_win_info_ptr ()->make_visible (false);
84 case SRC_DATA_COMMAND:
85 case DISASSEM_DATA_COMMAND:
89 /* Now show the new layout. */
91 show_source_command ();
93 case DISASSEM_COMMAND:
94 show_disasm_command ();
96 case SRC_DISASSEM_COMMAND:
97 show_source_disasm_command ();
103 tui_delete_invisible_windows ();
108 /* Function to set the layout to SRC_COMMAND, DISASSEM_COMMAND,
109 SRC_DISASSEM_COMMAND, SRC_DATA_COMMAND, or DISASSEM_DATA_COMMAND. */
111 tui_set_layout (enum tui_layout_type layout_type)
113 gdb_assert (layout_type != UNDEFINED_LAYOUT);
115 enum tui_layout_type cur_layout = tui_current_layout ();
116 struct gdbarch *gdbarch;
118 struct tui_win_info *win_with_focus = tui_win_with_focus ();
120 extract_display_start_addr (&gdbarch, &addr);
122 enum tui_layout_type new_layout = layout_type;
124 if (new_layout != cur_layout)
126 show_layout (new_layout);
128 /* Now determine where focus should be. */
129 if (win_with_focus != TUI_CMD_WIN)
134 tui_set_win_focus_to (TUI_SRC_WIN);
136 case DISASSEM_COMMAND:
137 /* The previous layout was not showing code.
138 This can happen if there is no source
141 1. if the source file is in another dir OR
142 2. if target was compiled without -g
143 We still want to show the assembly though! */
145 tui_get_begin_asm_address (&gdbarch, &addr);
146 tui_set_win_focus_to (TUI_DISASM_WIN);
148 case SRC_DISASSEM_COMMAND:
149 /* The previous layout was not showing code.
150 This can happen if there is no source
153 1. if the source file is in another dir OR
154 2. if target was compiled without -g
155 We still want to show the assembly though! */
157 tui_get_begin_asm_address (&gdbarch, &addr);
158 if (win_with_focus == TUI_SRC_WIN)
159 tui_set_win_focus_to (TUI_SRC_WIN);
161 tui_set_win_focus_to (TUI_DISASM_WIN);
163 case SRC_DATA_COMMAND:
164 if (win_with_focus != TUI_DATA_WIN)
165 tui_set_win_focus_to (TUI_SRC_WIN);
167 tui_set_win_focus_to (TUI_DATA_WIN);
169 case DISASSEM_DATA_COMMAND:
170 /* The previous layout was not showing code.
171 This can happen if there is no source
174 1. if the source file is in another dir OR
175 2. if target was compiled without -g
176 We still want to show the assembly though! */
178 tui_get_begin_asm_address (&gdbarch, &addr);
179 if (win_with_focus != TUI_DATA_WIN)
180 tui_set_win_focus_to (TUI_DISASM_WIN);
182 tui_set_win_focus_to (TUI_DATA_WIN);
189 * Now update the window content.
191 tui_update_source_windows_with_addr (gdbarch, addr);
192 if (new_layout == SRC_DATA_COMMAND
193 || new_layout == DISASSEM_DATA_COMMAND)
194 tui_show_registers (TUI_DATA_WIN->current_group);
198 /* Add the specified window to the layout in a logical way. This
199 means setting up the most logical layout given the window to be
202 tui_add_win_to_layout (enum tui_win_type type)
204 enum tui_layout_type cur_layout = tui_current_layout ();
209 if (cur_layout != SRC_COMMAND
210 && cur_layout != SRC_DISASSEM_COMMAND
211 && cur_layout != SRC_DATA_COMMAND)
213 tui_clear_source_windows_detail ();
214 if (cur_layout == DISASSEM_DATA_COMMAND)
215 show_layout (SRC_DATA_COMMAND);
217 show_layout (SRC_COMMAND);
221 if (cur_layout != DISASSEM_COMMAND
222 && cur_layout != SRC_DISASSEM_COMMAND
223 && cur_layout != DISASSEM_DATA_COMMAND)
225 tui_clear_source_windows_detail ();
226 if (cur_layout == SRC_DATA_COMMAND)
227 show_layout (DISASSEM_DATA_COMMAND);
229 show_layout (DISASSEM_COMMAND);
233 if (cur_layout != SRC_DATA_COMMAND
234 && cur_layout != DISASSEM_DATA_COMMAND)
236 if (cur_layout == DISASSEM_COMMAND)
237 show_layout (DISASSEM_DATA_COMMAND);
239 show_layout (SRC_DATA_COMMAND);
248 /* Answer the height of a window. If it hasn't been created yet,
249 answer what the height of a window would be based upon its type and
252 tui_default_win_height (enum tui_win_type type,
253 enum tui_layout_type layout)
257 if (tui_win_list[type] != NULL)
258 h = tui_win_list[type]->height;
264 case DISASSEM_COMMAND:
265 if (TUI_CMD_WIN == NULL)
266 h = tui_term_height () / 2;
268 h = tui_term_height () - TUI_CMD_WIN->height;
270 case SRC_DISASSEM_COMMAND:
271 case SRC_DATA_COMMAND:
272 case DISASSEM_DATA_COMMAND:
273 if (TUI_CMD_WIN == NULL)
274 h = tui_term_height () / 3;
276 h = (tui_term_height () - TUI_CMD_WIN->height) / 2;
288 /* Answer the height of a window. If it hasn't been created yet,
289 answer what the height of a window would be based upon its type and
292 tui_default_win_viewport_height (enum tui_win_type type,
293 enum tui_layout_type layout)
297 h = tui_default_win_height (type, layout);
307 /* Complete possible layout names. TEXT is the complete text entered so
308 far, WORD is the word currently being completed. */
311 layout_completer (struct cmd_list_element *ignore,
312 completion_tracker &tracker,
313 const char *text, const char *word)
315 static const char *layout_names [] =
316 { "src", "asm", "split", "regs", "next", "prev", NULL };
318 complete_on_enum (tracker, layout_names, text, word);
321 /* Function to initialize gdb commands, for tui window layout
325 _initialize_tui_layout (void)
327 struct cmd_list_element *cmd;
329 cmd = add_com ("layout", class_tui, tui_layout_command, _("\
330 Change the layout of windows.\n\
331 Usage: layout prev | next | LAYOUT-NAME\n\
333 src : Displays source and command windows.\n\
334 asm : Displays disassembly and command windows.\n\
335 split : Displays source, disassembly and command windows.\n\
336 regs : Displays register window. If existing layout\n\
337 is source/command or assembly/command, the \n\
338 register window is displayed. If the\n\
339 source/assembly/command (split) is displayed, \n\
340 the register window is displayed with \n\
341 the window that has current logical focus."));
342 set_cmd_completer (cmd, layout_completer);
346 /*************************
347 ** STATIC LOCAL FUNCTIONS
348 **************************/
351 /* Function to set the layout to SRC, ASM, SPLIT, NEXT, PREV, DATA, or
354 tui_layout_command (const char *layout_name, int from_tty)
357 enum tui_layout_type new_layout = UNDEFINED_LAYOUT;
358 enum tui_layout_type cur_layout = tui_current_layout ();
360 if (layout_name == NULL)
361 error (_("Usage: layout prev | next | LAYOUT-NAME"));
363 std::string copy = layout_name;
364 for (i = 0; i < copy.size (); i++)
365 copy[i] = toupper (copy[i]);
366 const char *buf_ptr = copy.c_str ();
368 /* First check for ambiguous input. */
369 if (strlen (buf_ptr) <= 1 && *buf_ptr == 'S')
370 error (_("Ambiguous command input."));
372 if (subset_compare (buf_ptr, "SRC"))
373 new_layout = SRC_COMMAND;
374 else if (subset_compare (buf_ptr, "ASM"))
375 new_layout = DISASSEM_COMMAND;
376 else if (subset_compare (buf_ptr, "SPLIT"))
377 new_layout = SRC_DISASSEM_COMMAND;
378 else if (subset_compare (buf_ptr, "REGS"))
380 if (cur_layout == SRC_COMMAND
381 || cur_layout == SRC_DATA_COMMAND)
382 new_layout = SRC_DATA_COMMAND;
384 new_layout = DISASSEM_DATA_COMMAND;
386 else if (subset_compare (buf_ptr, "NEXT"))
387 new_layout = next_layout ();
388 else if (subset_compare (buf_ptr, "PREV"))
389 new_layout = prev_layout ();
391 error (_("Unrecognized layout: %s"), layout_name);
393 /* Make sure the curses mode is enabled. */
395 tui_set_layout (new_layout);
400 extract_display_start_addr (struct gdbarch **gdbarch_p, CORE_ADDR *addr_p)
402 enum tui_layout_type cur_layout = tui_current_layout ();
403 struct gdbarch *gdbarch = get_current_arch ();
406 struct symtab_and_line cursal = get_current_source_symtab_and_line ();
411 case SRC_DATA_COMMAND:
412 gdbarch = TUI_SRC_WIN->gdbarch;
413 find_line_pc (cursal.symtab,
414 TUI_SRC_WIN->start_line_or_addr.u.line_no,
418 case DISASSEM_COMMAND:
419 case SRC_DISASSEM_COMMAND:
420 case DISASSEM_DATA_COMMAND:
421 gdbarch = TUI_DISASM_WIN->gdbarch;
422 addr = TUI_DISASM_WIN->start_line_or_addr.u.addr;
429 *gdbarch_p = gdbarch;
434 /* Answer the previous layout to cycle to. */
435 static enum tui_layout_type
440 new_layout = tui_current_layout ();
441 if (new_layout == UNDEFINED_LAYOUT)
442 new_layout = SRC_COMMAND;
446 if (new_layout == UNDEFINED_LAYOUT)
447 new_layout = SRC_COMMAND;
450 return (enum tui_layout_type) new_layout;
454 /* Answer the next layout to cycle to. */
455 static enum tui_layout_type
460 new_layout = tui_current_layout ();
461 if (new_layout == SRC_COMMAND)
462 new_layout = DISASSEM_DATA_COMMAND;
466 if (new_layout == UNDEFINED_LAYOUT)
467 new_layout = DISASSEM_DATA_COMMAND;
470 return (enum tui_layout_type) new_layout;
473 /* Show the Source/Command layout. */
475 show_source_command (void)
477 show_source_or_disasm_and_command (SRC_COMMAND);
481 /* Show the Dissassem/Command layout. */
483 show_disasm_command (void)
485 show_source_or_disasm_and_command (DISASSEM_COMMAND);
489 /* Show the Source/Disassem/Command layout. */
491 show_source_disasm_command (void)
493 int cmd_height, src_height, asm_height;
495 if (TUI_CMD_WIN != NULL)
496 cmd_height = TUI_CMD_WIN->height;
498 cmd_height = tui_term_height () / 3;
500 src_height = (tui_term_height () - cmd_height) / 2;
501 asm_height = tui_term_height () - (src_height + cmd_height);
503 if (TUI_SRC_WIN == NULL)
504 tui_win_list[SRC_WIN] = new tui_source_window ();
505 TUI_SRC_WIN->resize (src_height,
509 TUI_SRC_WIN->make_visible (true);
510 TUI_SRC_WIN->m_has_locator = false;
512 struct tui_locator_window *locator = tui_locator_win_info_ptr ();
513 gdb_assert (locator != nullptr);
515 TUI_SRC_WIN->show_source_content ();
516 if (TUI_DISASM_WIN == NULL)
517 tui_win_list[DISASSEM_WIN] = new tui_disasm_window ();
518 TUI_DISASM_WIN->resize (asm_height,
522 TUI_DISASM_WIN->make_visible (true);
523 locator->resize (2 /* 1 */ ,
526 (src_height + asm_height) - 1);
527 TUI_SRC_WIN->m_has_locator = false;
528 TUI_DISASM_WIN->m_has_locator = true;
529 locator->make_visible (true);
530 tui_show_locator_content ();
531 TUI_DISASM_WIN->show_source_content ();
533 if (TUI_CMD_WIN == NULL)
534 tui_win_list[CMD_WIN] = new tui_cmd_window ();
535 TUI_CMD_WIN->resize (cmd_height,
538 tui_term_height () - cmd_height);
539 TUI_CMD_WIN->make_visible (true);
540 current_layout = SRC_DISASSEM_COMMAND;
544 /* Show the Source/Data/Command or the Dissassembly/Data/Command
547 show_data (enum tui_layout_type new_layout)
549 int total_height = (tui_term_height () - TUI_CMD_WIN->height);
550 int src_height, data_height;
551 enum tui_win_type win_type;
553 struct tui_locator_window *locator = tui_locator_win_info_ptr ();
554 gdb_assert (locator != nullptr);
556 data_height = total_height / 2;
557 src_height = total_height - data_height;
558 if (tui_win_list[DATA_WIN] == nullptr)
559 tui_win_list[DATA_WIN] = new tui_data_window ();
560 tui_win_list[DATA_WIN]->resize (data_height, tui_term_width (), 0, 0);
561 tui_win_list[DATA_WIN]->make_visible (true);
563 if (new_layout == SRC_DATA_COMMAND)
566 win_type = DISASSEM_WIN;
568 if (tui_win_list[win_type] == NULL)
570 if (win_type == SRC_WIN)
571 tui_win_list[win_type] = new tui_source_window ();
573 tui_win_list[win_type] = new tui_disasm_window ();
576 tui_source_window_base *base
577 = (tui_source_window_base *) tui_win_list[win_type];
578 tui_win_list[win_type]->resize (src_height,
582 locator->resize (2 /* 1 */ ,
586 base->make_visible (true);
587 base->m_has_locator = true;
588 locator->make_visible (true);
589 tui_show_locator_content ();
590 TUI_CMD_WIN->make_visible (true);
591 current_layout = new_layout;
595 tui_gen_win_info::resize (int height_, int width_,
596 int origin_x_, int origin_y_)
604 viewport_height = h - 1;
610 origin.x = origin_x_;
611 origin.y = origin_y_;
614 /* Show the Source/Command or the Disassem layout. */
616 show_source_or_disasm_and_command (enum tui_layout_type layout_type)
618 struct tui_source_window_base *win_info;
619 int src_height, cmd_height;
620 struct tui_locator_window *locator = tui_locator_win_info_ptr ();
621 gdb_assert (locator != nullptr);
623 if (TUI_CMD_WIN != NULL)
624 cmd_height = TUI_CMD_WIN->height;
626 cmd_height = tui_term_height () / 3;
627 src_height = tui_term_height () - cmd_height;
629 if (layout_type == SRC_COMMAND)
631 if (tui_win_list[SRC_WIN] == nullptr)
632 tui_win_list[SRC_WIN] = new tui_source_window ();
633 win_info = TUI_SRC_WIN;
637 if (tui_win_list[DISASSEM_WIN] == nullptr)
638 tui_win_list[DISASSEM_WIN] = new tui_disasm_window ();
639 win_info = TUI_DISASM_WIN;
642 locator->resize (2 /* 1 */ ,
646 win_info->resize (src_height - 1,
650 win_info->make_visible (true);
653 win_info->m_has_locator = true;
654 locator->make_visible (true);
655 tui_show_locator_content ();
656 win_info->show_source_content ();
658 if (TUI_CMD_WIN == NULL)
659 tui_win_list[CMD_WIN] = new tui_cmd_window ();
660 TUI_CMD_WIN->resize (cmd_height,
664 TUI_CMD_WIN->make_visible (true);
665 current_layout = layout_type;