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