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 initialize gdb commands, for tui window layout
254 _initialize_tui_layout (void)
256 struct cmd_list_element
*cmd
;
258 cmd
= add_com ("layout", class_tui
, tui_layout_command
, _("\
259 Change the layout of windows.\n\
260 Usage: layout prev | next | LAYOUT-NAME\n\
262 src : Displays source and command windows.\n\
263 asm : Displays disassembly and command windows.\n\
264 split : Displays source, disassembly and command windows.\n\
265 regs : Displays register window. If existing layout\n\
266 is source/command or assembly/command, the \n\
267 register window is displayed. If the\n\
268 source/assembly/command (split) is displayed, \n\
269 the register window is displayed with \n\
270 the window that has current logical focus."));
271 set_cmd_completer (cmd
, layout_completer
);
275 /* Function to set the layout to SRC, ASM, SPLIT, NEXT, PREV, DATA, or
278 tui_layout_command (const char *layout_name
, int from_tty
)
280 enum tui_layout_type new_layout
= UNDEFINED_LAYOUT
;
281 enum tui_layout_type cur_layout
= tui_current_layout ();
283 if (layout_name
== NULL
|| *layout_name
== '\0')
284 error (_("Usage: layout prev | next | LAYOUT-NAME"));
286 /* First check for ambiguous input. */
287 if (strcmp (layout_name
, "s") == 0)
288 error (_("Ambiguous command input."));
290 if (subset_compare (layout_name
, "src"))
291 new_layout
= SRC_COMMAND
;
292 else if (subset_compare (layout_name
, "asm"))
293 new_layout
= DISASSEM_COMMAND
;
294 else if (subset_compare (layout_name
, "split"))
295 new_layout
= SRC_DISASSEM_COMMAND
;
296 else if (subset_compare (layout_name
, "regs"))
298 if (cur_layout
== SRC_COMMAND
299 || cur_layout
== SRC_DATA_COMMAND
)
300 new_layout
= SRC_DATA_COMMAND
;
302 new_layout
= DISASSEM_DATA_COMMAND
;
304 else if (subset_compare (layout_name
, "next"))
305 new_layout
= next_layout ();
306 else if (subset_compare (layout_name
, "prev"))
307 new_layout
= prev_layout ();
309 error (_("Unrecognized layout: %s"), layout_name
);
311 /* Make sure the curses mode is enabled. */
313 tui_set_layout (new_layout
);
318 extract_display_start_addr (struct gdbarch
**gdbarch_p
, CORE_ADDR
*addr_p
)
320 enum tui_layout_type cur_layout
= tui_current_layout ();
321 struct gdbarch
*gdbarch
= get_current_arch ();
324 struct symtab_and_line cursal
= get_current_source_symtab_and_line ();
329 case SRC_DATA_COMMAND
:
330 gdbarch
= TUI_SRC_WIN
->gdbarch
;
331 find_line_pc (cursal
.symtab
,
332 TUI_SRC_WIN
->start_line_or_addr
.u
.line_no
,
336 case DISASSEM_COMMAND
:
337 case SRC_DISASSEM_COMMAND
:
338 case DISASSEM_DATA_COMMAND
:
339 gdbarch
= TUI_DISASM_WIN
->gdbarch
;
340 addr
= TUI_DISASM_WIN
->start_line_or_addr
.u
.addr
;
347 *gdbarch_p
= gdbarch
;
352 /* Answer the previous layout to cycle to. */
353 static enum tui_layout_type
358 new_layout
= tui_current_layout ();
359 if (new_layout
== UNDEFINED_LAYOUT
)
360 new_layout
= SRC_COMMAND
;
364 if (new_layout
== UNDEFINED_LAYOUT
)
365 new_layout
= SRC_COMMAND
;
368 return (enum tui_layout_type
) new_layout
;
372 /* Answer the next layout to cycle to. */
373 static enum tui_layout_type
378 new_layout
= tui_current_layout ();
379 if (new_layout
== SRC_COMMAND
)
380 new_layout
= DISASSEM_DATA_COMMAND
;
384 if (new_layout
== UNDEFINED_LAYOUT
)
385 new_layout
= DISASSEM_DATA_COMMAND
;
388 return (enum tui_layout_type
) new_layout
;
391 /* Show the Source/Command layout. */
393 show_source_command (void)
395 show_source_or_disasm_and_command (SRC_COMMAND
);
399 /* Show the Dissassem/Command layout. */
401 show_disasm_command (void)
403 show_source_or_disasm_and_command (DISASSEM_COMMAND
);
407 /* Show the Source/Disassem/Command layout. */
409 show_source_disasm_command (void)
411 int cmd_height
, src_height
, asm_height
;
413 if (TUI_CMD_WIN
!= NULL
)
414 cmd_height
= TUI_CMD_WIN
->height
;
416 cmd_height
= tui_term_height () / 3;
418 src_height
= (tui_term_height () - cmd_height
) / 2;
419 asm_height
= tui_term_height () - (src_height
+ cmd_height
);
421 if (TUI_SRC_WIN
== NULL
)
422 tui_win_list
[SRC_WIN
] = new tui_source_window ();
423 TUI_SRC_WIN
->resize (src_height
,
428 struct tui_locator_window
*locator
= tui_locator_win_info_ptr ();
429 gdb_assert (locator
!= nullptr);
431 if (TUI_DISASM_WIN
== NULL
)
432 tui_win_list
[DISASSEM_WIN
] = new tui_disasm_window ();
433 TUI_DISASM_WIN
->resize (asm_height
,
437 locator
->resize (1, tui_term_width (),
438 0, (src_height
+ asm_height
) - 1);
440 if (TUI_CMD_WIN
== NULL
)
441 tui_win_list
[CMD_WIN
] = new tui_cmd_window ();
442 TUI_CMD_WIN
->resize (cmd_height
,
445 tui_term_height () - cmd_height
);
446 current_layout
= SRC_DISASSEM_COMMAND
;
450 /* Show the Source/Data/Command or the Dissassembly/Data/Command
453 show_data (enum tui_layout_type new_layout
)
455 int total_height
= (tui_term_height () - TUI_CMD_WIN
->height
);
456 int src_height
, data_height
;
457 enum tui_win_type win_type
;
459 struct tui_locator_window
*locator
= tui_locator_win_info_ptr ();
460 gdb_assert (locator
!= nullptr);
462 data_height
= total_height
/ 2;
463 src_height
= total_height
- data_height
;
464 if (tui_win_list
[DATA_WIN
] == nullptr)
465 tui_win_list
[DATA_WIN
] = new tui_data_window ();
466 tui_win_list
[DATA_WIN
]->resize (data_height
, tui_term_width (), 0, 0);
468 if (new_layout
== SRC_DATA_COMMAND
)
471 win_type
= DISASSEM_WIN
;
473 if (tui_win_list
[win_type
] == NULL
)
475 if (win_type
== SRC_WIN
)
476 tui_win_list
[win_type
] = new tui_source_window ();
478 tui_win_list
[win_type
] = new tui_disasm_window ();
481 tui_win_list
[win_type
]->resize (src_height
,
485 locator
->resize (1, tui_term_width (),
486 0, total_height
- 1);
487 TUI_CMD_WIN
->resize (TUI_CMD_WIN
->height
, tui_term_width (),
490 current_layout
= new_layout
;
494 tui_gen_win_info::resize (int height_
, int width_
,
495 int origin_x_
, int origin_y_
)
497 if (width
== width_
&& height
== height_
498 && origin
.x
== origin_x_
&& origin
.y
== origin_y_
499 && handle
!= nullptr)
505 viewport_height
= height
- 2;
508 origin
.x
= origin_x_
;
509 origin
.y
= origin_y_
;
511 if (handle
!= nullptr)
514 wresize (handle
.get (), height
, width
);
515 mvwin (handle
.get (), origin
.y
, origin
.x
);
516 wmove (handle
.get (), 0, 0);
518 handle
.reset (nullptr);
522 if (handle
== nullptr)
528 /* Show the Source/Command or the Disassem layout. */
530 show_source_or_disasm_and_command (enum tui_layout_type layout_type
)
532 struct tui_source_window_base
*win_info
;
533 int src_height
, cmd_height
;
534 struct tui_locator_window
*locator
= tui_locator_win_info_ptr ();
535 gdb_assert (locator
!= nullptr);
537 if (TUI_CMD_WIN
!= NULL
)
538 cmd_height
= TUI_CMD_WIN
->height
;
540 cmd_height
= tui_term_height () / 3;
541 src_height
= tui_term_height () - cmd_height
;
543 if (layout_type
== SRC_COMMAND
)
545 if (tui_win_list
[SRC_WIN
] == nullptr)
546 tui_win_list
[SRC_WIN
] = new tui_source_window ();
547 win_info
= TUI_SRC_WIN
;
551 if (tui_win_list
[DISASSEM_WIN
] == nullptr)
552 tui_win_list
[DISASSEM_WIN
] = new tui_disasm_window ();
553 win_info
= TUI_DISASM_WIN
;
556 locator
->resize (1, tui_term_width (),
558 win_info
->resize (src_height
- 1,
563 if (TUI_CMD_WIN
== NULL
)
564 tui_win_list
[CMD_WIN
] = new tui_cmd_window ();
565 TUI_CMD_WIN
->resize (cmd_height
,
569 current_layout
= layout_type
;