947608ad620b3666f3e587c5e23ed0ca63a13c70
[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
1145       wname = buf_ptr;
1146       buf_ptr = strchr (buf_ptr, ' ');
1147       if (buf_ptr != (char *) NULL)
1148         {
1149           *buf_ptr = (char) 0;
1150
1151           /* Validate the window name.  */
1152           for (i = 0; i < strlen (wname); i++)
1153             wname[i] = tolower (wname[i]);
1154           win_info = tui_partial_win_by_name (wname);
1155
1156           if (win_info == (struct tui_win_info *) NULL
1157               || !win_info->generic.is_visible)
1158             warning (_("Invalid window specified. \n\
1159 The window name specified must be valid and visible.\n"));
1160           else
1161             {
1162               /* Process the size.  */
1163               while (*(++buf_ptr) == ' ')
1164                 ;
1165
1166               if (*buf_ptr != (char) 0)
1167                 {
1168                   int negate = FALSE;
1169                   int fixed_size = TRUE;
1170                   int input_no;;
1171
1172                   if (*buf_ptr == '+' || *buf_ptr == '-')
1173                     {
1174                       if (*buf_ptr == '-')
1175                         negate = TRUE;
1176                       fixed_size = FALSE;
1177                       buf_ptr++;
1178                     }
1179                   input_no = atoi (buf_ptr);
1180                   if (input_no > 0)
1181                     {
1182                       if (negate)
1183                         input_no *= (-1);
1184                       if (fixed_size)
1185                         new_height = input_no;
1186                       else
1187                         new_height = win_info->generic.height + input_no;
1188
1189                       /* Now change the window's height, and adjust
1190                          all other windows around it.  */
1191                       if (tui_adjust_win_heights (win_info,
1192                                                 new_height) == TUI_FAILURE)
1193                         warning (_("Invalid window height specified.\n%s"),
1194                                  WIN_HEIGHT_USAGE);
1195                       else
1196                         tui_update_gdb_sizes ();
1197                     }
1198                   else
1199                     warning (_("Invalid window height specified.\n%s"),
1200                              WIN_HEIGHT_USAGE);
1201                 }
1202             }
1203         }
1204       else
1205         printf_filtered (WIN_HEIGHT_USAGE);
1206
1207       if (buf != (char *) NULL)
1208         xfree (buf);
1209     }
1210   else
1211     printf_filtered (WIN_HEIGHT_USAGE);
1212 }
1213
1214 /* Set the height of the specified window, with va_list.  */
1215 static void
1216 tui_set_win_height_command (char *arg, int from_tty)
1217 {
1218   /* Make sure the curses mode is enabled.  */
1219   tui_enable ();
1220   tui_set_win_height (arg, from_tty);
1221 }
1222
1223 /* Function to adjust all window heights around the primary.   */
1224 static enum tui_status
1225 tui_adjust_win_heights (struct tui_win_info *primary_win_info,
1226                         int new_height)
1227 {
1228   enum tui_status status = TUI_FAILURE;
1229
1230   if (new_height_ok (primary_win_info, new_height))
1231     {
1232       status = TUI_SUCCESS;
1233       if (new_height != primary_win_info->generic.height)
1234         {
1235           int diff;
1236           struct tui_win_info *win_info;
1237           struct tui_gen_win_info *locator = tui_locator_win_info_ptr ();
1238           enum tui_layout_type cur_layout = tui_current_layout ();
1239
1240           diff = (new_height - primary_win_info->generic.height) * (-1);
1241           if (cur_layout == SRC_COMMAND 
1242               || cur_layout == DISASSEM_COMMAND)
1243             {
1244               struct tui_win_info *src_win_info;
1245
1246               make_invisible_and_set_new_height (primary_win_info, new_height);
1247               if (primary_win_info->generic.type == CMD_WIN)
1248                 {
1249                   win_info = (tui_source_windows ())->list[0];
1250                   src_win_info = win_info;
1251                 }
1252               else
1253                 {
1254                   win_info = tui_win_list[CMD_WIN];
1255                   src_win_info = primary_win_info;
1256                 }
1257               make_invisible_and_set_new_height (win_info,
1258                                              win_info->generic.height + diff);
1259               TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1;
1260               make_visible_with_new_height (win_info);
1261               make_visible_with_new_height (primary_win_info);
1262               if (src_win_info->generic.content_size <= 0)
1263                 tui_erase_source_content (src_win_info, EMPTY_SOURCE_PROMPT);
1264             }
1265           else
1266             {
1267               struct tui_win_info *first_win;
1268               struct tui_win_info *second_win;
1269
1270               if (cur_layout == SRC_DISASSEM_COMMAND)
1271                 {
1272                   first_win = TUI_SRC_WIN;
1273                   second_win = TUI_DISASM_WIN;
1274                 }
1275               else
1276                 {
1277                   first_win = TUI_DATA_WIN;
1278                   second_win = (tui_source_windows ())->list[0];
1279                 }
1280               if (primary_win_info == TUI_CMD_WIN)
1281                 { /* Split the change in height accross the 1st & 2nd
1282                      windows, adjusting them as well.  */
1283                   /* Subtract the locator.  */
1284                   int first_split_diff = diff / 2;
1285                   int second_split_diff = first_split_diff;
1286
1287                   if (diff % 2)
1288                     {
1289                       if (first_win->generic.height >
1290                           second_win->generic.height)
1291                         if (diff < 0)
1292                           first_split_diff--;
1293                         else
1294                           first_split_diff++;
1295                       else
1296                         {
1297                           if (diff < 0)
1298                             second_split_diff--;
1299                           else
1300                             second_split_diff++;
1301                         }
1302                     }
1303                   /* Make sure that the minimum hieghts are
1304                      honored.  */
1305                   while ((first_win->generic.height + first_split_diff) < 3)
1306                     {
1307                       first_split_diff++;
1308                       second_split_diff--;
1309                     }
1310                   while ((second_win->generic.height + second_split_diff) < 3)
1311                     {
1312                       second_split_diff++;
1313                       first_split_diff--;
1314                     }
1315                   make_invisible_and_set_new_height (
1316                                                   first_win,
1317                                  first_win->generic.height + first_split_diff);
1318                   second_win->generic.origin.y = first_win->generic.height - 1;
1319                   make_invisible_and_set_new_height (second_win,
1320                                                      second_win->generic.height
1321                                                      + second_split_diff);
1322                   TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1;
1323                   make_invisible_and_set_new_height (TUI_CMD_WIN, new_height);
1324                 }
1325               else
1326                 {
1327                   if ((TUI_CMD_WIN->generic.height + diff) < 1)
1328                     { /* If there is no way to increase the command
1329                          window take real estate from the 1st or 2nd
1330                          window.  */
1331                       if ((TUI_CMD_WIN->generic.height + diff) < 1)
1332                         {
1333                           int i;
1334
1335                           for (i = TUI_CMD_WIN->generic.height + diff;
1336                                (i < 1); i++)
1337                             if (primary_win_info == first_win)
1338                               second_win->generic.height--;
1339                             else
1340                               first_win->generic.height--;
1341                         }
1342                     }
1343                   if (primary_win_info == first_win)
1344                     make_invisible_and_set_new_height (first_win, new_height);
1345                   else
1346                     make_invisible_and_set_new_height (
1347                                                     first_win,
1348                                                   first_win->generic.height);
1349                   second_win->generic.origin.y = first_win->generic.height - 1;
1350                   if (primary_win_info == second_win)
1351                     make_invisible_and_set_new_height (second_win, new_height);
1352                   else
1353                     make_invisible_and_set_new_height (
1354                                       second_win, second_win->generic.height);
1355                   TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1;
1356                   if ((TUI_CMD_WIN->generic.height + diff) < 1)
1357                     make_invisible_and_set_new_height (TUI_CMD_WIN, 1);
1358                   else
1359                     make_invisible_and_set_new_height (TUI_CMD_WIN,
1360                                                        TUI_CMD_WIN->generic.height + diff);
1361                 }
1362               make_visible_with_new_height (TUI_CMD_WIN);
1363               make_visible_with_new_height (second_win);
1364               make_visible_with_new_height (first_win);
1365               if (first_win->generic.content_size <= 0)
1366                 tui_erase_source_content (first_win, EMPTY_SOURCE_PROMPT);
1367               if (second_win->generic.content_size <= 0)
1368                 tui_erase_source_content (second_win, EMPTY_SOURCE_PROMPT);
1369             }
1370         }
1371     }
1372
1373   return status;
1374 }
1375
1376
1377 /* Function make the target window (and auxillary windows associated
1378    with the targer) invisible, and set the new height and
1379    location.  */
1380 static void
1381 make_invisible_and_set_new_height (struct tui_win_info *win_info, 
1382                                    int height)
1383 {
1384   int i;
1385   struct tui_gen_win_info *gen_win_info;
1386
1387   tui_make_invisible (&win_info->generic);
1388   win_info->generic.height = height;
1389   if (height > 1)
1390     win_info->generic.viewport_height = height - 1;
1391   else
1392     win_info->generic.viewport_height = height;
1393   if (win_info != TUI_CMD_WIN)
1394     win_info->generic.viewport_height--;
1395
1396   /* Now deal with the auxillary windows associated with win_info.  */
1397   switch (win_info->generic.type)
1398     {
1399     case SRC_WIN:
1400     case DISASSEM_WIN:
1401       gen_win_info = win_info->detail.source_info.execution_info;
1402       tui_make_invisible (gen_win_info);
1403       gen_win_info->height = height;
1404       gen_win_info->origin.y = win_info->generic.origin.y;
1405       if (height > 1)
1406         gen_win_info->viewport_height = height - 1;
1407       else
1408         gen_win_info->viewport_height = height;
1409       if (win_info != TUI_CMD_WIN)
1410         gen_win_info->viewport_height--;
1411
1412       if (tui_win_has_locator (win_info))
1413         {
1414           gen_win_info = tui_locator_win_info_ptr ();
1415           tui_make_invisible (gen_win_info);
1416           gen_win_info->origin.y = win_info->generic.origin.y + height;
1417         }
1418       break;
1419     case DATA_WIN:
1420       /* Delete all data item windows.  */
1421       for (i = 0; i < win_info->generic.content_size; i++)
1422         {
1423           gen_win_info = (struct tui_gen_win_info *)
1424             &((struct tui_win_element *)
1425               win_info->generic.content[i])->which_element.data_window;
1426           tui_delete_win (gen_win_info->handle);
1427           gen_win_info->handle = (WINDOW *) NULL;
1428         }
1429       break;
1430     default:
1431       break;
1432     }
1433 }
1434
1435
1436 /* Function to make the windows with new heights visible.  This means
1437    re-creating the windows' content since the window had to be
1438    destroyed to be made invisible.  */
1439 static void
1440 make_visible_with_new_height (struct tui_win_info *win_info)
1441 {
1442   struct symtab *s;
1443
1444   tui_make_visible (&win_info->generic);
1445   tui_check_and_display_highlight_if_needed (win_info);
1446   switch (win_info->generic.type)
1447     {
1448     case SRC_WIN:
1449     case DISASSEM_WIN:
1450       tui_free_win_content (win_info->detail.source_info.execution_info);
1451       tui_make_visible (win_info->detail.source_info.execution_info);
1452       if (win_info->generic.content != NULL)
1453         {
1454           struct gdbarch *gdbarch = win_info->detail.source_info.gdbarch;
1455           struct tui_line_or_address line_or_addr;
1456           struct symtab_and_line cursal
1457             = get_current_source_symtab_and_line ();
1458
1459           line_or_addr = win_info->detail.source_info.start_line_or_addr;
1460           tui_free_win_content (&win_info->generic);
1461           tui_update_source_window (win_info, gdbarch,
1462                                     cursal.symtab, line_or_addr, TRUE);
1463         }
1464       else if (deprecated_safe_get_selected_frame () != NULL)
1465         {
1466           struct tui_line_or_address line;
1467           struct symtab_and_line cursal
1468             = get_current_source_symtab_and_line ();
1469           struct frame_info *frame = deprecated_safe_get_selected_frame ();
1470           struct gdbarch *gdbarch = get_frame_arch (frame);
1471
1472           s = find_pc_line_symtab (get_frame_pc (frame));
1473           if (win_info->generic.type == SRC_WIN)
1474             {
1475               line.loa = LOA_LINE;
1476               line.u.line_no = cursal.line;
1477             }
1478           else
1479             {
1480               line.loa = LOA_ADDRESS;
1481               find_line_pc (s, cursal.line, &line.u.addr);
1482             }
1483           tui_update_source_window (win_info, gdbarch, s, line, TRUE);
1484         }
1485       if (tui_win_has_locator (win_info))
1486         {
1487           tui_make_visible (tui_locator_win_info_ptr ());
1488           tui_show_locator_content ();
1489         }
1490       break;
1491     case DATA_WIN:
1492       tui_display_all_data ();
1493       break;
1494     case CMD_WIN:
1495       win_info->detail.command_info.cur_line = 0;
1496       win_info->detail.command_info.curch = 0;
1497 #ifdef HAVE_WRESIZE
1498       wresize (TUI_CMD_WIN->generic.handle,
1499                TUI_CMD_WIN->generic.height,
1500                TUI_CMD_WIN->generic.width);
1501 #endif
1502       mvwin (TUI_CMD_WIN->generic.handle,
1503              TUI_CMD_WIN->generic.origin.y,
1504              TUI_CMD_WIN->generic.origin.x);
1505       wmove (win_info->generic.handle,
1506              win_info->detail.command_info.cur_line,
1507              win_info->detail.command_info.curch);
1508       break;
1509     default:
1510       break;
1511     }
1512 }
1513
1514
1515 static int
1516 new_height_ok (struct tui_win_info *primary_win_info, 
1517                int new_height)
1518 {
1519   int ok = (new_height < tui_term_height ());
1520
1521   if (ok)
1522     {
1523       int diff;
1524       enum tui_layout_type cur_layout = tui_current_layout ();
1525
1526       diff = (new_height - primary_win_info->generic.height) * (-1);
1527       if (cur_layout == SRC_COMMAND || cur_layout == DISASSEM_COMMAND)
1528         {
1529           ok = ((primary_win_info->generic.type == CMD_WIN 
1530                  && new_height <= (tui_term_height () - 4) 
1531                  && new_height >= MIN_CMD_WIN_HEIGHT) 
1532                 || (primary_win_info->generic.type != CMD_WIN 
1533                     && new_height <= (tui_term_height () - 2) 
1534                     && new_height >= MIN_WIN_HEIGHT));
1535           if (ok)
1536             {                   /* Check the total height.  */
1537               struct tui_win_info *win_info;
1538
1539               if (primary_win_info == TUI_CMD_WIN)
1540                 win_info = (tui_source_windows ())->list[0];
1541               else
1542                 win_info = TUI_CMD_WIN;
1543               ok = ((new_height +
1544                      (win_info->generic.height + diff)) <= tui_term_height ());
1545             }
1546         }
1547       else
1548         {
1549           int cur_total_height, total_height, min_height = 0;
1550           struct tui_win_info *first_win;
1551           struct tui_win_info *second_win;
1552
1553           if (cur_layout == SRC_DISASSEM_COMMAND)
1554             {
1555               first_win = TUI_SRC_WIN;
1556               second_win = TUI_DISASM_WIN;
1557             }
1558           else
1559             {
1560               first_win = TUI_DATA_WIN;
1561               second_win = (tui_source_windows ())->list[0];
1562             }
1563           /* We could simply add all the heights to obtain the same
1564              result but below is more explicit since we subtract 1 for
1565              the line that the first and second windows share, and add
1566              one for the locator.  */
1567           total_height = cur_total_height =
1568             (first_win->generic.height + second_win->generic.height - 1)
1569             + TUI_CMD_WIN->generic.height + 1;  /* Locator. */
1570           if (primary_win_info == TUI_CMD_WIN)
1571             {
1572               /* Locator included since first & second win share a line.  */
1573               ok = ((first_win->generic.height +
1574                      second_win->generic.height + diff) >=
1575                     (MIN_WIN_HEIGHT * 2) 
1576                     && new_height >= MIN_CMD_WIN_HEIGHT);
1577               if (ok)
1578                 {
1579                   total_height = new_height + 
1580                     (first_win->generic.height +
1581                      second_win->generic.height + diff);
1582                   min_height = MIN_CMD_WIN_HEIGHT;
1583                 }
1584             }
1585           else
1586             {
1587               min_height = MIN_WIN_HEIGHT;
1588
1589               /* First see if we can increase/decrease the command
1590                  window.  And make sure that the command window is at
1591                  least 1 line.  */
1592               ok = ((TUI_CMD_WIN->generic.height + diff) > 0);
1593               if (!ok)
1594                 { /* Looks like we have to increase/decrease one of
1595                      the other windows.  */
1596                   if (primary_win_info == first_win)
1597                     ok = (second_win->generic.height + diff) >= min_height;
1598                   else
1599                     ok = (first_win->generic.height + diff) >= min_height;
1600                 }
1601               if (ok)
1602                 {
1603                   if (primary_win_info == first_win)
1604                     total_height = new_height +
1605                       second_win->generic.height +
1606                       TUI_CMD_WIN->generic.height + diff;
1607                   else
1608                     total_height = new_height +
1609                       first_win->generic.height +
1610                       TUI_CMD_WIN->generic.height + diff;
1611                 }
1612             }
1613           /* Now make sure that the proposed total height doesn't
1614              exceed the old total height.  */
1615           if (ok)
1616             ok = (new_height >= min_height 
1617                   && total_height <= cur_total_height);
1618         }
1619     }
1620
1621   return ok;
1622 }
1623
1624
1625 static void
1626 parse_scrolling_args (char *arg, 
1627                       struct tui_win_info **win_to_scroll,
1628                       int *num_to_scroll)
1629 {
1630   if (num_to_scroll)
1631     *num_to_scroll = 0;
1632   *win_to_scroll = tui_win_with_focus ();
1633
1634   /* First set up the default window to scroll, in case there is no
1635      window name arg.  */
1636   if (arg != (char *) NULL)
1637     {
1638       char *buf, *buf_ptr;
1639
1640       /* Process the number of lines to scroll.  */
1641       buf = buf_ptr = xstrdup (arg);
1642       if (isdigit (*buf_ptr))
1643         {
1644           char *num_str;
1645
1646           num_str = buf_ptr;
1647           buf_ptr = strchr (buf_ptr, ' ');
1648           if (buf_ptr != (char *) NULL)
1649             {
1650               *buf_ptr = (char) 0;
1651               if (num_to_scroll)
1652                 *num_to_scroll = atoi (num_str);
1653               buf_ptr++;
1654             }
1655           else if (num_to_scroll)
1656             *num_to_scroll = atoi (num_str);
1657         }
1658
1659       /* Process the window name if one is specified.  */
1660       if (buf_ptr != (char *) NULL)
1661         {
1662           char *wname;
1663           int i;
1664
1665           if (*buf_ptr == ' ')
1666             while (*(++buf_ptr) == ' ')
1667               ;
1668
1669           if (*buf_ptr != (char) 0)
1670             {
1671               wname = buf_ptr;
1672
1673               /* Validate the window name.  */
1674               for (i = 0; i < strlen (wname); i++)
1675                 wname[i] = tolower (wname[i]);
1676             }
1677           else
1678             wname = "?";
1679           
1680           *win_to_scroll = tui_partial_win_by_name (wname);
1681
1682           if (*win_to_scroll == (struct tui_win_info *) NULL
1683               || !(*win_to_scroll)->generic.is_visible)
1684             error (_("Invalid window specified. \n\
1685 The window name specified must be valid and visible.\n"));
1686           else if (*win_to_scroll == TUI_CMD_WIN)
1687             *win_to_scroll = (tui_source_windows ())->list[0];
1688         }
1689       xfree (buf);
1690     }
1691 }