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