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