tui-win.c revision 1.9 1 /* TUI window generic functions.
2
3 Copyright (C) 1998-2020 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 "cli/cli-style.h"
34 #include "top.h"
35 #include "source.h"
36 #include "gdbsupport/event-loop.h"
37 #include "gdbcmd.h"
38 #include "async-event.h"
39
40 #include "tui/tui.h"
41 #include "tui/tui-io.h"
42 #include "tui/tui-command.h"
43 #include "tui/tui-data.h"
44 #include "tui/tui-layout.h"
45 #include "tui/tui-wingeneral.h"
46 #include "tui/tui-stack.h"
47 #include "tui/tui-regs.h"
48 #include "tui/tui-disasm.h"
49 #include "tui/tui-source.h"
50 #include "tui/tui-winsource.h"
51 #include "tui/tui-win.h"
52
53 #include "gdb_curses.h"
54 #include <ctype.h>
55 #include "readline/readline.h"
56 #include "gdbsupport/gdb_string_view.h"
57
58 #include <signal.h>
59
60 static void tui_set_tab_width_command (const char *, int);
61 static void tui_refresh_all_command (const char *, int);
62 static void tui_all_windows_info (const char *, int);
63 static void tui_scroll_forward_command (const char *, int);
64 static void tui_scroll_backward_command (const char *, int);
65 static void tui_scroll_left_command (const char *, int);
66 static void tui_scroll_right_command (const char *, int);
67 static void parse_scrolling_args (const char *,
68 struct tui_win_info **,
69 int *);
70
71
72 #ifndef ACS_LRCORNER
73 # define ACS_LRCORNER '+'
74 #endif
75 #ifndef ACS_LLCORNER
76 # define ACS_LLCORNER '+'
77 #endif
78 #ifndef ACS_ULCORNER
79 # define ACS_ULCORNER '+'
80 #endif
81 #ifndef ACS_URCORNER
82 # define ACS_URCORNER '+'
83 #endif
84 #ifndef ACS_HLINE
85 # define ACS_HLINE '-'
86 #endif
87 #ifndef ACS_VLINE
88 # define ACS_VLINE '|'
89 #endif
90
91 /* Possible values for tui-border-kind variable. */
92 static const char *const tui_border_kind_enums[] = {
93 "space",
94 "ascii",
95 "acs",
96 NULL
97 };
98
99 /* Possible values for tui-border-mode and tui-active-border-mode. */
100 static const char *const tui_border_mode_enums[] = {
101 "normal",
102 "standout",
103 "reverse",
104 "half",
105 "half-standout",
106 "bold",
107 "bold-standout",
108 NULL
109 };
110
111 struct tui_translate
112 {
113 const char *name;
114 int value;
115 };
116
117 /* Translation table for border-mode variables.
118 The list of values must be terminated by a NULL.
119 After the NULL value, an entry defines the default. */
120 static struct tui_translate tui_border_mode_translate[] = {
121 { "normal", A_NORMAL },
122 { "standout", A_STANDOUT },
123 { "reverse", A_REVERSE },
124 { "half", A_DIM },
125 { "half-standout", A_DIM | A_STANDOUT },
126 { "bold", A_BOLD },
127 { "bold-standout", A_BOLD | A_STANDOUT },
128 { 0, 0 },
129 { "normal", A_NORMAL }
130 };
131
132 /* Translation tables for border-kind, one for each border
133 character (see wborder, border curses operations).
134 -1 is used to indicate the ACS because ACS characters
135 are determined at run time by curses (depends on terminal). */
136 static struct tui_translate tui_border_kind_translate_vline[] = {
137 { "space", ' ' },
138 { "ascii", '|' },
139 { "acs", -1 },
140 { 0, 0 },
141 { "ascii", '|' }
142 };
143
144 static struct tui_translate tui_border_kind_translate_hline[] = {
145 { "space", ' ' },
146 { "ascii", '-' },
147 { "acs", -1 },
148 { 0, 0 },
149 { "ascii", '-' }
150 };
151
152 static struct tui_translate tui_border_kind_translate_ulcorner[] = {
153 { "space", ' ' },
154 { "ascii", '+' },
155 { "acs", -1 },
156 { 0, 0 },
157 { "ascii", '+' }
158 };
159
160 static struct tui_translate tui_border_kind_translate_urcorner[] = {
161 { "space", ' ' },
162 { "ascii", '+' },
163 { "acs", -1 },
164 { 0, 0 },
165 { "ascii", '+' }
166 };
167
168 static struct tui_translate tui_border_kind_translate_llcorner[] = {
169 { "space", ' ' },
170 { "ascii", '+' },
171 { "acs", -1 },
172 { 0, 0 },
173 { "ascii", '+' }
174 };
175
176 static struct tui_translate tui_border_kind_translate_lrcorner[] = {
177 { "space", ' ' },
178 { "ascii", '+' },
179 { "acs", -1 },
180 { 0, 0 },
181 { "ascii", '+' }
182 };
183
184
185 /* Tui configuration variables controlled with set/show command. */
186 static const char *tui_active_border_mode = "bold-standout";
187 static void
188 show_tui_active_border_mode (struct ui_file *file,
189 int from_tty,
190 struct cmd_list_element *c,
191 const char *value)
192 {
193 fprintf_filtered (file, _("\
194 The attribute mode to use for the active TUI window border is \"%s\".\n"),
195 value);
196 }
197
198 static const char *tui_border_mode = "normal";
199 static void
200 show_tui_border_mode (struct ui_file *file,
201 int from_tty,
202 struct cmd_list_element *c,
203 const char *value)
204 {
205 fprintf_filtered (file, _("\
206 The attribute mode to use for the TUI window borders is \"%s\".\n"),
207 value);
208 }
209
210 static const char *tui_border_kind = "acs";
211 static void
212 show_tui_border_kind (struct ui_file *file,
213 int from_tty,
214 struct cmd_list_element *c,
215 const char *value)
216 {
217 fprintf_filtered (file, _("The kind of border for TUI windows is \"%s\".\n"),
218 value);
219 }
220
221
222 /* Tui internal configuration variables. These variables are updated
223 by tui_update_variables to reflect the tui configuration
224 variables. */
225 chtype tui_border_vline;
226 chtype tui_border_hline;
227 chtype tui_border_ulcorner;
228 chtype tui_border_urcorner;
229 chtype tui_border_llcorner;
230 chtype tui_border_lrcorner;
231
232 int tui_border_attrs;
233 int tui_active_border_attrs;
234
235 /* Identify the item in the translation table.
236 When the item is not recognized, use the default entry. */
237 static struct tui_translate *
238 translate (const char *name, struct tui_translate *table)
239 {
240 while (table->name)
241 {
242 if (name && strcmp (table->name, name) == 0)
243 return table;
244 table++;
245 }
246
247 /* Not found, return default entry. */
248 table++;
249 return table;
250 }
251
252 /* Update the tui internal configuration according to gdb settings.
253 Returns 1 if the configuration has changed and the screen should
254 be redrawn. */
255 bool
256 tui_update_variables ()
257 {
258 bool need_redraw = false;
259 struct tui_translate *entry;
260
261 entry = translate (tui_border_mode, tui_border_mode_translate);
262 if (tui_border_attrs != entry->value)
263 {
264 tui_border_attrs = entry->value;
265 need_redraw = true;
266 }
267 entry = translate (tui_active_border_mode, tui_border_mode_translate);
268 if (tui_active_border_attrs != entry->value)
269 {
270 tui_active_border_attrs = entry->value;
271 need_redraw = true;
272 }
273
274 /* If one corner changes, all characters are changed.
275 Only check the first one. The ACS characters are determined at
276 run time by curses terminal management. */
277 entry = translate (tui_border_kind, tui_border_kind_translate_lrcorner);
278 if (tui_border_lrcorner != (chtype) entry->value)
279 {
280 tui_border_lrcorner = (entry->value < 0) ? ACS_LRCORNER : entry->value;
281 need_redraw = true;
282 }
283 entry = translate (tui_border_kind, tui_border_kind_translate_llcorner);
284 tui_border_llcorner = (entry->value < 0) ? ACS_LLCORNER : entry->value;
285
286 entry = translate (tui_border_kind, tui_border_kind_translate_ulcorner);
287 tui_border_ulcorner = (entry->value < 0) ? ACS_ULCORNER : entry->value;
288
289 entry = translate (tui_border_kind, tui_border_kind_translate_urcorner);
290 tui_border_urcorner = (entry->value < 0) ? ACS_URCORNER : entry->value;
291
292 entry = translate (tui_border_kind, tui_border_kind_translate_hline);
293 tui_border_hline = (entry->value < 0) ? ACS_HLINE : entry->value;
294
295 entry = translate (tui_border_kind, tui_border_kind_translate_vline);
296 tui_border_vline = (entry->value < 0) ? ACS_VLINE : entry->value;
297
298 return need_redraw;
299 }
300
301 static struct cmd_list_element *tuilist;
302
303 struct cmd_list_element **
304 tui_get_cmd_list (void)
305 {
306 if (tuilist == 0)
307 add_basic_prefix_cmd ("tui", class_tui,
308 _("Text User Interface commands."),
309 &tuilist, "tui ", 0, &cmdlist);
310 return &tuilist;
311 }
312
313 /* The set_func hook of "set tui ..." commands that affect the window
314 borders on the TUI display. */
315
316 static void
317 tui_set_var_cmd (const char *null_args,
318 int from_tty, struct cmd_list_element *c)
319 {
320 if (tui_update_variables () && tui_active)
321 tui_rehighlight_all ();
322 }
323
324
325
327 /* True if TUI resizes should print a message. This is used by the
328 test suite. */
329
330 static bool resize_message;
331
332 static void
333 show_tui_resize_message (struct ui_file *file, int from_tty,
334 struct cmd_list_element *c, const char *value)
335 {
336 fprintf_filtered (file, _("TUI resize messaging is %s.\n"), value);
337 }
338
339
340
342 /* Generic window name completion function. Complete window name pointed
343 to by TEXT and WORD. If INCLUDE_NEXT_PREV_P is true then the special
344 window names 'next' and 'prev' will also be considered as possible
345 completions of the window name. */
346
347 static void
348 window_name_completer (completion_tracker &tracker,
349 int include_next_prev_p,
350 const char *text, const char *word)
351 {
352 std::vector<const char *> completion_name_vec;
353
354 for (tui_win_info *win_info : all_tui_windows ())
355 {
356 const char *completion_name = NULL;
357
358 /* We can't focus on an invisible window. */
359 if (!win_info->is_visible ())
360 continue;
361
362 completion_name = win_info->name ();
363 gdb_assert (completion_name != NULL);
364 completion_name_vec.push_back (completion_name);
365 }
366
367 /* If no windows are considered visible then the TUI has not yet been
368 initialized. But still "focus src" and "focus cmd" will work because
369 invoking the focus command will entail initializing the TUI which sets the
370 default layout to "src". */
371 if (completion_name_vec.empty ())
372 {
373 completion_name_vec.push_back (SRC_NAME);
374 completion_name_vec.push_back (CMD_NAME);
375 }
376
377 if (include_next_prev_p)
378 {
379 completion_name_vec.push_back ("next");
380 completion_name_vec.push_back ("prev");
381 }
382
383
384 completion_name_vec.push_back (NULL);
385 complete_on_enum (tracker, completion_name_vec.data (), text, word);
386 }
387
388 /* Complete possible window names to focus on. TEXT is the complete text
389 entered so far, WORD is the word currently being completed. */
390
391 static void
392 focus_completer (struct cmd_list_element *ignore,
393 completion_tracker &tracker,
394 const char *text, const char *word)
395 {
396 window_name_completer (tracker, 1, text, word);
397 }
398
399 /* Complete possible window names for winheight command. TEXT is the
400 complete text entered so far, WORD is the word currently being
401 completed. */
402
403 static void
404 winheight_completer (struct cmd_list_element *ignore,
405 completion_tracker &tracker,
406 const char *text, const char *word)
407 {
408 /* The first word is the window name. That we can complete. Subsequent
409 words can't be completed. */
410 if (word != text)
411 return;
412
413 window_name_completer (tracker, 0, text, word);
414 }
415
416 /* Update gdb's knowledge of the terminal size. */
417 void
418 tui_update_gdb_sizes (void)
419 {
420 int width, height;
421
422 if (tui_active)
423 {
424 width = TUI_CMD_WIN->width;
425 height = TUI_CMD_WIN->height;
426 }
427 else
428 {
429 width = tui_term_width ();
430 height = tui_term_height ();
431 }
432
433 set_screen_width_and_height (width, height);
434 }
435
436
437 void
438 tui_win_info::forward_scroll (int num_to_scroll)
439 {
440 if (num_to_scroll == 0)
441 num_to_scroll = height - 3;
442
443 do_scroll_vertical (num_to_scroll);
444 }
445
446 void
447 tui_win_info::backward_scroll (int num_to_scroll)
448 {
449 if (num_to_scroll == 0)
450 num_to_scroll = height - 3;
451
452 do_scroll_vertical (-num_to_scroll);
453 }
454
455
456 void
457 tui_win_info::left_scroll (int num_to_scroll)
458 {
459 if (num_to_scroll == 0)
460 num_to_scroll = 1;
461
462 do_scroll_horizontal (num_to_scroll);
463 }
464
465
466 void
467 tui_win_info::right_scroll (int num_to_scroll)
468 {
469 if (num_to_scroll == 0)
470 num_to_scroll = 1;
471
472 do_scroll_horizontal (-num_to_scroll);
473 }
474
475
476 void
477 tui_refresh_all_win (void)
478 {
479 clearok (curscr, TRUE);
480 tui_refresh_all ();
481 }
482
483 void
484 tui_rehighlight_all (void)
485 {
486 for (tui_win_info *win_info : all_tui_windows ())
487 win_info->check_and_display_highlight_if_needed ();
488 }
489
490 /* Resize all the windows based on the terminal size. This function
491 gets called from within the readline SIGWINCH handler. */
492 void
493 tui_resize_all (void)
494 {
495 int height_diff, width_diff;
496 int screenheight, screenwidth;
497
498 rl_get_screen_size (&screenheight, &screenwidth);
499 width_diff = screenwidth - tui_term_width ();
500 height_diff = screenheight - tui_term_height ();
501 if (height_diff || width_diff)
502 {
503 struct tui_win_info *win_with_focus = tui_win_with_focus ();
504
505 #ifdef HAVE_RESIZE_TERM
506 resize_term (screenheight, screenwidth);
507 #endif
508 /* Turn keypad off while we resize. */
509 if (win_with_focus != TUI_CMD_WIN)
510 keypad (TUI_CMD_WIN->handle.get (), FALSE);
511 tui_update_gdb_sizes ();
512 tui_set_term_height_to (screenheight);
513 tui_set_term_width_to (screenwidth);
514
515 /* erase + clearok are used instead of a straightforward clear as
516 AIX 5.3 does not define clear. */
517 erase ();
518 clearok (curscr, TRUE);
519 tui_apply_current_layout ();
520 /* Turn keypad back on, unless focus is in the command
521 window. */
522 if (win_with_focus != TUI_CMD_WIN)
523 keypad (TUI_CMD_WIN->handle.get (), TRUE);
524 }
525 }
526
527 #ifdef SIGWINCH
528 /* Token for use by TUI's asynchronous SIGWINCH handler. */
529 static struct async_signal_handler *tui_sigwinch_token;
530
531 /* TUI's SIGWINCH signal handler. */
532 static void
533 tui_sigwinch_handler (int signal)
534 {
535 mark_async_signal_handler (tui_sigwinch_token);
536 tui_set_win_resized_to (true);
537 }
538
539 /* Callback for asynchronously resizing TUI following a SIGWINCH signal. */
540 static void
541 tui_async_resize_screen (gdb_client_data arg)
542 {
543 rl_resize_terminal ();
544
545 if (!tui_active)
546 {
547 int screen_height, screen_width;
548
549 rl_get_screen_size (&screen_height, &screen_width);
550 set_screen_width_and_height (screen_width, screen_height);
551
552 /* win_resized is left set so that the next call to tui_enable()
553 resizes the TUI windows. */
554 }
555 else
556 {
557 tui_set_win_resized_to (false);
558 tui_resize_all ();
559 tui_refresh_all_win ();
560 tui_update_gdb_sizes ();
561 if (resize_message)
562 {
563 static int count;
564 printf_unfiltered ("@@ resize done %d, size = %dx%d\n", count,
565 tui_term_width (), tui_term_height ());
566 ++count;
567 }
568 tui_redisplay_readline ();
569 }
570 }
571 #endif
572
573 /* Initialize TUI's SIGWINCH signal handler. Note that the handler is not
574 uninstalled when we exit TUI, so the handler should not assume that TUI is
575 always active. */
576 void
577 tui_initialize_win (void)
578 {
579 #ifdef SIGWINCH
580 tui_sigwinch_token
581 = create_async_signal_handler (tui_async_resize_screen, NULL);
582
583 {
584 #ifdef HAVE_SIGACTION
585 struct sigaction old_winch;
586
587 memset (&old_winch, 0, sizeof (old_winch));
588 old_winch.sa_handler = &tui_sigwinch_handler;
589 #ifdef SA_RESTART
590 old_winch.sa_flags = SA_RESTART;
591 #endif
592 sigaction (SIGWINCH, &old_winch, NULL);
593 #else
594 signal (SIGWINCH, &tui_sigwinch_handler);
595 #endif
596 }
597 #endif
598 }
599
600
601 static void
602 tui_scroll_forward_command (const char *arg, int from_tty)
603 {
604 int num_to_scroll = 1;
605 struct tui_win_info *win_to_scroll;
606
607 /* Make sure the curses mode is enabled. */
608 tui_enable ();
609 if (arg == NULL)
610 parse_scrolling_args (arg, &win_to_scroll, NULL);
611 else
612 parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
613 win_to_scroll->forward_scroll (num_to_scroll);
614 }
615
616
617 static void
618 tui_scroll_backward_command (const char *arg, int from_tty)
619 {
620 int num_to_scroll = 1;
621 struct tui_win_info *win_to_scroll;
622
623 /* Make sure the curses mode is enabled. */
624 tui_enable ();
625 if (arg == NULL)
626 parse_scrolling_args (arg, &win_to_scroll, NULL);
627 else
628 parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
629 win_to_scroll->backward_scroll (num_to_scroll);
630 }
631
632
633 static void
634 tui_scroll_left_command (const char *arg, int from_tty)
635 {
636 int num_to_scroll;
637 struct tui_win_info *win_to_scroll;
638
639 /* Make sure the curses mode is enabled. */
640 tui_enable ();
641 parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
642 win_to_scroll->left_scroll (num_to_scroll);
643 }
644
645
646 static void
647 tui_scroll_right_command (const char *arg, int from_tty)
648 {
649 int num_to_scroll;
650 struct tui_win_info *win_to_scroll;
651
652 /* Make sure the curses mode is enabled. */
653 tui_enable ();
654 parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
655 win_to_scroll->right_scroll (num_to_scroll);
656 }
657
658
659 /* Answer the window represented by name. */
660 static struct tui_win_info *
661 tui_partial_win_by_name (gdb::string_view name)
662 {
663 struct tui_win_info *best = nullptr;
664
665 for (tui_win_info *item : all_tui_windows ())
666 {
667 const char *cur_name = item->name ();
668
669 if (name == cur_name)
670 return item;
671 if (startswith (cur_name, name))
672 {
673 if (best != nullptr)
674 error (_("Window name \"%*s\" is ambiguous"),
675 (int) name.size (), name.data ());
676 best = item;
677 }
678 }
679
680 return best;
681 }
682
683 /* Set focus to the window named by 'arg'. */
684 static void
685 tui_set_focus_command (const char *arg, int from_tty)
686 {
687 tui_enable ();
688
689 if (arg == NULL)
690 error_no_arg (_("name of window to focus"));
691
692 struct tui_win_info *win_info = NULL;
693
694 if (subset_compare (arg, "next"))
695 win_info = tui_next_win (tui_win_with_focus ());
696 else if (subset_compare (arg, "prev"))
697 win_info = tui_prev_win (tui_win_with_focus ());
698 else
699 win_info = tui_partial_win_by_name (arg);
700
701 if (win_info == NULL)
702 error (_("Unrecognized window name \"%s\""), arg);
703 if (!win_info->is_visible ())
704 error (_("Window \"%s\" is not visible"), arg);
705
706 tui_set_win_focus_to (win_info);
707 keypad (TUI_CMD_WIN->handle.get (), win_info != TUI_CMD_WIN);
708 printf_filtered (_("Focus set to %s window.\n"),
709 tui_win_with_focus ()->name ());
710 }
711
712 static void
713 tui_all_windows_info (const char *arg, int from_tty)
714 {
715 if (!tui_active)
716 {
717 printf_filtered (_("The TUI is not active.\n"));
718 return;
719 }
720
721 struct tui_win_info *win_with_focus = tui_win_with_focus ();
722 struct ui_out *uiout = current_uiout;
723
724 ui_out_emit_table table_emitter (uiout, 3, -1, "tui-windows");
725 uiout->table_header (10, ui_left, "name", "Name");
726 uiout->table_header (5, ui_right, "lines", "Lines");
727 uiout->table_header (10, ui_left, "focus", "Focus");
728 uiout->table_body ();
729
730 for (tui_win_info *win_info : all_tui_windows ())
731 if (win_info->is_visible ())
732 {
733 ui_out_emit_tuple tuple_emitter (uiout, nullptr);
734
735 uiout->field_string ("name", win_info->name ());
736 uiout->field_signed ("lines", win_info->height);
737 if (win_with_focus == win_info)
738 uiout->field_string ("focus", _("(has focus)"));
739 else
740 uiout->field_skip ("focus");
741 uiout->text ("\n");
742 }
743 }
744
745
746 static void
747 tui_refresh_all_command (const char *arg, int from_tty)
748 {
749 /* Make sure the curses mode is enabled. */
750 tui_enable ();
751
752 tui_refresh_all_win ();
753 }
754
755 #define DEFAULT_TAB_LEN 8
756
757 /* The tab width that should be used by the TUI. */
758
759 unsigned int tui_tab_width = DEFAULT_TAB_LEN;
760
761 /* The tab width as set by the user. */
762
763 static unsigned int internal_tab_width = DEFAULT_TAB_LEN;
764
765 /* After the tab width is set, call this to update the relevant
766 windows. */
767
768 static void
769 update_tab_width ()
770 {
771 for (tui_win_info *win_info : all_tui_windows ())
772 {
773 if (win_info->is_visible ())
774 win_info->update_tab_width ();
775 }
776 }
777
778 /* Callback for "set tui tab-width". */
779
780 static void
781 tui_set_tab_width (const char *ignore,
782 int from_tty, struct cmd_list_element *c)
783 {
784 if (internal_tab_width == 0)
785 {
786 internal_tab_width = tui_tab_width;
787 error (_("Tab width must not be 0"));
788 }
789
790 tui_tab_width = internal_tab_width;
791 update_tab_width ();
792 }
793
794 /* Callback for "show tui tab-width". */
795
796 static void
797 tui_show_tab_width (struct ui_file *file, int from_tty,
798 struct cmd_list_element *c, const char *value)
799 {
800 fprintf_filtered (gdb_stdout, _("TUI tab width is %s spaces.\n"), value);
801
802 }
803
804 /* See tui-win.h. */
805
806 bool compact_source = false;
807
808 /* Callback for "set tui compact-source". */
809
810 static void
811 tui_set_compact_source (const char *ignore, int from_tty,
812 struct cmd_list_element *c)
813 {
814 if (TUI_SRC_WIN != nullptr)
815 TUI_SRC_WIN->refill ();
816 }
817
818 /* Callback for "show tui compact-source". */
819
820 static void
821 tui_show_compact_source (struct ui_file *file, int from_tty,
822 struct cmd_list_element *c, const char *value)
823 {
824 printf_filtered (_("TUI source window compactness is %s.\n"), value);
825 }
826
827 /* Set the tab width of the specified window. */
828 static void
829 tui_set_tab_width_command (const char *arg, int from_tty)
830 {
831 /* Make sure the curses mode is enabled. */
832 tui_enable ();
833 if (arg != NULL)
834 {
835 int ts;
836
837 ts = atoi (arg);
838 if (ts <= 0)
839 warning (_("Tab widths greater than 0 must be specified."));
840 else
841 {
842 internal_tab_width = ts;
843 tui_tab_width = ts;
844
845 update_tab_width ();
846 }
847 }
848 }
849
850
851 /* Set the height of the specified window. */
852 static void
853 tui_set_win_height_command (const char *arg, int from_tty)
854 {
855 /* Make sure the curses mode is enabled. */
856 tui_enable ();
857 if (arg == NULL)
858 error_no_arg (_("name of window"));
859
860 const char *buf = arg;
861 const char *buf_ptr = buf;
862 int new_height;
863 struct tui_win_info *win_info;
864
865 buf_ptr = skip_to_space (buf_ptr);
866
867 /* Validate the window name. */
868 gdb::string_view wname (buf, buf_ptr - buf);
869 win_info = tui_partial_win_by_name (wname);
870
871 if (win_info == NULL)
872 error (_("Unrecognized window name \"%s\""), arg);
873 if (!win_info->is_visible ())
874 error (_("Window \"%s\" is not visible"), arg);
875
876 /* Process the size. */
877 buf_ptr = skip_spaces (buf_ptr);
878
879 if (*buf_ptr != '\0')
880 {
881 bool negate = false;
882 bool fixed_size = true;
883 int input_no;;
884
885 if (*buf_ptr == '+' || *buf_ptr == '-')
886 {
887 if (*buf_ptr == '-')
888 negate = true;
889 fixed_size = false;
890 buf_ptr++;
891 }
892 input_no = atoi (buf_ptr);
893 if (input_no > 0)
894 {
895 if (negate)
896 input_no *= (-1);
897 if (fixed_size)
898 new_height = input_no;
899 else
900 new_height = win_info->height + input_no;
901
902 /* Now change the window's height, and adjust
903 all other windows around it. */
904 tui_adjust_window_height (win_info, new_height);
905 tui_update_gdb_sizes ();
906 }
907 else
908 error (_("Invalid window height specified"));
909 }
910 }
911
912 /* See tui-data.h. */
913
914 int
915 tui_win_info::max_height () const
916 {
917 return tui_term_height () - 2;
918 }
919
920 /* See tui-data.h. */
921
922 int
923 tui_win_info::max_width () const
924 {
925 return tui_term_width () - 2;
926 }
927
928 static void
929 parse_scrolling_args (const char *arg,
930 struct tui_win_info **win_to_scroll,
931 int *num_to_scroll)
932 {
933 if (num_to_scroll)
934 *num_to_scroll = 0;
935 *win_to_scroll = tui_win_with_focus ();
936
937 /* First set up the default window to scroll, in case there is no
938 window name arg. */
939 if (arg != NULL)
940 {
941 char *buf_ptr;
942
943 /* Process the number of lines to scroll. */
944 std::string copy = arg;
945 buf_ptr = ©[0];
946 if (isdigit (*buf_ptr))
947 {
948 char *num_str;
949
950 num_str = buf_ptr;
951 buf_ptr = strchr (buf_ptr, ' ');
952 if (buf_ptr != NULL)
953 {
954 *buf_ptr = '\0';
955 if (num_to_scroll)
956 *num_to_scroll = atoi (num_str);
957 buf_ptr++;
958 }
959 else if (num_to_scroll)
960 *num_to_scroll = atoi (num_str);
961 }
962
963 /* Process the window name if one is specified. */
964 if (buf_ptr != NULL)
965 {
966 const char *wname;
967
968 wname = skip_spaces (buf_ptr);
969
970 if (*wname != '\0')
971 {
972 *win_to_scroll = tui_partial_win_by_name (wname);
973
974 if (*win_to_scroll == NULL)
975 error (_("Unrecognized window `%s'"), wname);
976 if (!(*win_to_scroll)->is_visible ())
977 error (_("Window is not visible"));
978 else if (*win_to_scroll == TUI_CMD_WIN)
979 *win_to_scroll = *(tui_source_windows ().begin ());
980 }
981 }
982 }
983 }
984
985 /* Function to initialize gdb commands, for tui window
986 manipulation. */
987
988 void _initialize_tui_win ();
989 void
990 _initialize_tui_win ()
991 {
992 static struct cmd_list_element *tui_setlist;
993 static struct cmd_list_element *tui_showlist;
994 struct cmd_list_element *cmd;
995
996 /* Define the classes of commands.
997 They will appear in the help list in the reverse of this order. */
998 add_basic_prefix_cmd ("tui", class_tui,
999 _("TUI configuration variables."),
1000 &tui_setlist, "set tui ",
1001 0 /* allow-unknown */, &setlist);
1002 add_show_prefix_cmd ("tui", class_tui,
1003 _("TUI configuration variables."),
1004 &tui_showlist, "show tui ",
1005 0 /* allow-unknown */, &showlist);
1006
1007 add_com ("refresh", class_tui, tui_refresh_all_command,
1008 _("Refresh the terminal display."));
1009
1010 cmd = add_com ("tabset", class_tui, tui_set_tab_width_command, _("\
1011 Set the width (in characters) of tab stops.\n\
1012 Usage: tabset N"));
1013 deprecate_cmd (cmd, "set tui tab-width");
1014
1015 cmd = add_com ("winheight", class_tui, tui_set_win_height_command, _("\
1016 Set or modify the height of a specified window.\n\
1017 Usage: winheight WINDOW-NAME [+ | -] NUM-LINES\n\
1018 Use \"info win\" to see the names of the windows currently being displayed."));
1019 add_com_alias ("wh", "winheight", class_tui, 0);
1020 set_cmd_completer (cmd, winheight_completer);
1021 add_info ("win", tui_all_windows_info,
1022 _("List of all displayed windows.\n\
1023 Usage: info win"));
1024 cmd = add_com ("focus", class_tui, tui_set_focus_command, _("\
1025 Set focus to named window or next/prev window.\n\
1026 Usage: focus [WINDOW-NAME | next | prev]\n\
1027 Use \"info win\" to see the names of the windows currently being displayed."));
1028 add_com_alias ("fs", "focus", class_tui, 0);
1029 set_cmd_completer (cmd, focus_completer);
1030 add_com ("+", class_tui, tui_scroll_forward_command, _("\
1031 Scroll window forward.\n\
1032 Usage: + [N] [WIN]\n\
1033 Scroll window WIN N lines forwards. Both WIN and N are optional, N\n\
1034 defaults to 1, and WIN defaults to the currently focused window."));
1035 add_com ("-", class_tui, tui_scroll_backward_command, _("\
1036 Scroll window backward.\n\
1037 Usage: - [N] [WIN]\n\
1038 Scroll window WIN N lines backwards. Both WIN and N are optional, N\n\
1039 defaults to 1, and WIN defaults to the currently focused window."));
1040 add_com ("<", class_tui, tui_scroll_left_command, _("\
1041 Scroll window text to the left.\n\
1042 Usage: < [N] [WIN]\n\
1043 Scroll window WIN N characters left. Both WIN and N are optional, N\n\
1044 defaults to 1, and WIN defaults to the currently focused window."));
1045 add_com (">", class_tui, tui_scroll_right_command, _("\
1046 Scroll window text to the right.\n\
1047 Usage: > [N] [WIN]\n\
1048 Scroll window WIN N characters right. Both WIN and N are optional, N\n\
1049 defaults to 1, and WIN defaults to the currently focused window."));
1050
1051 /* Define the tui control variables. */
1052 add_setshow_enum_cmd ("border-kind", no_class, tui_border_kind_enums,
1053 &tui_border_kind, _("\
1054 Set the kind of border for TUI windows."), _("\
1055 Show the kind of border for TUI windows."), _("\
1056 This variable controls the border of TUI windows:\n\
1057 space use a white space\n\
1058 ascii use ascii characters + - | for the border\n\
1059 acs use the Alternate Character Set"),
1060 tui_set_var_cmd,
1061 show_tui_border_kind,
1062 &tui_setlist, &tui_showlist);
1063
1064 add_setshow_enum_cmd ("border-mode", no_class, tui_border_mode_enums,
1065 &tui_border_mode, _("\
1066 Set the attribute mode to use for the TUI window borders."), _("\
1067 Show the attribute mode to use for the TUI window borders."), _("\
1068 This variable controls the attributes to use for the window borders:\n\
1069 normal normal display\n\
1070 standout use highlight mode of terminal\n\
1071 reverse use reverse video mode\n\
1072 half use half bright\n\
1073 half-standout use half bright and standout mode\n\
1074 bold use extra bright or bold\n\
1075 bold-standout use extra bright or bold with standout mode"),
1076 tui_set_var_cmd,
1077 show_tui_border_mode,
1078 &tui_setlist, &tui_showlist);
1079
1080 add_setshow_enum_cmd ("active-border-mode", no_class, tui_border_mode_enums,
1081 &tui_active_border_mode, _("\
1082 Set the attribute mode to use for the active TUI window border."), _("\
1083 Show the attribute mode to use for the active TUI window border."), _("\
1084 This variable controls the attributes to use for the active window border:\n\
1085 normal normal display\n\
1086 standout use highlight mode of terminal\n\
1087 reverse use reverse video mode\n\
1088 half use half bright\n\
1089 half-standout use half bright and standout mode\n\
1090 bold use extra bright or bold\n\
1091 bold-standout use extra bright or bold with standout mode"),
1092 tui_set_var_cmd,
1093 show_tui_active_border_mode,
1094 &tui_setlist, &tui_showlist);
1095
1096 add_setshow_zuinteger_cmd ("tab-width", no_class,
1097 &internal_tab_width, _("\
1098 Set the tab width, in characters, for the TUI."), _("\
1099 Show the tab witdh, in characters, for the TUI."), _("\
1100 This variable controls how many spaces are used to display a tab character."),
1101 tui_set_tab_width, tui_show_tab_width,
1102 &tui_setlist, &tui_showlist);
1103
1104 add_setshow_boolean_cmd ("tui-resize-message", class_maintenance,
1105 &resize_message, _("\
1106 Set TUI resize messaging."), _("\
1107 Show TUI resize messaging."), _("\
1108 When enabled GDB will print a message when the terminal is resized."),
1109 nullptr,
1110 show_tui_resize_message,
1111 &maintenance_set_cmdlist,
1112 &maintenance_show_cmdlist);
1113
1114 add_setshow_boolean_cmd ("compact-source", class_tui,
1115 &compact_source, _("\
1116 Set whether the TUI source window is compact."), _("\
1117 Show whether the TUI source window is compact."), _("\
1118 This variable controls whether the TUI source window is shown\n\
1119 in a compact form. The compact form puts the source closer to\n\
1120 the line numbers and uses less horizontal space."),
1121 tui_set_compact_source, tui_show_compact_source,
1122 &tui_setlist, &tui_showlist);
1123
1124 tui_border_style.changed.attach (tui_rehighlight_all);
1125 tui_active_border_style.changed.attach (tui_rehighlight_all);
1126 }
1127