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