Simplify tui_make_all_invisible
[deliverable/binutils-gdb.git] / gdb / tui / tui-layout.c
1 /* TUI layout window management.
2
3 Copyright (C) 1998-2019 Free Software Foundation, Inc.
4
5 Contributed by Hewlett-Packard Company.
6
7 This file is part of GDB.
8
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.
13
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.
18
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/>. */
21
22 #include "defs.h"
23 #include "arch-utils.h"
24 #include "command.h"
25 #include "symtab.h"
26 #include "frame.h"
27 #include "source.h"
28 #include <ctype.h>
29
30 #include "tui/tui.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"
42
43 /*******************************
44 ** Static Local Decls
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 *);
56
57
58 static enum tui_layout_type current_layout = UNDEFINED_LAYOUT;
59
60 /* Accessor for the current layout. */
61 enum tui_layout_type
62 tui_current_layout (void)
63 {
64 return current_layout;
65 }
66
67 /***************************************
68 ** DEFINITIONS
69 ***************************************/
70
71 /* Show the screen layout defined. */
72 static void
73 show_layout (enum tui_layout_type layout)
74 {
75 enum tui_layout_type cur_layout = tui_current_layout ();
76
77 if (layout != cur_layout)
78 {
79 /* Since the new layout may cause changes in window size, we
80 should free the content and reallocate on next display of
81 source/asm. */
82 tui_clear_source_windows ();
83 /* First make the current layout be invisible. */
84 tui_make_all_invisible ();
85 tui_locator_win_info_ptr ()->make_visible (false);
86 if (layout == SRC_DATA_COMMAND
87 || layout == DISASSEM_DATA_COMMAND)
88 {
89 show_data (layout);
90 tui_refresh_all ();
91 }
92 else
93 {
94 switch (layout)
95 {
96 /* Now show the new layout. */
97 case SRC_COMMAND:
98 show_source_command ();
99 tui_add_to_source_windows (TUI_SRC_WIN);
100 break;
101 case DISASSEM_COMMAND:
102 show_disasm_command ();
103 tui_add_to_source_windows (TUI_DISASM_WIN);
104 break;
105 case SRC_DISASSEM_COMMAND:
106 show_source_disasm_command ();
107 tui_add_to_source_windows (TUI_SRC_WIN);
108 tui_add_to_source_windows (TUI_DISASM_WIN);
109 break;
110 default:
111 break;
112 }
113 }
114 }
115 }
116
117
118 /* Function to set the layout to SRC_COMMAND, DISASSEM_COMMAND,
119 SRC_DISASSEM_COMMAND, SRC_DATA_COMMAND, or DISASSEM_DATA_COMMAND. */
120 void
121 tui_set_layout (enum tui_layout_type layout_type)
122 {
123 gdb_assert (layout_type != UNDEFINED_LAYOUT);
124
125 enum tui_layout_type cur_layout = tui_current_layout ();
126 struct gdbarch *gdbarch;
127 CORE_ADDR addr;
128 struct tui_win_info *win_with_focus = tui_win_with_focus ();
129
130 extract_display_start_addr (&gdbarch, &addr);
131
132 enum tui_layout_type new_layout = layout_type;
133
134 if (new_layout != cur_layout)
135 {
136 show_layout (new_layout);
137
138 /* Now determine where focus should be. */
139 if (win_with_focus != TUI_CMD_WIN)
140 {
141 switch (new_layout)
142 {
143 case SRC_COMMAND:
144 tui_set_win_focus_to (TUI_SRC_WIN);
145 break;
146 case DISASSEM_COMMAND:
147 /* The previous layout was not showing code.
148 This can happen if there is no source
149 available:
150
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! */
154
155 tui_get_begin_asm_address (&gdbarch, &addr);
156 tui_set_win_focus_to (TUI_DISASM_WIN);
157 break;
158 case SRC_DISASSEM_COMMAND:
159 /* The previous layout was not showing code.
160 This can happen if there is no source
161 available:
162
163 1. if the source file is in another dir OR
164 2. if target was compiled without -g
165 We still want to show the assembly though! */
166
167 tui_get_begin_asm_address (&gdbarch, &addr);
168 if (win_with_focus == TUI_SRC_WIN)
169 tui_set_win_focus_to (TUI_SRC_WIN);
170 else
171 tui_set_win_focus_to (TUI_DISASM_WIN);
172 break;
173 case SRC_DATA_COMMAND:
174 if (win_with_focus != TUI_DATA_WIN)
175 tui_set_win_focus_to (TUI_SRC_WIN);
176 else
177 tui_set_win_focus_to (TUI_DATA_WIN);
178 break;
179 case DISASSEM_DATA_COMMAND:
180 /* The previous layout was not showing code.
181 This can happen if there is no source
182 available:
183
184 1. if the source file is in another dir OR
185 2. if target was compiled without -g
186 We still want to show the assembly though! */
187
188 tui_get_begin_asm_address (&gdbarch, &addr);
189 if (win_with_focus != TUI_DATA_WIN)
190 tui_set_win_focus_to (TUI_DISASM_WIN);
191 else
192 tui_set_win_focus_to (TUI_DATA_WIN);
193 break;
194 default:
195 break;
196 }
197 }
198 /*
199 * Now update the window content.
200 */
201 tui_update_source_windows_with_addr (gdbarch, addr);
202 if (new_layout == SRC_DATA_COMMAND
203 || new_layout == DISASSEM_DATA_COMMAND)
204 tui_show_registers (TUI_DATA_WIN->current_group);
205 }
206 }
207
208 /* Add the specified window to the layout in a logical way. This
209 means setting up the most logical layout given the window to be
210 added. */
211 void
212 tui_add_win_to_layout (enum tui_win_type type)
213 {
214 enum tui_layout_type cur_layout = tui_current_layout ();
215
216 switch (type)
217 {
218 case SRC_WIN:
219 if (cur_layout != SRC_COMMAND
220 && cur_layout != SRC_DISASSEM_COMMAND
221 && cur_layout != SRC_DATA_COMMAND)
222 {
223 tui_clear_source_windows_detail ();
224 if (cur_layout == DISASSEM_DATA_COMMAND)
225 show_layout (SRC_DATA_COMMAND);
226 else
227 show_layout (SRC_COMMAND);
228 }
229 break;
230 case DISASSEM_WIN:
231 if (cur_layout != DISASSEM_COMMAND
232 && cur_layout != SRC_DISASSEM_COMMAND
233 && cur_layout != DISASSEM_DATA_COMMAND)
234 {
235 tui_clear_source_windows_detail ();
236 if (cur_layout == SRC_DATA_COMMAND)
237 show_layout (DISASSEM_DATA_COMMAND);
238 else
239 show_layout (DISASSEM_COMMAND);
240 }
241 break;
242 case DATA_WIN:
243 if (cur_layout != SRC_DATA_COMMAND
244 && cur_layout != DISASSEM_DATA_COMMAND)
245 {
246 if (cur_layout == DISASSEM_COMMAND)
247 show_layout (DISASSEM_DATA_COMMAND);
248 else
249 show_layout (SRC_DATA_COMMAND);
250 }
251 break;
252 default:
253 break;
254 }
255 }
256
257
258 /* Answer the height of a window. If it hasn't been created yet,
259 answer what the height of a window would be based upon its type and
260 the layout. */
261 int
262 tui_default_win_height (enum tui_win_type type,
263 enum tui_layout_type layout)
264 {
265 int h;
266
267 if (tui_win_list[type] != NULL)
268 h = tui_win_list[type]->height;
269 else
270 {
271 switch (layout)
272 {
273 case SRC_COMMAND:
274 case DISASSEM_COMMAND:
275 if (TUI_CMD_WIN == NULL)
276 h = tui_term_height () / 2;
277 else
278 h = tui_term_height () - TUI_CMD_WIN->height;
279 break;
280 case SRC_DISASSEM_COMMAND:
281 case SRC_DATA_COMMAND:
282 case DISASSEM_DATA_COMMAND:
283 if (TUI_CMD_WIN == NULL)
284 h = tui_term_height () / 3;
285 else
286 h = (tui_term_height () - TUI_CMD_WIN->height) / 2;
287 break;
288 default:
289 h = 0;
290 break;
291 }
292 }
293
294 return h;
295 }
296
297
298 /* Answer the height of a window. If it hasn't been created yet,
299 answer what the height of a window would be based upon its type and
300 the layout. */
301 int
302 tui_default_win_viewport_height (enum tui_win_type type,
303 enum tui_layout_type layout)
304 {
305 int h;
306
307 h = tui_default_win_height (type, layout);
308
309 if (tui_win_list[type] == TUI_CMD_WIN)
310 h -= 1;
311 else
312 h -= 2;
313
314 return h;
315 }
316
317 /* Complete possible layout names. TEXT is the complete text entered so
318 far, WORD is the word currently being completed. */
319
320 static void
321 layout_completer (struct cmd_list_element *ignore,
322 completion_tracker &tracker,
323 const char *text, const char *word)
324 {
325 static const char *layout_names [] =
326 { "src", "asm", "split", "regs", "next", "prev", NULL };
327
328 complete_on_enum (tracker, layout_names, text, word);
329 }
330
331 /* Function to initialize gdb commands, for tui window layout
332 manipulation. */
333
334 void
335 _initialize_tui_layout (void)
336 {
337 struct cmd_list_element *cmd;
338
339 cmd = add_com ("layout", class_tui, tui_layout_command, _("\
340 Change the layout of windows.\n\
341 Usage: layout prev | next | LAYOUT-NAME\n\
342 Layout names are:\n\
343 src : Displays source and command windows.\n\
344 asm : Displays disassembly and command windows.\n\
345 split : Displays source, disassembly and command windows.\n\
346 regs : Displays register window. If existing layout\n\
347 is source/command or assembly/command, the \n\
348 register window is displayed. If the\n\
349 source/assembly/command (split) is displayed, \n\
350 the register window is displayed with \n\
351 the window that has current logical focus."));
352 set_cmd_completer (cmd, layout_completer);
353 }
354
355
356 /*************************
357 ** STATIC LOCAL FUNCTIONS
358 **************************/
359
360
361 /* Function to set the layout to SRC, ASM, SPLIT, NEXT, PREV, DATA, or
362 REGS. */
363 static void
364 tui_layout_command (const char *layout_name, int from_tty)
365 {
366 int i;
367 enum tui_layout_type new_layout = UNDEFINED_LAYOUT;
368 enum tui_layout_type cur_layout = tui_current_layout ();
369
370 if (layout_name == NULL)
371 error (_("Usage: layout prev | next | LAYOUT-NAME"));
372
373 std::string copy = layout_name;
374 for (i = 0; i < copy.size (); i++)
375 copy[i] = toupper (copy[i]);
376 const char *buf_ptr = copy.c_str ();
377
378 /* First check for ambiguous input. */
379 if (strlen (buf_ptr) <= 1 && *buf_ptr == 'S')
380 error (_("Ambiguous command input."));
381
382 if (subset_compare (buf_ptr, "SRC"))
383 new_layout = SRC_COMMAND;
384 else if (subset_compare (buf_ptr, "ASM"))
385 new_layout = DISASSEM_COMMAND;
386 else if (subset_compare (buf_ptr, "SPLIT"))
387 new_layout = SRC_DISASSEM_COMMAND;
388 else if (subset_compare (buf_ptr, "REGS"))
389 {
390 if (cur_layout == SRC_COMMAND
391 || cur_layout == SRC_DATA_COMMAND)
392 new_layout = SRC_DATA_COMMAND;
393 else
394 new_layout = DISASSEM_DATA_COMMAND;
395 }
396 else if (subset_compare (buf_ptr, "NEXT"))
397 new_layout = next_layout ();
398 else if (subset_compare (buf_ptr, "PREV"))
399 new_layout = prev_layout ();
400 else
401 error (_("Unrecognized layout: %s"), layout_name);
402
403 /* Make sure the curses mode is enabled. */
404 tui_enable ();
405 tui_set_layout (new_layout);
406 }
407
408
409 static void
410 extract_display_start_addr (struct gdbarch **gdbarch_p, CORE_ADDR *addr_p)
411 {
412 enum tui_layout_type cur_layout = tui_current_layout ();
413 struct gdbarch *gdbarch = get_current_arch ();
414 CORE_ADDR addr;
415 CORE_ADDR pc;
416 struct symtab_and_line cursal = get_current_source_symtab_and_line ();
417
418 switch (cur_layout)
419 {
420 case SRC_COMMAND:
421 case SRC_DATA_COMMAND:
422 gdbarch = TUI_SRC_WIN->gdbarch;
423 find_line_pc (cursal.symtab,
424 TUI_SRC_WIN->start_line_or_addr.u.line_no,
425 &pc);
426 addr = pc;
427 break;
428 case DISASSEM_COMMAND:
429 case SRC_DISASSEM_COMMAND:
430 case DISASSEM_DATA_COMMAND:
431 gdbarch = TUI_DISASM_WIN->gdbarch;
432 addr = TUI_DISASM_WIN->start_line_or_addr.u.addr;
433 break;
434 default:
435 addr = 0;
436 break;
437 }
438
439 *gdbarch_p = gdbarch;
440 *addr_p = addr;
441 }
442
443
444 /* Answer the previous layout to cycle to. */
445 static enum tui_layout_type
446 next_layout (void)
447 {
448 int new_layout;
449
450 new_layout = tui_current_layout ();
451 if (new_layout == UNDEFINED_LAYOUT)
452 new_layout = SRC_COMMAND;
453 else
454 {
455 new_layout++;
456 if (new_layout == UNDEFINED_LAYOUT)
457 new_layout = SRC_COMMAND;
458 }
459
460 return (enum tui_layout_type) new_layout;
461 }
462
463
464 /* Answer the next layout to cycle to. */
465 static enum tui_layout_type
466 prev_layout (void)
467 {
468 int new_layout;
469
470 new_layout = tui_current_layout ();
471 if (new_layout == SRC_COMMAND)
472 new_layout = DISASSEM_DATA_COMMAND;
473 else
474 {
475 new_layout--;
476 if (new_layout == UNDEFINED_LAYOUT)
477 new_layout = DISASSEM_DATA_COMMAND;
478 }
479
480 return (enum tui_layout_type) new_layout;
481 }
482
483 /* Show the Source/Command layout. */
484 static void
485 show_source_command (void)
486 {
487 show_source_or_disasm_and_command (SRC_COMMAND);
488 }
489
490
491 /* Show the Dissassem/Command layout. */
492 static void
493 show_disasm_command (void)
494 {
495 show_source_or_disasm_and_command (DISASSEM_COMMAND);
496 }
497
498
499 /* Show the Source/Disassem/Command layout. */
500 static void
501 show_source_disasm_command (void)
502 {
503 if (tui_current_layout () != SRC_DISASSEM_COMMAND)
504 {
505 int cmd_height, src_height, asm_height;
506
507 if (TUI_CMD_WIN != NULL)
508 cmd_height = TUI_CMD_WIN->height;
509 else
510 cmd_height = tui_term_height () / 3;
511
512 src_height = (tui_term_height () - cmd_height) / 2;
513 asm_height = tui_term_height () - (src_height + cmd_height);
514
515 if (TUI_SRC_WIN == NULL)
516 tui_win_list[SRC_WIN] = new tui_source_window ();
517 TUI_SRC_WIN->reset (src_height,
518 tui_term_width (),
519 0,
520 0);
521 TUI_SRC_WIN->make_visible (true);
522 TUI_SRC_WIN->m_has_locator = false;
523
524 struct tui_locator_window *locator = tui_locator_win_info_ptr ();
525 gdb_assert (locator != nullptr);
526
527 tui_show_source_content (TUI_SRC_WIN);
528 if (TUI_DISASM_WIN == NULL)
529 tui_win_list[DISASSEM_WIN] = new tui_disasm_window ();
530 TUI_DISASM_WIN->reset (asm_height,
531 tui_term_width (),
532 0,
533 src_height - 1);
534 TUI_DISASM_WIN->make_visible (true);
535 locator->reset (2 /* 1 */ ,
536 tui_term_width (),
537 0,
538 (src_height + asm_height) - 1);
539 TUI_SRC_WIN->m_has_locator = false;
540 TUI_DISASM_WIN->m_has_locator = true;
541 locator->make_visible (true);
542 tui_show_locator_content ();
543 tui_show_source_content (TUI_DISASM_WIN);
544
545 if (TUI_CMD_WIN == NULL)
546 tui_win_list[CMD_WIN] = new tui_cmd_window ();
547 TUI_CMD_WIN->reset (cmd_height,
548 tui_term_width (),
549 0,
550 tui_term_height () - cmd_height);
551 /* FIXME tui_cmd_window won't recreate the handle on
552 make_visible, so we need this instead. */
553 tui_make_window (TUI_CMD_WIN, DONT_BOX_WINDOW);
554 current_layout = SRC_DISASSEM_COMMAND;
555 }
556 }
557
558
559 /* Show the Source/Data/Command or the Dissassembly/Data/Command
560 layout. */
561 static void
562 show_data (enum tui_layout_type new_layout)
563 {
564 int total_height = (tui_term_height () - TUI_CMD_WIN->height);
565 int src_height, data_height;
566 enum tui_win_type win_type;
567
568 struct tui_locator_window *locator = tui_locator_win_info_ptr ();
569 gdb_assert (locator != nullptr);
570
571 data_height = total_height / 2;
572 src_height = total_height - data_height;
573 if (tui_win_list[DATA_WIN] == nullptr)
574 tui_win_list[DATA_WIN] = new tui_data_window ();
575 tui_win_list[DATA_WIN]->reset (data_height, tui_term_width (), 0, 0);
576 tui_win_list[DATA_WIN]->make_visible (true);
577
578 if (new_layout == SRC_DATA_COMMAND)
579 win_type = SRC_WIN;
580 else
581 win_type = DISASSEM_WIN;
582
583 if (tui_win_list[win_type] == NULL)
584 {
585 if (win_type == SRC_WIN)
586 tui_win_list[win_type] = new tui_source_window ();
587 else
588 tui_win_list[win_type] = new tui_disasm_window ();
589 }
590
591 tui_source_window_base *base
592 = (tui_source_window_base *) tui_win_list[win_type];
593 tui_win_list[win_type]->reset (src_height,
594 tui_term_width (),
595 0,
596 data_height - 1);
597 locator->reset (2 /* 1 */ ,
598 tui_term_width (),
599 0,
600 total_height - 1);
601 base->make_visible (true);
602 base->m_has_locator = true;
603 locator->make_visible (true);
604 tui_show_locator_content ();
605 tui_add_to_source_windows (base);
606 current_layout = new_layout;
607 }
608
609 void
610 tui_gen_win_info::reset (int height_, int width_,
611 int origin_x_, int origin_y_)
612 {
613 int h = height_;
614
615 width = width_;
616 height = h;
617 if (h > 1)
618 {
619 viewport_height = h - 1;
620 if (type != CMD_WIN)
621 viewport_height--;
622 }
623 else
624 viewport_height = 1;
625 origin.x = origin_x_;
626 origin.y = origin_y_;
627 }
628
629 /* Show the Source/Command or the Disassem layout. */
630 static void
631 show_source_or_disasm_and_command (enum tui_layout_type layout_type)
632 {
633 if (tui_current_layout () != layout_type)
634 {
635 struct tui_source_window_base *win_info;
636 int src_height, cmd_height;
637 struct tui_locator_window *locator = tui_locator_win_info_ptr ();
638 gdb_assert (locator != nullptr);
639
640 if (TUI_CMD_WIN != NULL)
641 cmd_height = TUI_CMD_WIN->height;
642 else
643 cmd_height = tui_term_height () / 3;
644 src_height = tui_term_height () - cmd_height;
645
646 if (layout_type == SRC_COMMAND)
647 {
648 if (tui_win_list[SRC_WIN] == nullptr)
649 tui_win_list[SRC_WIN] = new tui_source_window ();
650 win_info = TUI_SRC_WIN;
651 }
652 else
653 {
654 if (tui_win_list[DISASSEM_WIN] == nullptr)
655 tui_win_list[DISASSEM_WIN] = new tui_disasm_window ();
656 win_info = TUI_DISASM_WIN;
657 }
658
659 locator->reset (2 /* 1 */ ,
660 tui_term_width (),
661 0,
662 src_height - 1);
663 win_info->reset (src_height - 1,
664 tui_term_width (),
665 0,
666 0);
667 win_info->make_visible (true);
668
669
670 win_info->m_has_locator = true;
671 locator->make_visible (true);
672 tui_show_locator_content ();
673 tui_show_source_content (win_info);
674
675 if (TUI_CMD_WIN == NULL)
676 tui_win_list[CMD_WIN] = new tui_cmd_window ();
677 TUI_CMD_WIN->reset (cmd_height,
678 tui_term_width (),
679 0,
680 src_height);
681 /* FIXME tui_cmd_window won't recreate the handle on
682 make_visible, so we need this instead. */
683 tui_make_window (TUI_CMD_WIN, DONT_BOX_WINDOW);
684 current_layout = layout_type;
685 }
686 }
This page took 0.152937 seconds and 5 git commands to generate.