More type safety for TUI source window functions
[external/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-data.h"
32 #include "tui/tui-windata.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 "gdb_curses.h"
41
42 /*******************************
43 ** Static Local Decls
44 ********************************/
45 static void show_layout (enum tui_layout_type);
46 static tui_gen_win_info *init_and_make_win (tui_gen_win_info *,
47                                             enum tui_win_type,
48                                             int, int, int, int,
49                                             enum tui_box);
50 static void show_source_or_disasm_and_command (enum tui_layout_type);
51 static struct tui_win_info *make_source_or_disasm_window (enum tui_win_type, 
52                                                           int, int);
53 static struct tui_win_info *make_command_window (int, int);
54 static struct tui_win_info *make_source_window (int, int);
55 static struct tui_win_info *make_disasm_window (int, int);
56 static void make_data_window (struct tui_win_info **, int, int);
57 static void show_source_command (void);
58 static void show_disasm_command (void);
59 static void show_source_disasm_command (void);
60 static void show_data (enum tui_layout_type);
61 static enum tui_layout_type next_layout (void);
62 static enum tui_layout_type prev_layout (void);
63 static void tui_layout_command (const char *, int);
64 static void extract_display_start_addr (struct gdbarch **, CORE_ADDR *);
65
66
67 /***************************************
68 ** DEFINITIONS
69 ***************************************/
70
71 #define LAYOUT_USAGE     "Usage: layout prev | next | <layout_name> \n"
72
73 /* Show the screen layout defined.  */
74 static void
75 show_layout (enum tui_layout_type layout)
76 {
77   enum tui_layout_type cur_layout = tui_current_layout ();
78
79   if (layout != cur_layout)
80     {
81       /* Since the new layout may cause changes in window size, we
82          should free the content and reallocate on next display of
83          source/asm.  */
84       tui_free_all_source_wins_content ();
85       tui_clear_source_windows ();
86       if (layout == SRC_DATA_COMMAND 
87           || layout == DISASSEM_DATA_COMMAND)
88         {
89           show_data (layout);
90           tui_refresh_all (tui_win_list);
91         }
92       else
93         {
94           /* First make the current layout be invisible.  */
95           tui_make_all_invisible ();
96           tui_make_invisible (tui_locator_win_info_ptr ());
97
98           switch (layout)
99             {
100               /* Now show the new layout.  */
101             case SRC_COMMAND:
102               show_source_command ();
103               tui_add_to_source_windows (TUI_SRC_WIN);
104               break;
105             case DISASSEM_COMMAND:
106               show_disasm_command ();
107               tui_add_to_source_windows (TUI_DISASM_WIN);
108               break;
109             case SRC_DISASSEM_COMMAND:
110               show_source_disasm_command ();
111               tui_add_to_source_windows (TUI_SRC_WIN);
112               tui_add_to_source_windows (TUI_DISASM_WIN);
113               break;
114             default:
115               break;
116             }
117         }
118     }
119 }
120
121
122 /* Function to set the layout to SRC_COMMAND, DISASSEM_COMMAND,
123    SRC_DISASSEM_COMMAND, SRC_DATA_COMMAND, or DISASSEM_DATA_COMMAND.  */
124 enum tui_status
125 tui_set_layout (enum tui_layout_type layout_type)
126 {
127   enum tui_status status = TUI_SUCCESS;
128
129   if (layout_type != UNDEFINED_LAYOUT)
130     {
131       enum tui_layout_type cur_layout = tui_current_layout (),
132         new_layout = UNDEFINED_LAYOUT;
133       int regs_populate = FALSE;
134       struct gdbarch *gdbarch;
135       CORE_ADDR addr;
136       struct tui_win_info *win_with_focus = tui_win_with_focus ();
137       struct tui_layout_def *layout_def = tui_layout_def ();
138
139       extract_display_start_addr (&gdbarch, &addr);
140
141       new_layout = layout_type;
142
143       regs_populate = (new_layout == SRC_DATA_COMMAND
144                        || new_layout == DISASSEM_DATA_COMMAND);
145       if (new_layout != cur_layout)
146         {
147           show_layout (new_layout);
148
149           /* Now determine where focus should be.  */
150           if (win_with_focus != TUI_CMD_WIN)
151             {
152               switch (new_layout)
153                 {
154                 case SRC_COMMAND:
155                   tui_set_win_focus_to (TUI_SRC_WIN);
156                   layout_def->display_mode = SRC_WIN;
157                   break;
158                 case DISASSEM_COMMAND:
159                   /* The previous layout was not showing code.
160                      This can happen if there is no source
161                      available:
162
163                      1. if the source file is in another dir OR
164                      2. if target was compiled without -g
165                      We still want to show the assembly though!  */
166
167                   tui_get_begin_asm_address (&gdbarch, &addr);
168                   tui_set_win_focus_to (TUI_DISASM_WIN);
169                   layout_def->display_mode = DISASSEM_WIN;
170                   break;
171                 case SRC_DISASSEM_COMMAND:
172                   /* The previous layout was not showing code.
173                      This can happen if there is no source
174                      available:
175
176                      1. if the source file is in another dir OR
177                      2. if target was compiled without -g
178                      We still want to show the assembly though!  */
179
180                   tui_get_begin_asm_address (&gdbarch, &addr);
181                   if (win_with_focus == TUI_SRC_WIN)
182                     tui_set_win_focus_to (TUI_SRC_WIN);
183                   else
184                     tui_set_win_focus_to (TUI_DISASM_WIN);
185                   break;
186                 case SRC_DATA_COMMAND:
187                   if (win_with_focus != TUI_DATA_WIN)
188                     tui_set_win_focus_to (TUI_SRC_WIN);
189                   else
190                     tui_set_win_focus_to (TUI_DATA_WIN);
191                   layout_def->display_mode = SRC_WIN;
192                   break;
193                 case DISASSEM_DATA_COMMAND:
194                   /* The previous layout was not showing code.
195                      This can happen if there is no source
196                      available:
197
198                      1. if the source file is in another dir OR
199                      2. if target was compiled without -g
200                      We still want to show the assembly though!  */
201
202                   tui_get_begin_asm_address (&gdbarch, &addr);
203                   if (win_with_focus != TUI_DATA_WIN)
204                     tui_set_win_focus_to (TUI_DISASM_WIN);
205                   else
206                     tui_set_win_focus_to (TUI_DATA_WIN);
207                   layout_def->display_mode = DISASSEM_WIN;
208                   break;
209                 default:
210                   break;
211                 }
212             }
213           /*
214            * Now update the window content.
215            */
216           if (!regs_populate
217               && (new_layout == SRC_DATA_COMMAND
218                   || new_layout == DISASSEM_DATA_COMMAND))
219             tui_display_all_data ();
220
221           tui_update_source_windows_with_addr (gdbarch, addr);
222
223           if (regs_populate)
224             tui_show_registers (TUI_DATA_WIN->current_group);
225         }
226     }
227   else
228     status = TUI_FAILURE;
229
230   return status;
231 }
232
233 /* Add the specified window to the layout in a logical way.  This
234    means setting up the most logical layout given the window to be
235    added.  */
236 void
237 tui_add_win_to_layout (enum tui_win_type type)
238 {
239   enum tui_layout_type cur_layout = tui_current_layout ();
240
241   switch (type)
242     {
243     case SRC_WIN:
244       if (cur_layout != SRC_COMMAND
245           && cur_layout != SRC_DISASSEM_COMMAND
246           && cur_layout != SRC_DATA_COMMAND)
247         {
248           tui_clear_source_windows_detail ();
249           if (cur_layout == DISASSEM_DATA_COMMAND)
250             show_layout (SRC_DATA_COMMAND);
251           else
252             show_layout (SRC_COMMAND);
253         }
254       break;
255     case DISASSEM_WIN:
256       if (cur_layout != DISASSEM_COMMAND
257           && cur_layout != SRC_DISASSEM_COMMAND
258           && cur_layout != DISASSEM_DATA_COMMAND)
259         {
260           tui_clear_source_windows_detail ();
261           if (cur_layout == SRC_DATA_COMMAND)
262             show_layout (DISASSEM_DATA_COMMAND);
263           else
264             show_layout (DISASSEM_COMMAND);
265         }
266       break;
267     case DATA_WIN:
268       if (cur_layout != SRC_DATA_COMMAND
269           && cur_layout != DISASSEM_DATA_COMMAND)
270         {
271           if (cur_layout == DISASSEM_COMMAND)
272             show_layout (DISASSEM_DATA_COMMAND);
273           else
274             show_layout (SRC_DATA_COMMAND);
275         }
276       break;
277     default:
278       break;
279     }
280 }
281
282
283 /* Answer the height of a window.  If it hasn't been created yet,
284    answer what the height of a window would be based upon its type and
285    the layout.  */
286 int
287 tui_default_win_height (enum tui_win_type type, 
288                         enum tui_layout_type layout)
289 {
290   int h;
291
292   if (tui_win_list[type] != NULL)
293     h = tui_win_list[type]->height;
294   else
295     {
296       switch (layout)
297         {
298         case SRC_COMMAND:
299         case DISASSEM_COMMAND:
300           if (TUI_CMD_WIN == NULL)
301             h = tui_term_height () / 2;
302           else
303             h = tui_term_height () - TUI_CMD_WIN->height;
304           break;
305         case SRC_DISASSEM_COMMAND:
306         case SRC_DATA_COMMAND:
307         case DISASSEM_DATA_COMMAND:
308           if (TUI_CMD_WIN == NULL)
309             h = tui_term_height () / 3;
310           else
311             h = (tui_term_height () - TUI_CMD_WIN->height) / 2;
312           break;
313         default:
314           h = 0;
315           break;
316         }
317     }
318
319   return h;
320 }
321
322
323 /* Answer the height of a window.  If it hasn't been created yet,
324    answer what the height of a window would be based upon its type and
325    the layout.  */
326 int
327 tui_default_win_viewport_height (enum tui_win_type type,
328                                  enum tui_layout_type layout)
329 {
330   int h;
331
332   h = tui_default_win_height (type, layout);
333
334   if (tui_win_list[type] == TUI_CMD_WIN)
335     h -= 1;
336   else
337     h -= 2;
338
339   return h;
340 }
341
342 /* Complete possible layout names.  TEXT is the complete text entered so
343    far, WORD is the word currently being completed.  */
344
345 static void
346 layout_completer (struct cmd_list_element *ignore,
347                   completion_tracker &tracker,
348                   const char *text, const char *word)
349 {
350   static const char *layout_names [] =
351     { "src", "asm", "split", "regs", "next", "prev", NULL };
352
353   complete_on_enum (tracker, layout_names, text, word);
354 }
355
356 /* Function to initialize gdb commands, for tui window layout
357    manipulation.  */
358
359 void
360 _initialize_tui_layout (void)
361 {
362   struct cmd_list_element *cmd;
363
364   cmd = add_com ("layout", class_tui, tui_layout_command, _("\
365 Change the layout of windows.\n\
366 Usage: layout prev | next | LAYOUT-NAME\n\
367 Layout names are:\n\
368    src   : Displays source and command windows.\n\
369    asm   : Displays disassembly and command windows.\n\
370    split : Displays source, disassembly and command windows.\n\
371    regs  : Displays register window. If existing layout\n\
372            is source/command or assembly/command, the \n\
373            register window is displayed. If the\n\
374            source/assembly/command (split) is displayed, \n\
375            the register window is displayed with \n\
376            the window that has current logical focus."));
377   set_cmd_completer (cmd, layout_completer);
378 }
379
380
381 /*************************
382 ** STATIC LOCAL FUNCTIONS
383 **************************/
384
385
386 /* Function to set the layout to SRC, ASM, SPLIT, NEXT, PREV, DATA, or
387    REGS. */
388 enum tui_status
389 tui_set_layout_by_name (const char *layout_name)
390 {
391   enum tui_status status = TUI_SUCCESS;
392
393   if (layout_name != NULL)
394     {
395       int i;
396       enum tui_layout_type new_layout = UNDEFINED_LAYOUT;
397       enum tui_layout_type cur_layout = tui_current_layout ();
398
399       std::string copy = layout_name;
400       for (i = 0; i < copy.size (); i++)
401         copy[i] = toupper (copy[i]);
402       const char *buf_ptr = copy.c_str ();
403
404       /* First check for ambiguous input.  */
405       if (strlen (buf_ptr) <= 1 && *buf_ptr == 'S')
406         {
407           warning (_("Ambiguous command input."));
408           status = TUI_FAILURE;
409         }
410       else
411         {
412           if (subset_compare (buf_ptr, "SRC"))
413             new_layout = SRC_COMMAND;
414           else if (subset_compare (buf_ptr, "ASM"))
415             new_layout = DISASSEM_COMMAND;
416           else if (subset_compare (buf_ptr, "SPLIT"))
417             new_layout = SRC_DISASSEM_COMMAND;
418           else if (subset_compare (buf_ptr, "REGS"))
419             {
420               if (cur_layout == SRC_COMMAND
421                   || cur_layout == SRC_DATA_COMMAND)
422                 new_layout = SRC_DATA_COMMAND;
423               else
424                 new_layout = DISASSEM_DATA_COMMAND;
425             }
426           else if (subset_compare (buf_ptr, "NEXT"))
427             new_layout = next_layout ();
428           else if (subset_compare (buf_ptr, "PREV"))
429             new_layout = prev_layout ();
430           else
431             status = TUI_FAILURE;
432
433           if (status == TUI_SUCCESS)
434             {
435               /* Make sure the curses mode is enabled.  */
436               tui_enable ();
437               tui_set_layout (new_layout);
438             }
439         }
440     }
441   else
442     status = TUI_FAILURE;
443
444   return status;
445 }
446
447
448 static void
449 extract_display_start_addr (struct gdbarch **gdbarch_p, CORE_ADDR *addr_p)
450 {
451   enum tui_layout_type cur_layout = tui_current_layout ();
452   struct gdbarch *gdbarch = get_current_arch ();
453   CORE_ADDR addr;
454   CORE_ADDR pc;
455   struct symtab_and_line cursal = get_current_source_symtab_and_line ();
456
457   switch (cur_layout)
458     {
459     case SRC_COMMAND:
460     case SRC_DATA_COMMAND:
461       gdbarch = TUI_SRC_WIN->gdbarch;
462       find_line_pc (cursal.symtab,
463                     TUI_SRC_WIN->start_line_or_addr.u.line_no,
464                     &pc);
465       addr = pc;
466       break;
467     case DISASSEM_COMMAND:
468     case SRC_DISASSEM_COMMAND:
469     case DISASSEM_DATA_COMMAND:
470       gdbarch = TUI_DISASM_WIN->gdbarch;
471       addr = TUI_DISASM_WIN->start_line_or_addr.u.addr;
472       break;
473     default:
474       addr = 0;
475       break;
476     }
477
478   *gdbarch_p = gdbarch;
479   *addr_p = addr;
480 }
481
482
483 static void
484 tui_layout_command (const char *arg, int from_tty)
485 {
486   /* Switch to the selected layout.  */
487   if (tui_set_layout_by_name (arg) != TUI_SUCCESS)
488     warning (_("Invalid layout specified.\n%s"), LAYOUT_USAGE);
489 }
490
491 /* Answer the previous layout to cycle to.  */
492 static enum tui_layout_type
493 next_layout (void)
494 {
495   int new_layout;
496
497   new_layout = tui_current_layout ();
498   if (new_layout == UNDEFINED_LAYOUT)
499     new_layout = SRC_COMMAND;
500   else
501     {
502       new_layout++;
503       if (new_layout == UNDEFINED_LAYOUT)
504         new_layout = SRC_COMMAND;
505     }
506
507   return (enum tui_layout_type) new_layout;
508 }
509
510
511 /* Answer the next layout to cycle to.  */
512 static enum tui_layout_type
513 prev_layout (void)
514 {
515   int new_layout;
516
517   new_layout = tui_current_layout ();
518   if (new_layout == SRC_COMMAND)
519     new_layout = DISASSEM_DATA_COMMAND;
520   else
521     {
522       new_layout--;
523       if (new_layout == UNDEFINED_LAYOUT)
524         new_layout = DISASSEM_DATA_COMMAND;
525     }
526
527   return (enum tui_layout_type) new_layout;
528 }
529
530
531
532 static struct tui_win_info *
533 make_command_window (int height, int origin_y)
534 {
535   struct tui_win_info *result
536     = (struct tui_win_info *) init_and_make_win (NULL,
537                                                  CMD_WIN,
538                                                  height,
539                                                  tui_term_width (),
540                                                  0,
541                                                  origin_y,
542                                                  DONT_BOX_WINDOW);
543   return result;
544 }
545
546
547 /* make_source_window().
548  */
549 static struct tui_win_info *
550 make_source_window (int height, int origin_y)
551 {
552   return make_source_or_disasm_window (SRC_WIN, height, origin_y);
553 }                               /* make_source_window */
554
555
556 /* make_disasm_window().
557  */
558 static struct tui_win_info *
559 make_disasm_window (int height, int origin_y)
560 {
561   return make_source_or_disasm_window (DISASSEM_WIN, height, origin_y);
562 }                               /* make_disasm_window */
563
564
565 static void
566 make_data_window (struct tui_win_info **win_info_ptr, 
567                   int height, int origin_y)
568 {
569   *win_info_ptr
570     = (struct tui_win_info *) init_and_make_win (*win_info_ptr,
571                                                  DATA_WIN,
572                                                  height,
573                                                  tui_term_width (),
574                                                  0,
575                                                  origin_y,
576                                                  BOX_WINDOW);
577 }
578
579
580
581 /* Show the Source/Command layout.  */
582 static void
583 show_source_command (void)
584 {
585   show_source_or_disasm_and_command (SRC_COMMAND);
586 }
587
588
589 /* Show the Dissassem/Command layout.  */
590 static void
591 show_disasm_command (void)
592 {
593   show_source_or_disasm_and_command (DISASSEM_COMMAND);
594 }
595
596
597 /* Show the Source/Disassem/Command layout.  */
598 static void
599 show_source_disasm_command (void)
600 {
601   if (tui_current_layout () != SRC_DISASSEM_COMMAND)
602     {
603       int cmd_height, src_height, asm_height;
604
605       if (TUI_CMD_WIN != NULL)
606         cmd_height = TUI_CMD_WIN->height;
607       else
608         cmd_height = tui_term_height () / 3;
609
610       src_height = (tui_term_height () - cmd_height) / 2;
611       asm_height = tui_term_height () - (src_height + cmd_height);
612
613       if (TUI_SRC_WIN == NULL)
614         tui_win_list[SRC_WIN] = make_source_window (src_height, 0);
615       else
616         {
617           TUI_SRC_WIN->reset (TUI_SRC_WIN->type,
618                               src_height,
619                               TUI_SRC_WIN->width,
620                               TUI_SRC_WIN->execution_info->width,
621                               0);
622           TUI_SRC_WIN->execution_info->reset (EXEC_INFO_WIN,
623                                               src_height,
624                                               3,
625                                               0,
626                                               0);
627           tui_make_visible (TUI_SRC_WIN);
628           tui_make_visible (TUI_SRC_WIN->execution_info);
629           TUI_SRC_WIN->m_has_locator = false;
630         }
631
632       struct tui_locator_window *locator = tui_locator_win_info_ptr ();
633       gdb_assert (locator != nullptr);
634
635       tui_show_source_content (TUI_SRC_WIN);
636       if (TUI_DISASM_WIN == NULL)
637         {
638           tui_win_list[DISASSEM_WIN]
639             = make_disasm_window (asm_height, src_height - 1);
640           init_and_make_win (locator,
641                              LOCATOR_WIN,
642                              2 /* 1 */ ,
643                              tui_term_width (),
644                              0,
645                              (src_height + asm_height) - 1,
646                              DONT_BOX_WINDOW);
647         }
648       else
649         {
650           locator->reset (LOCATOR_WIN,
651                           2 /* 1 */ ,
652                           tui_term_width (),
653                           0,
654                           (src_height + asm_height) - 1);
655           TUI_DISASM_WIN->m_has_locator = true;
656           TUI_DISASM_WIN->reset (TUI_DISASM_WIN->type,
657                                  asm_height,
658                                  TUI_DISASM_WIN->width,
659                                  TUI_DISASM_WIN->execution_info->width,
660                                  src_height - 1);
661           TUI_DISASM_WIN->execution_info->reset (EXEC_INFO_WIN,
662                                                  asm_height,
663                                                  3,
664                                                  0,
665                                                  src_height - 1);
666           tui_make_visible (TUI_DISASM_WIN);
667           tui_make_visible (TUI_DISASM_WIN->execution_info);
668         }
669       TUI_SRC_WIN->m_has_locator = false;
670       TUI_DISASM_WIN->m_has_locator = true;
671       tui_make_visible (locator);
672       tui_show_locator_content ();
673       tui_show_source_content (TUI_DISASM_WIN);
674
675       if (TUI_CMD_WIN == NULL)
676         tui_win_list[CMD_WIN]
677           = make_command_window (cmd_height, tui_term_height () - cmd_height);
678       else
679         {
680           TUI_CMD_WIN->reset (TUI_CMD_WIN->type,
681                               TUI_CMD_WIN->height,
682                               TUI_CMD_WIN->width,
683                               0,
684                               TUI_CMD_WIN->origin.y);
685           tui_make_visible (TUI_CMD_WIN);
686         }
687       TUI_CMD_WIN->refresh_window ();
688       tui_set_current_layout_to (SRC_DISASSEM_COMMAND);
689     }
690 }
691
692
693 /* Show the Source/Data/Command or the Dissassembly/Data/Command
694    layout.  */
695 static void
696 show_data (enum tui_layout_type new_layout)
697 {
698   int total_height = (tui_term_height () - TUI_CMD_WIN->height);
699   int src_height, data_height;
700   enum tui_win_type win_type;
701
702   struct tui_locator_window *locator = tui_locator_win_info_ptr ();
703   gdb_assert (locator != nullptr);
704
705   data_height = total_height / 2;
706   src_height = total_height - data_height;
707   tui_make_all_invisible ();
708   tui_make_invisible (locator);
709   make_data_window (&tui_win_list[DATA_WIN], data_height, 0);
710   if (new_layout == SRC_DATA_COMMAND)
711     win_type = SRC_WIN;
712   else
713     win_type = DISASSEM_WIN;
714
715   tui_source_window_base *base;
716   if (tui_win_list[win_type] == NULL)
717     {
718       if (win_type == SRC_WIN)
719         tui_win_list[win_type]
720           = make_source_window (src_height, data_height - 1);
721       else
722         tui_win_list[win_type]
723           = make_disasm_window (src_height, data_height - 1);
724       init_and_make_win (locator,
725                              LOCATOR_WIN,
726                              2 /* 1 */ ,
727                              tui_term_width (),
728                              0,
729                              total_height - 1,
730                              DONT_BOX_WINDOW);
731       base = (tui_source_window_base *) tui_win_list[win_type];
732     }
733   else
734     {
735       base = (tui_source_window_base *) tui_win_list[win_type];
736       tui_win_list[win_type]->reset (tui_win_list[win_type]->type,
737                                      src_height,
738                                      tui_win_list[win_type]->width,
739                                      base->execution_info->width,
740                                      data_height - 1);
741       base->execution_info->reset (EXEC_INFO_WIN,
742                                    src_height,
743                                    3,
744                                    0,
745                                    data_height - 1);
746       tui_make_visible (tui_win_list[win_type]);
747       tui_make_visible (base->execution_info);
748       locator->reset (LOCATOR_WIN,
749                       2 /* 1 */ ,
750                       tui_term_width (),
751                       0,
752                       total_height - 1);
753     }
754   base->m_has_locator = true;
755   tui_make_visible (locator);
756   tui_show_locator_content ();
757   tui_add_to_source_windows
758     ((tui_source_window_base *) tui_win_list[win_type]);
759   tui_set_current_layout_to (new_layout);
760 }
761
762 void
763 tui_gen_win_info::reset (enum tui_win_type win_type,
764                          int height_, int width_,
765                          int origin_x_, int origin_y_)
766 {
767   int h = height_;
768
769   gdb_assert (type == win_type);
770
771   width = width_;
772   height = h;
773   if (h > 1)
774     {
775       viewport_height = h - 1;
776       if (type != CMD_WIN)
777         viewport_height--;
778     }
779   else
780     viewport_height = 1;
781   origin.x = origin_x_;
782   origin.y = origin_y_;
783 }
784
785 /* init_and_make_win().
786  */
787 static tui_gen_win_info *
788 init_and_make_win (tui_gen_win_info *win_info, 
789                    enum tui_win_type win_type,
790                    int height, int width, 
791                    int origin_x, int origin_y,
792                    enum tui_box box_it)
793 {
794   if (win_info == NULL)
795     {
796       switch (win_type)
797         {
798         case SRC_WIN:
799           win_info = new tui_source_window ();
800           break;
801
802         case DISASSEM_WIN:
803           win_info = new tui_disasm_window ();
804           break;
805
806         case DATA_WIN:
807           win_info = new tui_data_window ();
808           break;
809
810         case CMD_WIN:
811           win_info = new tui_cmd_window ();
812           break;
813
814         case EXEC_INFO_WIN:
815           win_info = new tui_exec_info_window ();
816           break;
817
818         default:
819           gdb_assert (tui_win_is_auxiliary (win_type));
820           win_info = new tui_gen_win_info (win_type);
821           break;
822         }
823     }
824
825   win_info->reset (win_type, height, width, origin_x, origin_y);
826   tui_make_window (win_info, box_it);
827
828   return win_info;
829 }
830
831
832 static struct tui_win_info *
833 make_source_or_disasm_window (enum tui_win_type type,
834                               int height, int origin_y)
835 {
836   struct tui_exec_info_window *execution_info
837     = (tui_exec_info_window *) init_and_make_win (nullptr,
838                                                   EXEC_INFO_WIN,
839                                                   height,
840                                                   3,
841                                                   0,
842                                                   origin_y,
843                                                   DONT_BOX_WINDOW);
844
845   /* Now create the source window.  */
846   struct tui_source_window_base *result
847     = ((struct tui_source_window_base *)
848        init_and_make_win (NULL,
849                           type,
850                           height,
851                           tui_term_width () - execution_info->width,
852                           execution_info->width,
853                           origin_y,
854                           BOX_WINDOW));
855   result->execution_info = execution_info;
856   return result;
857 }
858
859
860 /* Show the Source/Command or the Disassem layout.  */
861 static void
862 show_source_or_disasm_and_command (enum tui_layout_type layout_type)
863 {
864   if (tui_current_layout () != layout_type)
865     {
866       struct tui_win_info **win_info_ptr;
867       int src_height, cmd_height;
868       struct tui_locator_window *locator = tui_locator_win_info_ptr ();
869       gdb_assert (locator != nullptr);
870
871       if (TUI_CMD_WIN != NULL)
872         cmd_height = TUI_CMD_WIN->height;
873       else
874         cmd_height = tui_term_height () / 3;
875       src_height = tui_term_height () - cmd_height;
876
877       if (layout_type == SRC_COMMAND)
878         win_info_ptr = &tui_win_list[SRC_WIN];
879       else
880         win_info_ptr = &tui_win_list[DISASSEM_WIN];
881
882       tui_source_window_base *base;
883       if ((*win_info_ptr) == NULL)
884         {
885           if (layout_type == SRC_COMMAND)
886             *win_info_ptr = make_source_window (src_height - 1, 0);
887           else
888             *win_info_ptr = make_disasm_window (src_height - 1, 0);
889           init_and_make_win (locator,
890                              LOCATOR_WIN,
891                              2 /* 1 */ ,
892                              tui_term_width (),
893                              0,
894                              src_height - 1,
895                              DONT_BOX_WINDOW);
896           base = (tui_source_window_base *) *win_info_ptr;
897         }
898       else
899         {
900           base = (tui_source_window_base *) *win_info_ptr;
901           locator->reset (LOCATOR_WIN,
902                           2 /* 1 */ ,
903                           tui_term_width (),
904                           0,
905                           src_height - 1);
906           base->m_has_locator = true;
907           (*win_info_ptr)->reset ((*win_info_ptr)->type,
908                                   src_height - 1,
909                                   (*win_info_ptr)->width,
910                                   base->execution_info->width,
911                                   0);
912           base->execution_info->reset (EXEC_INFO_WIN,
913                                        src_height - 1,
914                                        3,
915                                        0,
916                                        0);
917           tui_make_visible (*win_info_ptr);
918           tui_make_visible (base->execution_info);
919         }
920
921       base->m_has_locator = true;
922       tui_make_visible (locator);
923       tui_show_locator_content ();
924       tui_show_source_content (base);
925
926       if (TUI_CMD_WIN == NULL)
927         {
928           tui_win_list[CMD_WIN] = make_command_window (cmd_height,
929                                                        src_height);
930           TUI_CMD_WIN->refresh_window ();
931         }
932       else
933         {
934           TUI_CMD_WIN->reset (TUI_CMD_WIN->type,
935                               TUI_CMD_WIN->height,
936                               TUI_CMD_WIN->width,
937                               TUI_CMD_WIN->origin.x,
938                               TUI_CMD_WIN->origin.y);
939           tui_make_visible (TUI_CMD_WIN);
940         }
941       tui_set_current_layout_to (layout_type);
942     }
943 }