]> Git Repo - binutils.git/blob - gdb/tui/tui-layout.c
Remove struct tui_point
[binutils.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       current_layout = layout;
95       tui_delete_invisible_windows ();
96     }
97 }
98
99
100 /* Function to set the layout to SRC_COMMAND, DISASSEM_COMMAND,
101    SRC_DISASSEM_COMMAND, SRC_DATA_COMMAND, or DISASSEM_DATA_COMMAND.  */
102 void
103 tui_set_layout (enum tui_layout_type layout_type)
104 {
105   gdb_assert (layout_type != UNDEFINED_LAYOUT);
106
107   enum tui_layout_type cur_layout = tui_current_layout ();
108   struct gdbarch *gdbarch;
109   CORE_ADDR addr;
110   struct tui_win_info *win_with_focus = tui_win_with_focus ();
111
112   extract_display_start_addr (&gdbarch, &addr);
113
114   enum tui_layout_type new_layout = layout_type;
115
116   if (new_layout != cur_layout)
117     {
118       show_layout (new_layout);
119
120       /* Now determine where focus should be.  */
121       if (win_with_focus != TUI_CMD_WIN)
122         {
123           switch (new_layout)
124             {
125             case SRC_COMMAND:
126               tui_set_win_focus_to (TUI_SRC_WIN);
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);
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);
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);
175               break;
176             default:
177               break;
178             }
179         }
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)
186         TUI_DATA_WIN->show_registers (TUI_DATA_WIN->get_current_group ());
187     }
188 }
189
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.  */
193 void
194 tui_add_win_to_layout (enum tui_win_type type)
195 {
196   enum tui_layout_type cur_layout = tui_current_layout ();
197
198   switch (type)
199     {
200     case SRC_WIN:
201       if (cur_layout != SRC_COMMAND
202           && cur_layout != SRC_DISASSEM_COMMAND
203           && cur_layout != SRC_DATA_COMMAND)
204         {
205           if (cur_layout == DISASSEM_DATA_COMMAND)
206             show_layout (SRC_DATA_COMMAND);
207           else
208             show_layout (SRC_COMMAND);
209         }
210       break;
211     case DISASSEM_WIN:
212       if (cur_layout != DISASSEM_COMMAND
213           && cur_layout != SRC_DISASSEM_COMMAND
214           && cur_layout != DISASSEM_DATA_COMMAND)
215         {
216           if (cur_layout == SRC_DATA_COMMAND)
217             show_layout (DISASSEM_DATA_COMMAND);
218           else
219             show_layout (DISASSEM_COMMAND);
220         }
221       break;
222     case DATA_WIN:
223       if (cur_layout != SRC_DATA_COMMAND
224           && cur_layout != DISASSEM_DATA_COMMAND)
225         {
226           if (cur_layout == DISASSEM_COMMAND)
227             show_layout (DISASSEM_DATA_COMMAND);
228           else
229             show_layout (SRC_DATA_COMMAND);
230         }
231       break;
232     default:
233       break;
234     }
235 }
236
237 /* Complete possible layout names.  TEXT is the complete text entered so
238    far, WORD is the word currently being completed.  */
239
240 static void
241 layout_completer (struct cmd_list_element *ignore,
242                   completion_tracker &tracker,
243                   const char *text, const char *word)
244 {
245   static const char *layout_names [] =
246     { "src", "asm", "split", "regs", "next", "prev", NULL };
247
248   complete_on_enum (tracker, layout_names, text, word);
249 }
250
251 /* Function to set the layout to SRC, ASM, SPLIT, NEXT, PREV, DATA, or
252    REGS. */
253 static void
254 tui_layout_command (const char *layout_name, int from_tty)
255 {
256   enum tui_layout_type new_layout = UNDEFINED_LAYOUT;
257   enum tui_layout_type cur_layout = tui_current_layout ();
258
259   if (layout_name == NULL || *layout_name == '\0')
260     error (_("Usage: layout prev | next | LAYOUT-NAME"));
261
262   /* First check for ambiguous input.  */
263   if (strcmp (layout_name, "s") == 0)
264     error (_("Ambiguous command input."));
265
266   if (subset_compare (layout_name, "src"))
267     new_layout = SRC_COMMAND;
268   else if (subset_compare (layout_name, "asm"))
269     new_layout = DISASSEM_COMMAND;
270   else if (subset_compare (layout_name, "split"))
271     new_layout = SRC_DISASSEM_COMMAND;
272   else if (subset_compare (layout_name, "regs"))
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;
279     }
280   else if (subset_compare (layout_name, "next"))
281     new_layout = next_layout ();
282   else if (subset_compare (layout_name, "prev"))
283     new_layout = prev_layout ();
284   else
285     error (_("Unrecognized layout: %s"), layout_name);
286
287   /* Make sure the curses mode is enabled.  */
288   tui_enable ();
289   tui_set_layout (new_layout);
290 }
291
292
293 static void
294 extract_display_start_addr (struct gdbarch **gdbarch_p, CORE_ADDR *addr_p)
295 {
296   enum tui_layout_type cur_layout = tui_current_layout ();
297   struct gdbarch *gdbarch = get_current_arch ();
298   CORE_ADDR addr;
299   CORE_ADDR pc;
300   struct symtab_and_line cursal = get_current_source_symtab_and_line ();
301
302   switch (cur_layout)
303     {
304     case SRC_COMMAND:
305     case SRC_DATA_COMMAND:
306       gdbarch = TUI_SRC_WIN->gdbarch;
307       find_line_pc (cursal.symtab,
308                     TUI_SRC_WIN->start_line_or_addr.u.line_no,
309                     &pc);
310       addr = pc;
311       break;
312     case DISASSEM_COMMAND:
313     case SRC_DISASSEM_COMMAND:
314     case DISASSEM_DATA_COMMAND:
315       gdbarch = TUI_DISASM_WIN->gdbarch;
316       addr = TUI_DISASM_WIN->start_line_or_addr.u.addr;
317       break;
318     default:
319       addr = 0;
320       break;
321     }
322
323   *gdbarch_p = gdbarch;
324   *addr_p = addr;
325 }
326
327
328 /* Answer the previous layout to cycle to.  */
329 static enum tui_layout_type
330 next_layout (void)
331 {
332   int new_layout;
333
334   new_layout = tui_current_layout ();
335   if (new_layout == UNDEFINED_LAYOUT)
336     new_layout = SRC_COMMAND;
337   else
338     {
339       new_layout++;
340       if (new_layout == UNDEFINED_LAYOUT)
341         new_layout = SRC_COMMAND;
342     }
343
344   return (enum tui_layout_type) new_layout;
345 }
346
347
348 /* Answer the next layout to cycle to.  */
349 static enum tui_layout_type
350 prev_layout (void)
351 {
352   int new_layout;
353
354   new_layout = tui_current_layout ();
355   if (new_layout == SRC_COMMAND)
356     new_layout = DISASSEM_DATA_COMMAND;
357   else
358     {
359       new_layout--;
360       if (new_layout == UNDEFINED_LAYOUT)
361         new_layout = DISASSEM_DATA_COMMAND;
362     }
363
364   return (enum tui_layout_type) new_layout;
365 }
366
367 /* Show the Source/Command layout.  */
368 static void
369 show_source_command (void)
370 {
371   show_source_or_disasm_and_command (SRC_COMMAND);
372 }
373
374
375 /* Show the Dissassem/Command layout.  */
376 static void
377 show_disasm_command (void)
378 {
379   show_source_or_disasm_and_command (DISASSEM_COMMAND);
380 }
381
382
383 /* Show the Source/Disassem/Command layout.  */
384 static void
385 show_source_disasm_command (void)
386 {
387   int cmd_height, src_height, asm_height;
388
389   if (TUI_CMD_WIN != NULL)
390     cmd_height = TUI_CMD_WIN->height;
391   else
392     cmd_height = tui_term_height () / 3;
393
394   src_height = (tui_term_height () - cmd_height) / 2;
395   asm_height = tui_term_height () - (src_height + cmd_height);
396
397   if (TUI_SRC_WIN == NULL)
398     tui_win_list[SRC_WIN] = new tui_source_window ();
399   TUI_SRC_WIN->resize (src_height,
400                        tui_term_width (),
401                        0,
402                        0);
403
404   struct tui_locator_window *locator = tui_locator_win_info_ptr ();
405   gdb_assert (locator != nullptr);
406
407   if (TUI_DISASM_WIN == NULL)
408     tui_win_list[DISASSEM_WIN] = new tui_disasm_window ();
409   TUI_DISASM_WIN->resize (asm_height,
410                           tui_term_width (),
411                           0,
412                           src_height - 1);
413   locator->resize (1, tui_term_width (),
414                    0, (src_height + asm_height) - 1);
415
416   if (TUI_CMD_WIN == NULL)
417     tui_win_list[CMD_WIN] = new tui_cmd_window ();
418   TUI_CMD_WIN->resize (cmd_height,
419                        tui_term_width (),
420                        0,
421                        tui_term_height () - cmd_height);
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
466 void
467 tui_gen_win_info::resize (int height_, int width_,
468                           int origin_x_, int origin_y_)
469 {
470   if (width == width_ && height == height_
471       && x == origin_x_ && y == origin_y_
472       && handle != nullptr)
473     return;
474
475   width = width_;
476   height = height_;
477   if (height > 1)
478     viewport_height = height - 2;
479   else
480     viewport_height = 1;
481   x = origin_x_;
482   y = origin_y_;
483
484   if (handle != nullptr)
485     {
486 #ifdef HAVE_WRESIZE
487       wresize (handle.get (), height, width);
488       mvwin (handle.get (), y, x);
489       wmove (handle.get (), 0, 0);
490 #else
491       handle.reset (nullptr);
492 #endif
493     }
494
495   if (handle == nullptr)
496     make_window ();
497
498   rerender ();
499 }
500
501 /* Show the Source/Command or the Disassem layout.  */
502 static void
503 show_source_or_disasm_and_command (enum tui_layout_type layout_type)
504 {
505   struct tui_source_window_base *win_info;
506   int src_height, cmd_height;
507   struct tui_locator_window *locator = tui_locator_win_info_ptr ();
508   gdb_assert (locator != nullptr);
509
510   if (TUI_CMD_WIN != NULL)
511     cmd_height = TUI_CMD_WIN->height;
512   else
513     cmd_height = tui_term_height () / 3;
514   src_height = tui_term_height () - cmd_height;
515
516   if (layout_type == SRC_COMMAND)
517     {
518       if (tui_win_list[SRC_WIN] == nullptr)
519         tui_win_list[SRC_WIN] = new tui_source_window ();
520       win_info = TUI_SRC_WIN;
521     }
522   else
523     {
524       if (tui_win_list[DISASSEM_WIN] == nullptr)
525         tui_win_list[DISASSEM_WIN] = new tui_disasm_window ();
526       win_info = TUI_DISASM_WIN;
527     }
528
529   locator->resize (1, tui_term_width (),
530                    0, src_height - 1);
531   win_info->resize (src_height - 1,
532                     tui_term_width (),
533                     0,
534                     0);
535
536   if (TUI_CMD_WIN == NULL)
537     tui_win_list[CMD_WIN] = new tui_cmd_window ();
538   TUI_CMD_WIN->resize (cmd_height,
539                        tui_term_width (),
540                        0,
541                        src_height);
542 }
543
544 \f
545
546 /* Function to initialize gdb commands, for tui window layout
547    manipulation.  */
548
549 void
550 _initialize_tui_layout (void)
551 {
552   struct cmd_list_element *cmd;
553
554   cmd = add_com ("layout", class_tui, tui_layout_command, _("\
555 Change the layout of windows.\n\
556 Usage: layout prev | next | LAYOUT-NAME\n\
557 Layout names are:\n\
558    src   : Displays source and command windows.\n\
559    asm   : Displays disassembly and command windows.\n\
560    split : Displays source, disassembly and command windows.\n\
561    regs  : Displays register window. If existing layout\n\
562            is source/command or assembly/command, the \n\
563            register window is displayed. If the\n\
564            source/assembly/command (split) is displayed, \n\
565            the register window is displayed with \n\
566            the window that has current logical focus."));
567   set_cmd_completer (cmd, layout_completer);
568 }
This page took 0.056488 seconds and 4 git commands to generate.