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