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