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