gdb/tui: Use cleanups to free string copies.
[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       completion_name = tui_win_name (&tui_win_list [win_type]->generic);
378       gdb_assert (completion_name != NULL);
379       VEC_safe_push (const_char_ptr, completion_name_vec, completion_name);
380     }
381
382   /* If no windows are considered visible then the TUI has not yet been
383      initialized.  But still "focus src" and "focus cmd" will work because
384      invoking the focus command will entail initializing the TUI which sets the
385      default layout to SRC_COMMAND.  */
386   if (VEC_length (const_char_ptr, completion_name_vec) == 0)
387     {
388       VEC_safe_push (const_char_ptr, completion_name_vec, SRC_NAME);
389       VEC_safe_push (const_char_ptr, completion_name_vec, CMD_NAME);
390     }
391
392   VEC_safe_push (const_char_ptr, completion_name_vec, "next");
393   VEC_safe_push (const_char_ptr, completion_name_vec, "prev");
394   VEC_safe_push (const_char_ptr, completion_name_vec, NULL);
395
396   matches_vec
397     = complete_on_enum (VEC_address (const_char_ptr, completion_name_vec),
398                         text, word);
399
400   VEC_free (const_char_ptr, completion_name_vec);
401
402   return matches_vec;
403 }
404
405 /* Function to initialize gdb commands, for tui window
406    manipulation.  */
407
408 /* Provide a prototype to silence -Wmissing-prototypes.  */
409 extern initialize_file_ftype _initialize_tui_win;
410
411 void
412 _initialize_tui_win (void)
413 {
414   static struct cmd_list_element *tui_setlist;
415   static struct cmd_list_element *tui_showlist;
416   struct cmd_list_element *focus_cmd;
417
418   /* Define the classes of commands.
419      They will appear in the help list in the reverse of this order.  */
420   add_prefix_cmd ("tui", class_tui, set_tui_cmd,
421                   _("TUI configuration variables"),
422                   &tui_setlist, "set tui ",
423                   0 /* allow-unknown */, &setlist);
424   add_prefix_cmd ("tui", class_tui, show_tui_cmd,
425                   _("TUI configuration variables"),
426                   &tui_showlist, "show tui ",
427                   0 /* allow-unknown */, &showlist);
428
429   add_com ("refresh", class_tui, tui_refresh_all_command,
430            _("Refresh the terminal display.\n"));
431   add_com ("tabset", class_tui, tui_set_tab_width_command, _("\
432 Set the width (in characters) of tab stops.\n\
433 Usage: tabset <n>\n"));
434   add_com ("winheight", class_tui, tui_set_win_height_command, _("\
435 Set the height of a specified window.\n\
436 Usage: winheight <win_name> [+ | -] <#lines>\n\
437 Window names are:\n\
438 src  : the source window\n\
439 cmd  : the command window\n\
440 asm  : the disassembly window\n\
441 regs : the register display\n"));
442   add_com_alias ("wh", "winheight", class_tui, 0);
443   add_info ("win", tui_all_windows_info,
444             _("List of all displayed windows.\n"));
445   focus_cmd = add_com ("focus", class_tui, tui_set_focus_command, _("\
446 Set focus to named window or next/prev window.\n\
447 Usage: focus {<win> | next | prev}\n\
448 Valid Window names are:\n\
449 src  : the source window\n\
450 asm  : the disassembly window\n\
451 regs : the register display\n\
452 cmd  : the command window\n"));
453   add_com_alias ("fs", "focus", class_tui, 0);
454   set_cmd_completer (focus_cmd, focus_completer);
455   add_com ("+", class_tui, tui_scroll_forward_command, _("\
456 Scroll window forward.\n\
457 Usage: + [win] [n]\n"));
458   add_com ("-", class_tui, tui_scroll_backward_command, _("\
459 Scroll window backward.\n\
460 Usage: - [win] [n]\n"));
461   add_com ("<", class_tui, tui_scroll_left_command, _("\
462 Scroll window text to the left.\n\
463 Usage: < [win] [n]\n"));
464   add_com (">", class_tui, tui_scroll_right_command, _("\
465 Scroll window text to the right.\n\
466 Usage: > [win] [n]\n"));
467
468   /* Define the tui control variables.  */
469   add_setshow_enum_cmd ("border-kind", no_class, tui_border_kind_enums,
470                         &tui_border_kind, _("\
471 Set the kind of border for TUI windows."), _("\
472 Show the kind of border for TUI windows."), _("\
473 This variable controls the border of TUI windows:\n\
474 space           use a white space\n\
475 ascii           use ascii characters + - | for the border\n\
476 acs             use the Alternate Character Set"),
477                         tui_set_var_cmd,
478                         show_tui_border_kind,
479                         &tui_setlist, &tui_showlist);
480
481   add_setshow_enum_cmd ("border-mode", no_class, tui_border_mode_enums,
482                         &tui_border_mode, _("\
483 Set the attribute mode to use for the TUI window borders."), _("\
484 Show the attribute mode to use for the TUI window borders."), _("\
485 This variable controls the attributes to use for the window borders:\n\
486 normal          normal display\n\
487 standout        use highlight mode of terminal\n\
488 reverse         use reverse video mode\n\
489 half            use half bright\n\
490 half-standout   use half bright and standout mode\n\
491 bold            use extra bright or bold\n\
492 bold-standout   use extra bright or bold with standout mode"),
493                         tui_set_var_cmd,
494                         show_tui_border_mode,
495                         &tui_setlist, &tui_showlist);
496
497   add_setshow_enum_cmd ("active-border-mode", no_class, tui_border_mode_enums,
498                         &tui_active_border_mode, _("\
499 Set the attribute mode to use for the active TUI window border."), _("\
500 Show the attribute mode to use for the active TUI window border."), _("\
501 This variable controls the attributes to use for the active window border:\n\
502 normal          normal display\n\
503 standout        use highlight mode of terminal\n\
504 reverse         use reverse video mode\n\
505 half            use half bright\n\
506 half-standout   use half bright and standout mode\n\
507 bold            use extra bright or bold\n\
508 bold-standout   use extra bright or bold with standout mode"),
509                         tui_set_var_cmd,
510                         show_tui_active_border_mode,
511                         &tui_setlist, &tui_showlist);
512 }
513
514 /* Update gdb's knowledge of the terminal size.  */
515 void
516 tui_update_gdb_sizes (void)
517 {
518   int width, height;
519
520   if (tui_active)
521     {
522       width = TUI_CMD_WIN->generic.width;
523       height = TUI_CMD_WIN->generic.height;
524     }
525   else
526     {
527       width = tui_term_width ();
528       height = tui_term_height ();
529     }
530
531   set_screen_width_and_height (width, height);
532 }
533
534
535 /* Set the logical focus to win_info.  */
536 void
537 tui_set_win_focus_to (struct tui_win_info *win_info)
538 {
539   if (win_info != NULL)
540     {
541       struct tui_win_info *win_with_focus = tui_win_with_focus ();
542
543       if (win_with_focus != NULL
544           && win_with_focus->generic.type != CMD_WIN)
545         tui_unhighlight_win (win_with_focus);
546       tui_set_win_with_focus (win_info);
547       if (win_info->generic.type != CMD_WIN)
548         tui_highlight_win (win_info);
549     }
550 }
551
552
553 void
554 tui_scroll_forward (struct tui_win_info *win_to_scroll, 
555                     int num_to_scroll)
556 {
557   if (win_to_scroll != TUI_CMD_WIN)
558     {
559       int _num_to_scroll = num_to_scroll;
560
561       if (num_to_scroll == 0)
562         _num_to_scroll = win_to_scroll->generic.height - 3;
563
564       /* If we are scrolling the source or disassembly window, do a
565          "psuedo" scroll since not all of the source is in memory,
566          only what is in the viewport.  If win_to_scroll is the
567          command window do nothing since the term should handle
568          it.  */
569       if (win_to_scroll == TUI_SRC_WIN)
570         tui_vertical_source_scroll (FORWARD_SCROLL, _num_to_scroll);
571       else if (win_to_scroll == TUI_DISASM_WIN)
572         tui_vertical_disassem_scroll (FORWARD_SCROLL, _num_to_scroll);
573       else if (win_to_scroll == TUI_DATA_WIN)
574         tui_vertical_data_scroll (FORWARD_SCROLL, _num_to_scroll);
575     }
576 }
577
578 void
579 tui_scroll_backward (struct tui_win_info *win_to_scroll, 
580                      int num_to_scroll)
581 {
582   if (win_to_scroll != TUI_CMD_WIN)
583     {
584       int _num_to_scroll = num_to_scroll;
585
586       if (num_to_scroll == 0)
587         _num_to_scroll = win_to_scroll->generic.height - 3;
588
589       /* If we are scrolling the source or disassembly window, do a
590          "psuedo" scroll since not all of the source is in memory,
591          only what is in the viewport.  If win_to_scroll is the
592          command window do nothing since the term should handle
593          it.  */
594       if (win_to_scroll == TUI_SRC_WIN)
595         tui_vertical_source_scroll (BACKWARD_SCROLL, _num_to_scroll);
596       else if (win_to_scroll == TUI_DISASM_WIN)
597         tui_vertical_disassem_scroll (BACKWARD_SCROLL, _num_to_scroll);
598       else if (win_to_scroll == TUI_DATA_WIN)
599         tui_vertical_data_scroll (BACKWARD_SCROLL, _num_to_scroll);
600     }
601 }
602
603
604 void
605 tui_scroll_left (struct tui_win_info *win_to_scroll,
606                  int num_to_scroll)
607 {
608   if (win_to_scroll != TUI_CMD_WIN)
609     {
610       int _num_to_scroll = num_to_scroll;
611
612       if (_num_to_scroll == 0)
613         _num_to_scroll = 1;
614
615       /* If we are scrolling the source or disassembly window, do a
616          "psuedo" scroll since not all of the source is in memory,
617          only what is in the viewport. If win_to_scroll is the command
618          window do nothing since the term should handle it.  */
619       if (win_to_scroll == TUI_SRC_WIN
620           || win_to_scroll == TUI_DISASM_WIN)
621         tui_horizontal_source_scroll (win_to_scroll, LEFT_SCROLL,
622                                       _num_to_scroll);
623     }
624 }
625
626
627 void
628 tui_scroll_right (struct tui_win_info *win_to_scroll, 
629                   int num_to_scroll)
630 {
631   if (win_to_scroll != TUI_CMD_WIN)
632     {
633       int _num_to_scroll = num_to_scroll;
634
635       if (_num_to_scroll == 0)
636         _num_to_scroll = 1;
637
638       /* If we are scrolling the source or disassembly window, do a
639          "psuedo" scroll since not all of the source is in memory,
640          only what is in the viewport. If win_to_scroll is the command
641          window do nothing since the term should handle it.  */
642       if (win_to_scroll == TUI_SRC_WIN
643           || win_to_scroll == TUI_DISASM_WIN)
644         tui_horizontal_source_scroll (win_to_scroll, RIGHT_SCROLL,
645                                       _num_to_scroll);
646     }
647 }
648
649
650 /* Scroll a window.  Arguments are passed through a va_list.  */
651 void
652 tui_scroll (enum tui_scroll_direction direction,
653             struct tui_win_info *win_to_scroll,
654             int num_to_scroll)
655 {
656   switch (direction)
657     {
658     case FORWARD_SCROLL:
659       tui_scroll_forward (win_to_scroll, num_to_scroll);
660       break;
661     case BACKWARD_SCROLL:
662       tui_scroll_backward (win_to_scroll, num_to_scroll);
663       break;
664     case LEFT_SCROLL:
665       tui_scroll_left (win_to_scroll, num_to_scroll);
666       break;
667     case RIGHT_SCROLL:
668       tui_scroll_right (win_to_scroll, num_to_scroll);
669       break;
670     default:
671       break;
672     }
673 }
674
675
676 void
677 tui_refresh_all_win (void)
678 {
679   int type;
680
681   clearok (curscr, TRUE);
682   tui_refresh_all (tui_win_list);
683   for (type = SRC_WIN; type < MAX_MAJOR_WINDOWS; type++)
684     {
685       if (tui_win_list[type] 
686           && tui_win_list[type]->generic.is_visible)
687         {
688           switch (type)
689             {
690             case SRC_WIN:
691             case DISASSEM_WIN:
692               tui_show_source_content (tui_win_list[type]);
693               tui_check_and_display_highlight_if_needed (tui_win_list[type]);
694               tui_erase_exec_info_content (tui_win_list[type]);
695               tui_update_exec_info (tui_win_list[type]);
696               break;
697             case DATA_WIN:
698               tui_refresh_data_win ();
699               break;
700             default:
701               break;
702             }
703         }
704     }
705   tui_show_locator_content ();
706 }
707
708 void
709 tui_rehighlight_all (void)
710 {
711   int type;
712
713   for (type = SRC_WIN; type < MAX_MAJOR_WINDOWS; type++)
714     tui_check_and_display_highlight_if_needed (tui_win_list[type]);
715 }
716
717 /* Resize all the windows based on the terminal size.  This function
718    gets called from within the readline sinwinch handler.  */
719 void
720 tui_resize_all (void)
721 {
722   int height_diff, width_diff;
723   int screenheight, screenwidth;
724
725   rl_get_screen_size (&screenheight, &screenwidth);
726   width_diff = screenwidth - tui_term_width ();
727   height_diff = screenheight - tui_term_height ();
728   if (height_diff || width_diff)
729     {
730       enum tui_layout_type cur_layout = tui_current_layout ();
731       struct tui_win_info *win_with_focus = tui_win_with_focus ();
732       struct tui_win_info *first_win;
733       struct tui_win_info *second_win;
734       struct tui_gen_win_info *locator = tui_locator_win_info_ptr ();
735       int win_type;
736       int new_height, split_diff, cmd_split_diff, num_wins_displayed = 2;
737
738 #ifdef HAVE_RESIZE_TERM
739       resize_term (screenheight, screenwidth);
740 #endif      
741       /* Turn keypad off while we resize.  */
742       if (win_with_focus != TUI_CMD_WIN)
743         keypad (TUI_CMD_WIN->generic.handle, FALSE);
744       tui_update_gdb_sizes ();
745       tui_set_term_height_to (screenheight);
746       tui_set_term_width_to (screenwidth);
747       if (cur_layout == SRC_DISASSEM_COMMAND 
748           || cur_layout == SRC_DATA_COMMAND
749           || cur_layout == DISASSEM_DATA_COMMAND)
750         num_wins_displayed++;
751       split_diff = height_diff / num_wins_displayed;
752       cmd_split_diff = split_diff;
753       if (height_diff % num_wins_displayed)
754         {
755           if (height_diff < 0)
756             cmd_split_diff--;
757           else
758            cmd_split_diff++;
759        }
760       /* Now adjust each window.  */
761       /* erase + clearok are used instead of a straightforward clear as
762          AIX 5.3 does not define clear.  */
763       erase ();
764       clearok (curscr, TRUE);
765       refresh ();
766       switch (cur_layout)
767        {
768         case SRC_COMMAND:
769         case DISASSEM_COMMAND:
770           first_win = (struct tui_win_info *) (tui_source_windows ())->list[0];
771           first_win->generic.width += width_diff;
772           locator->width += width_diff;
773           /* Check for invalid heights.  */
774           if (height_diff == 0)
775             new_height = first_win->generic.height;
776           else if ((first_win->generic.height + split_diff) >=
777                    (screenheight - MIN_CMD_WIN_HEIGHT - 1))
778             new_height = screenheight - MIN_CMD_WIN_HEIGHT - 1;
779           else if ((first_win->generic.height + split_diff) <= 0)
780             new_height = MIN_WIN_HEIGHT;
781           else
782             new_height = first_win->generic.height + split_diff;
783
784           locator->origin.y = new_height + 1;
785           make_invisible_and_set_new_height (first_win, new_height);
786           TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1;
787           TUI_CMD_WIN->generic.width += width_diff;
788           new_height = screenheight - TUI_CMD_WIN->generic.origin.y;
789           make_invisible_and_set_new_height (TUI_CMD_WIN, new_height);
790           make_visible_with_new_height (first_win);
791           make_visible_with_new_height (TUI_CMD_WIN);
792           if (first_win->generic.content_size <= 0)
793             tui_erase_source_content (first_win, EMPTY_SOURCE_PROMPT);
794           break;
795         default:
796           if (cur_layout == SRC_DISASSEM_COMMAND)
797             {
798               first_win = TUI_SRC_WIN;
799               first_win->generic.width += width_diff;
800               second_win = TUI_DISASM_WIN;
801               second_win->generic.width += width_diff;
802             }
803           else
804             {
805               first_win = TUI_DATA_WIN;
806               first_win->generic.width += width_diff;
807               second_win = (struct tui_win_info *)
808                 (tui_source_windows ())->list[0];
809               second_win->generic.width += width_diff;
810             }
811           /* Change the first window's height/width.  */
812           /* Check for invalid heights.  */
813           if (height_diff == 0)
814             new_height = first_win->generic.height;
815           else if ((first_win->generic.height +
816                     second_win->generic.height + (split_diff * 2)) >=
817                    (screenheight - MIN_CMD_WIN_HEIGHT - 1))
818             new_height = (screenheight - MIN_CMD_WIN_HEIGHT - 1) / 2;
819           else if ((first_win->generic.height + split_diff) <= 0)
820             new_height = MIN_WIN_HEIGHT;
821           else
822             new_height = first_win->generic.height + split_diff;
823           make_invisible_and_set_new_height (first_win, new_height);
824
825           locator->width += width_diff;
826
827           /* Change the second window's height/width.  */
828           /* Check for invalid heights.  */
829           if (height_diff == 0)
830             new_height = second_win->generic.height;
831           else if ((first_win->generic.height +
832                     second_win->generic.height + (split_diff * 2)) >=
833                    (screenheight - MIN_CMD_WIN_HEIGHT - 1))
834             {
835               new_height = screenheight - MIN_CMD_WIN_HEIGHT - 1;
836               if (new_height % 2)
837                 new_height = (new_height / 2) + 1;
838               else
839                 new_height /= 2;
840             }
841           else if ((second_win->generic.height + split_diff) <= 0)
842             new_height = MIN_WIN_HEIGHT;
843           else
844             new_height = second_win->generic.height + split_diff;
845           second_win->generic.origin.y = first_win->generic.height - 1;
846           make_invisible_and_set_new_height (second_win, new_height);
847
848           /* Change the command window's height/width.  */
849           TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1;
850           make_invisible_and_set_new_height (TUI_CMD_WIN,
851                                              TUI_CMD_WIN->generic.height
852                                              + cmd_split_diff);
853           make_visible_with_new_height (first_win);
854           make_visible_with_new_height (second_win);
855           make_visible_with_new_height (TUI_CMD_WIN);
856           if (first_win->generic.content_size <= 0)
857             tui_erase_source_content (first_win, EMPTY_SOURCE_PROMPT);
858           if (second_win->generic.content_size <= 0)
859             tui_erase_source_content (second_win, EMPTY_SOURCE_PROMPT);
860           break;
861         }
862       /* Now remove all invisible windows, and their content so that
863          they get created again when called for with the new size.  */
864       for (win_type = SRC_WIN; (win_type < MAX_MAJOR_WINDOWS); win_type++)
865         {
866           if (win_type != CMD_WIN 
867               && (tui_win_list[win_type] != NULL)
868               && !tui_win_list[win_type]->generic.is_visible)
869             {
870               tui_free_window (tui_win_list[win_type]);
871               tui_win_list[win_type] = (struct tui_win_info *) NULL;
872             }
873         }
874       /* Turn keypad back on, unless focus is in the command
875          window.  */
876       if (win_with_focus != TUI_CMD_WIN)
877         keypad (TUI_CMD_WIN->generic.handle, TRUE);
878     }
879 }
880
881 #ifdef SIGWINCH
882 /* Token for use by TUI's asynchronous SIGWINCH handler.  */
883 static struct async_signal_handler *tui_sigwinch_token;
884
885 /* TUI's SIGWINCH signal handler.  */
886 static void
887 tui_sigwinch_handler (int signal)
888 {
889   mark_async_signal_handler (tui_sigwinch_token);
890   tui_set_win_resized_to (TRUE);
891 }
892
893 /* Callback for asynchronously resizing TUI following a SIGWINCH signal.  */
894 static void
895 tui_async_resize_screen (gdb_client_data arg)
896 {
897   rl_resize_terminal ();
898
899   if (!tui_active)
900     {
901       int screen_height, screen_width;
902
903       rl_get_screen_size (&screen_height, &screen_width);
904       set_screen_width_and_height (screen_width, screen_height);
905
906       /* win_resized is left set so that the next call to tui_enable()
907          resizes the TUI windows.  */
908     }
909   else
910     {
911       tui_set_win_resized_to (FALSE);
912       tui_resize_all ();
913       tui_refresh_all_win ();
914       tui_update_gdb_sizes ();
915       tui_redisplay_readline ();
916     }
917 }
918 #endif
919
920 /* Initialize TUI's SIGWINCH signal handler.  Note that the handler is not
921    uninstalled when we exit TUI, so the handler should not assume that TUI is
922    always active.  */
923 void
924 tui_initialize_win (void)
925 {
926 #ifdef SIGWINCH
927   tui_sigwinch_token
928     = create_async_signal_handler (tui_async_resize_screen, NULL);
929
930   {
931 #ifdef HAVE_SIGACTION
932     struct sigaction old_winch;
933
934     memset (&old_winch, 0, sizeof (old_winch));
935     old_winch.sa_handler = &tui_sigwinch_handler;
936 #ifdef SA_RESTART
937     old_winch.sa_flags = SA_RESTART;
938 #endif
939     sigaction (SIGWINCH, &old_winch, NULL);
940 #else
941     signal (SIGWINCH, &tui_sigwinch_handler);
942 #endif
943   }
944 #endif
945 }
946
947
948 /*************************
949 ** STATIC LOCAL FUNCTIONS
950 **************************/
951
952
953 static void
954 tui_scroll_forward_command (char *arg, int from_tty)
955 {
956   int num_to_scroll = 1;
957   struct tui_win_info *win_to_scroll;
958
959   /* Make sure the curses mode is enabled.  */
960   tui_enable ();
961   if (arg == (char *) NULL)
962     parse_scrolling_args (arg, &win_to_scroll, (int *) NULL);
963   else
964     parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
965   tui_scroll (FORWARD_SCROLL, win_to_scroll, num_to_scroll);
966 }
967
968
969 static void
970 tui_scroll_backward_command (char *arg, int from_tty)
971 {
972   int num_to_scroll = 1;
973   struct tui_win_info *win_to_scroll;
974
975   /* Make sure the curses mode is enabled.  */
976   tui_enable ();
977   if (arg == (char *) NULL)
978     parse_scrolling_args (arg, &win_to_scroll, (int *) NULL);
979   else
980     parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
981   tui_scroll (BACKWARD_SCROLL, win_to_scroll, num_to_scroll);
982 }
983
984
985 static void
986 tui_scroll_left_command (char *arg, int from_tty)
987 {
988   int num_to_scroll;
989   struct tui_win_info *win_to_scroll;
990
991   /* Make sure the curses mode is enabled.  */
992   tui_enable ();
993   parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
994   tui_scroll (LEFT_SCROLL, win_to_scroll, num_to_scroll);
995 }
996
997
998 static void
999 tui_scroll_right_command (char *arg, int from_tty)
1000 {
1001   int num_to_scroll;
1002   struct tui_win_info *win_to_scroll;
1003
1004   /* Make sure the curses mode is enabled.  */
1005   tui_enable ();
1006   parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
1007   tui_scroll (RIGHT_SCROLL, win_to_scroll, num_to_scroll);
1008 }
1009
1010
1011 /* Set focus to the window named by 'arg'.  */
1012 static void
1013 tui_set_focus (char *arg, int from_tty)
1014 {
1015   if (arg != (char *) NULL)
1016     {
1017       char *buf_ptr = (char *) xstrdup (arg);
1018       int i;
1019       struct tui_win_info *win_info = (struct tui_win_info *) NULL;
1020
1021       for (i = 0; (i < strlen (buf_ptr)); i++)
1022         buf_ptr[i] = tolower (arg[i]);
1023
1024       if (subset_compare (buf_ptr, "next"))
1025         win_info = tui_next_win (tui_win_with_focus ());
1026       else if (subset_compare (buf_ptr, "prev"))
1027         win_info = tui_prev_win (tui_win_with_focus ());
1028       else
1029         win_info = tui_partial_win_by_name (buf_ptr);
1030
1031       if (win_info == (struct tui_win_info *) NULL
1032           || !win_info->generic.is_visible)
1033         warning (_("Invalid window specified. \n\
1034 The window name specified must be valid and visible.\n"));
1035       else
1036         {
1037           tui_set_win_focus_to (win_info);
1038           keypad (TUI_CMD_WIN->generic.handle, (win_info != TUI_CMD_WIN));
1039         }
1040
1041       if (TUI_DATA_WIN && TUI_DATA_WIN->generic.is_visible)
1042         tui_refresh_data_win ();
1043       xfree (buf_ptr);
1044       printf_filtered (_("Focus set to %s window.\n"),
1045                        tui_win_name (&tui_win_with_focus ()->generic));
1046     }
1047   else
1048     warning (_("Incorrect Number of Arguments.\n%s"), FOCUS_USAGE);
1049 }
1050
1051 static void
1052 tui_set_focus_command (char *arg, int from_tty)
1053 {
1054   /* Make sure the curses mode is enabled.  */
1055   tui_enable ();
1056   tui_set_focus (arg, from_tty);
1057 }
1058
1059
1060 static void
1061 tui_all_windows_info (char *arg, int from_tty)
1062 {
1063   int type;
1064   struct tui_win_info *win_with_focus = tui_win_with_focus ();
1065
1066   for (type = SRC_WIN; (type < MAX_MAJOR_WINDOWS); type++)
1067     if (tui_win_list[type] 
1068         && tui_win_list[type]->generic.is_visible)
1069       {
1070         if (win_with_focus == tui_win_list[type])
1071           printf_filtered ("        %s\t(%d lines)  <has focus>\n",
1072                            tui_win_name (&tui_win_list[type]->generic),
1073                            tui_win_list[type]->generic.height);
1074         else
1075           printf_filtered ("        %s\t(%d lines)\n",
1076                            tui_win_name (&tui_win_list[type]->generic),
1077                            tui_win_list[type]->generic.height);
1078       }
1079 }
1080
1081
1082 static void
1083 tui_refresh_all_command (char *arg, int from_tty)
1084 {
1085   /* Make sure the curses mode is enabled.  */
1086   tui_enable ();
1087
1088   tui_refresh_all_win ();
1089 }
1090
1091
1092 /* Set the tab width of the specified window.  */
1093 static void
1094 tui_set_tab_width_command (char *arg, int from_tty)
1095 {
1096   /* Make sure the curses mode is enabled.  */
1097   tui_enable ();
1098   if (arg != (char *) NULL)
1099     {
1100       int ts;
1101
1102       ts = atoi (arg);
1103       if (ts > 0)
1104         {
1105           tui_set_default_tab_len (ts);
1106           /* We don't really change the height of any windows, but
1107              calling these 2 functions causes a complete regeneration
1108              and redisplay of the window's contents, which will take
1109              the new tab width into account.  */
1110           if (tui_win_list[SRC_WIN]
1111               && tui_win_list[SRC_WIN]->generic.is_visible)
1112             {
1113               make_invisible_and_set_new_height (TUI_SRC_WIN,
1114                                                  TUI_SRC_WIN->generic.height);
1115               make_visible_with_new_height (TUI_SRC_WIN);
1116             }
1117           if (tui_win_list[DISASSEM_WIN]
1118               && tui_win_list[DISASSEM_WIN]->generic.is_visible)
1119             {
1120               make_invisible_and_set_new_height (TUI_DISASM_WIN,
1121                                                  TUI_DISASM_WIN->generic.height);
1122               make_visible_with_new_height (TUI_DISASM_WIN);
1123             }
1124         }
1125       else
1126         warning (_("Tab widths greater than 0 must be specified."));
1127     }
1128 }
1129
1130
1131 /* Set the height of the specified window.  */
1132 static void
1133 tui_set_win_height (char *arg, int from_tty)
1134 {
1135   /* Make sure the curses mode is enabled.  */
1136   tui_enable ();
1137   if (arg != (char *) NULL)
1138     {
1139       char *buf = xstrdup (arg);
1140       char *buf_ptr = buf;
1141       char *wname = (char *) NULL;
1142       int new_height, i;
1143       struct tui_win_info *win_info;
1144       struct cleanup *old_chain;
1145
1146       old_chain = make_cleanup (xfree, buf);
1147       wname = buf_ptr;
1148       buf_ptr = strchr (buf_ptr, ' ');
1149       if (buf_ptr != (char *) NULL)
1150         {
1151           *buf_ptr = (char) 0;
1152
1153           /* Validate the window name.  */
1154           for (i = 0; i < strlen (wname); i++)
1155             wname[i] = tolower (wname[i]);
1156           win_info = tui_partial_win_by_name (wname);
1157
1158           if (win_info == (struct tui_win_info *) NULL
1159               || !win_info->generic.is_visible)
1160             warning (_("Invalid window specified. \n\
1161 The window name specified must be valid and visible.\n"));
1162           else
1163             {
1164               /* Process the size.  */
1165               while (*(++buf_ptr) == ' ')
1166                 ;
1167
1168               if (*buf_ptr != (char) 0)
1169                 {
1170                   int negate = FALSE;
1171                   int fixed_size = TRUE;
1172                   int input_no;;
1173
1174                   if (*buf_ptr == '+' || *buf_ptr == '-')
1175                     {
1176                       if (*buf_ptr == '-')
1177                         negate = TRUE;
1178                       fixed_size = FALSE;
1179                       buf_ptr++;
1180                     }
1181                   input_no = atoi (buf_ptr);
1182                   if (input_no > 0)
1183                     {
1184                       if (negate)
1185                         input_no *= (-1);
1186                       if (fixed_size)
1187                         new_height = input_no;
1188                       else
1189                         new_height = win_info->generic.height + input_no;
1190
1191                       /* Now change the window's height, and adjust
1192                          all other windows around it.  */
1193                       if (tui_adjust_win_heights (win_info,
1194                                                 new_height) == TUI_FAILURE)
1195                         warning (_("Invalid window height specified.\n%s"),
1196                                  WIN_HEIGHT_USAGE);
1197                       else
1198                         tui_update_gdb_sizes ();
1199                     }
1200                   else
1201                     warning (_("Invalid window height specified.\n%s"),
1202                              WIN_HEIGHT_USAGE);
1203                 }
1204             }
1205         }
1206       else
1207         printf_filtered (WIN_HEIGHT_USAGE);
1208
1209       do_cleanups (old_chain);
1210     }
1211   else
1212     printf_filtered (WIN_HEIGHT_USAGE);
1213 }
1214
1215 /* Set the height of the specified window, with va_list.  */
1216 static void
1217 tui_set_win_height_command (char *arg, int from_tty)
1218 {
1219   /* Make sure the curses mode is enabled.  */
1220   tui_enable ();
1221   tui_set_win_height (arg, from_tty);
1222 }
1223
1224 /* Function to adjust all window heights around the primary.   */
1225 static enum tui_status
1226 tui_adjust_win_heights (struct tui_win_info *primary_win_info,
1227                         int new_height)
1228 {
1229   enum tui_status status = TUI_FAILURE;
1230
1231   if (new_height_ok (primary_win_info, new_height))
1232     {
1233       status = TUI_SUCCESS;
1234       if (new_height != primary_win_info->generic.height)
1235         {
1236           int diff;
1237           struct tui_win_info *win_info;
1238           struct tui_gen_win_info *locator = tui_locator_win_info_ptr ();
1239           enum tui_layout_type cur_layout = tui_current_layout ();
1240
1241           diff = (new_height - primary_win_info->generic.height) * (-1);
1242           if (cur_layout == SRC_COMMAND 
1243               || cur_layout == DISASSEM_COMMAND)
1244             {
1245               struct tui_win_info *src_win_info;
1246
1247               make_invisible_and_set_new_height (primary_win_info, new_height);
1248               if (primary_win_info->generic.type == CMD_WIN)
1249                 {
1250                   win_info = (tui_source_windows ())->list[0];
1251                   src_win_info = win_info;
1252                 }
1253               else
1254                 {
1255                   win_info = tui_win_list[CMD_WIN];
1256                   src_win_info = primary_win_info;
1257                 }
1258               make_invisible_and_set_new_height (win_info,
1259                                              win_info->generic.height + diff);
1260               TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1;
1261               make_visible_with_new_height (win_info);
1262               make_visible_with_new_height (primary_win_info);
1263               if (src_win_info->generic.content_size <= 0)
1264                 tui_erase_source_content (src_win_info, EMPTY_SOURCE_PROMPT);
1265             }
1266           else
1267             {
1268               struct tui_win_info *first_win;
1269               struct tui_win_info *second_win;
1270
1271               if (cur_layout == SRC_DISASSEM_COMMAND)
1272                 {
1273                   first_win = TUI_SRC_WIN;
1274                   second_win = TUI_DISASM_WIN;
1275                 }
1276               else
1277                 {
1278                   first_win = TUI_DATA_WIN;
1279                   second_win = (tui_source_windows ())->list[0];
1280                 }
1281               if (primary_win_info == TUI_CMD_WIN)
1282                 { /* Split the change in height accross the 1st & 2nd
1283                      windows, adjusting them as well.  */
1284                   /* Subtract the locator.  */
1285                   int first_split_diff = diff / 2;
1286                   int second_split_diff = first_split_diff;
1287
1288                   if (diff % 2)
1289                     {
1290                       if (first_win->generic.height >
1291                           second_win->generic.height)
1292                         if (diff < 0)
1293                           first_split_diff--;
1294                         else
1295                           first_split_diff++;
1296                       else
1297                         {
1298                           if (diff < 0)
1299                             second_split_diff--;
1300                           else
1301                             second_split_diff++;
1302                         }
1303                     }
1304                   /* Make sure that the minimum hieghts are
1305                      honored.  */
1306                   while ((first_win->generic.height + first_split_diff) < 3)
1307                     {
1308                       first_split_diff++;
1309                       second_split_diff--;
1310                     }
1311                   while ((second_win->generic.height + second_split_diff) < 3)
1312                     {
1313                       second_split_diff++;
1314                       first_split_diff--;
1315                     }
1316                   make_invisible_and_set_new_height (
1317                                                   first_win,
1318                                  first_win->generic.height + first_split_diff);
1319                   second_win->generic.origin.y = first_win->generic.height - 1;
1320                   make_invisible_and_set_new_height (second_win,
1321                                                      second_win->generic.height
1322                                                      + second_split_diff);
1323                   TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1;
1324                   make_invisible_and_set_new_height (TUI_CMD_WIN, new_height);
1325                 }
1326               else
1327                 {
1328                   if ((TUI_CMD_WIN->generic.height + diff) < 1)
1329                     { /* If there is no way to increase the command
1330                          window take real estate from the 1st or 2nd
1331                          window.  */
1332                       if ((TUI_CMD_WIN->generic.height + diff) < 1)
1333                         {
1334                           int i;
1335
1336                           for (i = TUI_CMD_WIN->generic.height + diff;
1337                                (i < 1); i++)
1338                             if (primary_win_info == first_win)
1339                               second_win->generic.height--;
1340                             else
1341                               first_win->generic.height--;
1342                         }
1343                     }
1344                   if (primary_win_info == first_win)
1345                     make_invisible_and_set_new_height (first_win, new_height);
1346                   else
1347                     make_invisible_and_set_new_height (
1348                                                     first_win,
1349                                                   first_win->generic.height);
1350                   second_win->generic.origin.y = first_win->generic.height - 1;
1351                   if (primary_win_info == second_win)
1352                     make_invisible_and_set_new_height (second_win, new_height);
1353                   else
1354                     make_invisible_and_set_new_height (
1355                                       second_win, second_win->generic.height);
1356                   TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1;
1357                   if ((TUI_CMD_WIN->generic.height + diff) < 1)
1358                     make_invisible_and_set_new_height (TUI_CMD_WIN, 1);
1359                   else
1360                     make_invisible_and_set_new_height (TUI_CMD_WIN,
1361                                                        TUI_CMD_WIN->generic.height + diff);
1362                 }
1363               make_visible_with_new_height (TUI_CMD_WIN);
1364               make_visible_with_new_height (second_win);
1365               make_visible_with_new_height (first_win);
1366               if (first_win->generic.content_size <= 0)
1367                 tui_erase_source_content (first_win, EMPTY_SOURCE_PROMPT);
1368               if (second_win->generic.content_size <= 0)
1369                 tui_erase_source_content (second_win, EMPTY_SOURCE_PROMPT);
1370             }
1371         }
1372     }
1373
1374   return status;
1375 }
1376
1377
1378 /* Function make the target window (and auxillary windows associated
1379    with the targer) invisible, and set the new height and
1380    location.  */
1381 static void
1382 make_invisible_and_set_new_height (struct tui_win_info *win_info, 
1383                                    int height)
1384 {
1385   int i;
1386   struct tui_gen_win_info *gen_win_info;
1387
1388   tui_make_invisible (&win_info->generic);
1389   win_info->generic.height = height;
1390   if (height > 1)
1391     win_info->generic.viewport_height = height - 1;
1392   else
1393     win_info->generic.viewport_height = height;
1394   if (win_info != TUI_CMD_WIN)
1395     win_info->generic.viewport_height--;
1396
1397   /* Now deal with the auxillary windows associated with win_info.  */
1398   switch (win_info->generic.type)
1399     {
1400     case SRC_WIN:
1401     case DISASSEM_WIN:
1402       gen_win_info = win_info->detail.source_info.execution_info;
1403       tui_make_invisible (gen_win_info);
1404       gen_win_info->height = height;
1405       gen_win_info->origin.y = win_info->generic.origin.y;
1406       if (height > 1)
1407         gen_win_info->viewport_height = height - 1;
1408       else
1409         gen_win_info->viewport_height = height;
1410       if (win_info != TUI_CMD_WIN)
1411         gen_win_info->viewport_height--;
1412
1413       if (tui_win_has_locator (win_info))
1414         {
1415           gen_win_info = tui_locator_win_info_ptr ();
1416           tui_make_invisible (gen_win_info);
1417           gen_win_info->origin.y = win_info->generic.origin.y + height;
1418         }
1419       break;
1420     case DATA_WIN:
1421       /* Delete all data item windows.  */
1422       for (i = 0; i < win_info->generic.content_size; i++)
1423         {
1424           gen_win_info = (struct tui_gen_win_info *)
1425             &((struct tui_win_element *)
1426               win_info->generic.content[i])->which_element.data_window;
1427           tui_delete_win (gen_win_info->handle);
1428           gen_win_info->handle = (WINDOW *) NULL;
1429         }
1430       break;
1431     default:
1432       break;
1433     }
1434 }
1435
1436
1437 /* Function to make the windows with new heights visible.  This means
1438    re-creating the windows' content since the window had to be
1439    destroyed to be made invisible.  */
1440 static void
1441 make_visible_with_new_height (struct tui_win_info *win_info)
1442 {
1443   struct symtab *s;
1444
1445   tui_make_visible (&win_info->generic);
1446   tui_check_and_display_highlight_if_needed (win_info);
1447   switch (win_info->generic.type)
1448     {
1449     case SRC_WIN:
1450     case DISASSEM_WIN:
1451       tui_free_win_content (win_info->detail.source_info.execution_info);
1452       tui_make_visible (win_info->detail.source_info.execution_info);
1453       if (win_info->generic.content != NULL)
1454         {
1455           struct gdbarch *gdbarch = win_info->detail.source_info.gdbarch;
1456           struct tui_line_or_address line_or_addr;
1457           struct symtab_and_line cursal
1458             = get_current_source_symtab_and_line ();
1459
1460           line_or_addr = win_info->detail.source_info.start_line_or_addr;
1461           tui_free_win_content (&win_info->generic);
1462           tui_update_source_window (win_info, gdbarch,
1463                                     cursal.symtab, line_or_addr, TRUE);
1464         }
1465       else if (deprecated_safe_get_selected_frame () != NULL)
1466         {
1467           struct tui_line_or_address line;
1468           struct symtab_and_line cursal
1469             = get_current_source_symtab_and_line ();
1470           struct frame_info *frame = deprecated_safe_get_selected_frame ();
1471           struct gdbarch *gdbarch = get_frame_arch (frame);
1472
1473           s = find_pc_line_symtab (get_frame_pc (frame));
1474           if (win_info->generic.type == SRC_WIN)
1475             {
1476               line.loa = LOA_LINE;
1477               line.u.line_no = cursal.line;
1478             }
1479           else
1480             {
1481               line.loa = LOA_ADDRESS;
1482               find_line_pc (s, cursal.line, &line.u.addr);
1483             }
1484           tui_update_source_window (win_info, gdbarch, s, line, TRUE);
1485         }
1486       if (tui_win_has_locator (win_info))
1487         {
1488           tui_make_visible (tui_locator_win_info_ptr ());
1489           tui_show_locator_content ();
1490         }
1491       break;
1492     case DATA_WIN:
1493       tui_display_all_data ();
1494       break;
1495     case CMD_WIN:
1496       win_info->detail.command_info.cur_line = 0;
1497       win_info->detail.command_info.curch = 0;
1498 #ifdef HAVE_WRESIZE
1499       wresize (TUI_CMD_WIN->generic.handle,
1500                TUI_CMD_WIN->generic.height,
1501                TUI_CMD_WIN->generic.width);
1502 #endif
1503       mvwin (TUI_CMD_WIN->generic.handle,
1504              TUI_CMD_WIN->generic.origin.y,
1505              TUI_CMD_WIN->generic.origin.x);
1506       wmove (win_info->generic.handle,
1507              win_info->detail.command_info.cur_line,
1508              win_info->detail.command_info.curch);
1509       break;
1510     default:
1511       break;
1512     }
1513 }
1514
1515
1516 static int
1517 new_height_ok (struct tui_win_info *primary_win_info, 
1518                int new_height)
1519 {
1520   int ok = (new_height < tui_term_height ());
1521
1522   if (ok)
1523     {
1524       int diff;
1525       enum tui_layout_type cur_layout = tui_current_layout ();
1526
1527       diff = (new_height - primary_win_info->generic.height) * (-1);
1528       if (cur_layout == SRC_COMMAND || cur_layout == DISASSEM_COMMAND)
1529         {
1530           ok = ((primary_win_info->generic.type == CMD_WIN 
1531                  && new_height <= (tui_term_height () - 4) 
1532                  && new_height >= MIN_CMD_WIN_HEIGHT) 
1533                 || (primary_win_info->generic.type != CMD_WIN 
1534                     && new_height <= (tui_term_height () - 2) 
1535                     && new_height >= MIN_WIN_HEIGHT));
1536           if (ok)
1537             {                   /* Check the total height.  */
1538               struct tui_win_info *win_info;
1539
1540               if (primary_win_info == TUI_CMD_WIN)
1541                 win_info = (tui_source_windows ())->list[0];
1542               else
1543                 win_info = TUI_CMD_WIN;
1544               ok = ((new_height +
1545                      (win_info->generic.height + diff)) <= tui_term_height ());
1546             }
1547         }
1548       else
1549         {
1550           int cur_total_height, total_height, min_height = 0;
1551           struct tui_win_info *first_win;
1552           struct tui_win_info *second_win;
1553
1554           if (cur_layout == SRC_DISASSEM_COMMAND)
1555             {
1556               first_win = TUI_SRC_WIN;
1557               second_win = TUI_DISASM_WIN;
1558             }
1559           else
1560             {
1561               first_win = TUI_DATA_WIN;
1562               second_win = (tui_source_windows ())->list[0];
1563             }
1564           /* We could simply add all the heights to obtain the same
1565              result but below is more explicit since we subtract 1 for
1566              the line that the first and second windows share, and add
1567              one for the locator.  */
1568           total_height = cur_total_height =
1569             (first_win->generic.height + second_win->generic.height - 1)
1570             + TUI_CMD_WIN->generic.height + 1;  /* Locator. */
1571           if (primary_win_info == TUI_CMD_WIN)
1572             {
1573               /* Locator included since first & second win share a line.  */
1574               ok = ((first_win->generic.height +
1575                      second_win->generic.height + diff) >=
1576                     (MIN_WIN_HEIGHT * 2) 
1577                     && new_height >= MIN_CMD_WIN_HEIGHT);
1578               if (ok)
1579                 {
1580                   total_height = new_height + 
1581                     (first_win->generic.height +
1582                      second_win->generic.height + diff);
1583                   min_height = MIN_CMD_WIN_HEIGHT;
1584                 }
1585             }
1586           else
1587             {
1588               min_height = MIN_WIN_HEIGHT;
1589
1590               /* First see if we can increase/decrease the command
1591                  window.  And make sure that the command window is at
1592                  least 1 line.  */
1593               ok = ((TUI_CMD_WIN->generic.height + diff) > 0);
1594               if (!ok)
1595                 { /* Looks like we have to increase/decrease one of
1596                      the other windows.  */
1597                   if (primary_win_info == first_win)
1598                     ok = (second_win->generic.height + diff) >= min_height;
1599                   else
1600                     ok = (first_win->generic.height + diff) >= min_height;
1601                 }
1602               if (ok)
1603                 {
1604                   if (primary_win_info == first_win)
1605                     total_height = new_height +
1606                       second_win->generic.height +
1607                       TUI_CMD_WIN->generic.height + diff;
1608                   else
1609                     total_height = new_height +
1610                       first_win->generic.height +
1611                       TUI_CMD_WIN->generic.height + diff;
1612                 }
1613             }
1614           /* Now make sure that the proposed total height doesn't
1615              exceed the old total height.  */
1616           if (ok)
1617             ok = (new_height >= min_height 
1618                   && total_height <= cur_total_height);
1619         }
1620     }
1621
1622   return ok;
1623 }
1624
1625
1626 static void
1627 parse_scrolling_args (char *arg, 
1628                       struct tui_win_info **win_to_scroll,
1629                       int *num_to_scroll)
1630 {
1631   if (num_to_scroll)
1632     *num_to_scroll = 0;
1633   *win_to_scroll = tui_win_with_focus ();
1634
1635   /* First set up the default window to scroll, in case there is no
1636      window name arg.  */
1637   if (arg != (char *) NULL)
1638     {
1639       char *buf, *buf_ptr;
1640       struct cleanup *old_chain;
1641
1642       /* Process the number of lines to scroll.  */
1643       buf = buf_ptr = xstrdup (arg);
1644       old_chain = make_cleanup (xfree, buf);
1645       if (isdigit (*buf_ptr))
1646         {
1647           char *num_str;
1648
1649           num_str = buf_ptr;
1650           buf_ptr = strchr (buf_ptr, ' ');
1651           if (buf_ptr != (char *) NULL)
1652             {
1653               *buf_ptr = (char) 0;
1654               if (num_to_scroll)
1655                 *num_to_scroll = atoi (num_str);
1656               buf_ptr++;
1657             }
1658           else if (num_to_scroll)
1659             *num_to_scroll = atoi (num_str);
1660         }
1661
1662       /* Process the window name if one is specified.  */
1663       if (buf_ptr != (char *) NULL)
1664         {
1665           char *wname;
1666           int i;
1667
1668           if (*buf_ptr == ' ')
1669             while (*(++buf_ptr) == ' ')
1670               ;
1671
1672           if (*buf_ptr != (char) 0)
1673             {
1674               wname = buf_ptr;
1675
1676               /* Validate the window name.  */
1677               for (i = 0; i < strlen (wname); i++)
1678                 wname[i] = tolower (wname[i]);
1679             }
1680           else
1681             wname = "?";
1682           
1683           *win_to_scroll = tui_partial_win_by_name (wname);
1684
1685           if (*win_to_scroll == (struct tui_win_info *) NULL
1686               || !(*win_to_scroll)->generic.is_visible)
1687             error (_("Invalid window specified. \n\
1688 The window name specified must be valid and visible.\n"));
1689           else if (*win_to_scroll == TUI_CMD_WIN)
1690             *win_to_scroll = (tui_source_windows ())->list[0];
1691         }
1692       do_cleanups (old_chain);
1693     }
1694 }