Remove flickering from the TUI
[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 /* Add the specified window to the layout in a logical way. This
191 means setting up the most logical layout given the window to be
192 added. */
193 void
194 tui_add_win_to_layout (enum tui_win_type type)
195 {
196 enum tui_layout_type cur_layout = tui_current_layout ();
197
198 switch (type)
199 {
200 case SRC_WIN:
201 if (cur_layout != SRC_COMMAND
202 && cur_layout != SRC_DISASSEM_COMMAND
203 && cur_layout != SRC_DATA_COMMAND)
204 {
205 if (cur_layout == DISASSEM_DATA_COMMAND)
206 tui_set_layout (SRC_DATA_COMMAND);
207 else
208 tui_set_layout (SRC_COMMAND);
209 }
210 break;
211 case DISASSEM_WIN:
212 if (cur_layout != DISASSEM_COMMAND
213 && cur_layout != SRC_DISASSEM_COMMAND
214 && cur_layout != DISASSEM_DATA_COMMAND)
215 {
216 if (cur_layout == SRC_DATA_COMMAND)
217 tui_set_layout (DISASSEM_DATA_COMMAND);
218 else
219 tui_set_layout (DISASSEM_COMMAND);
220 }
221 break;
222 case DATA_WIN:
223 if (cur_layout != SRC_DATA_COMMAND
224 && cur_layout != DISASSEM_DATA_COMMAND)
225 {
226 if (cur_layout == DISASSEM_COMMAND)
227 tui_set_layout (DISASSEM_DATA_COMMAND);
228 else
229 tui_set_layout (SRC_DATA_COMMAND);
230 }
231 break;
232 default:
233 break;
234 }
235 }
236
237 /* Complete possible layout names. TEXT is the complete text entered so
238 far, WORD is the word currently being completed. */
239
240 static void
241 layout_completer (struct cmd_list_element *ignore,
242 completion_tracker &tracker,
243 const char *text, const char *word)
244 {
245 static const char *layout_names [] =
246 { "src", "asm", "split", "regs", "next", "prev", NULL };
247
248 complete_on_enum (tracker, layout_names, text, word);
249 }
250
251 /* Function to set the layout to SRC, ASM, SPLIT, NEXT, PREV, DATA, or
252 REGS. */
253 static void
254 tui_layout_command (const char *layout_name, int from_tty)
255 {
256 enum tui_layout_type new_layout = UNDEFINED_LAYOUT;
257 enum tui_layout_type cur_layout = tui_current_layout ();
258
259 if (layout_name == NULL || *layout_name == '\0')
260 error (_("Usage: layout prev | next | LAYOUT-NAME"));
261
262 /* First check for ambiguous input. */
263 if (strcmp (layout_name, "s") == 0)
264 error (_("Ambiguous command input."));
265
266 if (subset_compare (layout_name, "src"))
267 new_layout = SRC_COMMAND;
268 else if (subset_compare (layout_name, "asm"))
269 new_layout = DISASSEM_COMMAND;
270 else if (subset_compare (layout_name, "split"))
271 new_layout = SRC_DISASSEM_COMMAND;
272 else if (subset_compare (layout_name, "regs"))
273 {
274 if (cur_layout == SRC_COMMAND
275 || cur_layout == SRC_DATA_COMMAND)
276 new_layout = SRC_DATA_COMMAND;
277 else
278 new_layout = DISASSEM_DATA_COMMAND;
279 }
280 else if (subset_compare (layout_name, "next"))
281 new_layout = next_layout ();
282 else if (subset_compare (layout_name, "prev"))
283 new_layout = prev_layout ();
284 else
285 error (_("Unrecognized layout: %s"), layout_name);
286
287 /* Make sure the curses mode is enabled. */
288 tui_enable ();
289 tui_set_layout (new_layout);
290 }
291
292
293 static void
294 extract_display_start_addr (struct gdbarch **gdbarch_p, CORE_ADDR *addr_p)
295 {
296 enum tui_layout_type cur_layout = tui_current_layout ();
297 struct gdbarch *gdbarch = get_current_arch ();
298 CORE_ADDR addr;
299 CORE_ADDR pc;
300 struct symtab_and_line cursal = get_current_source_symtab_and_line ();
301
302 switch (cur_layout)
303 {
304 case SRC_COMMAND:
305 case SRC_DATA_COMMAND:
306 gdbarch = TUI_SRC_WIN->gdbarch;
307 find_line_pc (cursal.symtab,
308 TUI_SRC_WIN->start_line_or_addr.u.line_no,
309 &pc);
310 addr = pc;
311 break;
312 case DISASSEM_COMMAND:
313 case SRC_DISASSEM_COMMAND:
314 case DISASSEM_DATA_COMMAND:
315 gdbarch = TUI_DISASM_WIN->gdbarch;
316 addr = TUI_DISASM_WIN->start_line_or_addr.u.addr;
317 break;
318 default:
319 addr = 0;
320 break;
321 }
322
323 *gdbarch_p = gdbarch;
324 *addr_p = addr;
325 }
326
327
328 /* Answer the previous layout to cycle to. */
329 static enum tui_layout_type
330 next_layout (void)
331 {
332 int new_layout;
333
334 new_layout = tui_current_layout ();
335 if (new_layout == UNDEFINED_LAYOUT)
336 new_layout = SRC_COMMAND;
337 else
338 {
339 new_layout++;
340 if (new_layout == UNDEFINED_LAYOUT)
341 new_layout = SRC_COMMAND;
342 }
343
344 return (enum tui_layout_type) new_layout;
345 }
346
347
348 /* Answer the next layout to cycle to. */
349 static enum tui_layout_type
350 prev_layout (void)
351 {
352 int new_layout;
353
354 new_layout = tui_current_layout ();
355 if (new_layout == SRC_COMMAND)
356 new_layout = DISASSEM_DATA_COMMAND;
357 else
358 {
359 new_layout--;
360 if (new_layout == UNDEFINED_LAYOUT)
361 new_layout = DISASSEM_DATA_COMMAND;
362 }
363
364 return (enum tui_layout_type) new_layout;
365 }
366
367 void
368 tui_gen_win_info::resize (int height_, int width_,
369 int origin_x_, int origin_y_)
370 {
371 if (width == width_ && height == height_
372 && x == origin_x_ && y == origin_y_
373 && handle != nullptr)
374 return;
375
376 width = width_;
377 height = height_;
378 x = origin_x_;
379 y = origin_y_;
380
381 if (handle != nullptr)
382 {
383 #ifdef HAVE_WRESIZE
384 wresize (handle.get (), height, width);
385 mvwin (handle.get (), y, x);
386 wmove (handle.get (), 0, 0);
387 #else
388 handle.reset (nullptr);
389 #endif
390 }
391
392 if (handle == nullptr)
393 make_window ();
394
395 rerender ();
396 }
397
398 \f
399
400 /* Helper function that returns a TUI window, given its name. */
401
402 static tui_gen_win_info *
403 tui_get_window_by_name (const std::string &name)
404 {
405 if (name == "src")
406 {
407 if (tui_win_list[SRC_WIN] == nullptr)
408 tui_win_list[SRC_WIN] = new tui_source_window ();
409 return tui_win_list[SRC_WIN];
410 }
411 else if (name == "cmd")
412 {
413 if (tui_win_list[CMD_WIN] == nullptr)
414 tui_win_list[CMD_WIN] = new tui_cmd_window ();
415 return tui_win_list[CMD_WIN];
416 }
417 else if (name == "regs")
418 {
419 if (tui_win_list[DATA_WIN] == nullptr)
420 tui_win_list[DATA_WIN] = new tui_data_window ();
421 return tui_win_list[DATA_WIN];
422 }
423 else if (name == "asm")
424 {
425 if (tui_win_list[DISASSEM_WIN] == nullptr)
426 tui_win_list[DISASSEM_WIN] = new tui_disasm_window ();
427 return tui_win_list[DISASSEM_WIN];
428 }
429 else
430 {
431 gdb_assert (name == "locator");
432 return tui_locator_win_info_ptr ();
433 }
434 }
435
436 /* See tui-layout.h. */
437
438 std::unique_ptr<tui_layout_base>
439 tui_layout_window::clone () const
440 {
441 tui_layout_window *result = new tui_layout_window (m_contents.c_str ());
442 return std::unique_ptr<tui_layout_base> (result);
443 }
444
445 /* See tui-layout.h. */
446
447 void
448 tui_layout_window::apply (int x_, int y_, int width_, int height_)
449 {
450 x = x_;
451 y = y_;
452 width = width_;
453 height = height_;
454 gdb_assert (m_window != nullptr);
455 m_window->resize (height, width, x, y);
456 }
457
458 /* See tui-layout.h. */
459
460 void
461 tui_layout_window::get_sizes (int *min_height, int *max_height)
462 {
463 if (m_window == nullptr)
464 m_window = tui_get_window_by_name (m_contents);
465 *min_height = m_window->min_height ();
466 *max_height = m_window->max_height ();
467 }
468
469 /* See tui-layout.h. */
470
471 bool
472 tui_layout_window::top_boxed_p () const
473 {
474 gdb_assert (m_window != nullptr);
475 return m_window->can_box ();
476 }
477
478 /* See tui-layout.h. */
479
480 bool
481 tui_layout_window::bottom_boxed_p () const
482 {
483 gdb_assert (m_window != nullptr);
484 return m_window->can_box ();
485 }
486
487 /* See tui-layout.h. */
488
489 tui_layout_split *
490 tui_layout_split::add_split (int weight)
491 {
492 tui_layout_split *result = new tui_layout_split ();
493 split s = {weight, std::unique_ptr<tui_layout_base> (result)};
494 m_splits.push_back (std::move (s));
495 return result;
496 }
497
498 /* See tui-layout.h. */
499
500 void
501 tui_layout_split::add_window (const char *name, int weight)
502 {
503 tui_layout_window *result = new tui_layout_window (name);
504 split s = {weight, std::unique_ptr<tui_layout_base> (result)};
505 m_splits.push_back (std::move (s));
506 }
507
508 /* See tui-layout.h. */
509
510 std::unique_ptr<tui_layout_base>
511 tui_layout_split::clone () const
512 {
513 tui_layout_split *result = new tui_layout_split ();
514 for (const split &item : m_splits)
515 {
516 std::unique_ptr<tui_layout_base> next = item.layout->clone ();
517 split s = {item.weight, std::move (next)};
518 result->m_splits.push_back (std::move (s));
519 }
520 return std::unique_ptr<tui_layout_base> (result);
521 }
522
523 /* See tui-layout.h. */
524
525 void
526 tui_layout_split::get_sizes (int *min_height, int *max_height)
527 {
528 *min_height = 0;
529 *max_height = 0;
530 for (const split &item : m_splits)
531 {
532 int new_min, new_max;
533 item.layout->get_sizes (&new_min, &new_max);
534 *min_height += new_min;
535 *max_height += new_max;
536 }
537 }
538
539 /* See tui-layout.h. */
540
541 bool
542 tui_layout_split::top_boxed_p () const
543 {
544 if (m_splits.empty ())
545 return false;
546 return m_splits[0].layout->top_boxed_p ();
547 }
548
549 /* See tui-layout.h. */
550
551 bool
552 tui_layout_split::bottom_boxed_p () const
553 {
554 if (m_splits.empty ())
555 return false;
556 return m_splits.back ().layout->top_boxed_p ();
557 }
558
559 /* See tui-layout.h. */
560
561 void
562 tui_layout_split::set_weights_from_heights ()
563 {
564 for (int i = 0; i < m_splits.size (); ++i)
565 m_splits[i].weight = m_splits[i].layout->height;
566 }
567
568 /* See tui-layout.h. */
569
570 bool
571 tui_layout_split::adjust_size (const char *name, int new_height)
572 {
573 /* Look through the children. If one is a layout holding the named
574 window, we're done; or if one actually is the named window,
575 update it. */
576 int found_index = -1;
577 for (int i = 0; i < m_splits.size (); ++i)
578 {
579 if (m_splits[i].layout->adjust_size (name, new_height))
580 return true;
581 const char *win_name = m_splits[i].layout->get_name ();
582 if (win_name != nullptr && strcmp (name, win_name) == 0)
583 {
584 found_index = i;
585 break;
586 }
587 }
588
589 if (found_index == -1)
590 return false;
591 if (m_splits[found_index].layout->height == new_height)
592 return true;
593
594 set_weights_from_heights ();
595 int delta = m_splits[found_index].weight - new_height;
596 m_splits[found_index].weight = new_height;
597
598 /* Distribute the "delta" over the next window; but if the next
599 window cannot hold it all, keep going until we either find a
600 window that does, or until we loop all the way around. */
601 for (int i = 0; delta != 0 && i < m_splits.size () - 1; ++i)
602 {
603 int index = (found_index + 1 + i) % m_splits.size ();
604
605 int new_min, new_max;
606 m_splits[index].layout->get_sizes (&new_min, &new_max);
607
608 if (delta < 0)
609 {
610 /* The primary window grew, so we are trying to shrink other
611 windows. */
612 int available = m_splits[index].weight - new_min;
613 int shrink_by = std::min (available, -delta);
614 m_splits[index].weight -= shrink_by;
615 delta += shrink_by;
616 }
617 else
618 {
619 /* The primary window shrank, so we are trying to grow other
620 windows. */
621 int available = new_max - m_splits[index].weight;
622 int grow_by = std::min (available, delta);
623 m_splits[index].weight += grow_by;
624 delta -= grow_by;
625 }
626 }
627
628 if (delta != 0)
629 {
630 warning (_("Invalid window height specified"));
631 /* Effectively undo any modifications made here. */
632 set_weights_from_heights ();
633 }
634 else
635 {
636 /* Simply re-apply the updated layout. */
637 apply (x, y, width, height);
638 }
639
640 return true;
641 }
642
643 /* See tui-layout.h. */
644
645 void
646 tui_layout_split::apply (int x_, int y_, int width_, int height_)
647 {
648 x = x_;
649 y = y_;
650 width = width_;
651 height = height_;
652
653 struct height_info
654 {
655 int height;
656 int min_height;
657 int max_height;
658 /* True if this window will share a box border with the previous
659 window in the list. */
660 bool share_box;
661 };
662
663 std::vector<height_info> info (m_splits.size ());
664
665 /* Step 1: Find the min and max height of each sub-layout.
666 Fixed-sized layouts are given their desired height, and then the
667 remaining space is distributed among the remaining windows
668 according to the weights given. */
669 int available_height = height;
670 int last_index = -1;
671 int total_weight = 0;
672 for (int i = 0; i < m_splits.size (); ++i)
673 {
674 bool cmd_win_already_exists = TUI_CMD_WIN != nullptr;
675
676 /* Always call get_sizes, to ensure that the window is
677 instantiated. This is a bit gross but less gross than adding
678 special cases for this in other places. */
679 m_splits[i].layout->get_sizes (&info[i].min_height, &info[i].max_height);
680
681 if (!m_applied
682 && cmd_win_already_exists
683 && m_splits[i].layout->get_name () != nullptr
684 && strcmp (m_splits[i].layout->get_name (), "cmd") == 0)
685 {
686 /* If this layout has never been applied, then it means the
687 user just changed the layout. In this situation, it's
688 desirable to keep the size of the command window the
689 same. Setting the min and max heights this way ensures
690 that the resizing step, below, does the right thing with
691 this window. */
692 info[i].min_height = TUI_CMD_WIN->height;
693 info[i].max_height = TUI_CMD_WIN->height;
694 }
695
696 if (info[i].min_height == info[i].max_height)
697 available_height -= info[i].min_height;
698 else
699 {
700 last_index = i;
701 total_weight += m_splits[i].weight;
702 }
703
704 /* Two adjacent boxed windows will share a border, making a bit
705 more height available. */
706 if (i > 0
707 && m_splits[i - 1].layout->bottom_boxed_p ()
708 && m_splits[i].layout->top_boxed_p ())
709 info[i].share_box = true;
710 }
711
712 /* Step 2: Compute the height of each sub-layout. Fixed-sized items
713 are given their fixed size, while others are resized according to
714 their weight. */
715 int used_height = 0;
716 for (int i = 0; i < m_splits.size (); ++i)
717 {
718 /* Compute the height and clamp to the allowable range. */
719 info[i].height = available_height * m_splits[i].weight / total_weight;
720 if (info[i].height > info[i].max_height)
721 info[i].height = info[i].max_height;
722 if (info[i].height < info[i].min_height)
723 info[i].height = info[i].min_height;
724 /* If there is any leftover height, just redistribute it to the
725 last resizeable window, by dropping it from the allocated
726 height. We could try to be fancier here perhaps, by
727 redistributing this height among all windows, not just the
728 last window. */
729 if (info[i].min_height != info[i].max_height)
730 {
731 used_height += info[i].height;
732 if (info[i].share_box)
733 --used_height;
734 }
735 }
736
737 /* Allocate any leftover height. */
738 if (available_height >= used_height && last_index != -1)
739 info[last_index].height += available_height - used_height;
740
741 /* Step 3: Resize. */
742 int height_accum = 0;
743 for (int i = 0; i < m_splits.size (); ++i)
744 {
745 /* If we fall off the bottom, just make allocations overlap.
746 GIGO. */
747 if (height_accum + info[i].height > height)
748 height_accum = height - info[i].height;
749 else if (info[i].share_box)
750 --height_accum;
751 m_splits[i].layout->apply (x, y + height_accum, width, info[i].height);
752 height_accum += info[i].height;
753 }
754
755 m_applied = true;
756 }
757
758 static void
759 initialize_layouts ()
760 {
761 standard_layouts[SRC_COMMAND] = new tui_layout_split ();
762 standard_layouts[SRC_COMMAND]->add_window ("src", 2);
763 standard_layouts[SRC_COMMAND]->add_window ("locator", 0);
764 standard_layouts[SRC_COMMAND]->add_window ("cmd", 1);
765
766 standard_layouts[DISASSEM_COMMAND] = new tui_layout_split ();
767 standard_layouts[DISASSEM_COMMAND]->add_window ("asm", 2);
768 standard_layouts[DISASSEM_COMMAND]->add_window ("locator", 0);
769 standard_layouts[DISASSEM_COMMAND]->add_window ("cmd", 1);
770
771 standard_layouts[SRC_DATA_COMMAND] = new tui_layout_split ();
772 standard_layouts[SRC_DATA_COMMAND]->add_window ("regs", 1);
773 standard_layouts[SRC_DATA_COMMAND]->add_window ("src", 1);
774 standard_layouts[SRC_DATA_COMMAND]->add_window ("locator", 0);
775 standard_layouts[SRC_DATA_COMMAND]->add_window ("cmd", 1);
776
777 standard_layouts[DISASSEM_DATA_COMMAND] = new tui_layout_split ();
778 standard_layouts[DISASSEM_DATA_COMMAND]->add_window ("regs", 1);
779 standard_layouts[DISASSEM_DATA_COMMAND]->add_window ("asm", 1);
780 standard_layouts[DISASSEM_DATA_COMMAND]->add_window ("locator", 0);
781 standard_layouts[DISASSEM_DATA_COMMAND]->add_window ("cmd", 1);
782
783 standard_layouts[SRC_DISASSEM_COMMAND] = new tui_layout_split ();
784 standard_layouts[SRC_DISASSEM_COMMAND]->add_window ("src", 1);
785 standard_layouts[SRC_DISASSEM_COMMAND]->add_window ("asm", 1);
786 standard_layouts[SRC_DISASSEM_COMMAND]->add_window ("locator", 0);
787 standard_layouts[SRC_DISASSEM_COMMAND]->add_window ("cmd", 1);
788 }
789
790 \f
791
792 /* Function to initialize gdb commands, for tui window layout
793 manipulation. */
794
795 void _initialize_tui_layout ();
796 void
797 _initialize_tui_layout ()
798 {
799 struct cmd_list_element *cmd;
800
801 cmd = add_com ("layout", class_tui, tui_layout_command, _("\
802 Change the layout of windows.\n\
803 Usage: layout prev | next | LAYOUT-NAME\n\
804 Layout names are:\n\
805 src : Displays source and command windows.\n\
806 asm : Displays disassembly and command windows.\n\
807 split : Displays source, disassembly and command windows.\n\
808 regs : Displays register window. If existing layout\n\
809 is source/command or assembly/command, the \n\
810 register window is displayed. If the\n\
811 source/assembly/command (split) is displayed, \n\
812 the register window is displayed with \n\
813 the window that has current logical focus."));
814 set_cmd_completer (cmd, layout_completer);
815
816 initialize_layouts ();
817 }
This page took 0.045765 seconds and 4 git commands to generate.