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