Make TUI window handle a unique_ptr
[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 initialize gdb commands, for tui window layout
251 manipulation. */
252
253 void
254 _initialize_tui_layout (void)
255 {
256 struct cmd_list_element *cmd;
257
258 cmd = add_com ("layout", class_tui, tui_layout_command, _("\
259 Change the layout of windows.\n\
260 Usage: layout prev | next | LAYOUT-NAME\n\
261 Layout names are:\n\
262 src : Displays source and command windows.\n\
263 asm : Displays disassembly and command windows.\n\
264 split : Displays source, disassembly and command windows.\n\
265 regs : Displays register window. If existing layout\n\
266 is source/command or assembly/command, the \n\
267 register window is displayed. If the\n\
268 source/assembly/command (split) is displayed, \n\
269 the register window is displayed with \n\
270 the window that has current logical focus."));
271 set_cmd_completer (cmd, layout_completer);
272 }
273
274
275 /* Function to set the layout to SRC, ASM, SPLIT, NEXT, PREV, DATA, or
276 REGS. */
277 static void
278 tui_layout_command (const char *layout_name, int from_tty)
279 {
280 enum tui_layout_type new_layout = UNDEFINED_LAYOUT;
281 enum tui_layout_type cur_layout = tui_current_layout ();
282
283 if (layout_name == NULL || *layout_name == '\0')
284 error (_("Usage: layout prev | next | LAYOUT-NAME"));
285
286 /* First check for ambiguous input. */
287 if (strcmp (layout_name, "s") == 0)
288 error (_("Ambiguous command input."));
289
290 if (subset_compare (layout_name, "src"))
291 new_layout = SRC_COMMAND;
292 else if (subset_compare (layout_name, "asm"))
293 new_layout = DISASSEM_COMMAND;
294 else if (subset_compare (layout_name, "split"))
295 new_layout = SRC_DISASSEM_COMMAND;
296 else if (subset_compare (layout_name, "regs"))
297 {
298 if (cur_layout == SRC_COMMAND
299 || cur_layout == SRC_DATA_COMMAND)
300 new_layout = SRC_DATA_COMMAND;
301 else
302 new_layout = DISASSEM_DATA_COMMAND;
303 }
304 else if (subset_compare (layout_name, "next"))
305 new_layout = next_layout ();
306 else if (subset_compare (layout_name, "prev"))
307 new_layout = prev_layout ();
308 else
309 error (_("Unrecognized layout: %s"), layout_name);
310
311 /* Make sure the curses mode is enabled. */
312 tui_enable ();
313 tui_set_layout (new_layout);
314 }
315
316
317 static void
318 extract_display_start_addr (struct gdbarch **gdbarch_p, CORE_ADDR *addr_p)
319 {
320 enum tui_layout_type cur_layout = tui_current_layout ();
321 struct gdbarch *gdbarch = get_current_arch ();
322 CORE_ADDR addr;
323 CORE_ADDR pc;
324 struct symtab_and_line cursal = get_current_source_symtab_and_line ();
325
326 switch (cur_layout)
327 {
328 case SRC_COMMAND:
329 case SRC_DATA_COMMAND:
330 gdbarch = TUI_SRC_WIN->gdbarch;
331 find_line_pc (cursal.symtab,
332 TUI_SRC_WIN->start_line_or_addr.u.line_no,
333 &pc);
334 addr = pc;
335 break;
336 case DISASSEM_COMMAND:
337 case SRC_DISASSEM_COMMAND:
338 case DISASSEM_DATA_COMMAND:
339 gdbarch = TUI_DISASM_WIN->gdbarch;
340 addr = TUI_DISASM_WIN->start_line_or_addr.u.addr;
341 break;
342 default:
343 addr = 0;
344 break;
345 }
346
347 *gdbarch_p = gdbarch;
348 *addr_p = addr;
349 }
350
351
352 /* Answer the previous layout to cycle to. */
353 static enum tui_layout_type
354 next_layout (void)
355 {
356 int new_layout;
357
358 new_layout = tui_current_layout ();
359 if (new_layout == UNDEFINED_LAYOUT)
360 new_layout = SRC_COMMAND;
361 else
362 {
363 new_layout++;
364 if (new_layout == UNDEFINED_LAYOUT)
365 new_layout = SRC_COMMAND;
366 }
367
368 return (enum tui_layout_type) new_layout;
369 }
370
371
372 /* Answer the next layout to cycle to. */
373 static enum tui_layout_type
374 prev_layout (void)
375 {
376 int new_layout;
377
378 new_layout = tui_current_layout ();
379 if (new_layout == SRC_COMMAND)
380 new_layout = DISASSEM_DATA_COMMAND;
381 else
382 {
383 new_layout--;
384 if (new_layout == UNDEFINED_LAYOUT)
385 new_layout = DISASSEM_DATA_COMMAND;
386 }
387
388 return (enum tui_layout_type) new_layout;
389 }
390
391 /* Show the Source/Command layout. */
392 static void
393 show_source_command (void)
394 {
395 show_source_or_disasm_and_command (SRC_COMMAND);
396 }
397
398
399 /* Show the Dissassem/Command layout. */
400 static void
401 show_disasm_command (void)
402 {
403 show_source_or_disasm_and_command (DISASSEM_COMMAND);
404 }
405
406
407 /* Show the Source/Disassem/Command layout. */
408 static void
409 show_source_disasm_command (void)
410 {
411 int cmd_height, src_height, asm_height;
412
413 if (TUI_CMD_WIN != NULL)
414 cmd_height = TUI_CMD_WIN->height;
415 else
416 cmd_height = tui_term_height () / 3;
417
418 src_height = (tui_term_height () - cmd_height) / 2;
419 asm_height = tui_term_height () - (src_height + cmd_height);
420
421 if (TUI_SRC_WIN == NULL)
422 tui_win_list[SRC_WIN] = new tui_source_window ();
423 TUI_SRC_WIN->resize (src_height,
424 tui_term_width (),
425 0,
426 0);
427
428 struct tui_locator_window *locator = tui_locator_win_info_ptr ();
429 gdb_assert (locator != nullptr);
430
431 if (TUI_DISASM_WIN == NULL)
432 tui_win_list[DISASSEM_WIN] = new tui_disasm_window ();
433 TUI_DISASM_WIN->resize (asm_height,
434 tui_term_width (),
435 0,
436 src_height - 1);
437 locator->resize (1, tui_term_width (),
438 0, (src_height + asm_height) - 1);
439
440 if (TUI_CMD_WIN == NULL)
441 tui_win_list[CMD_WIN] = new tui_cmd_window ();
442 TUI_CMD_WIN->resize (cmd_height,
443 tui_term_width (),
444 0,
445 tui_term_height () - cmd_height);
446 current_layout = SRC_DISASSEM_COMMAND;
447 }
448
449
450 /* Show the Source/Data/Command or the Dissassembly/Data/Command
451 layout. */
452 static void
453 show_data (enum tui_layout_type new_layout)
454 {
455 int total_height = (tui_term_height () - TUI_CMD_WIN->height);
456 int src_height, data_height;
457 enum tui_win_type win_type;
458
459 struct tui_locator_window *locator = tui_locator_win_info_ptr ();
460 gdb_assert (locator != nullptr);
461
462 data_height = total_height / 2;
463 src_height = total_height - data_height;
464 if (tui_win_list[DATA_WIN] == nullptr)
465 tui_win_list[DATA_WIN] = new tui_data_window ();
466 tui_win_list[DATA_WIN]->resize (data_height, tui_term_width (), 0, 0);
467
468 if (new_layout == SRC_DATA_COMMAND)
469 win_type = SRC_WIN;
470 else
471 win_type = DISASSEM_WIN;
472
473 if (tui_win_list[win_type] == NULL)
474 {
475 if (win_type == SRC_WIN)
476 tui_win_list[win_type] = new tui_source_window ();
477 else
478 tui_win_list[win_type] = new tui_disasm_window ();
479 }
480
481 tui_win_list[win_type]->resize (src_height,
482 tui_term_width (),
483 0,
484 data_height - 1);
485 locator->resize (1, tui_term_width (),
486 0, total_height - 1);
487 TUI_CMD_WIN->resize (TUI_CMD_WIN->height, tui_term_width (),
488 0, total_height);
489
490 current_layout = new_layout;
491 }
492
493 void
494 tui_gen_win_info::resize (int height_, int width_,
495 int origin_x_, int origin_y_)
496 {
497 if (width == width_ && height == height_
498 && origin.x == origin_x_ && origin.y == origin_y_
499 && handle != nullptr)
500 return;
501
502 width = width_;
503 height = height_;
504 if (height > 1)
505 viewport_height = height - 2;
506 else
507 viewport_height = 1;
508 origin.x = origin_x_;
509 origin.y = origin_y_;
510
511 if (handle != nullptr)
512 {
513 #ifdef HAVE_WRESIZE
514 wresize (handle.get (), height, width);
515 mvwin (handle.get (), origin.y, origin.x);
516 wmove (handle.get (), 0, 0);
517 #else
518 handle.reset (nullptr);
519 #endif
520 }
521
522 if (handle == nullptr)
523 make_window ();
524
525 rerender ();
526 }
527
528 /* Show the Source/Command or the Disassem layout. */
529 static void
530 show_source_or_disasm_and_command (enum tui_layout_type layout_type)
531 {
532 struct tui_source_window_base *win_info;
533 int src_height, cmd_height;
534 struct tui_locator_window *locator = tui_locator_win_info_ptr ();
535 gdb_assert (locator != nullptr);
536
537 if (TUI_CMD_WIN != NULL)
538 cmd_height = TUI_CMD_WIN->height;
539 else
540 cmd_height = tui_term_height () / 3;
541 src_height = tui_term_height () - cmd_height;
542
543 if (layout_type == SRC_COMMAND)
544 {
545 if (tui_win_list[SRC_WIN] == nullptr)
546 tui_win_list[SRC_WIN] = new tui_source_window ();
547 win_info = TUI_SRC_WIN;
548 }
549 else
550 {
551 if (tui_win_list[DISASSEM_WIN] == nullptr)
552 tui_win_list[DISASSEM_WIN] = new tui_disasm_window ();
553 win_info = TUI_DISASM_WIN;
554 }
555
556 locator->resize (1, tui_term_width (),
557 0, src_height - 1);
558 win_info->resize (src_height - 1,
559 tui_term_width (),
560 0,
561 0);
562
563 if (TUI_CMD_WIN == NULL)
564 tui_win_list[CMD_WIN] = new tui_cmd_window ();
565 TUI_CMD_WIN->resize (cmd_height,
566 tui_term_width (),
567 0,
568 src_height);
569 current_layout = layout_type;
570 }
This page took 0.058385 seconds and 5 git commands to generate.