2007-08-14 Michael Snyder <msnyder@access-company.com>
[external/binutils.git] / gdb / tui / tui-layout.c
1 /* TUI layout window management.
2
3    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007
4    Free Software Foundation, Inc.
5
6    Contributed by Hewlett-Packard Company.
7
8    This file is part of GDB.
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor,
23    Boston, MA 02110-1301, USA.  */
24
25 #include "defs.h"
26 #include "command.h"
27 #include "symtab.h"
28 #include "frame.h"
29 #include "source.h"
30 #include <ctype.h>
31
32 #include "tui/tui.h"
33 #include "tui/tui-data.h"
34 #include "tui/tui-windata.h"
35 #include "tui/tui-wingeneral.h"
36 #include "tui/tui-stack.h"
37 #include "tui/tui-regs.h"
38 #include "tui/tui-win.h"
39 #include "tui/tui-winsource.h"
40 #include "tui/tui-disasm.h"
41
42 #include "gdb_string.h"
43 #include "gdb_curses.h"
44
45 /*******************************
46 ** Static Local Decls
47 ********************************/
48 static void show_layout (enum tui_layout_type);
49 static void init_gen_win_info (struct tui_gen_win_info *, 
50                                enum tui_win_type, 
51                                int, int, int, int);
52 static void *init_and_make_win (void *, enum tui_win_type, 
53                                 int, int, int, int, int);
54 static void show_source_or_disasm_and_command (enum tui_layout_type);
55 static void make_source_or_disasm_window (struct tui_win_info **, 
56                                           enum tui_win_type, 
57                                           int, int);
58 static void make_command_window (struct tui_win_info **, int, int);
59 static void make_source_window (struct tui_win_info **, int, int);
60 static void make_disasm_window (struct tui_win_info **, int, int);
61 static void make_data_window (struct tui_win_info **, int, int);
62 static void show_source_command (void);
63 static void show_disasm_command (void);
64 static void show_source_disasm_command (void);
65 static void show_data (enum tui_layout_type);
66 static enum tui_layout_type next_layout (void);
67 static enum tui_layout_type prev_layout (void);
68 static void tui_layout_command (char *, int);
69 static void tui_toggle_layout_command (char *, int);
70 static void tui_toggle_split_layout_command (char *, int);
71 static CORE_ADDR extract_display_start_addr (void);
72 static void tui_handle_xdb_layout (struct tui_layout_def *);
73
74
75 /***************************************
76 ** DEFINITIONS
77 ***************************************/
78
79 #define LAYOUT_USAGE     "Usage: layout prev | next | <layout_name> \n"
80
81 /* Show the screen layout defined.  */
82 static void
83 show_layout (enum tui_layout_type layout)
84 {
85   enum tui_layout_type cur_layout = tui_current_layout ();
86
87   if (layout != cur_layout)
88     {
89       /* Since the new layout may cause changes in window size, we
90          should free the content and reallocate on next display of
91          source/asm.  */
92       tui_free_all_source_wins_content ();
93       tui_clear_source_windows ();
94       if (layout == SRC_DATA_COMMAND 
95           || layout == DISASSEM_DATA_COMMAND)
96         {
97           show_data (layout);
98           tui_refresh_all (tui_win_list);
99         }
100       else
101         {
102           /* First make the current layout be invisible.  */
103           tui_make_all_invisible ();
104           tui_make_invisible (tui_locator_win_info_ptr ());
105
106           switch (layout)
107             {
108               /* Now show the new layout.  */
109             case SRC_COMMAND:
110               show_source_command ();
111               tui_add_to_source_windows (TUI_SRC_WIN);
112               break;
113             case DISASSEM_COMMAND:
114               show_disasm_command ();
115               tui_add_to_source_windows (TUI_DISASM_WIN);
116               break;
117             case SRC_DISASSEM_COMMAND:
118               show_source_disasm_command ();
119               tui_add_to_source_windows (TUI_SRC_WIN);
120               tui_add_to_source_windows (TUI_DISASM_WIN);
121               break;
122             default:
123               break;
124             }
125         }
126     }
127 }
128
129
130 /* Function to set the layout to SRC_COMMAND, DISASSEM_COMMAND,
131    SRC_DISASSEM_COMMAND, SRC_DATA_COMMAND, or DISASSEM_DATA_COMMAND.
132    If the layout is SRC_DATA_COMMAND, DISASSEM_DATA_COMMAND, or
133    UNDEFINED_LAYOUT, then the data window is populated according to
134    regs_display_type.  */
135 enum tui_status
136 tui_set_layout (enum tui_layout_type layout_type,
137                 enum tui_register_display_type regs_display_type)
138 {
139   enum tui_status status = TUI_SUCCESS;
140
141   if (layout_type != UNDEFINED_LAYOUT 
142       || regs_display_type != TUI_UNDEFINED_REGS)
143     {
144       enum tui_layout_type cur_layout = tui_current_layout (),
145         new_layout = UNDEFINED_LAYOUT;
146       int regs_populate = FALSE;
147       CORE_ADDR addr = extract_display_start_addr ();
148       struct tui_win_info *win_with_focus = tui_win_with_focus ();
149       struct tui_layout_def *layout_def = tui_layout_def ();
150
151
152       if (layout_type == UNDEFINED_LAYOUT
153           && regs_display_type != TUI_UNDEFINED_REGS)
154         {
155           if (cur_layout == SRC_DISASSEM_COMMAND)
156             new_layout = DISASSEM_DATA_COMMAND;
157           else if (cur_layout == SRC_COMMAND 
158                    || cur_layout == SRC_DATA_COMMAND)
159             new_layout = SRC_DATA_COMMAND;
160           else if (cur_layout == DISASSEM_COMMAND 
161                    || cur_layout == DISASSEM_DATA_COMMAND)
162             new_layout = DISASSEM_DATA_COMMAND;
163         }
164       else
165         new_layout = layout_type;
166
167       regs_populate = (new_layout == SRC_DATA_COMMAND 
168                        || new_layout == DISASSEM_DATA_COMMAND 
169                        || regs_display_type != TUI_UNDEFINED_REGS);
170       if (new_layout != cur_layout
171           || regs_display_type != TUI_UNDEFINED_REGS)
172         {
173           if (new_layout != cur_layout)
174             {
175               show_layout (new_layout);
176
177               /* Now determine where focus should be.  */
178               if (win_with_focus != TUI_CMD_WIN)
179                 {
180                   switch (new_layout)
181                     {
182                     case SRC_COMMAND:
183                       tui_set_win_focus_to (TUI_SRC_WIN);
184                       layout_def->display_mode = SRC_WIN;
185                       layout_def->split = FALSE;
186                       break;
187                     case DISASSEM_COMMAND:
188                       /* The previous layout was not showing code.
189                          This can happen if there is no source
190                          available:
191
192                          1. if the source file is in another dir OR
193                          2. if target was compiled without -g
194                          We still want to show the assembly though!  */
195
196                       addr = tui_get_begin_asm_address ();
197                       tui_set_win_focus_to (TUI_DISASM_WIN);
198                       layout_def->display_mode = DISASSEM_WIN;
199                       layout_def->split = FALSE;
200                       break;
201                     case SRC_DISASSEM_COMMAND:
202                       /* The previous layout was not showing code.
203                          This can happen if there is no source
204                          available:
205
206                          1. if the source file is in another dir OR
207                          2. if target was compiled without -g
208                          We still want to show the assembly though!  */
209
210                       addr = tui_get_begin_asm_address ();
211                       if (win_with_focus == TUI_SRC_WIN)
212                         tui_set_win_focus_to (TUI_SRC_WIN);
213                       else
214                         tui_set_win_focus_to (TUI_DISASM_WIN);
215                       layout_def->split = TRUE;
216                       break;
217                     case SRC_DATA_COMMAND:
218                       if (win_with_focus != TUI_DATA_WIN)
219                         tui_set_win_focus_to (TUI_SRC_WIN);
220                       else
221                         tui_set_win_focus_to (TUI_DATA_WIN);
222                       layout_def->display_mode = SRC_WIN;
223                       layout_def->split = FALSE;
224                       break;
225                     case DISASSEM_DATA_COMMAND:
226                       /* The previous layout was not showing code.
227                          This can happen if there is no source
228                          available:
229
230                          1. if the source file is in another dir OR
231                          2. if target was compiled without -g
232                          We still want to show the assembly though!  */
233
234                       addr = tui_get_begin_asm_address ();
235                       if (win_with_focus != TUI_DATA_WIN)
236                         tui_set_win_focus_to (TUI_DISASM_WIN);
237                       else
238                         tui_set_win_focus_to (TUI_DATA_WIN);
239                       layout_def->display_mode = DISASSEM_WIN;
240                       layout_def->split = FALSE;
241                       break;
242                     default:
243                       break;
244                     }
245                 }
246               /*
247                * Now update the window content.
248                */
249               if (!regs_populate 
250                   && (new_layout == SRC_DATA_COMMAND 
251                       || new_layout == DISASSEM_DATA_COMMAND))
252                 tui_display_all_data ();
253
254               tui_update_source_windows_with_addr (addr);
255             }
256           if (regs_populate)
257             {
258               tui_show_registers (TUI_DATA_WIN->detail.data_display_info.current_group);
259             }
260         }
261     }
262   else
263     status = TUI_FAILURE;
264
265   return status;
266 }
267
268 /* Add the specified window to the layout in a logical way.  This
269    means setting up the most logical layout given the window to be
270    added.  */
271 void
272 tui_add_win_to_layout (enum tui_win_type type)
273 {
274   enum tui_layout_type cur_layout = tui_current_layout ();
275
276   switch (type)
277     {
278     case SRC_WIN:
279       if (cur_layout != SRC_COMMAND
280           && cur_layout != SRC_DISASSEM_COMMAND
281           && cur_layout != SRC_DATA_COMMAND)
282         {
283           tui_clear_source_windows_detail ();
284           if (cur_layout == DISASSEM_DATA_COMMAND)
285             show_layout (SRC_DATA_COMMAND);
286           else
287             show_layout (SRC_COMMAND);
288         }
289       break;
290     case DISASSEM_WIN:
291       if (cur_layout != DISASSEM_COMMAND
292           && cur_layout != SRC_DISASSEM_COMMAND
293           && cur_layout != DISASSEM_DATA_COMMAND)
294         {
295           tui_clear_source_windows_detail ();
296           if (cur_layout == SRC_DATA_COMMAND)
297             show_layout (DISASSEM_DATA_COMMAND);
298           else
299             show_layout (DISASSEM_COMMAND);
300         }
301       break;
302     case DATA_WIN:
303       if (cur_layout != SRC_DATA_COMMAND
304           && cur_layout != DISASSEM_DATA_COMMAND)
305         {
306           if (cur_layout == DISASSEM_COMMAND)
307             show_layout (DISASSEM_DATA_COMMAND);
308           else
309             show_layout (SRC_DATA_COMMAND);
310         }
311       break;
312     default:
313       break;
314     }
315 }
316
317
318 /* Answer the height of a window.  If it hasn't been created yet,
319    answer what the height of a window would be based upon its type and
320    the layout.  */
321 int
322 tui_default_win_height (enum tui_win_type type, 
323                         enum tui_layout_type layout)
324 {
325   int h;
326
327   if (tui_win_list[type] != (struct tui_win_info *) NULL)
328     h = tui_win_list[type]->generic.height;
329   else
330     {
331       switch (layout)
332         {
333         case SRC_COMMAND:
334         case DISASSEM_COMMAND:
335           if (TUI_CMD_WIN == NULL)
336             h = tui_term_height () / 2;
337           else
338             h = tui_term_height () - TUI_CMD_WIN->generic.height;
339           break;
340         case SRC_DISASSEM_COMMAND:
341         case SRC_DATA_COMMAND:
342         case DISASSEM_DATA_COMMAND:
343           if (TUI_CMD_WIN == NULL)
344             h = tui_term_height () / 3;
345           else
346             h = (tui_term_height () - TUI_CMD_WIN->generic.height) / 2;
347           break;
348         default:
349           h = 0;
350           break;
351         }
352     }
353
354   return h;
355 }
356
357
358 /* Answer the height of a window.  If it hasn't been created yet,
359    answer what the height of a window would be based upon its type and
360    the layout.  */
361 int
362 tui_default_win_viewport_height (enum tui_win_type type,
363                                  enum tui_layout_type layout)
364 {
365   int h;
366
367   h = tui_default_win_height (type, layout);
368
369   if (tui_win_list[type] == TUI_CMD_WIN)
370     h -= 1;
371   else
372     h -= 2;
373
374   return h;
375 }
376
377
378 /* Function to initialize gdb commands, for tui window layout
379    manipulation.  */
380 void
381 _initialize_tui_layout (void)
382 {
383   add_com ("layout", class_tui, tui_layout_command, _("\
384 Change the layout of windows.\n\
385 Usage: layout prev | next | <layout_name> \n\
386 Layout names are:\n\
387    src   : Displays source and command windows.\n\
388    asm   : Displays disassembly and command windows.\n\
389    split : Displays source, disassembly and command windows.\n\
390    regs  : Displays register window. If existing layout\n\
391            is source/command or assembly/command, the \n\
392            register window is displayed. If the\n\
393            source/assembly/command (split) is displayed, \n\
394            the register window is displayed with \n\
395            the window that has current logical focus.\n"));
396   if (xdb_commands)
397     {
398       add_com ("td", class_tui, tui_toggle_layout_command, _("\
399 Toggle between Source/Command and Disassembly/Command layouts.\n"));
400       add_com ("ts", class_tui, tui_toggle_split_layout_command, _("\
401 Toggle between Source/Command or Disassembly/Command and \n\
402 Source/Disassembly/Command layouts.\n"));
403     }
404 }
405
406
407 /*************************
408 ** STATIC LOCAL FUNCTIONS
409 **************************/
410
411
412 /* Function to set the layout to SRC, ASM, SPLIT, NEXT, PREV, DATA,
413    REGS, $REGS, $GREGS, $FREGS, $SREGS.  */
414 enum tui_status
415 tui_set_layout_for_display_command (const char *layout_name)
416 {
417   enum tui_status status = TUI_SUCCESS;
418
419   if (layout_name != (char *) NULL)
420     {
421       int i;
422       char *buf_ptr;
423       enum tui_layout_type new_layout = UNDEFINED_LAYOUT;
424       enum tui_register_display_type dpy_type = TUI_UNDEFINED_REGS;
425       enum tui_layout_type cur_layout = tui_current_layout ();
426
427       buf_ptr = (char *) xstrdup (layout_name);
428       for (i = 0; (i < strlen (layout_name)); i++)
429         buf_ptr[i] = toupper (buf_ptr[i]);
430
431       /* First check for ambiguous input.  */
432       if (strlen (buf_ptr) <= 1 
433           && (*buf_ptr == 'S' || *buf_ptr == '$'))
434         {
435           warning (_("Ambiguous command input."));
436           status = TUI_FAILURE;
437         }
438       else
439         {
440           if (subset_compare (buf_ptr, "SRC"))
441             new_layout = SRC_COMMAND;
442           else if (subset_compare (buf_ptr, "ASM"))
443             new_layout = DISASSEM_COMMAND;
444           else if (subset_compare (buf_ptr, "SPLIT"))
445             new_layout = SRC_DISASSEM_COMMAND;
446           else if (subset_compare (buf_ptr, "REGS") 
447                    || subset_compare (buf_ptr, TUI_GENERAL_SPECIAL_REGS_NAME)
448                    || subset_compare (buf_ptr, TUI_GENERAL_REGS_NAME)
449                    || subset_compare (buf_ptr, TUI_FLOAT_REGS_NAME)
450                    || subset_compare (buf_ptr, TUI_SPECIAL_REGS_NAME))
451             {
452               if (cur_layout == SRC_COMMAND 
453                   || cur_layout == SRC_DATA_COMMAND)
454                 new_layout = SRC_DATA_COMMAND;
455               else
456                 new_layout = DISASSEM_DATA_COMMAND;
457
458               /* Could ifdef out the following code. when compile with
459                  -z, there are null pointer references that cause a
460                  core dump if 'layout regs' is the first layout
461                  command issued by the user. HP has asked us to hook
462                  up this code.  - edie epstein  */
463               if (subset_compare (buf_ptr, TUI_FLOAT_REGS_NAME))
464                 {
465                   if (TUI_DATA_WIN->detail.data_display_info.regs_display_type != TUI_SFLOAT_REGS
466                       && TUI_DATA_WIN->detail.data_display_info.regs_display_type != TUI_DFLOAT_REGS)
467                     dpy_type = TUI_SFLOAT_REGS;
468                   else
469                     dpy_type =
470                       TUI_DATA_WIN->detail.data_display_info.regs_display_type;
471                 }
472               else if (subset_compare (buf_ptr,
473                                       TUI_GENERAL_SPECIAL_REGS_NAME))
474                 dpy_type = TUI_GENERAL_AND_SPECIAL_REGS;
475               else if (subset_compare (buf_ptr, TUI_GENERAL_REGS_NAME))
476                 dpy_type = TUI_GENERAL_REGS;
477               else if (subset_compare (buf_ptr, TUI_SPECIAL_REGS_NAME))
478                 dpy_type = TUI_SPECIAL_REGS;
479               else if (TUI_DATA_WIN)
480                 {
481                   if (TUI_DATA_WIN->detail.data_display_info.regs_display_type !=
482                       TUI_UNDEFINED_REGS)
483                     dpy_type =
484                       TUI_DATA_WIN->detail.data_display_info.regs_display_type;
485                   else
486                     dpy_type = TUI_GENERAL_REGS;
487                 }
488
489               /* End of potential ifdef.
490                */
491
492               /* If ifdefed out code above, then assume that the user
493                  wishes to display the general purpose registers .
494               */
495
496               /* dpy_type = TUI_GENERAL_REGS; */
497             }
498           else if (subset_compare (buf_ptr, "NEXT"))
499             new_layout = next_layout ();
500           else if (subset_compare (buf_ptr, "PREV"))
501             new_layout = prev_layout ();
502           else
503             status = TUI_FAILURE;
504
505           tui_set_layout (new_layout, dpy_type);
506         }
507       xfree (buf_ptr);
508     }
509   else
510     status = TUI_FAILURE;
511
512   return status;
513 }
514
515
516 static CORE_ADDR
517 extract_display_start_addr (void)
518 {
519   enum tui_layout_type cur_layout = tui_current_layout ();
520   CORE_ADDR addr;
521   CORE_ADDR pc;
522   struct symtab_and_line cursal = get_current_source_symtab_and_line ();
523
524   switch (cur_layout)
525     {
526     case SRC_COMMAND:
527     case SRC_DATA_COMMAND:
528       find_line_pc (cursal.symtab,
529                     TUI_SRC_WIN->detail.source_info.start_line_or_addr.u.line_no,
530                     &pc);
531       addr = pc;
532       break;
533     case DISASSEM_COMMAND:
534     case SRC_DISASSEM_COMMAND:
535     case DISASSEM_DATA_COMMAND:
536       addr = TUI_DISASM_WIN->detail.source_info.start_line_or_addr.u.addr;
537       break;
538     default:
539       addr = 0;
540       break;
541     }
542
543   return addr;
544 }
545
546
547 static void
548 tui_handle_xdb_layout (struct tui_layout_def *layout_def)
549 {
550   if (layout_def->split)
551     {
552       tui_set_layout (SRC_DISASSEM_COMMAND, TUI_UNDEFINED_REGS);
553       tui_set_win_focus_to (tui_win_list[layout_def->display_mode]);
554     }
555   else
556     {
557       if (layout_def->display_mode == SRC_WIN)
558         tui_set_layout (SRC_COMMAND, TUI_UNDEFINED_REGS);
559       else
560         tui_set_layout (DISASSEM_DATA_COMMAND, layout_def->regs_display_type);
561     }
562 }
563
564
565 static void
566 tui_toggle_layout_command (char *arg, int from_tty)
567 {
568   struct tui_layout_def *layout_def = tui_layout_def ();
569
570   /* Make sure the curses mode is enabled.  */
571   tui_enable ();
572   if (layout_def->display_mode == SRC_WIN)
573     layout_def->display_mode = DISASSEM_WIN;
574   else
575     layout_def->display_mode = SRC_WIN;
576
577   if (!layout_def->split)
578     tui_handle_xdb_layout (layout_def);
579 }
580
581
582 static void
583 tui_toggle_split_layout_command (char *arg, int from_tty)
584 {
585   struct tui_layout_def *layout_def = tui_layout_def ();
586
587   /* Make sure the curses mode is enabled.  */
588   tui_enable ();
589   layout_def->split = (!layout_def->split);
590   tui_handle_xdb_layout (layout_def);
591 }
592
593
594 static void
595 tui_layout_command (char *arg, int from_tty)
596 {
597   /* Make sure the curses mode is enabled.  */
598   tui_enable ();
599
600   /* Switch to the selected layout.  */
601   if (tui_set_layout_for_display_command (arg) != TUI_SUCCESS)
602     warning (_("Invalid layout specified.\n%s"), LAYOUT_USAGE);
603
604 }
605
606 /* Answer the previous layout to cycle to.  */
607 static enum tui_layout_type
608 next_layout (void)
609 {
610   enum tui_layout_type new_layout;
611
612   new_layout = tui_current_layout ();
613   if (new_layout == UNDEFINED_LAYOUT)
614     new_layout = SRC_COMMAND;
615   else
616     {
617       new_layout++;
618       if (new_layout == UNDEFINED_LAYOUT)
619         new_layout = SRC_COMMAND;
620     }
621
622   return new_layout;
623 }
624
625
626 /* Answer the next layout to cycle to.  */
627 static enum tui_layout_type
628 prev_layout (void)
629 {
630   enum tui_layout_type new_layout;
631
632   new_layout = tui_current_layout ();
633   if (new_layout == SRC_COMMAND)
634     new_layout = DISASSEM_DATA_COMMAND;
635   else
636     {
637       new_layout--;
638       if (new_layout == UNDEFINED_LAYOUT)
639         new_layout = DISASSEM_DATA_COMMAND;
640     }
641
642   return new_layout;
643 }
644
645
646
647 static void
648 make_command_window (struct tui_win_info **win_info_ptr, 
649                      int height, int origin_y)
650 {
651   *win_info_ptr = init_and_make_win (*win_info_ptr,
652                                      CMD_WIN,
653                                      height,
654                                      tui_term_width (),
655                                      0,
656                                      origin_y,
657                                      DONT_BOX_WINDOW);
658
659   (*win_info_ptr)->can_highlight = FALSE;
660 }
661
662
663 /* make_source_window().
664  */
665 static void
666 make_source_window (struct tui_win_info **win_info_ptr, 
667                     int height, int origin_y)
668 {
669   make_source_or_disasm_window (win_info_ptr, SRC_WIN, height, origin_y);
670
671   return;
672 }                               /* make_source_window */
673
674
675 /* make_disasm_window().
676  */
677 static void
678 make_disasm_window (struct tui_win_info **win_info_ptr, 
679                     int height, int origin_y)
680 {
681   make_source_or_disasm_window (win_info_ptr, DISASSEM_WIN, height, origin_y);
682
683   return;
684 }                               /* make_disasm_window */
685
686
687 static void
688 make_data_window (struct tui_win_info **win_info_ptr, 
689                   int height, int origin_y)
690 {
691   *win_info_ptr = init_and_make_win (*win_info_ptr,
692                                      DATA_WIN,
693                                      height,
694                                      tui_term_width (),
695                                      0,
696                                      origin_y,
697                                      BOX_WINDOW);
698 }
699
700
701
702 /* Show the Source/Command layout.  */
703 static void
704 show_source_command (void)
705 {
706   show_source_or_disasm_and_command (SRC_COMMAND);
707 }
708
709
710 /* Show the Dissassem/Command layout.  */
711 static void
712 show_disasm_command (void)
713 {
714   show_source_or_disasm_and_command (DISASSEM_COMMAND);
715 }
716
717
718 /* Show the Source/Disassem/Command layout.  */
719 static void
720 show_source_disasm_command (void)
721 {
722   if (tui_current_layout () != SRC_DISASSEM_COMMAND)
723     {
724       int cmd_height, src_height, asm_height;
725
726       if (TUI_CMD_WIN != NULL)
727         cmd_height = TUI_CMD_WIN->generic.height;
728       else
729         cmd_height = tui_term_height () / 3;
730
731       src_height = (tui_term_height () - cmd_height) / 2;
732       asm_height = tui_term_height () - (src_height + cmd_height);
733
734       if (TUI_SRC_WIN == NULL)
735         make_source_window (&TUI_SRC_WIN, src_height, 0);
736       else
737         {
738           init_gen_win_info (&TUI_SRC_WIN->generic,
739                              TUI_SRC_WIN->generic.type,
740                              src_height,
741                              TUI_SRC_WIN->generic.width,
742                              TUI_SRC_WIN->detail.source_info.execution_info->width,
743                              0);
744           TUI_SRC_WIN->can_highlight = TRUE;
745           init_gen_win_info (TUI_SRC_WIN->detail.source_info.execution_info,
746                              EXEC_INFO_WIN,
747                              src_height,
748                              3,
749                              0,
750                              0);
751           tui_make_visible (&TUI_SRC_WIN->generic);
752           tui_make_visible (TUI_SRC_WIN->detail.source_info.execution_info);
753           TUI_SRC_WIN->detail.source_info.has_locator = FALSE;;
754         }
755       if (TUI_SRC_WIN != NULL)
756         {
757           struct tui_gen_win_info *locator = tui_locator_win_info_ptr ();
758
759           tui_show_source_content (TUI_SRC_WIN);
760           if (TUI_DISASM_WIN == NULL)
761             {
762               make_disasm_window (&TUI_DISASM_WIN, asm_height, src_height - 1);
763               locator = init_and_make_win (locator,
764                                            LOCATOR_WIN,
765                                            2 /* 1 */ ,
766                                            tui_term_width (),
767                                            0,
768                                            (src_height + asm_height) - 1,
769                                            DONT_BOX_WINDOW);
770             }
771           else
772             {
773               init_gen_win_info (locator,
774                                  LOCATOR_WIN,
775                                  2 /* 1 */ ,
776                                  tui_term_width (),
777                                  0,
778                                  (src_height + asm_height) - 1);
779               TUI_DISASM_WIN->detail.source_info.has_locator = TRUE;
780               init_gen_win_info (&TUI_DISASM_WIN->generic,
781                                  TUI_DISASM_WIN->generic.type,
782                                  asm_height,
783                                  TUI_DISASM_WIN->generic.width,
784                                  TUI_DISASM_WIN->detail.source_info.execution_info->width,
785                                  src_height - 1);
786               init_gen_win_info (TUI_DISASM_WIN->detail.source_info.execution_info,
787                                  EXEC_INFO_WIN,
788                                  asm_height,
789                                  3,
790                                  0,
791                                  src_height - 1);
792               TUI_DISASM_WIN->can_highlight = TRUE;
793               tui_make_visible (&TUI_DISASM_WIN->generic);
794               tui_make_visible (TUI_DISASM_WIN->detail.source_info.execution_info);
795             }
796           if (TUI_DISASM_WIN != NULL)
797             {
798               TUI_SRC_WIN->detail.source_info.has_locator = FALSE;
799               TUI_DISASM_WIN->detail.source_info.has_locator = TRUE;
800               tui_make_visible (locator);
801               tui_show_locator_content ();
802               tui_show_source_content (TUI_DISASM_WIN);
803
804               if (TUI_CMD_WIN == NULL)
805                 make_command_window (&TUI_CMD_WIN,
806                                      cmd_height,
807                                      tui_term_height () - cmd_height);
808               else
809                 {
810                   init_gen_win_info (&TUI_CMD_WIN->generic,
811                                      TUI_CMD_WIN->generic.type,
812                                      TUI_CMD_WIN->generic.height,
813                                      TUI_CMD_WIN->generic.width,
814                                      0,
815                                      TUI_CMD_WIN->generic.origin.y);
816                   TUI_CMD_WIN->can_highlight = FALSE;
817                   tui_make_visible (&TUI_CMD_WIN->generic);
818                 }
819               if (TUI_CMD_WIN != NULL)
820                 tui_refresh_win (&TUI_CMD_WIN->generic);
821             }
822         }
823       tui_set_current_layout_to (SRC_DISASSEM_COMMAND);
824     }
825 }
826
827
828 /* Show the Source/Data/Command or the Dissassembly/Data/Command
829    layout.  */
830 static void
831 show_data (enum tui_layout_type new_layout)
832 {
833   int total_height = (tui_term_height () - TUI_CMD_WIN->generic.height);
834   int src_height, data_height;
835   enum tui_win_type win_type;
836   struct tui_gen_win_info *locator = tui_locator_win_info_ptr ();
837
838
839   data_height = total_height / 2;
840   src_height = total_height - data_height;
841   tui_make_all_invisible ();
842   tui_make_invisible (locator);
843   make_data_window (&TUI_DATA_WIN, data_height, 0);
844   TUI_DATA_WIN->can_highlight = TRUE;
845   if (new_layout == SRC_DATA_COMMAND)
846     win_type = SRC_WIN;
847   else
848     win_type = DISASSEM_WIN;
849   if (tui_win_list[win_type] == NULL)
850     {
851       if (win_type == SRC_WIN)
852         make_source_window (&tui_win_list[win_type], src_height, data_height - 1);
853       else
854         make_disasm_window (&tui_win_list[win_type], src_height, data_height - 1);
855       locator = init_and_make_win (locator,
856                                    LOCATOR_WIN,
857                                    2 /* 1 */ ,
858                                    tui_term_width (),
859                                    0,
860                                    total_height - 1,
861                                    DONT_BOX_WINDOW);
862     }
863   else
864     {
865       init_gen_win_info (&tui_win_list[win_type]->generic,
866                          tui_win_list[win_type]->generic.type,
867                          src_height,
868                          tui_win_list[win_type]->generic.width,
869                          tui_win_list[win_type]->detail.source_info.execution_info->width,
870                          data_height - 1);
871       init_gen_win_info (tui_win_list[win_type]->detail.source_info.execution_info,
872                          EXEC_INFO_WIN,
873                          src_height,
874                          3,
875                          0,
876                          data_height - 1);
877       tui_make_visible (&tui_win_list[win_type]->generic);
878       tui_make_visible (tui_win_list[win_type]->detail.source_info.execution_info);
879       init_gen_win_info (locator,
880                          LOCATOR_WIN,
881                          2 /* 1 */ ,
882                          tui_term_width (),
883                          0,
884                          total_height - 1);
885     }
886   tui_win_list[win_type]->detail.source_info.has_locator = TRUE;
887   tui_make_visible (locator);
888   tui_show_locator_content ();
889   tui_add_to_source_windows (tui_win_list[win_type]);
890   tui_set_current_layout_to (new_layout);
891 }
892
893 /* init_gen_win_info().
894  */
895 static void
896 init_gen_win_info (struct tui_gen_win_info *win_info, 
897                    enum tui_win_type type,
898                    int height, int width, 
899                    int origin_x, int origin_y)
900 {
901   int h = height;
902
903   win_info->type = type;
904   win_info->width = width;
905   win_info->height = h;
906   if (h > 1)
907     {
908       win_info->viewport_height = h - 1;
909       if (win_info->type != CMD_WIN)
910         win_info->viewport_height--;
911     }
912   else
913     win_info->viewport_height = 1;
914   win_info->origin.x = origin_x;
915   win_info->origin.y = origin_y;
916
917   return;
918 }                               /* init_gen_win_info */
919
920 /* init_and_make_win().
921  */
922 static void *
923 init_and_make_win (void *opaque_win_info, 
924                    enum tui_win_type win_type,
925                    int height, int width, 
926                    int origin_x, int origin_y,
927                    int box_it)
928 {
929   struct tui_gen_win_info *generic;
930
931   if (opaque_win_info == NULL)
932     {
933       if (tui_win_is_auxillary (win_type))
934         opaque_win_info = (void *) tui_alloc_generic_win_info ();
935       else
936         opaque_win_info = (void *) tui_alloc_win_info (win_type);
937     }
938   if (tui_win_is_auxillary (win_type))
939     generic = (struct tui_gen_win_info *) opaque_win_info;
940   else
941     generic = &((struct tui_win_info *) opaque_win_info)->generic;
942
943   if (opaque_win_info != NULL)
944     {
945       init_gen_win_info (generic, win_type, height, width, origin_x, origin_y);
946       if (!tui_win_is_auxillary (win_type))
947         {
948           if (generic->type == CMD_WIN)
949             ((struct tui_win_info *) opaque_win_info)->can_highlight = FALSE;
950           else
951             ((struct tui_win_info *) opaque_win_info)->can_highlight = TRUE;
952         }
953       tui_make_window (generic, box_it);
954     }
955   return opaque_win_info;
956 }
957
958
959 static void
960 make_source_or_disasm_window (struct tui_win_info **win_info_ptr, 
961                               enum tui_win_type type,
962                               int height, int origin_y)
963 {
964   struct tui_gen_win_info *execution_info = (struct tui_gen_win_info *) NULL;
965
966   /* Create the exeuction info window.  */
967   if (type == SRC_WIN)
968     execution_info = tui_source_exec_info_win_ptr ();
969   else
970     execution_info = tui_disassem_exec_info_win_ptr ();
971   execution_info = init_and_make_win (execution_info,
972                                       EXEC_INFO_WIN,
973                                       height,
974                                       3,
975                                       0,
976                                       origin_y,
977                                       DONT_BOX_WINDOW);
978
979   /* Now create the source window.  */
980   *win_info_ptr = init_and_make_win (*win_info_ptr,
981                                      type,
982                                      height,
983                                      tui_term_width () - execution_info->width,
984                                      execution_info->width,
985                                      origin_y,
986                                      BOX_WINDOW);
987
988   (*win_info_ptr)->detail.source_info.execution_info = execution_info;
989 }
990
991
992 /* Show the Source/Command or the Disassem layout.  */
993 static void
994 show_source_or_disasm_and_command (enum tui_layout_type layout_type)
995 {
996   if (tui_current_layout () != layout_type)
997     {
998       struct tui_win_info **win_info_ptr;
999       int src_height, cmd_height;
1000       struct tui_gen_win_info *locator = tui_locator_win_info_ptr ();
1001
1002       if (TUI_CMD_WIN != NULL)
1003         cmd_height = TUI_CMD_WIN->generic.height;
1004       else
1005         cmd_height = tui_term_height () / 3;
1006       src_height = tui_term_height () - cmd_height;
1007
1008       if (layout_type == SRC_COMMAND)
1009         win_info_ptr = &TUI_SRC_WIN;
1010       else
1011         win_info_ptr = &TUI_DISASM_WIN;
1012
1013       if ((*win_info_ptr) == NULL)
1014         {
1015           if (layout_type == SRC_COMMAND)
1016             make_source_window (win_info_ptr, src_height - 1, 0);
1017           else
1018             make_disasm_window (win_info_ptr, src_height - 1, 0);
1019           locator = init_and_make_win (locator,
1020                                        LOCATOR_WIN,
1021                                        2 /* 1 */ ,
1022                                        tui_term_width (),
1023                                        0,
1024                                        src_height - 1,
1025                                        DONT_BOX_WINDOW);
1026         }
1027       else
1028         {
1029           init_gen_win_info (locator,
1030                              LOCATOR_WIN,
1031                              2 /* 1 */ ,
1032                              tui_term_width (),
1033                              0,
1034                              src_height - 1);
1035           (*win_info_ptr)->detail.source_info.has_locator = TRUE;
1036           init_gen_win_info (&(*win_info_ptr)->generic,
1037                              (*win_info_ptr)->generic.type,
1038                              src_height - 1,
1039                              (*win_info_ptr)->generic.width,
1040                              (*win_info_ptr)->detail.source_info.execution_info->width,
1041                              0);
1042           init_gen_win_info ((*win_info_ptr)->detail.source_info.execution_info,
1043                              EXEC_INFO_WIN,
1044                              src_height - 1,
1045                              3,
1046                              0,
1047                              0);
1048           (*win_info_ptr)->can_highlight = TRUE;
1049           tui_make_visible (&(*win_info_ptr)->generic);
1050           tui_make_visible ((*win_info_ptr)->detail.source_info.execution_info);
1051         }
1052       if ((*win_info_ptr) != NULL)
1053         {
1054           (*win_info_ptr)->detail.source_info.has_locator = TRUE;
1055           tui_make_visible (locator);
1056           tui_show_locator_content ();
1057           tui_show_source_content (*win_info_ptr);
1058
1059           if (TUI_CMD_WIN == NULL)
1060             {
1061               make_command_window (&TUI_CMD_WIN, cmd_height, src_height);
1062               tui_refresh_win (&TUI_CMD_WIN->generic);
1063             }
1064           else
1065             {
1066               init_gen_win_info (&TUI_CMD_WIN->generic,
1067                                  TUI_CMD_WIN->generic.type,
1068                                  TUI_CMD_WIN->generic.height,
1069                                  TUI_CMD_WIN->generic.width,
1070                                  TUI_CMD_WIN->generic.origin.x,
1071                                  TUI_CMD_WIN->generic.origin.y);
1072               TUI_CMD_WIN->can_highlight = FALSE;
1073               tui_make_visible (&TUI_CMD_WIN->generic);
1074             }
1075         }
1076       tui_set_current_layout_to (layout_type);
1077     }
1078 }