e9642584fdd25bd2c5c11ee247c51ca65fae32cf
[deliverable/binutils-gdb.git] / gdb / tui / tui-layout.c
1 /* TUI layout window management.
2
3 Copyright (C) 1998-2020 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 static void show_layout (enum tui_layout_type);
44 static enum tui_layout_type next_layout (void);
45 static enum tui_layout_type prev_layout (void);
46 static void tui_layout_command (const char *, int);
47 static void extract_display_start_addr (struct gdbarch **, CORE_ADDR *);
48
49
50 /* The pre-defined layouts. */
51 static tui_layout_split *standard_layouts[UNDEFINED_LAYOUT];
52
53 /* The layout that is currently applied. */
54 static std::unique_ptr<tui_layout_base> applied_layout;
55
56 static enum tui_layout_type current_layout = UNDEFINED_LAYOUT;
57
58 /* Accessor for the current layout. */
59 enum tui_layout_type
60 tui_current_layout (void)
61 {
62 return current_layout;
63 }
64
65 /* See tui-layout.h. */
66
67 void
68 tui_apply_current_layout ()
69 {
70 applied_layout->apply (0, 0, tui_term_width (), tui_term_height ());
71 }
72
73 /* See tui-layout. */
74
75 void
76 tui_adjust_window_height (struct tui_win_info *win, int new_height)
77 {
78 applied_layout->adjust_size (win->name (), new_height);
79 }
80
81 /* Show the screen layout defined. */
82 static void
83 show_layout (enum tui_layout_type layout)
84 {
85 enum tui_layout_type cur_layout = tui_current_layout ();
86
87 if (layout != cur_layout)
88 {
89 tui_make_all_invisible ();
90 applied_layout = standard_layouts[layout]->clone ();
91 tui_apply_current_layout ();
92 current_layout = layout;
93 tui_delete_invisible_windows ();
94 }
95 }
96
97
98 /* Function to set the layout to SRC_COMMAND, DISASSEM_COMMAND,
99 SRC_DISASSEM_COMMAND, SRC_DATA_COMMAND, or DISASSEM_DATA_COMMAND. */
100 void
101 tui_set_layout (enum tui_layout_type layout_type)
102 {
103 gdb_assert (layout_type != UNDEFINED_LAYOUT);
104
105 enum tui_layout_type cur_layout = tui_current_layout ();
106 struct gdbarch *gdbarch;
107 CORE_ADDR addr;
108 struct tui_win_info *win_with_focus = tui_win_with_focus ();
109
110 extract_display_start_addr (&gdbarch, &addr);
111
112 enum tui_layout_type new_layout = layout_type;
113
114 if (new_layout != cur_layout)
115 {
116 tui_suppress_output suppress;
117
118 show_layout (new_layout);
119
120 /* Now determine where focus should be. */
121 if (win_with_focus != TUI_CMD_WIN)
122 {
123 switch (new_layout)
124 {
125 case SRC_COMMAND:
126 tui_set_win_focus_to (TUI_SRC_WIN);
127 break;
128 case DISASSEM_COMMAND:
129 /* The previous layout was not showing code.
130 This can happen if there is no source
131 available:
132
133 1. if the source file is in another dir OR
134 2. if target was compiled without -g
135 We still want to show the assembly though! */
136
137 tui_get_begin_asm_address (&gdbarch, &addr);
138 tui_set_win_focus_to (TUI_DISASM_WIN);
139 break;
140 case SRC_DISASSEM_COMMAND:
141 /* The previous layout was not showing code.
142 This can happen if there is no source
143 available:
144
145 1. if the source file is in another dir OR
146 2. if target was compiled without -g
147 We still want to show the assembly though! */
148
149 tui_get_begin_asm_address (&gdbarch, &addr);
150 if (win_with_focus == TUI_SRC_WIN)
151 tui_set_win_focus_to (TUI_SRC_WIN);
152 else
153 tui_set_win_focus_to (TUI_DISASM_WIN);
154 break;
155 case SRC_DATA_COMMAND:
156 if (win_with_focus != TUI_DATA_WIN)
157 tui_set_win_focus_to (TUI_SRC_WIN);
158 else
159 tui_set_win_focus_to (TUI_DATA_WIN);
160 break;
161 case DISASSEM_DATA_COMMAND:
162 /* The previous layout was not showing code.
163 This can happen if there is no source
164 available:
165
166 1. if the source file is in another dir OR
167 2. if target was compiled without -g
168 We still want to show the assembly though! */
169
170 tui_get_begin_asm_address (&gdbarch, &addr);
171 if (win_with_focus != TUI_DATA_WIN)
172 tui_set_win_focus_to (TUI_DISASM_WIN);
173 else
174 tui_set_win_focus_to (TUI_DATA_WIN);
175 break;
176 default:
177 break;
178 }
179 }
180 /*
181 * Now update the window content.
182 */
183 tui_update_source_windows_with_addr (gdbarch, addr);
184 if (new_layout == SRC_DATA_COMMAND
185 || new_layout == DISASSEM_DATA_COMMAND)
186 TUI_DATA_WIN->show_registers (TUI_DATA_WIN->get_current_group ());
187 }
188 }
189
190 /* See tui-layout.h. */
191
192 void
193 tui_add_win_to_layout (enum tui_win_type type)
194 {
195 gdb_assert (type == SRC_WIN || type == DISASSEM_WIN);
196
197 enum tui_layout_type cur_layout = tui_current_layout ();
198
199 switch (type)
200 {
201 case SRC_WIN:
202 if (cur_layout != SRC_COMMAND
203 && cur_layout != SRC_DISASSEM_COMMAND
204 && cur_layout != SRC_DATA_COMMAND)
205 {
206 if (cur_layout == DISASSEM_DATA_COMMAND)
207 tui_set_layout (SRC_DATA_COMMAND);
208 else
209 tui_set_layout (SRC_COMMAND);
210 }
211 break;
212 case DISASSEM_WIN:
213 if (cur_layout != DISASSEM_COMMAND
214 && cur_layout != SRC_DISASSEM_COMMAND
215 && cur_layout != DISASSEM_DATA_COMMAND)
216 {
217 if (cur_layout == SRC_DATA_COMMAND)
218 tui_set_layout (DISASSEM_DATA_COMMAND);
219 else
220 tui_set_layout (DISASSEM_COMMAND);
221 }
222 break;
223 }
224 }
225
226 /* Complete possible layout names. TEXT is the complete text entered so
227 far, WORD is the word currently being completed. */
228
229 static void
230 layout_completer (struct cmd_list_element *ignore,
231 completion_tracker &tracker,
232 const char *text, const char *word)
233 {
234 static const char *layout_names [] =
235 { "src", "asm", "split", "regs", "next", "prev", NULL };
236
237 complete_on_enum (tracker, layout_names, text, word);
238 }
239
240 /* Function to set the layout to SRC, ASM, SPLIT, NEXT, PREV, DATA, or
241 REGS. */
242 static void
243 tui_layout_command (const char *layout_name, int from_tty)
244 {
245 enum tui_layout_type new_layout = UNDEFINED_LAYOUT;
246 enum tui_layout_type cur_layout = tui_current_layout ();
247
248 if (layout_name == NULL || *layout_name == '\0')
249 error (_("Usage: layout prev | next | LAYOUT-NAME"));
250
251 /* First check for ambiguous input. */
252 if (strcmp (layout_name, "s") == 0)
253 error (_("Ambiguous command input."));
254
255 if (subset_compare (layout_name, "src"))
256 new_layout = SRC_COMMAND;
257 else if (subset_compare (layout_name, "asm"))
258 new_layout = DISASSEM_COMMAND;
259 else if (subset_compare (layout_name, "split"))
260 new_layout = SRC_DISASSEM_COMMAND;
261 else if (subset_compare (layout_name, "regs"))
262 {
263 if (cur_layout == SRC_COMMAND
264 || cur_layout == SRC_DATA_COMMAND)
265 new_layout = SRC_DATA_COMMAND;
266 else
267 new_layout = DISASSEM_DATA_COMMAND;
268 }
269 else if (subset_compare (layout_name, "next"))
270 new_layout = next_layout ();
271 else if (subset_compare (layout_name, "prev"))
272 new_layout = prev_layout ();
273 else
274 error (_("Unrecognized layout: %s"), layout_name);
275
276 /* Make sure the curses mode is enabled. */
277 tui_enable ();
278 tui_set_layout (new_layout);
279 }
280
281 /* See tui-layout.h. */
282
283 void
284 tui_next_layout ()
285 {
286 tui_layout_command ("next", 0);
287 }
288
289 /* See tui-layout.h. */
290
291 void
292 tui_remove_some_windows ()
293 {
294 tui_win_info *focus = tui_win_with_focus ();
295
296 if (strcmp (focus->name (), "cmd") == 0)
297 {
298 /* Try leaving the source or disassembly window. If neither
299 exists, just do nothing. */
300 focus = TUI_SRC_WIN;
301 if (focus == nullptr)
302 focus = TUI_DISASM_WIN;
303 if (focus == nullptr)
304 return;
305 }
306
307 applied_layout->remove_windows (focus->name ());
308 tui_apply_current_layout ();
309 }
310
311 static void
312 extract_display_start_addr (struct gdbarch **gdbarch_p, CORE_ADDR *addr_p)
313 {
314 enum tui_layout_type cur_layout = tui_current_layout ();
315 struct gdbarch *gdbarch = get_current_arch ();
316 CORE_ADDR addr;
317 CORE_ADDR pc;
318 struct symtab_and_line cursal = get_current_source_symtab_and_line ();
319
320 switch (cur_layout)
321 {
322 case SRC_COMMAND:
323 case SRC_DATA_COMMAND:
324 gdbarch = TUI_SRC_WIN->gdbarch;
325 find_line_pc (cursal.symtab,
326 TUI_SRC_WIN->start_line_or_addr.u.line_no,
327 &pc);
328 addr = pc;
329 break;
330 case DISASSEM_COMMAND:
331 case SRC_DISASSEM_COMMAND:
332 case DISASSEM_DATA_COMMAND:
333 gdbarch = TUI_DISASM_WIN->gdbarch;
334 addr = TUI_DISASM_WIN->start_line_or_addr.u.addr;
335 break;
336 default:
337 addr = 0;
338 break;
339 }
340
341 *gdbarch_p = gdbarch;
342 *addr_p = addr;
343 }
344
345
346 /* Answer the previous layout to cycle to. */
347 static enum tui_layout_type
348 next_layout (void)
349 {
350 int new_layout;
351
352 new_layout = tui_current_layout ();
353 if (new_layout == UNDEFINED_LAYOUT)
354 new_layout = SRC_COMMAND;
355 else
356 {
357 new_layout++;
358 if (new_layout == UNDEFINED_LAYOUT)
359 new_layout = SRC_COMMAND;
360 }
361
362 return (enum tui_layout_type) new_layout;
363 }
364
365
366 /* Answer the next layout to cycle to. */
367 static enum tui_layout_type
368 prev_layout (void)
369 {
370 int new_layout;
371
372 new_layout = tui_current_layout ();
373 if (new_layout == SRC_COMMAND)
374 new_layout = DISASSEM_DATA_COMMAND;
375 else
376 {
377 new_layout--;
378 if (new_layout == UNDEFINED_LAYOUT)
379 new_layout = DISASSEM_DATA_COMMAND;
380 }
381
382 return (enum tui_layout_type) new_layout;
383 }
384
385 void
386 tui_gen_win_info::resize (int height_, int width_,
387 int origin_x_, int origin_y_)
388 {
389 if (width == width_ && height == height_
390 && x == origin_x_ && y == origin_y_
391 && handle != nullptr)
392 return;
393
394 width = width_;
395 height = height_;
396 x = origin_x_;
397 y = origin_y_;
398
399 if (handle != nullptr)
400 {
401 #ifdef HAVE_WRESIZE
402 wresize (handle.get (), height, width);
403 mvwin (handle.get (), y, x);
404 wmove (handle.get (), 0, 0);
405 #else
406 handle.reset (nullptr);
407 #endif
408 }
409
410 if (handle == nullptr)
411 make_window ();
412
413 rerender ();
414 }
415
416 \f
417
418 /* Helper function that returns a TUI window, given its name. */
419
420 static tui_gen_win_info *
421 tui_get_window_by_name (const std::string &name)
422 {
423 if (name == "src")
424 {
425 if (tui_win_list[SRC_WIN] == nullptr)
426 tui_win_list[SRC_WIN] = new tui_source_window ();
427 return tui_win_list[SRC_WIN];
428 }
429 else if (name == "cmd")
430 {
431 if (tui_win_list[CMD_WIN] == nullptr)
432 tui_win_list[CMD_WIN] = new tui_cmd_window ();
433 return tui_win_list[CMD_WIN];
434 }
435 else if (name == "regs")
436 {
437 if (tui_win_list[DATA_WIN] == nullptr)
438 tui_win_list[DATA_WIN] = new tui_data_window ();
439 return tui_win_list[DATA_WIN];
440 }
441 else if (name == "asm")
442 {
443 if (tui_win_list[DISASSEM_WIN] == nullptr)
444 tui_win_list[DISASSEM_WIN] = new tui_disasm_window ();
445 return tui_win_list[DISASSEM_WIN];
446 }
447 else
448 {
449 gdb_assert (name == "locator");
450 return tui_locator_win_info_ptr ();
451 }
452 }
453
454 /* See tui-layout.h. */
455
456 std::unique_ptr<tui_layout_base>
457 tui_layout_window::clone () const
458 {
459 tui_layout_window *result = new tui_layout_window (m_contents.c_str ());
460 return std::unique_ptr<tui_layout_base> (result);
461 }
462
463 /* See tui-layout.h. */
464
465 void
466 tui_layout_window::apply (int x_, int y_, int width_, int height_)
467 {
468 x = x_;
469 y = y_;
470 width = width_;
471 height = height_;
472 gdb_assert (m_window != nullptr);
473 m_window->resize (height, width, x, y);
474 }
475
476 /* See tui-layout.h. */
477
478 void
479 tui_layout_window::get_sizes (int *min_height, int *max_height)
480 {
481 if (m_window == nullptr)
482 m_window = tui_get_window_by_name (m_contents);
483 *min_height = m_window->min_height ();
484 *max_height = m_window->max_height ();
485 }
486
487 /* See tui-layout.h. */
488
489 bool
490 tui_layout_window::top_boxed_p () const
491 {
492 gdb_assert (m_window != nullptr);
493 return m_window->can_box ();
494 }
495
496 /* See tui-layout.h. */
497
498 bool
499 tui_layout_window::bottom_boxed_p () const
500 {
501 gdb_assert (m_window != nullptr);
502 return m_window->can_box ();
503 }
504
505 /* See tui-layout.h. */
506
507 tui_layout_split *
508 tui_layout_split::add_split (int weight)
509 {
510 tui_layout_split *result = new tui_layout_split ();
511 split s = {weight, std::unique_ptr<tui_layout_base> (result)};
512 m_splits.push_back (std::move (s));
513 return result;
514 }
515
516 /* See tui-layout.h. */
517
518 void
519 tui_layout_split::add_window (const char *name, int weight)
520 {
521 tui_layout_window *result = new tui_layout_window (name);
522 split s = {weight, std::unique_ptr<tui_layout_base> (result)};
523 m_splits.push_back (std::move (s));
524 }
525
526 /* See tui-layout.h. */
527
528 std::unique_ptr<tui_layout_base>
529 tui_layout_split::clone () const
530 {
531 tui_layout_split *result = new tui_layout_split ();
532 for (const split &item : m_splits)
533 {
534 std::unique_ptr<tui_layout_base> next = item.layout->clone ();
535 split s = {item.weight, std::move (next)};
536 result->m_splits.push_back (std::move (s));
537 }
538 return std::unique_ptr<tui_layout_base> (result);
539 }
540
541 /* See tui-layout.h. */
542
543 void
544 tui_layout_split::get_sizes (int *min_height, int *max_height)
545 {
546 *min_height = 0;
547 *max_height = 0;
548 for (const split &item : m_splits)
549 {
550 int new_min, new_max;
551 item.layout->get_sizes (&new_min, &new_max);
552 *min_height += new_min;
553 *max_height += new_max;
554 }
555 }
556
557 /* See tui-layout.h. */
558
559 bool
560 tui_layout_split::top_boxed_p () const
561 {
562 if (m_splits.empty ())
563 return false;
564 return m_splits[0].layout->top_boxed_p ();
565 }
566
567 /* See tui-layout.h. */
568
569 bool
570 tui_layout_split::bottom_boxed_p () const
571 {
572 if (m_splits.empty ())
573 return false;
574 return m_splits.back ().layout->top_boxed_p ();
575 }
576
577 /* See tui-layout.h. */
578
579 void
580 tui_layout_split::set_weights_from_heights ()
581 {
582 for (int i = 0; i < m_splits.size (); ++i)
583 m_splits[i].weight = m_splits[i].layout->height;
584 }
585
586 /* See tui-layout.h. */
587
588 bool
589 tui_layout_split::adjust_size (const char *name, int new_height)
590 {
591 /* Look through the children. If one is a layout holding the named
592 window, we're done; or if one actually is the named window,
593 update it. */
594 int found_index = -1;
595 for (int i = 0; i < m_splits.size (); ++i)
596 {
597 if (m_splits[i].layout->adjust_size (name, new_height))
598 return true;
599 const char *win_name = m_splits[i].layout->get_name ();
600 if (win_name != nullptr && strcmp (name, win_name) == 0)
601 {
602 found_index = i;
603 break;
604 }
605 }
606
607 if (found_index == -1)
608 return false;
609 if (m_splits[found_index].layout->height == new_height)
610 return true;
611
612 set_weights_from_heights ();
613 int delta = m_splits[found_index].weight - new_height;
614 m_splits[found_index].weight = new_height;
615
616 /* Distribute the "delta" over the next window; but if the next
617 window cannot hold it all, keep going until we either find a
618 window that does, or until we loop all the way around. */
619 for (int i = 0; delta != 0 && i < m_splits.size () - 1; ++i)
620 {
621 int index = (found_index + 1 + i) % m_splits.size ();
622
623 int new_min, new_max;
624 m_splits[index].layout->get_sizes (&new_min, &new_max);
625
626 if (delta < 0)
627 {
628 /* The primary window grew, so we are trying to shrink other
629 windows. */
630 int available = m_splits[index].weight - new_min;
631 int shrink_by = std::min (available, -delta);
632 m_splits[index].weight -= shrink_by;
633 delta += shrink_by;
634 }
635 else
636 {
637 /* The primary window shrank, so we are trying to grow other
638 windows. */
639 int available = new_max - m_splits[index].weight;
640 int grow_by = std::min (available, delta);
641 m_splits[index].weight += grow_by;
642 delta -= grow_by;
643 }
644 }
645
646 if (delta != 0)
647 {
648 warning (_("Invalid window height specified"));
649 /* Effectively undo any modifications made here. */
650 set_weights_from_heights ();
651 }
652 else
653 {
654 /* Simply re-apply the updated layout. */
655 apply (x, y, width, height);
656 }
657
658 return true;
659 }
660
661 /* See tui-layout.h. */
662
663 void
664 tui_layout_split::apply (int x_, int y_, int width_, int height_)
665 {
666 x = x_;
667 y = y_;
668 width = width_;
669 height = height_;
670
671 struct height_info
672 {
673 int height;
674 int min_height;
675 int max_height;
676 /* True if this window will share a box border with the previous
677 window in the list. */
678 bool share_box;
679 };
680
681 std::vector<height_info> info (m_splits.size ());
682
683 /* Step 1: Find the min and max height of each sub-layout.
684 Fixed-sized layouts are given their desired height, and then the
685 remaining space is distributed among the remaining windows
686 according to the weights given. */
687 int available_height = height;
688 int last_index = -1;
689 int total_weight = 0;
690 for (int i = 0; i < m_splits.size (); ++i)
691 {
692 bool cmd_win_already_exists = TUI_CMD_WIN != nullptr;
693
694 /* Always call get_sizes, to ensure that the window is
695 instantiated. This is a bit gross but less gross than adding
696 special cases for this in other places. */
697 m_splits[i].layout->get_sizes (&info[i].min_height, &info[i].max_height);
698
699 if (!m_applied
700 && cmd_win_already_exists
701 && m_splits[i].layout->get_name () != nullptr
702 && strcmp (m_splits[i].layout->get_name (), "cmd") == 0)
703 {
704 /* If this layout has never been applied, then it means the
705 user just changed the layout. In this situation, it's
706 desirable to keep the size of the command window the
707 same. Setting the min and max heights this way ensures
708 that the resizing step, below, does the right thing with
709 this window. */
710 info[i].min_height = TUI_CMD_WIN->height;
711 info[i].max_height = TUI_CMD_WIN->height;
712 }
713
714 if (info[i].min_height == info[i].max_height)
715 available_height -= info[i].min_height;
716 else
717 {
718 last_index = i;
719 total_weight += m_splits[i].weight;
720 }
721
722 /* Two adjacent boxed windows will share a border, making a bit
723 more height available. */
724 if (i > 0
725 && m_splits[i - 1].layout->bottom_boxed_p ()
726 && m_splits[i].layout->top_boxed_p ())
727 info[i].share_box = true;
728 }
729
730 /* Step 2: Compute the height of each sub-layout. Fixed-sized items
731 are given their fixed size, while others are resized according to
732 their weight. */
733 int used_height = 0;
734 for (int i = 0; i < m_splits.size (); ++i)
735 {
736 /* Compute the height and clamp to the allowable range. */
737 info[i].height = available_height * m_splits[i].weight / total_weight;
738 if (info[i].height > info[i].max_height)
739 info[i].height = info[i].max_height;
740 if (info[i].height < info[i].min_height)
741 info[i].height = info[i].min_height;
742 /* If there is any leftover height, just redistribute it to the
743 last resizeable window, by dropping it from the allocated
744 height. We could try to be fancier here perhaps, by
745 redistributing this height among all windows, not just the
746 last window. */
747 if (info[i].min_height != info[i].max_height)
748 {
749 used_height += info[i].height;
750 if (info[i].share_box)
751 --used_height;
752 }
753 }
754
755 /* Allocate any leftover height. */
756 if (available_height >= used_height && last_index != -1)
757 info[last_index].height += available_height - used_height;
758
759 /* Step 3: Resize. */
760 int height_accum = 0;
761 for (int i = 0; i < m_splits.size (); ++i)
762 {
763 /* If we fall off the bottom, just make allocations overlap.
764 GIGO. */
765 if (height_accum + info[i].height > height)
766 height_accum = height - info[i].height;
767 else if (info[i].share_box)
768 --height_accum;
769 m_splits[i].layout->apply (x, y + height_accum, width, info[i].height);
770 height_accum += info[i].height;
771 }
772
773 m_applied = true;
774 }
775
776 /* See tui-layout.h. */
777
778 void
779 tui_layout_split::remove_windows (const char *name)
780 {
781 for (int i = 0; i < m_splits.size (); ++i)
782 {
783 const char *this_name = m_splits[i].layout->get_name ();
784 if (this_name == nullptr)
785 m_splits[i].layout->remove_windows (name);
786 else
787 {
788 if (strcmp (this_name, name) == 0
789 || strcmp (this_name, "cmd") == 0)
790 {
791 /* Keep. */
792 }
793 m_splits.erase (m_splits.begin () + i);
794 --i;
795 }
796 }
797 }
798
799 static void
800 initialize_layouts ()
801 {
802 standard_layouts[SRC_COMMAND] = new tui_layout_split ();
803 standard_layouts[SRC_COMMAND]->add_window ("src", 2);
804 standard_layouts[SRC_COMMAND]->add_window ("locator", 0);
805 standard_layouts[SRC_COMMAND]->add_window ("cmd", 1);
806
807 standard_layouts[DISASSEM_COMMAND] = new tui_layout_split ();
808 standard_layouts[DISASSEM_COMMAND]->add_window ("asm", 2);
809 standard_layouts[DISASSEM_COMMAND]->add_window ("locator", 0);
810 standard_layouts[DISASSEM_COMMAND]->add_window ("cmd", 1);
811
812 standard_layouts[SRC_DATA_COMMAND] = new tui_layout_split ();
813 standard_layouts[SRC_DATA_COMMAND]->add_window ("regs", 1);
814 standard_layouts[SRC_DATA_COMMAND]->add_window ("src", 1);
815 standard_layouts[SRC_DATA_COMMAND]->add_window ("locator", 0);
816 standard_layouts[SRC_DATA_COMMAND]->add_window ("cmd", 1);
817
818 standard_layouts[DISASSEM_DATA_COMMAND] = new tui_layout_split ();
819 standard_layouts[DISASSEM_DATA_COMMAND]->add_window ("regs", 1);
820 standard_layouts[DISASSEM_DATA_COMMAND]->add_window ("asm", 1);
821 standard_layouts[DISASSEM_DATA_COMMAND]->add_window ("locator", 0);
822 standard_layouts[DISASSEM_DATA_COMMAND]->add_window ("cmd", 1);
823
824 standard_layouts[SRC_DISASSEM_COMMAND] = new tui_layout_split ();
825 standard_layouts[SRC_DISASSEM_COMMAND]->add_window ("src", 1);
826 standard_layouts[SRC_DISASSEM_COMMAND]->add_window ("asm", 1);
827 standard_layouts[SRC_DISASSEM_COMMAND]->add_window ("locator", 0);
828 standard_layouts[SRC_DISASSEM_COMMAND]->add_window ("cmd", 1);
829 }
830
831 \f
832
833 /* Function to initialize gdb commands, for tui window layout
834 manipulation. */
835
836 void _initialize_tui_layout ();
837 void
838 _initialize_tui_layout ()
839 {
840 struct cmd_list_element *cmd;
841
842 cmd = add_com ("layout", class_tui, tui_layout_command, _("\
843 Change the layout of windows.\n\
844 Usage: layout prev | next | LAYOUT-NAME\n\
845 Layout names are:\n\
846 src : Displays source and command windows.\n\
847 asm : Displays disassembly and command windows.\n\
848 split : Displays source, disassembly and command windows.\n\
849 regs : Displays register window. If existing layout\n\
850 is source/command or assembly/command, the \n\
851 register window is displayed. If the\n\
852 source/assembly/command (split) is displayed, \n\
853 the register window is displayed with \n\
854 the window that has current logical focus."));
855 set_cmd_completer (cmd, layout_completer);
856
857 initialize_layouts ();
858 }
This page took 0.047747 seconds and 4 git commands to generate.