Update copyright year range in all GDB files.
[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_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 }