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_show_locator_content ();
526 TUI_DISASM_WIN
->show_source_content ();
528 if (TUI_CMD_WIN
== NULL
)
529 tui_win_list
[CMD_WIN
] = new tui_cmd_window ();
530 TUI_CMD_WIN
->resize (cmd_height
,
533 tui_term_height () - cmd_height
);
534 current_layout
= SRC_DISASSEM_COMMAND
;
538 /* Show the Source/Data/Command or the Dissassembly/Data/Command
541 show_data (enum tui_layout_type new_layout
)
543 int total_height
= (tui_term_height () - TUI_CMD_WIN
->height
);
544 int src_height
, data_height
;
545 enum tui_win_type win_type
;
547 struct tui_locator_window
*locator
= tui_locator_win_info_ptr ();
548 gdb_assert (locator
!= nullptr);
550 data_height
= total_height
/ 2;
551 src_height
= total_height
- data_height
;
552 if (tui_win_list
[DATA_WIN
] == nullptr)
553 tui_win_list
[DATA_WIN
] = new tui_data_window ();
554 tui_win_list
[DATA_WIN
]->resize (data_height
, tui_term_width (), 0, 0);
556 if (new_layout
== SRC_DATA_COMMAND
)
559 win_type
= DISASSEM_WIN
;
561 if (tui_win_list
[win_type
] == NULL
)
563 if (win_type
== SRC_WIN
)
564 tui_win_list
[win_type
] = new tui_source_window ();
566 tui_win_list
[win_type
] = new tui_disasm_window ();
569 tui_source_window_base
*base
570 = (tui_source_window_base
*) tui_win_list
[win_type
];
571 tui_win_list
[win_type
]->resize (src_height
,
575 locator
->resize (2 /* 1 */ ,
579 TUI_CMD_WIN
->resize (TUI_CMD_WIN
->height
, tui_term_width (),
582 base
->m_has_locator
= true;
583 tui_show_locator_content ();
584 current_layout
= new_layout
;
588 tui_gen_win_info::resize (int height_
, int width_
,
589 int origin_x_
, int origin_y_
)
594 viewport_height
= height
- 2;
597 origin
.x
= origin_x_
;
598 origin
.y
= origin_y_
;
600 if (handle
!= nullptr)
603 wresize (handle
, height
, width
);
604 mvwin (handle
, origin
.y
, origin
.x
);
605 wmove (handle
, 0, 0);
607 tui_delete_win (handle
);
612 if (handle
== nullptr)
613 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 tui_show_locator_content ();
655 win_info
->show_source_content ();
657 if (TUI_CMD_WIN
== NULL
)
658 tui_win_list
[CMD_WIN
] = new tui_cmd_window ();
659 TUI_CMD_WIN
->resize (cmd_height
,
663 current_layout
= layout_type
;