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