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