* tuiDisassem.c (tui_disassemble): New function to disassemble
[external/binutils.git] / gdb / tui / tuiWin.c
1 /* TUI window generic functions.
2
3    Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation,
4    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 /* This module contains procedures for handling tui window functions
26    like resize, scrolling, scrolling, changing focus, etc.
27
28    Author: Susan B. Macchia  */
29
30 /* FIXME: cagney/2002-02-28: The GDB coding standard indicates that
31    "defs.h" should be included first.  Unfortunatly some systems
32    (currently Debian GNU/Linux) include the <stdbool.h> via <curses.h>
33    and they clash with "bfd.h"'s definiton of true/false.  The correct
34    fix is to remove true/false from "bfd.h", however, until that
35    happens, hack around it by including "config.h" and <curses.h>
36    first.  */
37
38 #include "config.h"
39 #ifdef HAVE_NCURSES_H       
40 #include <ncurses.h>
41 #else
42 #ifdef HAVE_CURSES_H
43 #include <curses.h>
44 #endif
45 #endif
46
47 #include <string.h>
48 #include <ctype.h>
49 #include "defs.h"
50 #include "command.h"
51 #include "symtab.h"
52 #include "breakpoint.h"
53 #include "frame.h"
54 #include "cli/cli-cmds.h"
55 #include "top.h"
56
57 #include "tui.h"
58 #include "tuiData.h"
59 #include "tuiGeneralWin.h"
60 #include "tuiStack.h"
61 #include "tuiRegs.h"
62 #include "tuiDisassem.h"
63 #include "tuiSource.h"
64 #include "tuiSourceWin.h"
65 #include "tuiDataWin.h"
66
67 /*******************************
68 ** Static Local Decls
69 ********************************/
70 static void _makeVisibleWithNewHeight (TuiWinInfoPtr);
71 static void _makeInvisibleAndSetNewHeight (TuiWinInfoPtr, int);
72 static TuiStatus _tuiAdjustWinHeights (TuiWinInfoPtr, int);
73 static int _newHeightOk (TuiWinInfoPtr, int);
74 static void _tuiSetTabWidth_command (char *, int);
75 static void _tuiRefreshAll_command (char *, int);
76 static void _tuiSetWinHeight_command (char *, int);
77 static void _tuiXDBsetWinHeight_command (char *, int);
78 static void _tuiAllWindowsInfo (char *, int);
79 static void _tuiSetFocus_command (char *, int);
80 static void _tuiScrollForward_command (char *, int);
81 static void _tuiScrollBackward_command (char *, int);
82 static void _tuiScrollLeft_command (char *, int);
83 static void _tuiScrollRight_command (char *, int);
84 static void _parseScrollingArgs (char *, TuiWinInfoPtr *, int *);
85
86
87 /***************************************
88 ** DEFINITIONS
89 ***************************************/
90 #define WIN_HEIGHT_USAGE      "Usage: winheight <win_name> [+ | -] <#lines>\n"
91 #define XDBWIN_HEIGHT_USAGE   "Usage: w <#lines>\n"
92 #define FOCUS_USAGE           "Usage: focus {<win> | next | prev}\n"
93
94 /***************************************
95 ** PUBLIC FUNCTIONS
96 ***************************************/
97
98 /* Possible values for tui-border-kind variable.  */
99 static const char *tui_border_kind_enums[] = {
100   "space",
101   "ascii",
102   "acs",
103   NULL
104 };
105
106 /* Possible values for tui-border-mode and tui-active-border-mode.  */
107 static const char *tui_border_mode_enums[] = {
108   "normal",
109   "standout",
110   "reverse",
111   "half",
112   "half-standout",
113   "bold",
114   "bold-standout",
115   NULL
116 };
117
118 struct tui_translate
119 {
120   const char *name;
121   int value;
122 };
123
124 /* Translation table for border-mode variables.
125    The list of values must be terminated by a NULL.
126    After the NULL value, an entry defines the default.  */
127 struct tui_translate tui_border_mode_translate[] = {
128   { "normal",           A_NORMAL },
129   { "standout",         A_STANDOUT },
130   { "reverse",          A_REVERSE },
131   { "half",             A_DIM },
132   { "half-standout",    A_DIM | A_STANDOUT },
133   { "bold",             A_BOLD },
134   { "bold-standout",    A_BOLD | A_STANDOUT },
135   { 0, 0 },
136   { "normal",           A_NORMAL }
137 };
138
139 /* Translation tables for border-kind, one for each border
140    character (see wborder, border curses operations).
141    -1 is used to indicate the ACS because ACS characters
142    are determined at run time by curses (depends on terminal).  */
143 struct tui_translate tui_border_kind_translate_vline[] = {
144   { "space",    ' ' },
145   { "ascii",    '|' },
146   { "acs",      -1 },
147   { 0, 0 },
148   { "ascii",    '|' }
149 };
150
151 struct tui_translate tui_border_kind_translate_hline[] = {
152   { "space",    ' ' },
153   { "ascii",    '-' },
154   { "acs",      -1 },
155   { 0, 0 },
156   { "ascii",    '-' }
157 };
158
159 struct tui_translate tui_border_kind_translate_ulcorner[] = {
160   { "space",    ' ' },
161   { "ascii",    '+' },
162   { "acs",      -1 },
163   { 0, 0 },
164   { "ascii",    '+' }
165 };
166
167 struct tui_translate tui_border_kind_translate_urcorner[] = {
168   { "space",    ' ' },
169   { "ascii",    '+' },
170   { "acs",      -1 },
171   { 0, 0 },
172   { "ascii",    '+' }
173 };
174
175 struct tui_translate tui_border_kind_translate_llcorner[] = {
176   { "space",    ' ' },
177   { "ascii",    '+' },
178   { "acs",      -1 },
179   { 0, 0 },
180   { "ascii",    '+' }
181 };
182
183 struct tui_translate tui_border_kind_translate_lrcorner[] = {
184   { "space",    ' ' },
185   { "ascii",    '+' },
186   { "acs",      -1 },
187   { 0, 0 },
188   { "ascii",    '+' }
189 };
190
191
192 /* Tui configuration variables controlled with set/show command.  */
193 const char *tui_active_border_mode = "bold-standout";
194 const char *tui_border_mode = "normal";
195 const char *tui_border_kind = "acs";
196
197 /* Tui internal configuration variables.  These variables are
198    updated by tui_update_variables to reflect the tui configuration
199    variables.  */
200 chtype tui_border_vline;
201 chtype tui_border_hline;
202 chtype tui_border_ulcorner;
203 chtype tui_border_urcorner;
204 chtype tui_border_llcorner;
205 chtype tui_border_lrcorner;
206
207 int tui_border_attrs;
208 int tui_active_border_attrs;
209
210 /* Identify the item in the translation table.
211    When the item is not recognized, use the default entry.  */
212 static struct tui_translate *
213 translate (const char *name, struct tui_translate *table)
214 {
215   while (table->name)
216     {
217       if (name && strcmp (table->name, name) == 0)
218         return table;
219       table++;
220     }
221
222   /* Not found, return default entry.  */
223   table++;
224   return table;
225 }
226
227 /* Update the tui internal configuration according to gdb settings.
228    Returns 1 if the configuration has changed and the screen should
229    be redrawn.  */
230 int
231 tui_update_variables ()
232 {
233   int need_redraw = 0;
234   struct tui_translate *entry;
235
236   entry = translate (tui_border_mode, tui_border_mode_translate);
237   if (tui_border_attrs != entry->value)
238     {
239       tui_border_attrs = entry->value;
240       need_redraw = 1;
241     }
242   entry = translate (tui_active_border_mode, tui_border_mode_translate);
243   if (tui_active_border_attrs != entry->value)
244     {
245       tui_active_border_attrs = entry->value;
246       need_redraw = 1;
247     }
248
249   /* If one corner changes, all characters are changed.
250      Only check the first one.  The ACS characters are determined at
251      run time by curses terminal management.  */
252   entry = translate (tui_border_kind, tui_border_kind_translate_lrcorner);
253   if (tui_border_lrcorner != (chtype) entry->value)
254     {
255       tui_border_lrcorner = (entry->value < 0) ? ACS_LRCORNER : entry->value;
256       need_redraw = 1;
257     }
258   entry = translate (tui_border_kind, tui_border_kind_translate_llcorner);
259   tui_border_llcorner = (entry->value < 0) ? ACS_LLCORNER : entry->value;
260
261   entry = translate (tui_border_kind, tui_border_kind_translate_ulcorner);
262   tui_border_ulcorner = (entry->value < 0) ? ACS_ULCORNER : entry->value;
263
264   entry = translate (tui_border_kind, tui_border_kind_translate_urcorner);
265   tui_border_urcorner = (entry->value < 0) ? ACS_URCORNER : entry->value;
266
267   entry = translate (tui_border_kind, tui_border_kind_translate_hline);
268   tui_border_hline = (entry->value < 0) ? ACS_HLINE : entry->value;
269
270   entry = translate (tui_border_kind, tui_border_kind_translate_vline);
271   tui_border_vline = (entry->value < 0) ? ACS_VLINE : entry->value;
272
273   return need_redraw;
274 }
275
276 static void
277 set_tui_cmd (char *args, int from_tty)
278 {
279 }
280
281 static void
282 show_tui_cmd (char *args, int from_tty)
283 {
284 }
285
286 /*
287    ** _initialize_tuiWin().
288    **        Function to initialize gdb commands, for tui window manipulation.
289  */
290 void
291 _initialize_tuiWin (void)
292 {
293   struct cmd_list_element *c;
294   static struct cmd_list_element *tui_setlist;
295   static struct cmd_list_element *tui_showlist;
296
297   /* Define the classes of commands.
298      They will appear in the help list in the reverse of this order.  */
299   add_cmd ("tui", class_tui, NULL,
300            "Text User Interface commands.",
301            &cmdlist);
302
303   add_prefix_cmd ("tui", class_tui, set_tui_cmd,
304                   "TUI configuration variables",
305                   &tui_setlist, "set tui ",
306                   0/*allow-unknown*/, &setlist);
307   add_prefix_cmd ("tui", class_tui, show_tui_cmd,
308                   "TUI configuration variables",
309                   &tui_showlist, "show tui ",
310                   0/*allow-unknown*/, &showlist);
311
312   add_com ("refresh", class_tui, _tuiRefreshAll_command,
313            "Refresh the terminal display.\n");
314   if (xdb_commands)
315     add_com_alias ("U", "refresh", class_tui, 0);
316   add_com ("tabset", class_tui, _tuiSetTabWidth_command,
317            "Set the width (in characters) of tab stops.\n\
318 Usage: tabset <n>\n");
319   add_com ("winheight", class_tui, _tuiSetWinHeight_command,
320            "Set the height of a specified window.\n\
321 Usage: winheight <win_name> [+ | -] <#lines>\n\
322 Window names are:\n\
323 src  : the source window\n\
324 cmd  : the command window\n\
325 asm  : the disassembly window\n\
326 regs : the register display\n");
327   add_com_alias ("wh", "winheight", class_tui, 0);
328   add_info ("win", _tuiAllWindowsInfo,
329             "List of all displayed windows.\n");
330   add_com ("focus", class_tui, _tuiSetFocus_command,
331            "Set focus to named window or next/prev window.\n\
332 Usage: focus {<win> | next | prev}\n\
333 Valid Window names are:\n\
334 src  : the source window\n\
335 asm  : the disassembly window\n\
336 regs : the register display\n\
337 cmd  : the command window\n");
338   add_com_alias ("fs", "focus", class_tui, 0);
339   add_com ("+", class_tui, _tuiScrollForward_command,
340            "Scroll window forward.\nUsage: + [win] [n]\n");
341   add_com ("-", class_tui, _tuiScrollBackward_command,
342            "Scroll window backward.\nUsage: - [win] [n]\n");
343   add_com ("<", class_tui, _tuiScrollLeft_command,
344            "Scroll window forward.\nUsage: < [win] [n]\n");
345   add_com (">", class_tui, _tuiScrollRight_command,
346            "Scroll window backward.\nUsage: > [win] [n]\n");
347   if (xdb_commands)
348     add_com ("w", class_xdb, _tuiXDBsetWinHeight_command,
349              "XDB compatibility command for setting the height of a command window.\n\
350 Usage: w <#lines>\n");
351
352   /* Define the tui control variables.  */
353   c = add_set_enum_cmd
354     ("border-kind", no_class,
355      tui_border_kind_enums, &tui_border_kind,
356      "Set the kind of border for TUI windows.\n"
357      "This variable controls the border of TUI windows:\n"
358      "space           use a white space\n"
359      "ascii           use ascii characters + - | for the border\n"
360      "acs             use the Alternate Character Set\n",
361      &tui_setlist);
362   add_show_from_set (c, &tui_showlist);
363
364   c = add_set_enum_cmd
365     ("border-mode", no_class,
366      tui_border_mode_enums, &tui_border_mode,
367      "Set the attribute mode to use for the TUI window borders.\n"
368      "This variable controls the attributes to use for the window borders:\n"
369      "normal          normal display\n"
370      "standout        use highlight mode of terminal\n"
371      "reverse         use reverse video mode\n"
372      "half            use half bright\n"
373      "half-standout   use half bright and standout mode\n"
374      "bold            use extra bright or bold\n"
375      "bold-standout   use extra bright or bold with standout mode\n",
376      &tui_setlist);
377   add_show_from_set (c, &tui_showlist);
378
379   c = add_set_enum_cmd
380     ("active-border-mode", no_class,
381      tui_border_mode_enums, &tui_active_border_mode,
382      "Set the attribute mode to use for the active TUI window border.\n"
383      "This variable controls the attributes to use for the active window border:\n"
384      "normal          normal display\n"
385      "standout        use highlight mode of terminal\n"
386      "reverse         use reverse video mode\n"
387      "half            use half bright\n"
388      "half-standout   use half bright and standout mode\n"
389      "bold            use extra bright or bold\n"
390      "bold-standout   use extra bright or bold with standout mode\n",
391      &tui_setlist);
392   add_show_from_set (c, &tui_showlist);
393 }
394
395 /* Update gdb's knowledge of the terminal size.  */
396 void
397 tui_update_gdb_sizes ()
398 {
399   char cmd[50];
400   extern int screenheight, screenwidth;         /* in readline */
401
402   /* Set to TUI command window dimension or use readline values.  */
403   sprintf (cmd, "set width %d",
404            tui_active ? cmdWin->generic.width : screenwidth);
405   execute_command (cmd, 0);
406   sprintf (cmd, "set height %d",
407            tui_active ? cmdWin->generic.height : screenheight);
408   execute_command (cmd, 0);
409 }
410
411
412 /*
413    ** tuiSetWinFocusTo
414    **        Set the logical focus to winInfo
415  */
416 void
417 tuiSetWinFocusTo (TuiWinInfoPtr winInfo)
418 {
419   if (m_winPtrNotNull (winInfo))
420     {
421       TuiWinInfoPtr winWithFocus = tuiWinWithFocus ();
422
423       if (m_winPtrNotNull (winWithFocus) &&
424           winWithFocus->generic.type != CMD_WIN)
425         unhighlightWin (winWithFocus);
426       tuiSetWinWithFocus (winInfo);
427       if (winInfo->generic.type != CMD_WIN)
428         highlightWin (winInfo);
429     }
430
431   return;
432 }                               /* tuiSetWinFocusTo */
433
434
435 /*
436    ** tuiScrollForward().
437  */
438 void
439 tuiScrollForward (TuiWinInfoPtr winToScroll, int numToScroll)
440 {
441   if (winToScroll != cmdWin)
442     {
443       int _numToScroll = numToScroll;
444
445       if (numToScroll == 0)
446         _numToScroll = winToScroll->generic.height - 3;
447       /*
448          ** If we are scrolling the source or disassembly window, do a
449          ** "psuedo" scroll since not all of the source is in memory,
450          ** only what is in the viewport.  If winToScroll is the
451          ** command window do nothing since the term should handle it.
452        */
453       if (winToScroll == srcWin)
454         tuiVerticalSourceScroll (FORWARD_SCROLL, _numToScroll);
455       else if (winToScroll == disassemWin)
456         tuiVerticalDisassemScroll (FORWARD_SCROLL, _numToScroll);
457       else if (winToScroll == dataWin)
458         tuiVerticalDataScroll (FORWARD_SCROLL, _numToScroll);
459     }
460
461   return;
462 }                               /* tuiScrollForward */
463
464
465 /*
466    ** tuiScrollBackward().
467  */
468 void
469 tuiScrollBackward (TuiWinInfoPtr winToScroll, int numToScroll)
470 {
471   if (winToScroll != cmdWin)
472     {
473       int _numToScroll = numToScroll;
474
475       if (numToScroll == 0)
476         _numToScroll = winToScroll->generic.height - 3;
477       /*
478          ** If we are scrolling the source or disassembly window, do a
479          ** "psuedo" scroll since not all of the source is in memory,
480          ** only what is in the viewport.  If winToScroll is the
481          ** command window do nothing since the term should handle it.
482        */
483       if (winToScroll == srcWin)
484         tuiVerticalSourceScroll (BACKWARD_SCROLL, _numToScroll);
485       else if (winToScroll == disassemWin)
486         tuiVerticalDisassemScroll (BACKWARD_SCROLL, _numToScroll);
487       else if (winToScroll == dataWin)
488         tuiVerticalDataScroll (BACKWARD_SCROLL, _numToScroll);
489     }
490   return;
491 }                               /* tuiScrollBackward */
492
493
494 /*
495    ** tuiScrollLeft().
496  */
497 void
498 tuiScrollLeft (TuiWinInfoPtr winToScroll, int numToScroll)
499 {
500   if (winToScroll != cmdWin)
501     {
502       int _numToScroll = numToScroll;
503
504       if (_numToScroll == 0)
505         _numToScroll = 1;
506       /*
507          ** If we are scrolling the source or disassembly window, do a
508          ** "psuedo" scroll since not all of the source is in memory,
509          ** only what is in the viewport. If winToScroll is the
510          ** command window do nothing since the term should handle it.
511        */
512       if (winToScroll == srcWin || winToScroll == disassemWin)
513         tuiHorizontalSourceScroll (winToScroll, LEFT_SCROLL, _numToScroll);
514     }
515   return;
516 }                               /* tuiScrollLeft */
517
518
519 /*
520    ** tuiScrollRight().
521  */
522 void
523 tuiScrollRight (TuiWinInfoPtr winToScroll, int numToScroll)
524 {
525   if (winToScroll != cmdWin)
526     {
527       int _numToScroll = numToScroll;
528
529       if (_numToScroll == 0)
530         _numToScroll = 1;
531       /*
532          ** If we are scrolling the source or disassembly window, do a
533          ** "psuedo" scroll since not all of the source is in memory,
534          ** only what is in the viewport. If winToScroll is the
535          ** command window do nothing since the term should handle it.
536        */
537       if (winToScroll == srcWin || winToScroll == disassemWin)
538         tuiHorizontalSourceScroll (winToScroll, RIGHT_SCROLL, _numToScroll);
539     }
540   return;
541 }                               /* tuiScrollRight */
542
543
544 /*
545    ** tui_scroll().
546    **    Scroll a window.  Arguments are passed through a va_list.
547  */
548 void
549 tui_scroll (TuiScrollDirection direction,
550             TuiWinInfoPtr winToScroll,
551             int numToScroll)
552 {
553   switch (direction)
554     {
555     case FORWARD_SCROLL:
556       tuiScrollForward (winToScroll, numToScroll);
557       break;
558     case BACKWARD_SCROLL:
559       tuiScrollBackward (winToScroll, numToScroll);
560       break;
561     case LEFT_SCROLL:
562       tuiScrollLeft (winToScroll, numToScroll);
563       break;
564     case RIGHT_SCROLL:
565       tuiScrollRight (winToScroll, numToScroll);
566       break;
567     default:
568       break;
569     }
570 }
571
572
573 /*
574    ** tuiRefreshAll().
575  */
576 void
577 tuiRefreshAll (void)
578 {
579   TuiWinType type;
580
581   clearok (curscr, TRUE);
582   refreshAll (winList);
583   for (type = SRC_WIN; type < MAX_MAJOR_WINDOWS; type++)
584     {
585       if (winList[type] && winList[type]->generic.isVisible)
586         {
587           switch (type)
588             {
589             case SRC_WIN:
590             case DISASSEM_WIN:
591               tuiShowSourceContent (winList[type]);
592               checkAndDisplayHighlightIfNeeded (winList[type]);
593               tuiEraseExecInfoContent (winList[type]);
594               tuiUpdateExecInfo (winList[type]);
595               break;
596             case DATA_WIN:
597               tuiRefreshDataWin ();
598               break;
599             default:
600               break;
601             }
602         }
603     }
604   tuiShowLocatorContent ();
605 }
606
607
608 /*
609    ** tuiResizeAll().
610    **      Resize all the windows based on the the terminal size.  This
611    **      function gets called from within the readline sinwinch handler.
612  */
613 void
614 tuiResizeAll (void)
615 {
616   int heightDiff, widthDiff;
617   extern int screenheight, screenwidth;         /* in readline */
618
619   widthDiff = screenwidth - termWidth ();
620   heightDiff = screenheight - termHeight ();
621   if (heightDiff || widthDiff)
622     {
623       TuiLayoutType curLayout = currentLayout ();
624       TuiWinInfoPtr winWithFocus = tuiWinWithFocus ();
625       TuiWinInfoPtr firstWin, secondWin;
626       TuiGenWinInfoPtr locator = locatorWinInfoPtr ();
627       TuiWinType winType;
628       int newHeight, splitDiff, cmdSplitDiff, numWinsDisplayed = 2;
629
630       /* turn keypad off while we resize */
631       if (winWithFocus != cmdWin)
632         keypad (cmdWin->generic.handle, FALSE);
633       tui_update_gdb_sizes ();
634       setTermHeightTo (screenheight);
635       setTermWidthTo (screenwidth);
636       if (curLayout == SRC_DISASSEM_COMMAND ||
637         curLayout == SRC_DATA_COMMAND || curLayout == DISASSEM_DATA_COMMAND)
638         numWinsDisplayed++;
639       splitDiff = heightDiff / numWinsDisplayed;
640       cmdSplitDiff = splitDiff;
641       if (heightDiff % numWinsDisplayed)
642         {
643           if (heightDiff < 0)
644             cmdSplitDiff--;
645           else
646             cmdSplitDiff++;
647         }
648       /* now adjust each window */
649       clear ();
650       refresh ();
651       switch (curLayout)
652         {
653         case SRC_COMMAND:
654         case DISASSEM_COMMAND:
655           firstWin = (TuiWinInfoPtr) (sourceWindows ())->list[0];
656           firstWin->generic.width += widthDiff;
657           locator->width += widthDiff;
658           /* check for invalid heights */
659           if (heightDiff == 0)
660             newHeight = firstWin->generic.height;
661           else if ((firstWin->generic.height + splitDiff) >=
662                    (screenheight - MIN_CMD_WIN_HEIGHT - 1))
663             newHeight = screenheight - MIN_CMD_WIN_HEIGHT - 1;
664           else if ((firstWin->generic.height + splitDiff) <= 0)
665             newHeight = MIN_WIN_HEIGHT;
666           else
667             newHeight = firstWin->generic.height + splitDiff;
668
669           _makeInvisibleAndSetNewHeight (firstWin, newHeight);
670           cmdWin->generic.origin.y = locator->origin.y + 1;
671           cmdWin->generic.width += widthDiff;
672           newHeight = screenheight - cmdWin->generic.origin.y;
673           _makeInvisibleAndSetNewHeight (cmdWin, newHeight);
674           _makeVisibleWithNewHeight (firstWin);
675           _makeVisibleWithNewHeight (cmdWin);
676           if (firstWin->generic.contentSize <= 0)
677             tuiEraseSourceContent (firstWin, EMPTY_SOURCE_PROMPT);
678           break;
679         default:
680           if (curLayout == SRC_DISASSEM_COMMAND)
681             {
682               firstWin = srcWin;
683               firstWin->generic.width += widthDiff;
684               secondWin = disassemWin;
685               secondWin->generic.width += widthDiff;
686             }
687           else
688             {
689               firstWin = dataWin;
690               firstWin->generic.width += widthDiff;
691               secondWin = (TuiWinInfoPtr) (sourceWindows ())->list[0];
692               secondWin->generic.width += widthDiff;
693             }
694           /* Change the first window's height/width */
695           /* check for invalid heights */
696           if (heightDiff == 0)
697             newHeight = firstWin->generic.height;
698           else if ((firstWin->generic.height +
699                     secondWin->generic.height + (splitDiff * 2)) >=
700                    (screenheight - MIN_CMD_WIN_HEIGHT - 1))
701             newHeight = (screenheight - MIN_CMD_WIN_HEIGHT - 1) / 2;
702           else if ((firstWin->generic.height + splitDiff) <= 0)
703             newHeight = MIN_WIN_HEIGHT;
704           else
705             newHeight = firstWin->generic.height + splitDiff;
706           _makeInvisibleAndSetNewHeight (firstWin, newHeight);
707
708           if (firstWin == dataWin && widthDiff != 0)
709             firstWin->detail.dataDisplayInfo.regsColumnCount =
710               tuiCalculateRegsColumnCount (
711                           firstWin->detail.dataDisplayInfo.regsDisplayType);
712           locator->width += widthDiff;
713
714           /* Change the second window's height/width */
715           /* check for invalid heights */
716           if (heightDiff == 0)
717             newHeight = secondWin->generic.height;
718           else if ((firstWin->generic.height +
719                     secondWin->generic.height + (splitDiff * 2)) >=
720                    (screenheight - MIN_CMD_WIN_HEIGHT - 1))
721             {
722               newHeight = screenheight - MIN_CMD_WIN_HEIGHT - 1;
723               if (newHeight % 2)
724                 newHeight = (newHeight / 2) + 1;
725               else
726                 newHeight /= 2;
727             }
728           else if ((secondWin->generic.height + splitDiff) <= 0)
729             newHeight = MIN_WIN_HEIGHT;
730           else
731             newHeight = secondWin->generic.height + splitDiff;
732           secondWin->generic.origin.y = firstWin->generic.height - 1;
733           _makeInvisibleAndSetNewHeight (secondWin, newHeight);
734
735           /* Change the command window's height/width */
736           cmdWin->generic.origin.y = locator->origin.y + 1;
737           _makeInvisibleAndSetNewHeight (
738                              cmdWin, cmdWin->generic.height + cmdSplitDiff);
739           _makeVisibleWithNewHeight (firstWin);
740           _makeVisibleWithNewHeight (secondWin);
741           _makeVisibleWithNewHeight (cmdWin);
742           if (firstWin->generic.contentSize <= 0)
743             tuiEraseSourceContent (firstWin, EMPTY_SOURCE_PROMPT);
744           if (secondWin->generic.contentSize <= 0)
745             tuiEraseSourceContent (secondWin, EMPTY_SOURCE_PROMPT);
746           break;
747         }
748       /*
749          ** Now remove all invisible windows, and their content so that they get
750          ** created again when called for with the new size
751        */
752       for (winType = SRC_WIN; (winType < MAX_MAJOR_WINDOWS); winType++)
753         {
754           if (winType != CMD_WIN && m_winPtrNotNull (winList[winType]) &&
755               !winList[winType]->generic.isVisible)
756             {
757               freeWindow (winList[winType]);
758               winList[winType] = (TuiWinInfoPtr) NULL;
759             }
760         }
761       tuiSetWinResizedTo (TRUE);
762       /* turn keypad back on, unless focus is in the command window */
763       if (winWithFocus != cmdWin)
764         keypad (cmdWin->generic.handle, TRUE);
765     }
766   return;
767 }                               /* tuiResizeAll */
768
769
770 /*
771    ** tuiSigwinchHandler()
772    **    SIGWINCH signal handler for the tui.  This signal handler is
773    **    always called, even when the readline package clears signals
774    **    because it is set as the old_sigwinch() (TUI only)
775  */
776 void
777 tuiSigwinchHandler (int signal)
778 {
779   /*
780      ** Say that a resize was done so that the readline can do it
781      ** later when appropriate.
782    */
783   tuiSetWinResizedTo (TRUE);
784
785   return;
786 }                               /* tuiSigwinchHandler */
787
788
789
790 /*************************
791 ** STATIC LOCAL FUNCTIONS
792 **************************/
793
794
795 /*
796    ** _tuiScrollForward_command().
797  */
798 static void
799 _tuiScrollForward_command (char *arg, int fromTTY)
800 {
801   int numToScroll = 1;
802   TuiWinInfoPtr winToScroll;
803
804   /* Make sure the curses mode is enabled.  */
805   tui_enable ();
806   if (arg == (char *) NULL)
807     _parseScrollingArgs (arg, &winToScroll, (int *) NULL);
808   else
809     _parseScrollingArgs (arg, &winToScroll, &numToScroll);
810   tui_scroll (FORWARD_SCROLL, winToScroll, numToScroll);
811 }
812
813
814 /*
815    ** _tuiScrollBackward_command().
816  */
817 static void
818 _tuiScrollBackward_command (char *arg, int fromTTY)
819 {
820   int numToScroll = 1;
821   TuiWinInfoPtr winToScroll;
822
823   /* Make sure the curses mode is enabled.  */
824   tui_enable ();
825   if (arg == (char *) NULL)
826     _parseScrollingArgs (arg, &winToScroll, (int *) NULL);
827   else
828     _parseScrollingArgs (arg, &winToScroll, &numToScroll);
829   tui_scroll (BACKWARD_SCROLL, winToScroll, numToScroll);
830 }
831
832
833 /*
834    ** _tuiScrollLeft_command().
835  */
836 static void
837 _tuiScrollLeft_command (char *arg, int fromTTY)
838 {
839   int numToScroll;
840   TuiWinInfoPtr winToScroll;
841
842   /* Make sure the curses mode is enabled.  */
843   tui_enable ();
844   _parseScrollingArgs (arg, &winToScroll, &numToScroll);
845   tui_scroll (LEFT_SCROLL, winToScroll, numToScroll);
846 }
847
848
849 /*
850    ** _tuiScrollRight_command().
851  */
852 static void
853 _tuiScrollRight_command (char *arg, int fromTTY)
854 {
855   int numToScroll;
856   TuiWinInfoPtr winToScroll;
857
858   /* Make sure the curses mode is enabled.  */
859   tui_enable ();
860   _parseScrollingArgs (arg, &winToScroll, &numToScroll);
861   tui_scroll (RIGHT_SCROLL, winToScroll, numToScroll);
862 }
863
864
865 /*
866    ** _tuiSetFocus().
867    **     Set focus to the window named by 'arg'
868  */
869 static void
870 _tuiSetFocus (char *arg, int fromTTY)
871 {
872   if (arg != (char *) NULL)
873     {
874       char *bufPtr = (char *) xstrdup (arg);
875       int i;
876       TuiWinInfoPtr winInfo = (TuiWinInfoPtr) NULL;
877
878       for (i = 0; (i < strlen (bufPtr)); i++)
879         bufPtr[i] = toupper (arg[i]);
880
881       if (subset_compare (bufPtr, "NEXT"))
882         winInfo = tuiNextWin (tuiWinWithFocus ());
883       else if (subset_compare (bufPtr, "PREV"))
884         winInfo = tuiPrevWin (tuiWinWithFocus ());
885       else
886         winInfo = partialWinByName (bufPtr);
887
888       if (winInfo == (TuiWinInfoPtr) NULL || !winInfo->generic.isVisible)
889         warning ("Invalid window specified. \n\
890 The window name specified must be valid and visible.\n");
891       else
892         {
893           tuiSetWinFocusTo (winInfo);
894           keypad (cmdWin->generic.handle, (winInfo != cmdWin));
895         }
896
897       if (dataWin && dataWin->generic.isVisible)
898         tuiRefreshDataWin ();
899       tuiFree (bufPtr);
900       printf_filtered ("Focus set to %s window.\n",
901                        winName ((TuiGenWinInfoPtr) tuiWinWithFocus ()));
902     }
903   else
904     warning ("Incorrect Number of Arguments.\n%s", FOCUS_USAGE);
905
906   return;
907 }                               /* _tuiSetFocus */
908
909 /*
910    ** _tuiSetFocus_command()
911  */
912 static void
913 _tuiSetFocus_command (char *arg, int fromTTY)
914 {
915   /* Make sure the curses mode is enabled.  */
916   tui_enable ();
917   _tuiSetFocus (arg, fromTTY);
918 }
919
920
921 /*
922    ** _tuiAllWindowsInfo().
923  */
924 static void
925 _tuiAllWindowsInfo (char *arg, int fromTTY)
926 {
927   TuiWinType type;
928   TuiWinInfoPtr winWithFocus = tuiWinWithFocus ();
929
930   for (type = SRC_WIN; (type < MAX_MAJOR_WINDOWS); type++)
931     if (winList[type]->generic.isVisible)
932       {
933         if (winWithFocus == winList[type])
934           printf_filtered ("        %s\t(%d lines)  <has focus>\n",
935                            winName (&winList[type]->generic),
936                            winList[type]->generic.height);
937         else
938           printf_filtered ("        %s\t(%d lines)\n",
939                            winName (&winList[type]->generic),
940                            winList[type]->generic.height);
941       }
942
943   return;
944 }                               /* _tuiAllWindowsInfo */
945
946
947 /*
948    ** _tuiRefreshAll_command().
949  */
950 static void
951 _tuiRefreshAll_command (char *arg, int fromTTY)
952 {
953   /* Make sure the curses mode is enabled.  */
954   tui_enable ();
955
956   tuiRefreshAll ();
957 }
958
959
960 /*
961    ** _tuiSetWinTabWidth_command().
962    **        Set the height of the specified window.
963  */
964 static void
965 _tuiSetTabWidth_command (char *arg, int fromTTY)
966 {
967   /* Make sure the curses mode is enabled.  */
968   tui_enable ();
969   if (arg != (char *) NULL)
970     {
971       int ts;
972
973       ts = atoi (arg);
974       if (ts > 0)
975         tuiSetDefaultTabLen (ts);
976       else
977         warning ("Tab widths greater than 0 must be specified.\n");
978     }
979
980   return;
981 }                               /* _tuiSetTabWidth_command */
982
983
984 /*
985    ** _tuiSetWinHeight().
986    **        Set the height of the specified window.
987  */
988 static void
989 _tuiSetWinHeight (char *arg, int fromTTY)
990 {
991   /* Make sure the curses mode is enabled.  */
992   tui_enable ();
993   if (arg != (char *) NULL)
994     {
995       char *buf = xstrdup (arg);
996       char *bufPtr = buf;
997       char *wname = (char *) NULL;
998       int newHeight, i;
999       TuiWinInfoPtr winInfo;
1000
1001       wname = bufPtr;
1002       bufPtr = strchr (bufPtr, ' ');
1003       if (bufPtr != (char *) NULL)
1004         {
1005           *bufPtr = (char) 0;
1006
1007           /*
1008              ** Validate the window name
1009            */
1010           for (i = 0; i < strlen (wname); i++)
1011             wname[i] = toupper (wname[i]);
1012           winInfo = partialWinByName (wname);
1013
1014           if (winInfo == (TuiWinInfoPtr) NULL || !winInfo->generic.isVisible)
1015             warning ("Invalid window specified. \n\
1016 The window name specified must be valid and visible.\n");
1017           else
1018             {
1019               /* Process the size */
1020               while (*(++bufPtr) == ' ')
1021                 ;
1022
1023               if (*bufPtr != (char) 0)
1024                 {
1025                   int negate = FALSE;
1026                   int fixedSize = TRUE;
1027                   int inputNo;;
1028
1029                   if (*bufPtr == '+' || *bufPtr == '-')
1030                     {
1031                       if (*bufPtr == '-')
1032                         negate = TRUE;
1033                       fixedSize = FALSE;
1034                       bufPtr++;
1035                     }
1036                   inputNo = atoi (bufPtr);
1037                   if (inputNo > 0)
1038                     {
1039                       if (negate)
1040                         inputNo *= (-1);
1041                       if (fixedSize)
1042                         newHeight = inputNo;
1043                       else
1044                         newHeight = winInfo->generic.height + inputNo;
1045                       /*
1046                          ** Now change the window's height, and adjust all
1047                          ** other windows around it
1048                        */
1049                       if (_tuiAdjustWinHeights (winInfo,
1050                                                 newHeight) == TUI_FAILURE)
1051                         warning ("Invalid window height specified.\n%s",
1052                                  WIN_HEIGHT_USAGE);
1053                       else
1054                         tui_update_gdb_sizes ();
1055                     }
1056                   else
1057                     warning ("Invalid window height specified.\n%s",
1058                              WIN_HEIGHT_USAGE);
1059                 }
1060             }
1061         }
1062       else
1063         printf_filtered (WIN_HEIGHT_USAGE);
1064
1065       if (buf != (char *) NULL)
1066         tuiFree (buf);
1067     }
1068   else
1069     printf_filtered (WIN_HEIGHT_USAGE);
1070
1071   return;
1072 }                               /* _tuiSetWinHeight */
1073
1074 /*
1075    ** _tuiSetWinHeight_command().
1076    **        Set the height of the specified window, with va_list.
1077  */
1078 static void
1079 _tuiSetWinHeight_command (char *arg, int fromTTY)
1080 {
1081   /* Make sure the curses mode is enabled.  */
1082   tui_enable ();
1083   _tuiSetWinHeight (arg, fromTTY);
1084 }
1085
1086
1087 /*
1088    ** _tuiXDBsetWinHeight().
1089    **        XDB Compatibility command for setting the window height.  This will
1090    **        increase or decrease the command window by the specified amount.
1091  */
1092 static void
1093 _tuiXDBsetWinHeight (char *arg, int fromTTY)
1094 {
1095   /* Make sure the curses mode is enabled.  */
1096   tui_enable ();
1097   if (arg != (char *) NULL)
1098     {
1099       int inputNo = atoi (arg);
1100
1101       if (inputNo > 0)
1102         {                       /* Add 1 for the locator */
1103           int newHeight = termHeight () - (inputNo + 1);
1104
1105           if (!_newHeightOk (winList[CMD_WIN], newHeight) ||
1106               _tuiAdjustWinHeights (winList[CMD_WIN],
1107                                     newHeight) == TUI_FAILURE)
1108             warning ("Invalid window height specified.\n%s",
1109                      XDBWIN_HEIGHT_USAGE);
1110         }
1111       else
1112         warning ("Invalid window height specified.\n%s",
1113                  XDBWIN_HEIGHT_USAGE);
1114     }
1115   else
1116     warning ("Invalid window height specified.\n%s", XDBWIN_HEIGHT_USAGE);
1117
1118   return;
1119 }                               /* _tuiXDBsetWinHeight */
1120
1121 /*
1122    ** _tuiSetWinHeight_command().
1123    **        Set the height of the specified window, with va_list.
1124  */
1125 static void
1126 _tuiXDBsetWinHeight_command (char *arg, int fromTTY)
1127 {
1128   _tuiXDBsetWinHeight (arg, fromTTY);
1129 }
1130
1131
1132 /*
1133    ** _tuiAdjustWinHeights().
1134    **        Function to adjust all window heights around the primary
1135  */
1136 static TuiStatus
1137 _tuiAdjustWinHeights (TuiWinInfoPtr primaryWinInfo, int newHeight)
1138 {
1139   TuiStatus status = TUI_FAILURE;
1140
1141   if (_newHeightOk (primaryWinInfo, newHeight))
1142     {
1143       status = TUI_SUCCESS;
1144       if (newHeight != primaryWinInfo->generic.height)
1145         {
1146           int diff;
1147           TuiWinInfoPtr winInfo;
1148           TuiGenWinInfoPtr locator = locatorWinInfoPtr ();
1149           TuiLayoutType curLayout = currentLayout ();
1150
1151           diff = (newHeight - primaryWinInfo->generic.height) * (-1);
1152           if (curLayout == SRC_COMMAND || curLayout == DISASSEM_COMMAND)
1153             {
1154               TuiWinInfoPtr srcWinInfo;
1155
1156               _makeInvisibleAndSetNewHeight (primaryWinInfo, newHeight);
1157               if (primaryWinInfo->generic.type == CMD_WIN)
1158                 {
1159                   winInfo = (TuiWinInfoPtr) (sourceWindows ())->list[0];
1160                   srcWinInfo = winInfo;
1161                 }
1162               else
1163                 {
1164                   winInfo = winList[CMD_WIN];
1165                   srcWinInfo = primaryWinInfo;
1166                 }
1167               _makeInvisibleAndSetNewHeight (winInfo,
1168                                              winInfo->generic.height + diff);
1169               cmdWin->generic.origin.y = locator->origin.y + 1;
1170               _makeVisibleWithNewHeight (winInfo);
1171               _makeVisibleWithNewHeight (primaryWinInfo);
1172               if (srcWinInfo->generic.contentSize <= 0)
1173                 tuiEraseSourceContent (srcWinInfo, EMPTY_SOURCE_PROMPT);
1174             }
1175           else
1176             {
1177               TuiWinInfoPtr firstWin, secondWin;
1178
1179               if (curLayout == SRC_DISASSEM_COMMAND)
1180                 {
1181                   firstWin = srcWin;
1182                   secondWin = disassemWin;
1183                 }
1184               else
1185                 {
1186                   firstWin = dataWin;
1187                   secondWin = (TuiWinInfoPtr) (sourceWindows ())->list[0];
1188                 }
1189               if (primaryWinInfo == cmdWin)
1190                 {               /*
1191                                    ** Split the change in height accross the 1st & 2nd windows
1192                                    ** adjusting them as well.
1193                                  */
1194                   int firstSplitDiff = diff / 2;        /* subtract the locator */
1195                   int secondSplitDiff = firstSplitDiff;
1196
1197                   if (diff % 2)
1198                     {
1199                       if (firstWin->generic.height >
1200                           secondWin->generic.height)
1201                         if (diff < 0)
1202                           firstSplitDiff--;
1203                         else
1204                           firstSplitDiff++;
1205                       else
1206                         {
1207                           if (diff < 0)
1208                             secondSplitDiff--;
1209                           else
1210                             secondSplitDiff++;
1211                         }
1212                     }
1213                   /* make sure that the minimum hieghts are honored */
1214                   while ((firstWin->generic.height + firstSplitDiff) < 3)
1215                     {
1216                       firstSplitDiff++;
1217                       secondSplitDiff--;
1218                     }
1219                   while ((secondWin->generic.height + secondSplitDiff) < 3)
1220                     {
1221                       secondSplitDiff++;
1222                       firstSplitDiff--;
1223                     }
1224                   _makeInvisibleAndSetNewHeight (
1225                                                   firstWin,
1226                                  firstWin->generic.height + firstSplitDiff);
1227                   secondWin->generic.origin.y = firstWin->generic.height - 1;
1228                   _makeInvisibleAndSetNewHeight (
1229                     secondWin, secondWin->generic.height + secondSplitDiff);
1230                   cmdWin->generic.origin.y = locator->origin.y + 1;
1231                   _makeInvisibleAndSetNewHeight (cmdWin, newHeight);
1232                 }
1233               else
1234                 {
1235                   if ((cmdWin->generic.height + diff) < 1)
1236                     {           /*
1237                                    ** If there is no way to increase the command window
1238                                    ** take real estate from the 1st or 2nd window.
1239                                  */
1240                       if ((cmdWin->generic.height + diff) < 1)
1241                         {
1242                           int i;
1243                           for (i = cmdWin->generic.height + diff;
1244                                (i < 1); i++)
1245                             if (primaryWinInfo == firstWin)
1246                               secondWin->generic.height--;
1247                             else
1248                               firstWin->generic.height--;
1249                         }
1250                     }
1251                   if (primaryWinInfo == firstWin)
1252                     _makeInvisibleAndSetNewHeight (firstWin, newHeight);
1253                   else
1254                     _makeInvisibleAndSetNewHeight (
1255                                                     firstWin,
1256                                                   firstWin->generic.height);
1257                   secondWin->generic.origin.y = firstWin->generic.height - 1;
1258                   if (primaryWinInfo == secondWin)
1259                     _makeInvisibleAndSetNewHeight (secondWin, newHeight);
1260                   else
1261                     _makeInvisibleAndSetNewHeight (
1262                                       secondWin, secondWin->generic.height);
1263                   cmdWin->generic.origin.y = locator->origin.y + 1;
1264                   if ((cmdWin->generic.height + diff) < 1)
1265                     _makeInvisibleAndSetNewHeight (cmdWin, 1);
1266                   else
1267                     _makeInvisibleAndSetNewHeight (
1268                                      cmdWin, cmdWin->generic.height + diff);
1269                 }
1270               _makeVisibleWithNewHeight (cmdWin);
1271               _makeVisibleWithNewHeight (secondWin);
1272               _makeVisibleWithNewHeight (firstWin);
1273               if (firstWin->generic.contentSize <= 0)
1274                 tuiEraseSourceContent (firstWin, EMPTY_SOURCE_PROMPT);
1275               if (secondWin->generic.contentSize <= 0)
1276                 tuiEraseSourceContent (secondWin, EMPTY_SOURCE_PROMPT);
1277             }
1278         }
1279     }
1280
1281   return status;
1282 }                               /* _tuiAdjustWinHeights */
1283
1284
1285 /*
1286    ** _makeInvisibleAndSetNewHeight().
1287    **        Function make the target window (and auxillary windows associated
1288    **        with the targer) invisible, and set the new height and location.
1289  */
1290 static void
1291 _makeInvisibleAndSetNewHeight (TuiWinInfoPtr winInfo, int height)
1292 {
1293   int i;
1294   TuiGenWinInfoPtr genWinInfo;
1295
1296
1297   m_beInvisible (&winInfo->generic);
1298   winInfo->generic.height = height;
1299   if (height > 1)
1300     winInfo->generic.viewportHeight = height - 1;
1301   else
1302     winInfo->generic.viewportHeight = height;
1303   if (winInfo != cmdWin)
1304     winInfo->generic.viewportHeight--;
1305
1306   /* Now deal with the auxillary windows associated with winInfo */
1307   switch (winInfo->generic.type)
1308     {
1309     case SRC_WIN:
1310     case DISASSEM_WIN:
1311       genWinInfo = winInfo->detail.sourceInfo.executionInfo;
1312       m_beInvisible (genWinInfo);
1313       genWinInfo->height = height;
1314       genWinInfo->origin.y = winInfo->generic.origin.y;
1315       if (height > 1)
1316         genWinInfo->viewportHeight = height - 1;
1317       else
1318         genWinInfo->viewportHeight = height;
1319       if (winInfo != cmdWin)
1320         genWinInfo->viewportHeight--;
1321
1322       if (m_hasLocator (winInfo))
1323         {
1324           genWinInfo = locatorWinInfoPtr ();
1325           m_beInvisible (genWinInfo);
1326           genWinInfo->origin.y = winInfo->generic.origin.y + height;
1327         }
1328       break;
1329     case DATA_WIN:
1330       /* delete all data item windows */
1331       for (i = 0; i < winInfo->generic.contentSize; i++)
1332         {
1333           genWinInfo = (TuiGenWinInfoPtr) & ((TuiWinElementPtr)
1334                       winInfo->generic.content[i])->whichElement.dataWindow;
1335           tuiDelwin (genWinInfo->handle);
1336           genWinInfo->handle = (WINDOW *) NULL;
1337         }
1338       break;
1339     default:
1340       break;
1341     }
1342 }
1343
1344
1345 /*
1346    ** _makeVisibleWithNewHeight().
1347    **        Function to make the windows with new heights visible.
1348    **        This means re-creating the windows' content since the window
1349    **        had to be destroyed to be made invisible.
1350  */
1351 static void
1352 _makeVisibleWithNewHeight (TuiWinInfoPtr winInfo)
1353 {
1354   struct symtab *s;
1355
1356   m_beVisible (&winInfo->generic);
1357   checkAndDisplayHighlightIfNeeded (winInfo);
1358   switch (winInfo->generic.type)
1359     {
1360     case SRC_WIN:
1361     case DISASSEM_WIN:
1362       freeWinContent (winInfo->detail.sourceInfo.executionInfo);
1363       m_beVisible (winInfo->detail.sourceInfo.executionInfo);
1364       if (winInfo->generic.content != (OpaquePtr) NULL)
1365         {
1366           TuiLineOrAddress lineOrAddr;
1367
1368           if (winInfo->generic.type == SRC_WIN)
1369             lineOrAddr.lineNo =
1370               winInfo->detail.sourceInfo.startLineOrAddr.lineNo;
1371           else
1372             lineOrAddr.addr =
1373               winInfo->detail.sourceInfo.startLineOrAddr.addr;
1374           freeWinContent (&winInfo->generic);
1375           tuiUpdateSourceWindow (winInfo,
1376                                  current_source_symtab, lineOrAddr, TRUE);
1377         }
1378       else if (selected_frame != (struct frame_info *) NULL)
1379         {
1380           TuiLineOrAddress line;
1381           extern int current_source_line;
1382
1383           s = find_pc_symtab (selected_frame->pc);
1384           if (winInfo->generic.type == SRC_WIN)
1385             line.lineNo = current_source_line;
1386           else
1387             {
1388               find_line_pc (s, current_source_line, &line.addr);
1389             }
1390           tuiUpdateSourceWindow (winInfo, s, line, TRUE);
1391         }
1392       if (m_hasLocator (winInfo))
1393         {
1394           m_beVisible (locatorWinInfoPtr ());
1395           tuiShowLocatorContent ();
1396         }
1397       break;
1398     case DATA_WIN:
1399       tuiDisplayAllData ();
1400       break;
1401     case CMD_WIN:
1402       winInfo->detail.commandInfo.curLine = 0;
1403       winInfo->detail.commandInfo.curch = 0;
1404       wmove (winInfo->generic.handle,
1405              winInfo->detail.commandInfo.curLine,
1406              winInfo->detail.commandInfo.curch);
1407       break;
1408     default:
1409       break;
1410     }
1411
1412   return;
1413 }                               /* _makeVisibleWithNewHeight */
1414
1415
1416 static int
1417 _newHeightOk (TuiWinInfoPtr primaryWinInfo, int newHeight)
1418 {
1419   int ok = (newHeight < termHeight ());
1420
1421   if (ok)
1422     {
1423       int diff;
1424       TuiLayoutType curLayout = currentLayout ();
1425
1426       diff = (newHeight - primaryWinInfo->generic.height) * (-1);
1427       if (curLayout == SRC_COMMAND || curLayout == DISASSEM_COMMAND)
1428         {
1429           ok = ((primaryWinInfo->generic.type == CMD_WIN &&
1430                  newHeight <= (termHeight () - 4) &&
1431                  newHeight >= MIN_CMD_WIN_HEIGHT) ||
1432                 (primaryWinInfo->generic.type != CMD_WIN &&
1433                  newHeight <= (termHeight () - 2) &&
1434                  newHeight >= MIN_WIN_HEIGHT));
1435           if (ok)
1436             {                   /* check the total height */
1437               TuiWinInfoPtr winInfo;
1438
1439               if (primaryWinInfo == cmdWin)
1440                 winInfo = (TuiWinInfoPtr) (sourceWindows ())->list[0];
1441               else
1442                 winInfo = cmdWin;
1443               ok = ((newHeight +
1444                      (winInfo->generic.height + diff)) <= termHeight ());
1445             }
1446         }
1447       else
1448         {
1449           int curTotalHeight, totalHeight, minHeight;
1450           TuiWinInfoPtr firstWin, secondWin;
1451
1452           if (curLayout == SRC_DISASSEM_COMMAND)
1453             {
1454               firstWin = srcWin;
1455               secondWin = disassemWin;
1456             }
1457           else
1458             {
1459               firstWin = dataWin;
1460               secondWin = (TuiWinInfoPtr) (sourceWindows ())->list[0];
1461             }
1462           /*
1463              ** We could simply add all the heights to obtain the same result
1464              ** but below is more explicit since we subtract 1 for the
1465              ** line that the first and second windows share, and add one
1466              ** for the locator.
1467            */
1468           curTotalHeight =
1469             (firstWin->generic.height + secondWin->generic.height - 1)
1470             + cmdWin->generic.height + 1 /*locator */ ;
1471           if (primaryWinInfo == cmdWin)
1472             {
1473               /* locator included since first & second win share a line */
1474               ok = ((firstWin->generic.height +
1475                      secondWin->generic.height + diff) >=
1476                     (MIN_WIN_HEIGHT * 2) &&
1477                     newHeight >= MIN_CMD_WIN_HEIGHT);
1478               if (ok)
1479                 {
1480                   totalHeight = newHeight + (firstWin->generic.height +
1481                                           secondWin->generic.height + diff);
1482                   minHeight = MIN_CMD_WIN_HEIGHT;
1483                 }
1484             }
1485           else
1486             {
1487               minHeight = MIN_WIN_HEIGHT;
1488               /*
1489                  ** First see if we can increase/decrease the command
1490                  ** window.  And make sure that the command window is
1491                  ** at least 1 line
1492                */
1493               ok = ((cmdWin->generic.height + diff) > 0);
1494               if (!ok)
1495                 {               /*
1496                                    ** Looks like we have to increase/decrease one of
1497                                    ** the other windows
1498                                  */
1499                   if (primaryWinInfo == firstWin)
1500                     ok = (secondWin->generic.height + diff) >= minHeight;
1501                   else
1502                     ok = (firstWin->generic.height + diff) >= minHeight;
1503                 }
1504               if (ok)
1505                 {
1506                   if (primaryWinInfo == firstWin)
1507                     totalHeight = newHeight +
1508                       secondWin->generic.height +
1509                       cmdWin->generic.height + diff;
1510                   else
1511                     totalHeight = newHeight +
1512                       firstWin->generic.height +
1513                       cmdWin->generic.height + diff;
1514                 }
1515             }
1516           /*
1517              ** Now make sure that the proposed total height doesn't exceed
1518              ** the old total height.
1519            */
1520           if (ok)
1521             ok = (newHeight >= minHeight && totalHeight <= curTotalHeight);
1522         }
1523     }
1524
1525   return ok;
1526 }                               /* _newHeightOk */
1527
1528
1529 /*
1530    ** _parseScrollingArgs().
1531  */
1532 static void
1533 _parseScrollingArgs (char *arg, TuiWinInfoPtr * winToScroll, int *numToScroll)
1534 {
1535   if (numToScroll)
1536     *numToScroll = 0;
1537   *winToScroll = tuiWinWithFocus ();
1538
1539   /*
1540      ** First set up the default window to scroll, in case there is no
1541      ** window name arg
1542    */
1543   if (arg != (char *) NULL)
1544     {
1545       char *buf, *bufPtr;
1546
1547       /* process the number of lines to scroll */
1548       buf = bufPtr = xstrdup (arg);
1549       if (isdigit (*bufPtr))
1550         {
1551           char *numStr;
1552
1553           numStr = bufPtr;
1554           bufPtr = strchr (bufPtr, ' ');
1555           if (bufPtr != (char *) NULL)
1556             {
1557               *bufPtr = (char) 0;
1558               if (numToScroll)
1559                 *numToScroll = atoi (numStr);
1560               bufPtr++;
1561             }
1562           else if (numToScroll)
1563             *numToScroll = atoi (numStr);
1564         }
1565
1566       /* process the window name if one is specified */
1567       if (bufPtr != (char *) NULL)
1568         {
1569           char *wname;
1570           int i;
1571
1572           if (*bufPtr == ' ')
1573             while (*(++bufPtr) == ' ')
1574               ;
1575
1576           if (*bufPtr != (char) 0)
1577             wname = bufPtr;
1578           else
1579             wname = "?";
1580           
1581           /* Validate the window name */
1582           for (i = 0; i < strlen (wname); i++)
1583             wname[i] = toupper (wname[i]);
1584           *winToScroll = partialWinByName (wname);
1585
1586           if (*winToScroll == (TuiWinInfoPtr) NULL ||
1587               !(*winToScroll)->generic.isVisible)
1588             warning ("Invalid window specified. \n\
1589 The window name specified must be valid and visible.\n");
1590           else if (*winToScroll == cmdWin)
1591             *winToScroll = (TuiWinInfoPtr) (sourceWindows ())->list[0];
1592         }
1593       tuiFree (buf);
1594     }
1595
1596   return;
1597 }                               /* _parseScrollingArgs */