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