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