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