Move _initialize_tui_layout to end of file
[deliverable/binutils-gdb.git] / gdb / tui / tui-layout.c
1 /* TUI layout window management.
2
3 Copyright (C) 1998-2019 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 void show_source_or_disasm_and_command (enum tui_layout_type);
45 static void show_source_command (void);
46 static void show_disasm_command (void);
47 static void show_source_disasm_command (void);
48 static void show_data (enum tui_layout_type);
49 static enum tui_layout_type next_layout (void);
50 static enum tui_layout_type prev_layout (void);
51 static void tui_layout_command (const char *, int);
52 static void extract_display_start_addr (struct gdbarch **, CORE_ADDR *);
53
54
55 static enum tui_layout_type current_layout = UNDEFINED_LAYOUT;
56
57 /* Accessor for the current layout. */
58 enum tui_layout_type
59 tui_current_layout (void)
60 {
61 return current_layout;
62 }
63
64
65 /* Show the screen layout defined. */
66 static void
67 show_layout (enum tui_layout_type layout)
68 {
69 enum tui_layout_type cur_layout = tui_current_layout ();
70
71 if (layout != cur_layout)
72 {
73 tui_make_all_invisible ();
74 switch (layout)
75 {
76 case SRC_DATA_COMMAND:
77 case DISASSEM_DATA_COMMAND:
78 show_data (layout);
79 break;
80 /* Now show the new layout. */
81 case SRC_COMMAND:
82 show_source_command ();
83 break;
84 case DISASSEM_COMMAND:
85 show_disasm_command ();
86 break;
87 case SRC_DISASSEM_COMMAND:
88 show_source_disasm_command ();
89 break;
90 default:
91 break;
92 }
93
94 tui_delete_invisible_windows ();
95 }
96 }
97
98
99 /* Function to set the layout to SRC_COMMAND, DISASSEM_COMMAND,
100 SRC_DISASSEM_COMMAND, SRC_DATA_COMMAND, or DISASSEM_DATA_COMMAND. */
101 void
102 tui_set_layout (enum tui_layout_type layout_type)
103 {
104 gdb_assert (layout_type != UNDEFINED_LAYOUT);
105
106 enum tui_layout_type cur_layout = tui_current_layout ();
107 struct gdbarch *gdbarch;
108 CORE_ADDR addr;
109 struct tui_win_info *win_with_focus = tui_win_with_focus ();
110
111 extract_display_start_addr (&gdbarch, &addr);
112
113 enum tui_layout_type new_layout = layout_type;
114
115 if (new_layout != cur_layout)
116 {
117 show_layout (new_layout);
118
119 /* Now determine where focus should be. */
120 if (win_with_focus != TUI_CMD_WIN)
121 {
122 switch (new_layout)
123 {
124 case SRC_COMMAND:
125 tui_set_win_focus_to (TUI_SRC_WIN);
126 break;
127 case DISASSEM_COMMAND:
128 /* The previous layout was not showing code.
129 This can happen if there is no source
130 available:
131
132 1. if the source file is in another dir OR
133 2. if target was compiled without -g
134 We still want to show the assembly though! */
135
136 tui_get_begin_asm_address (&gdbarch, &addr);
137 tui_set_win_focus_to (TUI_DISASM_WIN);
138 break;
139 case SRC_DISASSEM_COMMAND:
140 /* The previous layout was not showing code.
141 This can happen if there is no source
142 available:
143
144 1. if the source file is in another dir OR
145 2. if target was compiled without -g
146 We still want to show the assembly though! */
147
148 tui_get_begin_asm_address (&gdbarch, &addr);
149 if (win_with_focus == TUI_SRC_WIN)
150 tui_set_win_focus_to (TUI_SRC_WIN);
151 else
152 tui_set_win_focus_to (TUI_DISASM_WIN);
153 break;
154 case SRC_DATA_COMMAND:
155 if (win_with_focus != TUI_DATA_WIN)
156 tui_set_win_focus_to (TUI_SRC_WIN);
157 else
158 tui_set_win_focus_to (TUI_DATA_WIN);
159 break;
160 case DISASSEM_DATA_COMMAND:
161 /* The previous layout was not showing code.
162 This can happen if there is no source
163 available:
164
165 1. if the source file is in another dir OR
166 2. if target was compiled without -g
167 We still want to show the assembly though! */
168
169 tui_get_begin_asm_address (&gdbarch, &addr);
170 if (win_with_focus != TUI_DATA_WIN)
171 tui_set_win_focus_to (TUI_DISASM_WIN);
172 else
173 tui_set_win_focus_to (TUI_DATA_WIN);
174 break;
175 default:
176 break;
177 }
178 }
179 /*
180 * Now update the window content.
181 */
182 tui_update_source_windows_with_addr (gdbarch, addr);
183 if (new_layout == SRC_DATA_COMMAND
184 || new_layout == DISASSEM_DATA_COMMAND)
185 TUI_DATA_WIN->show_registers (TUI_DATA_WIN->get_current_group ());
186 }
187 }
188
189 /* Add the specified window to the layout in a logical way. This
190 means setting up the most logical layout given the window to be
191 added. */
192 void
193 tui_add_win_to_layout (enum tui_win_type type)
194 {
195 enum tui_layout_type cur_layout = tui_current_layout ();
196
197 switch (type)
198 {
199 case SRC_WIN:
200 if (cur_layout != SRC_COMMAND
201 && cur_layout != SRC_DISASSEM_COMMAND
202 && cur_layout != SRC_DATA_COMMAND)
203 {
204 if (cur_layout == DISASSEM_DATA_COMMAND)
205 show_layout (SRC_DATA_COMMAND);
206 else
207 show_layout (SRC_COMMAND);
208 }
209 break;
210 case DISASSEM_WIN:
211 if (cur_layout != DISASSEM_COMMAND
212 && cur_layout != SRC_DISASSEM_COMMAND
213 && cur_layout != DISASSEM_DATA_COMMAND)
214 {
215 if (cur_layout == SRC_DATA_COMMAND)
216 show_layout (DISASSEM_DATA_COMMAND);
217 else
218 show_layout (DISASSEM_COMMAND);
219 }
220 break;
221 case DATA_WIN:
222 if (cur_layout != SRC_DATA_COMMAND
223 && cur_layout != DISASSEM_DATA_COMMAND)
224 {
225 if (cur_layout == DISASSEM_COMMAND)
226 show_layout (DISASSEM_DATA_COMMAND);
227 else
228 show_layout (SRC_DATA_COMMAND);
229 }
230 break;
231 default:
232 break;
233 }
234 }
235
236 /* Complete possible layout names. TEXT is the complete text entered so
237 far, WORD is the word currently being completed. */
238
239 static void
240 layout_completer (struct cmd_list_element *ignore,
241 completion_tracker &tracker,
242 const char *text, const char *word)
243 {
244 static const char *layout_names [] =
245 { "src", "asm", "split", "regs", "next", "prev", NULL };
246
247 complete_on_enum (tracker, layout_names, text, word);
248 }
249
250 /* Function to set the layout to SRC, ASM, SPLIT, NEXT, PREV, DATA, or
251 REGS. */
252 static void
253 tui_layout_command (const char *layout_name, int from_tty)
254 {
255 enum tui_layout_type new_layout = UNDEFINED_LAYOUT;
256 enum tui_layout_type cur_layout = tui_current_layout ();
257
258 if (layout_name == NULL || *layout_name == '\0')
259 error (_("Usage: layout prev | next | LAYOUT-NAME"));
260
261 /* First check for ambiguous input. */
262 if (strcmp (layout_name, "s") == 0)
263 error (_("Ambiguous command input."));
264
265 if (subset_compare (layout_name, "src"))
266 new_layout = SRC_COMMAND;
267 else if (subset_compare (layout_name, "asm"))
268 new_layout = DISASSEM_COMMAND;
269 else if (subset_compare (layout_name, "split"))
270 new_layout = SRC_DISASSEM_COMMAND;
271 else if (subset_compare (layout_name, "regs"))
272 {
273 if (cur_layout == SRC_COMMAND
274 || cur_layout == SRC_DATA_COMMAND)
275 new_layout = SRC_DATA_COMMAND;
276 else
277 new_layout = DISASSEM_DATA_COMMAND;
278 }
279 else if (subset_compare (layout_name, "next"))
280 new_layout = next_layout ();
281 else if (subset_compare (layout_name, "prev"))
282 new_layout = prev_layout ();
283 else
284 error (_("Unrecognized layout: %s"), layout_name);
285
286 /* Make sure the curses mode is enabled. */
287 tui_enable ();
288 tui_set_layout (new_layout);
289 }
290
291
292 static void
293 extract_display_start_addr (struct gdbarch **gdbarch_p, CORE_ADDR *addr_p)
294 {
295 enum tui_layout_type cur_layout = tui_current_layout ();
296 struct gdbarch *gdbarch = get_current_arch ();
297 CORE_ADDR addr;
298 CORE_ADDR pc;
299 struct symtab_and_line cursal = get_current_source_symtab_and_line ();
300
301 switch (cur_layout)
302 {
303 case SRC_COMMAND:
304 case SRC_DATA_COMMAND:
305 gdbarch = TUI_SRC_WIN->gdbarch;
306 find_line_pc (cursal.symtab,
307 TUI_SRC_WIN->start_line_or_addr.u.line_no,
308 &pc);
309 addr = pc;
310 break;
311 case DISASSEM_COMMAND:
312 case SRC_DISASSEM_COMMAND:
313 case DISASSEM_DATA_COMMAND:
314 gdbarch = TUI_DISASM_WIN->gdbarch;
315 addr = TUI_DISASM_WIN->start_line_or_addr.u.addr;
316 break;
317 default:
318 addr = 0;
319 break;
320 }
321
322 *gdbarch_p = gdbarch;
323 *addr_p = addr;
324 }
325
326
327 /* Answer the previous layout to cycle to. */
328 static enum tui_layout_type
329 next_layout (void)
330 {
331 int new_layout;
332
333 new_layout = tui_current_layout ();
334 if (new_layout == UNDEFINED_LAYOUT)
335 new_layout = SRC_COMMAND;
336 else
337 {
338 new_layout++;
339 if (new_layout == UNDEFINED_LAYOUT)
340 new_layout = SRC_COMMAND;
341 }
342
343 return (enum tui_layout_type) new_layout;
344 }
345
346
347 /* Answer the next layout to cycle to. */
348 static enum tui_layout_type
349 prev_layout (void)
350 {
351 int new_layout;
352
353 new_layout = tui_current_layout ();
354 if (new_layout == SRC_COMMAND)
355 new_layout = DISASSEM_DATA_COMMAND;
356 else
357 {
358 new_layout--;
359 if (new_layout == UNDEFINED_LAYOUT)
360 new_layout = DISASSEM_DATA_COMMAND;
361 }
362
363 return (enum tui_layout_type) new_layout;
364 }
365
366 /* Show the Source/Command layout. */
367 static void
368 show_source_command (void)
369 {
370 show_source_or_disasm_and_command (SRC_COMMAND);
371 }
372
373
374 /* Show the Dissassem/Command layout. */
375 static void
376 show_disasm_command (void)
377 {
378 show_source_or_disasm_and_command (DISASSEM_COMMAND);
379 }
380
381
382 /* Show the Source/Disassem/Command layout. */
383 static void
384 show_source_disasm_command (void)
385 {
386 int cmd_height, src_height, asm_height;
387
388 if (TUI_CMD_WIN != NULL)
389 cmd_height = TUI_CMD_WIN->height;
390 else
391 cmd_height = tui_term_height () / 3;
392
393 src_height = (tui_term_height () - cmd_height) / 2;
394 asm_height = tui_term_height () - (src_height + cmd_height);
395
396 if (TUI_SRC_WIN == NULL)
397 tui_win_list[SRC_WIN] = new tui_source_window ();
398 TUI_SRC_WIN->resize (src_height,
399 tui_term_width (),
400 0,
401 0);
402
403 struct tui_locator_window *locator = tui_locator_win_info_ptr ();
404 gdb_assert (locator != nullptr);
405
406 if (TUI_DISASM_WIN == NULL)
407 tui_win_list[DISASSEM_WIN] = new tui_disasm_window ();
408 TUI_DISASM_WIN->resize (asm_height,
409 tui_term_width (),
410 0,
411 src_height - 1);
412 locator->resize (1, tui_term_width (),
413 0, (src_height + asm_height) - 1);
414
415 if (TUI_CMD_WIN == NULL)
416 tui_win_list[CMD_WIN] = new tui_cmd_window ();
417 TUI_CMD_WIN->resize (cmd_height,
418 tui_term_width (),
419 0,
420 tui_term_height () - cmd_height);
421 current_layout = SRC_DISASSEM_COMMAND;
422 }
423
424
425 /* Show the Source/Data/Command or the Dissassembly/Data/Command
426 layout. */
427 static void
428 show_data (enum tui_layout_type new_layout)
429 {
430 int total_height = (tui_term_height () - TUI_CMD_WIN->height);
431 int src_height, data_height;
432 enum tui_win_type win_type;
433
434 struct tui_locator_window *locator = tui_locator_win_info_ptr ();
435 gdb_assert (locator != nullptr);
436
437 data_height = total_height / 2;
438 src_height = total_height - data_height;
439 if (tui_win_list[DATA_WIN] == nullptr)
440 tui_win_list[DATA_WIN] = new tui_data_window ();
441 tui_win_list[DATA_WIN]->resize (data_height, tui_term_width (), 0, 0);
442
443 if (new_layout == SRC_DATA_COMMAND)
444 win_type = SRC_WIN;
445 else
446 win_type = DISASSEM_WIN;
447
448 if (tui_win_list[win_type] == NULL)
449 {
450 if (win_type == SRC_WIN)
451 tui_win_list[win_type] = new tui_source_window ();
452 else
453 tui_win_list[win_type] = new tui_disasm_window ();
454 }
455
456 tui_win_list[win_type]->resize (src_height,
457 tui_term_width (),
458 0,
459 data_height - 1);
460 locator->resize (1, tui_term_width (),
461 0, total_height - 1);
462 TUI_CMD_WIN->resize (TUI_CMD_WIN->height, tui_term_width (),
463 0, total_height);
464
465 current_layout = new_layout;
466 }
467
468 void
469 tui_gen_win_info::resize (int height_, int width_,
470 int origin_x_, int origin_y_)
471 {
472 if (width == width_ && height == height_
473 && origin.x == origin_x_ && origin.y == origin_y_
474 && handle != nullptr)
475 return;
476
477 width = width_;
478 height = height_;
479 if (height > 1)
480 viewport_height = height - 2;
481 else
482 viewport_height = 1;
483 origin.x = origin_x_;
484 origin.y = origin_y_;
485
486 if (handle != nullptr)
487 {
488 #ifdef HAVE_WRESIZE
489 wresize (handle.get (), height, width);
490 mvwin (handle.get (), origin.y, origin.x);
491 wmove (handle.get (), 0, 0);
492 #else
493 handle.reset (nullptr);
494 #endif
495 }
496
497 if (handle == nullptr)
498 make_window ();
499
500 rerender ();
501 }
502
503 /* Show the Source/Command or the Disassem layout. */
504 static void
505 show_source_or_disasm_and_command (enum tui_layout_type layout_type)
506 {
507 struct tui_source_window_base *win_info;
508 int src_height, cmd_height;
509 struct tui_locator_window *locator = tui_locator_win_info_ptr ();
510 gdb_assert (locator != nullptr);
511
512 if (TUI_CMD_WIN != NULL)
513 cmd_height = TUI_CMD_WIN->height;
514 else
515 cmd_height = tui_term_height () / 3;
516 src_height = tui_term_height () - cmd_height;
517
518 if (layout_type == SRC_COMMAND)
519 {
520 if (tui_win_list[SRC_WIN] == nullptr)
521 tui_win_list[SRC_WIN] = new tui_source_window ();
522 win_info = TUI_SRC_WIN;
523 }
524 else
525 {
526 if (tui_win_list[DISASSEM_WIN] == nullptr)
527 tui_win_list[DISASSEM_WIN] = new tui_disasm_window ();
528 win_info = TUI_DISASM_WIN;
529 }
530
531 locator->resize (1, tui_term_width (),
532 0, src_height - 1);
533 win_info->resize (src_height - 1,
534 tui_term_width (),
535 0,
536 0);
537
538 if (TUI_CMD_WIN == NULL)
539 tui_win_list[CMD_WIN] = new tui_cmd_window ();
540 TUI_CMD_WIN->resize (cmd_height,
541 tui_term_width (),
542 0,
543 src_height);
544 current_layout = layout_type;
545 }
546
547 \f
548
549 /* Function to initialize gdb commands, for tui window layout
550 manipulation. */
551
552 void
553 _initialize_tui_layout (void)
554 {
555 struct cmd_list_element *cmd;
556
557 cmd = add_com ("layout", class_tui, tui_layout_command, _("\
558 Change the layout of windows.\n\
559 Usage: layout prev | next | LAYOUT-NAME\n\
560 Layout names are:\n\
561 src : Displays source and command windows.\n\
562 asm : Displays disassembly and command windows.\n\
563 split : Displays source, disassembly and command windows.\n\
564 regs : Displays register window. If existing layout\n\
565 is source/command or assembly/command, the \n\
566 register window is displayed. If the\n\
567 source/assembly/command (split) is displayed, \n\
568 the register window is displayed with \n\
569 the window that has current logical focus."));
570 set_cmd_completer (cmd, layout_completer);
571 }
This page took 0.040185 seconds and 4 git commands to generate.