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