gdb/tui: Disassembler scrolling of very small programs
[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
080ce8c0
AC
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. */
c906108c 193void
080ce8c0 194tui_add_win_to_layout (enum tui_win_type type)
c906108c 195{
6ba8e26f 196 enum tui_layout_type cur_layout = tui_current_layout ();
c906108c
SS
197
198 switch (type)
199 {
200 case SRC_WIN:
e5908723
MS
201 if (cur_layout != SRC_COMMAND
202 && cur_layout != SRC_DISASSEM_COMMAND
203 && cur_layout != SRC_DATA_COMMAND)
c906108c 204 {
6ba8e26f 205 if (cur_layout == DISASSEM_DATA_COMMAND)
f2302a34 206 tui_set_layout (SRC_DATA_COMMAND);
c906108c 207 else
f2302a34 208 tui_set_layout (SRC_COMMAND);
c906108c
SS
209 }
210 break;
211 case DISASSEM_WIN:
e5908723
MS
212 if (cur_layout != DISASSEM_COMMAND
213 && cur_layout != SRC_DISASSEM_COMMAND
214 && cur_layout != DISASSEM_DATA_COMMAND)
c906108c 215 {
6ba8e26f 216 if (cur_layout == SRC_DATA_COMMAND)
f2302a34 217 tui_set_layout (DISASSEM_DATA_COMMAND);
c906108c 218 else
f2302a34 219 tui_set_layout (DISASSEM_COMMAND);
c906108c
SS
220 }
221 break;
222 case DATA_WIN:
e5908723
MS
223 if (cur_layout != SRC_DATA_COMMAND
224 && cur_layout != DISASSEM_DATA_COMMAND)
c906108c 225 {
6ba8e26f 226 if (cur_layout == DISASSEM_COMMAND)
f2302a34 227 tui_set_layout (DISASSEM_DATA_COMMAND);
c906108c 228 else
f2302a34 229 tui_set_layout (SRC_DATA_COMMAND);
c906108c
SS
230 }
231 break;
232 default:
233 break;
234 }
6ba8e26f 235}
c906108c 236
a0145030
AB
237/* Complete possible layout names. TEXT is the complete text entered so
238 far, WORD is the word currently being completed. */
239
eb3ff9a5 240static void
a0145030 241layout_completer (struct cmd_list_element *ignore,
eb3ff9a5 242 completion_tracker &tracker,
a0145030
AB
243 const char *text, const char *word)
244{
245 static const char *layout_names [] =
246 { "src", "asm", "split", "regs", "next", "prev", NULL };
247
eb3ff9a5 248 complete_on_enum (tracker, layout_names, text, word);
a0145030
AB
249}
250
7bd0be3a
AB
251/* Function to set the layout to SRC, ASM, SPLIT, NEXT, PREV, DATA, or
252 REGS. */
0379b883
TT
253static void
254tui_layout_command (const char *layout_name, int from_tty)
c906108c 255{
0379b883
TT
256 enum tui_layout_type new_layout = UNDEFINED_LAYOUT;
257 enum tui_layout_type cur_layout = tui_current_layout ();
c906108c 258
78e8cb91 259 if (layout_name == NULL || *layout_name == '\0')
0379b883 260 error (_("Usage: layout prev | next | LAYOUT-NAME"));
c906108c 261
0379b883 262 /* First check for ambiguous input. */
78e8cb91 263 if (strcmp (layout_name, "s") == 0)
0379b883 264 error (_("Ambiguous command input."));
c906108c 265
78e8cb91 266 if (subset_compare (layout_name, "src"))
0379b883 267 new_layout = SRC_COMMAND;
78e8cb91 268 else if (subset_compare (layout_name, "asm"))
0379b883 269 new_layout = DISASSEM_COMMAND;
78e8cb91 270 else if (subset_compare (layout_name, "split"))
0379b883 271 new_layout = SRC_DISASSEM_COMMAND;
78e8cb91 272 else if (subset_compare (layout_name, "regs"))
0379b883
TT
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;
c906108c 279 }
78e8cb91 280 else if (subset_compare (layout_name, "next"))
0379b883 281 new_layout = next_layout ();
78e8cb91 282 else if (subset_compare (layout_name, "prev"))
0379b883 283 new_layout = prev_layout ();
c906108c 284 else
0379b883 285 error (_("Unrecognized layout: %s"), layout_name);
c906108c 286
0379b883
TT
287 /* Make sure the curses mode is enabled. */
288 tui_enable ();
289 tui_set_layout (new_layout);
e8b915dc 290}
c906108c
SS
291
292
13274fc3
UW
293static void
294extract_display_start_addr (struct gdbarch **gdbarch_p, CORE_ADDR *addr_p)
c906108c 295{
6ba8e26f 296 enum tui_layout_type cur_layout = tui_current_layout ();
957b8b5a 297 struct gdbarch *gdbarch = get_current_arch ();
c774cec6 298 CORE_ADDR addr;
84b1e7c7 299 CORE_ADDR pc;
52575520 300 struct symtab_and_line cursal = get_current_source_symtab_and_line ();
c906108c 301
6ba8e26f 302 switch (cur_layout)
c906108c
SS
303 {
304 case SRC_COMMAND:
305 case SRC_DATA_COMMAND:
e6e41501 306 gdbarch = TUI_SRC_WIN->gdbarch;
52575520 307 find_line_pc (cursal.symtab,
e6e41501 308 TUI_SRC_WIN->start_line_or_addr.u.line_no,
84b1e7c7 309 &pc);
c774cec6 310 addr = pc;
c906108c
SS
311 break;
312 case DISASSEM_COMMAND:
313 case SRC_DISASSEM_COMMAND:
314 case DISASSEM_DATA_COMMAND:
e6e41501
TT
315 gdbarch = TUI_DISASM_WIN->gdbarch;
316 addr = TUI_DISASM_WIN->start_line_or_addr.u.addr;
c906108c
SS
317 break;
318 default:
c774cec6 319 addr = 0;
c906108c
SS
320 break;
321 }
322
13274fc3
UW
323 *gdbarch_p = gdbarch;
324 *addr_p = addr;
6ba8e26f 325}
c906108c
SS
326
327
6ba8e26f 328/* Answer the previous layout to cycle to. */
2a8854a7 329static enum tui_layout_type
6ba8e26f 330next_layout (void)
c906108c 331{
570dc176 332 int new_layout;
c906108c 333
6ba8e26f
AC
334 new_layout = tui_current_layout ();
335 if (new_layout == UNDEFINED_LAYOUT)
336 new_layout = SRC_COMMAND;
c906108c
SS
337 else
338 {
6ba8e26f
AC
339 new_layout++;
340 if (new_layout == UNDEFINED_LAYOUT)
341 new_layout = SRC_COMMAND;
c906108c
SS
342 }
343
570dc176 344 return (enum tui_layout_type) new_layout;
6ba8e26f 345}
c906108c
SS
346
347
6ba8e26f 348/* Answer the next layout to cycle to. */
2a8854a7 349static enum tui_layout_type
6ba8e26f 350prev_layout (void)
c906108c 351{
570dc176 352 int new_layout;
c906108c 353
6ba8e26f
AC
354 new_layout = tui_current_layout ();
355 if (new_layout == SRC_COMMAND)
356 new_layout = DISASSEM_DATA_COMMAND;
c906108c
SS
357 else
358 {
6ba8e26f
AC
359 new_layout--;
360 if (new_layout == UNDEFINED_LAYOUT)
361 new_layout = DISASSEM_DATA_COMMAND;
c906108c
SS
362 }
363
570dc176 364 return (enum tui_layout_type) new_layout;
6ba8e26f 365}
c906108c 366
d6ba6a11 367void
ee556432
TT
368tui_gen_win_info::resize (int height_, int width_,
369 int origin_x_, int origin_y_)
c906108c 370{
cdaa6eb4 371 if (width == width_ && height == height_
fb3184d8 372 && x == origin_x_ && y == origin_y_
cdaa6eb4
TT
373 && handle != nullptr)
374 return;
375
d6ba6a11 376 width = width_;
db502012 377 height = height_;
fb3184d8
TT
378 x = origin_x_;
379 y = origin_y_;
db502012
TT
380
381 if (handle != nullptr)
382 {
383#ifdef HAVE_WRESIZE
7523da63 384 wresize (handle.get (), height, width);
fb3184d8 385 mvwin (handle.get (), y, x);
7523da63 386 wmove (handle.get (), 0, 0);
db502012 387#else
7523da63 388 handle.reset (nullptr);
db502012
TT
389#endif
390 }
391
392 if (handle == nullptr)
ab0e1f1a 393 make_window ();
3df505f6
TT
394
395 rerender ();
d6ba6a11 396}
c906108c 397
d9fcefd5
TT
398\f
399
389e7ddb
TT
400/* Helper function that returns a TUI window, given its name. */
401
402static tui_gen_win_info *
403tui_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
438std::unique_ptr<tui_layout_base>
439tui_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
447void
448tui_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
460void
461tui_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
471bool
472tui_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
480bool
481tui_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
489tui_layout_split *
490tui_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
500void
501tui_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
510std::unique_ptr<tui_layout_base>
511tui_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
525void
526tui_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
541bool
542tui_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
551bool
552tui_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
561void
562tui_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
570bool
571tui_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
645void
646tui_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
2192a9d3
TT
758static void
759initialize_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
389e7ddb
TT
790\f
791
d9fcefd5
TT
792/* Function to initialize gdb commands, for tui window layout
793 manipulation. */
794
6c265988 795void _initialize_tui_layout ();
d9fcefd5 796void
6c265988 797_initialize_tui_layout ()
d9fcefd5
TT
798{
799 struct cmd_list_element *cmd;
800
801 cmd = add_com ("layout", class_tui, tui_layout_command, _("\
802Change the layout of windows.\n\
803Usage: layout prev | next | LAYOUT-NAME\n\
804Layout 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);
2192a9d3
TT
815
816 initialize_layouts ();
d9fcefd5 817}
This page took 2.247655 seconds and 4 git commands to generate.