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_DATA_WIN
->show_registers (TUI_DATA_WIN
->get_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
,
508 struct tui_locator_window
*locator
= tui_locator_win_info_ptr ();
509 gdb_assert (locator
!= nullptr);
511 TUI_SRC_WIN
->show_source_content ();
512 if (TUI_DISASM_WIN
== NULL
)
513 tui_win_list
[DISASSEM_WIN
] = new tui_disasm_window ();
514 TUI_DISASM_WIN
->resize (asm_height
,
518 locator
->resize (2 /* 1 */ ,
521 (src_height
+ asm_height
) - 1);
522 TUI_DISASM_WIN
->show_source_content ();
524 if (TUI_CMD_WIN
== NULL
)
525 tui_win_list
[CMD_WIN
] = new tui_cmd_window ();
526 TUI_CMD_WIN
->resize (cmd_height
,
529 tui_term_height () - cmd_height
);
530 current_layout
= SRC_DISASSEM_COMMAND
;
534 /* Show the Source/Data/Command or the Dissassembly/Data/Command
537 show_data (enum tui_layout_type new_layout
)
539 int total_height
= (tui_term_height () - TUI_CMD_WIN
->height
);
540 int src_height
, data_height
;
541 enum tui_win_type win_type
;
543 struct tui_locator_window
*locator
= tui_locator_win_info_ptr ();
544 gdb_assert (locator
!= nullptr);
546 data_height
= total_height
/ 2;
547 src_height
= total_height
- data_height
;
548 if (tui_win_list
[DATA_WIN
] == nullptr)
549 tui_win_list
[DATA_WIN
] = new tui_data_window ();
550 tui_win_list
[DATA_WIN
]->resize (data_height
, tui_term_width (), 0, 0);
552 if (new_layout
== SRC_DATA_COMMAND
)
555 win_type
= DISASSEM_WIN
;
557 if (tui_win_list
[win_type
] == NULL
)
559 if (win_type
== SRC_WIN
)
560 tui_win_list
[win_type
] = new tui_source_window ();
562 tui_win_list
[win_type
] = new tui_disasm_window ();
565 tui_win_list
[win_type
]->resize (src_height
,
569 locator
->resize (2 /* 1 */ ,
573 TUI_CMD_WIN
->resize (TUI_CMD_WIN
->height
, tui_term_width (),
576 current_layout
= new_layout
;
580 tui_gen_win_info::resize (int height_
, int width_
,
581 int origin_x_
, int origin_y_
)
586 viewport_height
= height
- 2;
589 origin
.x
= origin_x_
;
590 origin
.y
= origin_y_
;
592 if (handle
!= nullptr)
595 wresize (handle
, height
, width
);
596 mvwin (handle
, origin
.y
, origin
.x
);
597 wmove (handle
, 0, 0);
599 tui_delete_win (handle
);
604 if (handle
== nullptr)
610 /* Show the Source/Command or the Disassem layout. */
612 show_source_or_disasm_and_command (enum tui_layout_type layout_type
)
614 struct tui_source_window_base
*win_info
;
615 int src_height
, cmd_height
;
616 struct tui_locator_window
*locator
= tui_locator_win_info_ptr ();
617 gdb_assert (locator
!= nullptr);
619 if (TUI_CMD_WIN
!= NULL
)
620 cmd_height
= TUI_CMD_WIN
->height
;
622 cmd_height
= tui_term_height () / 3;
623 src_height
= tui_term_height () - cmd_height
;
625 if (layout_type
== SRC_COMMAND
)
627 if (tui_win_list
[SRC_WIN
] == nullptr)
628 tui_win_list
[SRC_WIN
] = new tui_source_window ();
629 win_info
= TUI_SRC_WIN
;
633 if (tui_win_list
[DISASSEM_WIN
] == nullptr)
634 tui_win_list
[DISASSEM_WIN
] = new tui_disasm_window ();
635 win_info
= TUI_DISASM_WIN
;
638 locator
->resize (2 /* 1 */ ,
642 win_info
->resize (src_height
- 1,
647 win_info
->show_source_content ();
649 if (TUI_CMD_WIN
== NULL
)
650 tui_win_list
[CMD_WIN
] = new tui_cmd_window ();
651 TUI_CMD_WIN
->resize (cmd_height
,
655 current_layout
= layout_type
;