OSDN Git Service

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