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