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 tui_make_all_invisible ();
82 case SRC_DATA_COMMAND:
83 case DISASSEM_DATA_COMMAND:
87 /* Now show the new layout. */
89 show_source_command ();
91 case DISASSEM_COMMAND:
92 show_disasm_command ();
94 case SRC_DISASSEM_COMMAND:
95 show_source_disasm_command ();
101 tui_delete_invisible_windows ();
106 /* Function to set the layout to SRC_COMMAND, DISASSEM_COMMAND,
107 SRC_DISASSEM_COMMAND, SRC_DATA_COMMAND, or DISASSEM_DATA_COMMAND. */
109 tui_set_layout (enum tui_layout_type layout_type)
111 gdb_assert (layout_type != UNDEFINED_LAYOUT);
113 enum tui_layout_type cur_layout = tui_current_layout ();
114 struct gdbarch *gdbarch;
116 struct tui_win_info *win_with_focus = tui_win_with_focus ();
118 extract_display_start_addr (&gdbarch, &addr);
120 enum tui_layout_type new_layout = layout_type;
122 if (new_layout != cur_layout)
124 show_layout (new_layout);
126 /* Now determine where focus should be. */
127 if (win_with_focus != TUI_CMD_WIN)
132 tui_set_win_focus_to (TUI_SRC_WIN);
134 case DISASSEM_COMMAND:
135 /* The previous layout was not showing code.
136 This can happen if there is no source
139 1. if the source file is in another dir OR
140 2. if target was compiled without -g
141 We still want to show the assembly though! */
143 tui_get_begin_asm_address (&gdbarch, &addr);
144 tui_set_win_focus_to (TUI_DISASM_WIN);
146 case SRC_DISASSEM_COMMAND:
147 /* The previous layout was not showing code.
148 This can happen if there is no source
151 1. if the source file is in another dir OR
152 2. if target was compiled without -g
153 We still want to show the assembly though! */
155 tui_get_begin_asm_address (&gdbarch, &addr);
156 if (win_with_focus == TUI_SRC_WIN)
157 tui_set_win_focus_to (TUI_SRC_WIN);
159 tui_set_win_focus_to (TUI_DISASM_WIN);
161 case SRC_DATA_COMMAND:
162 if (win_with_focus != TUI_DATA_WIN)
163 tui_set_win_focus_to (TUI_SRC_WIN);
165 tui_set_win_focus_to (TUI_DATA_WIN);
167 case DISASSEM_DATA_COMMAND:
168 /* The previous layout was not showing code.
169 This can happen if there is no source
172 1. if the source file is in another dir OR
173 2. if target was compiled without -g
174 We still want to show the assembly though! */
176 tui_get_begin_asm_address (&gdbarch, &addr);
177 if (win_with_focus != TUI_DATA_WIN)
178 tui_set_win_focus_to (TUI_DISASM_WIN);
180 tui_set_win_focus_to (TUI_DATA_WIN);
187 * Now update the window content.
189 tui_update_source_windows_with_addr (gdbarch, addr);
190 if (new_layout == SRC_DATA_COMMAND
191 || new_layout == DISASSEM_DATA_COMMAND)
192 tui_show_registers (TUI_DATA_WIN->current_group);
196 /* Add the specified window to the layout in a logical way. This
197 means setting up the most logical layout given the window to be
200 tui_add_win_to_layout (enum tui_win_type type)
202 enum tui_layout_type cur_layout = tui_current_layout ();
207 if (cur_layout != SRC_COMMAND
208 && cur_layout != SRC_DISASSEM_COMMAND
209 && cur_layout != SRC_DATA_COMMAND)
211 tui_clear_source_windows_detail ();
212 if (cur_layout == DISASSEM_DATA_COMMAND)
213 show_layout (SRC_DATA_COMMAND);
215 show_layout (SRC_COMMAND);
219 if (cur_layout != DISASSEM_COMMAND
220 && cur_layout != SRC_DISASSEM_COMMAND
221 && cur_layout != DISASSEM_DATA_COMMAND)
223 tui_clear_source_windows_detail ();
224 if (cur_layout == SRC_DATA_COMMAND)
225 show_layout (DISASSEM_DATA_COMMAND);
227 show_layout (DISASSEM_COMMAND);
231 if (cur_layout != SRC_DATA_COMMAND
232 && cur_layout != DISASSEM_DATA_COMMAND)
234 if (cur_layout == DISASSEM_COMMAND)
235 show_layout (DISASSEM_DATA_COMMAND);
237 show_layout (SRC_DATA_COMMAND);
246 /* Answer the height of a window. If it hasn't been created yet,
247 answer what the height of a window would be based upon its type and
250 tui_default_win_height (enum tui_win_type type,
251 enum tui_layout_type layout)
255 if (tui_win_list[type] != NULL)
256 h = tui_win_list[type]->height;
262 case DISASSEM_COMMAND:
263 if (TUI_CMD_WIN == NULL)
264 h = tui_term_height () / 2;
266 h = tui_term_height () - TUI_CMD_WIN->height;
268 case SRC_DISASSEM_COMMAND:
269 case SRC_DATA_COMMAND:
270 case DISASSEM_DATA_COMMAND:
271 if (TUI_CMD_WIN == NULL)
272 h = tui_term_height () / 3;
274 h = (tui_term_height () - TUI_CMD_WIN->height) / 2;
286 /* Answer the height of a window. If it hasn't been created yet,
287 answer what the height of a window would be based upon its type and
290 tui_default_win_viewport_height (enum tui_win_type type,
291 enum tui_layout_type layout)
295 h = tui_default_win_height (type, layout);
305 /* Complete possible layout names. TEXT is the complete text entered so
306 far, WORD is the word currently being completed. */
309 layout_completer (struct cmd_list_element *ignore,
310 completion_tracker &tracker,
311 const char *text, const char *word)
313 static const char *layout_names [] =
314 { "src", "asm", "split", "regs", "next", "prev", NULL };
316 complete_on_enum (tracker, layout_names, text, word);
319 /* Function to initialize gdb commands, for tui window layout
323 _initialize_tui_layout (void)
325 struct cmd_list_element *cmd;
327 cmd = add_com ("layout", class_tui, tui_layout_command, _("\
328 Change the layout of windows.\n\
329 Usage: layout prev | next | LAYOUT-NAME\n\
331 src : Displays source and command windows.\n\
332 asm : Displays disassembly and command windows.\n\
333 split : Displays source, disassembly and command windows.\n\
334 regs : Displays register window. If existing layout\n\
335 is source/command or assembly/command, the \n\
336 register window is displayed. If the\n\
337 source/assembly/command (split) is displayed, \n\
338 the register window is displayed with \n\
339 the window that has current logical focus."));
340 set_cmd_completer (cmd, layout_completer);
344 /*************************
345 ** STATIC LOCAL FUNCTIONS
346 **************************/
349 /* Function to set the layout to SRC, ASM, SPLIT, NEXT, PREV, DATA, or
352 tui_layout_command (const char *layout_name, int from_tty)
355 enum tui_layout_type new_layout = UNDEFINED_LAYOUT;
356 enum tui_layout_type cur_layout = tui_current_layout ();
358 if (layout_name == NULL)
359 error (_("Usage: layout prev | next | LAYOUT-NAME"));
361 std::string copy = layout_name;
362 for (i = 0; i < copy.size (); i++)
363 copy[i] = toupper (copy[i]);
364 const char *buf_ptr = copy.c_str ();
366 /* First check for ambiguous input. */
367 if (strlen (buf_ptr) <= 1 && *buf_ptr == 'S')
368 error (_("Ambiguous command input."));
370 if (subset_compare (buf_ptr, "SRC"))
371 new_layout = SRC_COMMAND;
372 else if (subset_compare (buf_ptr, "ASM"))
373 new_layout = DISASSEM_COMMAND;
374 else if (subset_compare (buf_ptr, "SPLIT"))
375 new_layout = SRC_DISASSEM_COMMAND;
376 else if (subset_compare (buf_ptr, "REGS"))
378 if (cur_layout == SRC_COMMAND
379 || cur_layout == SRC_DATA_COMMAND)
380 new_layout = SRC_DATA_COMMAND;
382 new_layout = DISASSEM_DATA_COMMAND;
384 else if (subset_compare (buf_ptr, "NEXT"))
385 new_layout = next_layout ();
386 else if (subset_compare (buf_ptr, "PREV"))
387 new_layout = prev_layout ();
389 error (_("Unrecognized layout: %s"), layout_name);
391 /* Make sure the curses mode is enabled. */
393 tui_set_layout (new_layout);
398 extract_display_start_addr (struct gdbarch **gdbarch_p, CORE_ADDR *addr_p)
400 enum tui_layout_type cur_layout = tui_current_layout ();
401 struct gdbarch *gdbarch = get_current_arch ();
404 struct symtab_and_line cursal = get_current_source_symtab_and_line ();
409 case SRC_DATA_COMMAND:
410 gdbarch = TUI_SRC_WIN->gdbarch;
411 find_line_pc (cursal.symtab,
412 TUI_SRC_WIN->start_line_or_addr.u.line_no,
416 case DISASSEM_COMMAND:
417 case SRC_DISASSEM_COMMAND:
418 case DISASSEM_DATA_COMMAND:
419 gdbarch = TUI_DISASM_WIN->gdbarch;
420 addr = TUI_DISASM_WIN->start_line_or_addr.u.addr;
427 *gdbarch_p = gdbarch;
432 /* Answer the previous layout to cycle to. */
433 static enum tui_layout_type
438 new_layout = tui_current_layout ();
439 if (new_layout == UNDEFINED_LAYOUT)
440 new_layout = SRC_COMMAND;
444 if (new_layout == UNDEFINED_LAYOUT)
445 new_layout = SRC_COMMAND;
448 return (enum tui_layout_type) new_layout;
452 /* Answer the next layout to cycle to. */
453 static enum tui_layout_type
458 new_layout = tui_current_layout ();
459 if (new_layout == SRC_COMMAND)
460 new_layout = DISASSEM_DATA_COMMAND;
464 if (new_layout == UNDEFINED_LAYOUT)
465 new_layout = DISASSEM_DATA_COMMAND;
468 return (enum tui_layout_type) new_layout;
471 /* Show the Source/Command layout. */
473 show_source_command (void)
475 show_source_or_disasm_and_command (SRC_COMMAND);
479 /* Show the Dissassem/Command layout. */
481 show_disasm_command (void)
483 show_source_or_disasm_and_command (DISASSEM_COMMAND);
487 /* Show the Source/Disassem/Command layout. */
489 show_source_disasm_command (void)
491 int cmd_height, src_height, asm_height;
493 if (TUI_CMD_WIN != NULL)
494 cmd_height = TUI_CMD_WIN->height;
496 cmd_height = tui_term_height () / 3;
498 src_height = (tui_term_height () - cmd_height) / 2;
499 asm_height = tui_term_height () - (src_height + cmd_height);
501 if (TUI_SRC_WIN == NULL)
502 tui_win_list[SRC_WIN] = new tui_source_window ();
503 TUI_SRC_WIN->resize (src_height,
507 TUI_SRC_WIN->m_has_locator = false;
509 struct tui_locator_window *locator = tui_locator_win_info_ptr ();
510 gdb_assert (locator != nullptr);
512 TUI_SRC_WIN->show_source_content ();
513 if (TUI_DISASM_WIN == NULL)
514 tui_win_list[DISASSEM_WIN] = new tui_disasm_window ();
515 TUI_DISASM_WIN->resize (asm_height,
519 locator->resize (2 /* 1 */ ,
522 (src_height + asm_height) - 1);
523 TUI_SRC_WIN->m_has_locator = false;
524 TUI_DISASM_WIN->m_has_locator = true;
525 TUI_DISASM_WIN->show_source_content ();
527 if (TUI_CMD_WIN == NULL)
528 tui_win_list[CMD_WIN] = new tui_cmd_window ();
529 TUI_CMD_WIN->resize (cmd_height,
532 tui_term_height () - cmd_height);
533 current_layout = SRC_DISASSEM_COMMAND;
537 /* Show the Source/Data/Command or the Dissassembly/Data/Command
540 show_data (enum tui_layout_type new_layout)
542 int total_height = (tui_term_height () - TUI_CMD_WIN->height);
543 int src_height, data_height;
544 enum tui_win_type win_type;
546 struct tui_locator_window *locator = tui_locator_win_info_ptr ();
547 gdb_assert (locator != nullptr);
549 data_height = total_height / 2;
550 src_height = total_height - data_height;
551 if (tui_win_list[DATA_WIN] == nullptr)
552 tui_win_list[DATA_WIN] = new tui_data_window ();
553 tui_win_list[DATA_WIN]->resize (data_height, tui_term_width (), 0, 0);
555 if (new_layout == SRC_DATA_COMMAND)
558 win_type = DISASSEM_WIN;
560 if (tui_win_list[win_type] == NULL)
562 if (win_type == SRC_WIN)
563 tui_win_list[win_type] = new tui_source_window ();
565 tui_win_list[win_type] = new tui_disasm_window ();
568 tui_source_window_base *base
569 = (tui_source_window_base *) tui_win_list[win_type];
570 tui_win_list[win_type]->resize (src_height,
574 locator->resize (2 /* 1 */ ,
578 TUI_CMD_WIN->resize (TUI_CMD_WIN->height, tui_term_width (),
581 base->m_has_locator = true;
582 current_layout = new_layout;
586 tui_gen_win_info::resize (int height_, int width_,
587 int origin_x_, int origin_y_)
592 viewport_height = height - 2;
595 origin.x = origin_x_;
596 origin.y = origin_y_;
598 if (handle != nullptr)
601 wresize (handle, height, width);
602 mvwin (handle, origin.y, origin.x);
603 wmove (handle, 0, 0);
605 tui_delete_win (handle);
610 if (handle == nullptr)
611 tui_make_window (this);
616 /* Show the Source/Command or the Disassem layout. */
618 show_source_or_disasm_and_command (enum tui_layout_type layout_type)
620 struct tui_source_window_base *win_info;
621 int src_height, cmd_height;
622 struct tui_locator_window *locator = tui_locator_win_info_ptr ();
623 gdb_assert (locator != nullptr);
625 if (TUI_CMD_WIN != NULL)
626 cmd_height = TUI_CMD_WIN->height;
628 cmd_height = tui_term_height () / 3;
629 src_height = tui_term_height () - cmd_height;
631 if (layout_type == SRC_COMMAND)
633 if (tui_win_list[SRC_WIN] == nullptr)
634 tui_win_list[SRC_WIN] = new tui_source_window ();
635 win_info = TUI_SRC_WIN;
639 if (tui_win_list[DISASSEM_WIN] == nullptr)
640 tui_win_list[DISASSEM_WIN] = new tui_disasm_window ();
641 win_info = TUI_DISASM_WIN;
644 locator->resize (2 /* 1 */ ,
648 win_info->resize (src_height - 1,
653 win_info->m_has_locator = true;
654 win_info->show_source_content ();
656 if (TUI_CMD_WIN == NULL)
657 tui_win_list[CMD_WIN] = new tui_cmd_window ();
658 TUI_CMD_WIN->resize (cmd_height,
662 current_layout = layout_type;