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