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