Automatic date update in version.in
[binutils-gdb.git] / gdb / tui / tui-win.c
blob414d4699bea7e1cffd8a22439d739e4101abc40c
1 /* TUI window generic functions.
3 Copyright (C) 1998-2024 Free Software Foundation, Inc.
5 Contributed by Hewlett-Packard Company.
7 This file is part of GDB.
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.
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.
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/>. */
22 /* This module contains procedures for handling tui window functions
23 like resize, scrolling, scrolling, changing focus, etc.
25 Author: Susan B. Macchia */
27 #include "async-event.h"
28 #include "command.h"
29 #include "symtab.h"
30 #include "frame.h"
31 #include "cli/cli-cmds.h"
32 #include "cli/cli-style.h"
33 #include "ui-out.h"
34 #include "utils.h"
36 #include "tui/tui.h"
37 #include "tui/tui-io.h"
38 #include "tui/tui-command.h"
39 #include "tui/tui-data.h"
40 #include "tui/tui-layout.h"
41 #include "tui/tui-wingeneral.h"
42 #include "tui/tui-disasm.h"
43 #include "tui/tui-source.h"
44 #include "tui/tui-winsource.h"
45 #include "tui/tui-win.h"
47 #include "gdb_curses.h"
48 #include <ctype.h>
49 #include "readline/readline.h"
50 #include <signal.h>
51 #include <string_view>
53 static void tui_set_tab_width_command (const char *, int);
54 static void tui_refresh_all_command (const char *, int);
55 static void tui_all_windows_info (const char *, int);
56 static void tui_scroll_forward_command (const char *, int);
57 static void tui_scroll_backward_command (const char *, int);
58 static void tui_scroll_left_command (const char *, int);
59 static void tui_scroll_right_command (const char *, int);
60 static void parse_scrolling_args (const char *,
61 struct tui_win_info **,
62 int *);
65 #ifndef ACS_LRCORNER
66 # define ACS_LRCORNER '+'
67 #endif
68 #ifndef ACS_LLCORNER
69 # define ACS_LLCORNER '+'
70 #endif
71 #ifndef ACS_ULCORNER
72 # define ACS_ULCORNER '+'
73 #endif
74 #ifndef ACS_URCORNER
75 # define ACS_URCORNER '+'
76 #endif
77 #ifndef ACS_HLINE
78 # define ACS_HLINE '-'
79 #endif
80 #ifndef ACS_VLINE
81 # define ACS_VLINE '|'
82 #endif
84 /* Possible values for tui-border-kind variable. */
85 static const char *const tui_border_kind_enums[] = {
86 "space",
87 "ascii",
88 "acs",
89 NULL
92 /* Possible values for tui-border-mode and tui-active-border-mode. */
93 static const char *const tui_border_mode_enums[] = {
94 "normal",
95 "standout",
96 "reverse",
97 "half",
98 "half-standout",
99 "bold",
100 "bold-standout",
101 NULL
104 struct tui_translate
106 const char *name;
107 int value;
110 /* Translation table for border-mode variables.
111 The list of values must be terminated by a NULL. */
112 static struct tui_translate tui_border_mode_translate[] = {
113 { "normal", A_NORMAL },
114 { "standout", A_STANDOUT },
115 { "reverse", A_REVERSE },
116 { "half", A_DIM },
117 { "half-standout", A_DIM | A_STANDOUT },
118 { "bold", A_BOLD },
119 { "bold-standout", A_BOLD | A_STANDOUT },
120 { 0, 0 }
123 /* Translation tables for border-kind (acs excluded), one for vline, hline and
124 corners (see wborder, border curses operations). */
125 static struct tui_translate tui_border_kind_translate_vline[] = {
126 { "space", ' ' },
127 { "ascii", '|' },
128 { 0, 0 }
131 static struct tui_translate tui_border_kind_translate_hline[] = {
132 { "space", ' ' },
133 { "ascii", '-' },
134 { 0, 0 }
137 static struct tui_translate tui_border_kind_translate_corner[] = {
138 { "space", ' ' },
139 { "ascii", '+' },
140 { 0, 0 }
144 /* Tui configuration variables controlled with set/show command. */
145 static const char *tui_active_border_mode = "bold-standout";
146 static void
147 show_tui_active_border_mode (struct ui_file *file,
148 int from_tty,
149 struct cmd_list_element *c,
150 const char *value)
152 gdb_printf (file, _("\
153 The attribute mode to use for the active TUI window border is \"%s\".\n"),
154 value);
157 static const char *tui_border_mode = "normal";
158 static void
159 show_tui_border_mode (struct ui_file *file,
160 int from_tty,
161 struct cmd_list_element *c,
162 const char *value)
164 gdb_printf (file, _("\
165 The attribute mode to use for the TUI window borders is \"%s\".\n"),
166 value);
169 static const char *tui_border_kind = "acs";
170 static void
171 show_tui_border_kind (struct ui_file *file,
172 int from_tty,
173 struct cmd_list_element *c,
174 const char *value)
176 gdb_printf (file, _("The kind of border for TUI windows is \"%s\".\n"),
177 value);
180 /* Implementation of the "set/show style tui-current-position" commands. */
182 bool style_tui_current_position = false;
184 static void
185 show_style_tui_current_position (ui_file *file,
186 int from_tty,
187 cmd_list_element *c,
188 const char *value)
190 gdb_printf (file, _("\
191 Styling the text highlighted by the TUI's current position indicator is %s.\n"),
192 value);
195 static void
196 set_style_tui_current_position (const char *ignore, int from_tty,
197 cmd_list_element *c)
199 if (tui_src_win () != nullptr)
200 tui_src_win ()->refill ();
201 if (tui_disasm_win () != nullptr)
202 tui_disasm_win ()->refill ();
205 /* Tui internal configuration variables. These variables are updated
206 by tui_update_variables to reflect the tui configuration
207 variables. */
208 chtype tui_border_vline;
209 chtype tui_border_hline;
210 chtype tui_border_ulcorner;
211 chtype tui_border_urcorner;
212 chtype tui_border_llcorner;
213 chtype tui_border_lrcorner;
215 int tui_border_attrs;
216 int tui_active_border_attrs;
218 /* Identify the item in the translation table, and return the corresponding value. */
219 static int
220 translate (const char *name, struct tui_translate *table)
222 while (table->name)
224 if (name && strcmp (table->name, name) == 0)
225 return table->value;
226 table++;
229 gdb_assert_not_reached ("");
232 /* Translate NAME to a value. If NAME is "acs", use ACS_CHAR. Otherwise, use
233 translation table TABLE. */
234 static int
235 translate_acs (const char *name, struct tui_translate *table, int acs_char)
237 /* The ACS characters are determined at run time by curses terminal
238 management. */
239 if (strcmp (name, "acs") == 0)
240 return acs_char;
242 return translate (name, table);
245 /* Update the tui internal configuration according to gdb settings.
246 Returns 1 if the configuration has changed and the screen should
247 be redrawn. */
248 bool
249 tui_update_variables ()
251 bool need_redraw = false;
252 int val;
254 val = translate (tui_border_mode, tui_border_mode_translate);
255 need_redraw |= assign_return_if_changed<int> (tui_border_attrs, val);
257 val = translate (tui_active_border_mode, tui_border_mode_translate);
258 need_redraw |= assign_return_if_changed<int> (tui_active_border_attrs, val);
260 /* If one corner changes, all characters are changed. Only check the first
261 one. */
262 val = translate_acs (tui_border_kind, tui_border_kind_translate_corner,
263 ACS_LRCORNER);
264 need_redraw |= assign_return_if_changed<chtype> (tui_border_lrcorner, val);
266 tui_border_llcorner
267 = translate_acs (tui_border_kind, tui_border_kind_translate_corner,
268 ACS_LLCORNER);
270 tui_border_ulcorner
271 = translate_acs (tui_border_kind, tui_border_kind_translate_corner,
272 ACS_ULCORNER);
274 tui_border_urcorner =
275 translate_acs (tui_border_kind, tui_border_kind_translate_corner,
276 ACS_URCORNER);
278 tui_border_hline
279 = translate_acs (tui_border_kind, tui_border_kind_translate_hline,
280 ACS_HLINE);
282 tui_border_vline
283 = translate_acs (tui_border_kind, tui_border_kind_translate_vline,
284 ACS_VLINE);
286 return need_redraw;
289 static struct cmd_list_element *tuilist;
291 struct cmd_list_element **
292 tui_get_cmd_list (void)
294 if (tuilist == 0)
295 add_basic_prefix_cmd ("tui", class_tui,
296 _("Text User Interface commands."),
297 &tuilist, 0, &cmdlist);
298 return &tuilist;
301 /* The set_func hook of "set tui ..." commands that affect the window
302 borders on the TUI display. */
304 static void
305 tui_set_var_cmd (const char *null_args,
306 int from_tty, struct cmd_list_element *c)
308 if (tui_update_variables () && tui_active)
309 tui_rehighlight_all ();
314 /* True if TUI resizes should print a message. This is used by the
315 test suite. */
317 static bool resize_message;
319 static void
320 show_tui_resize_message (struct ui_file *file, int from_tty,
321 struct cmd_list_element *c, const char *value)
323 gdb_printf (file, _("TUI resize messaging is %s.\n"), value);
328 /* Generic window name completion function. Complete window name pointed
329 to by TEXT and WORD.
331 If EXCLUDE_CANNOT_FOCUS_P is true, then windows that can't take focus
332 will be excluded from the completions, otherwise they will be included.
334 If INCLUDE_NEXT_PREV_P is true then the special window names 'next' and
335 'prev' will also be considered as possible completions of the window
336 name. This is independent of EXCLUDE_CANNOT_FOCUS_P. */
338 static void
339 window_name_completer (completion_tracker &tracker,
340 bool include_next_prev_p,
341 bool exclude_cannot_focus_p,
342 const char *text, const char *word)
344 std::vector<const char *> completion_name_vec;
346 for (tui_win_info *win_info : all_tui_windows ())
348 const char *completion_name = NULL;
350 /* Don't include an invisible window. */
351 if (!win_info->is_visible ())
352 continue;
354 /* If requested, exclude windows that can't be focused. */
355 if (exclude_cannot_focus_p && !win_info->can_focus ())
356 continue;
358 completion_name = win_info->name ();
359 gdb_assert (completion_name != NULL);
360 completion_name_vec.push_back (completion_name);
363 /* If no windows are considered visible then the TUI has not yet been
364 initialized. But still "focus src" and "focus cmd" will work because
365 invoking the focus command will entail initializing the TUI which sets the
366 default layout to "src". */
367 if (completion_name_vec.empty ())
369 completion_name_vec.push_back (SRC_NAME);
370 completion_name_vec.push_back (CMD_NAME);
373 if (include_next_prev_p)
375 completion_name_vec.push_back ("next");
376 completion_name_vec.push_back ("prev");
380 completion_name_vec.push_back (NULL);
381 complete_on_enum (tracker, completion_name_vec.data (), text, word);
384 /* Complete possible window names to focus on. TEXT is the complete text
385 entered so far, WORD is the word currently being completed. */
387 static void
388 focus_completer (struct cmd_list_element *ignore,
389 completion_tracker &tracker,
390 const char *text, const char *word)
392 window_name_completer (tracker, true, true, text, word);
395 /* Complete possible window names for winheight command. TEXT is the
396 complete text entered so far, WORD is the word currently being
397 completed. */
399 static void
400 winheight_completer (struct cmd_list_element *ignore,
401 completion_tracker &tracker,
402 const char *text, const char *word)
404 /* The first word is the window name. That we can complete. Subsequent
405 words can't be completed. */
406 if (word != text)
407 return;
409 window_name_completer (tracker, false, false, text, word);
412 /* Update gdb's knowledge of the terminal size. */
413 void
414 tui_update_gdb_sizes (void)
416 int width, height;
418 if (tui_active)
420 width = tui_cmd_win ()->width;
421 height = tui_cmd_win ()->height;
423 else
425 width = tui_term_width ();
426 height = tui_term_height ();
429 set_screen_width_and_height (width, height);
433 void
434 tui_win_info::forward_scroll (int num_to_scroll)
436 if (num_to_scroll == 0)
437 num_to_scroll = height - 3;
439 do_scroll_vertical (num_to_scroll);
442 void
443 tui_win_info::backward_scroll (int num_to_scroll)
445 if (num_to_scroll == 0)
446 num_to_scroll = height - 3;
448 do_scroll_vertical (-num_to_scroll);
452 void
453 tui_win_info::left_scroll (int num_to_scroll)
455 if (num_to_scroll == 0)
456 num_to_scroll = 1;
458 do_scroll_horizontal (num_to_scroll);
462 void
463 tui_win_info::right_scroll (int num_to_scroll)
465 if (num_to_scroll == 0)
466 num_to_scroll = 1;
468 do_scroll_horizontal (-num_to_scroll);
472 void
473 tui_refresh_all_win (void)
475 clearok (curscr, TRUE);
476 doupdate ();
479 void
480 tui_rehighlight_all (void)
482 for (tui_win_info *win_info : all_tui_windows ())
483 win_info->check_and_display_highlight_if_needed ();
486 /* Resize all the windows based on the terminal size. This function
487 gets called from within the readline SIGWINCH handler. */
488 void
489 tui_resize_all (void)
491 int height_diff, width_diff;
492 int screenheight, screenwidth;
494 rl_get_screen_size (&screenheight, &screenwidth);
495 screenwidth += readline_hidden_cols;
497 width_diff = screenwidth - tui_term_width ();
498 height_diff = screenheight - tui_term_height ();
499 if (height_diff || width_diff)
501 #ifdef HAVE_RESIZE_TERM
502 resize_term (screenheight, screenwidth);
503 #endif
504 /* Turn keypad off while we resize. */
505 keypad (tui_cmd_win ()->handle.get (), FALSE);
506 tui_update_gdb_sizes ();
507 tui_set_term_height_to (screenheight);
508 tui_set_term_width_to (screenwidth);
510 /* erase + clearok are used instead of a straightforward clear as
511 AIX 5.3 does not define clear. */
512 erase ();
513 clearok (curscr, TRUE);
514 /* Apply the current layout. The 'false' here allows the command
515 window to resize proportionately with containing terminal, rather
516 than maintaining a fixed size. */
517 tui_apply_current_layout (false); /* Turn keypad back on. */
518 keypad (tui_cmd_win ()->handle.get (), TRUE);
522 #ifdef SIGWINCH
523 /* Token for use by TUI's asynchronous SIGWINCH handler. */
524 static struct async_signal_handler *tui_sigwinch_token;
526 /* TUI's SIGWINCH signal handler. */
527 static void
528 tui_sigwinch_handler (int signal)
530 scoped_restore restore_errno = make_scoped_restore (&errno);
531 mark_async_signal_handler (tui_sigwinch_token);
532 tui_set_win_resized_to (true);
535 /* Callback for asynchronously resizing TUI following a SIGWINCH signal. */
536 static void
537 tui_async_resize_screen (gdb_client_data arg)
539 rl_resize_terminal ();
541 if (!tui_active)
543 int screen_height, screen_width;
545 rl_get_screen_size (&screen_height, &screen_width);
546 screen_width += readline_hidden_cols;
547 set_screen_width_and_height (screen_width, screen_height);
549 /* win_resized is left set so that the next call to tui_enable()
550 resizes the TUI windows. */
552 else
554 tui_set_win_resized_to (false);
555 tui_resize_all ();
556 tui_refresh_all_win ();
557 tui_update_gdb_sizes ();
558 if (resize_message)
560 static int count;
561 printf_unfiltered ("@@ resize done %d, size = %dx%d\n", count,
562 tui_term_width (), tui_term_height ());
563 ++count;
565 tui_redisplay_readline ();
568 #endif
570 /* Initialize TUI's SIGWINCH signal handler. Note that the handler is not
571 uninstalled when we exit TUI, so the handler should not assume that TUI is
572 always active. */
573 void
574 tui_initialize_win (void)
576 #ifdef SIGWINCH
577 tui_sigwinch_token
578 = create_async_signal_handler (tui_async_resize_screen, NULL,
579 "tui-sigwinch");
582 #ifdef HAVE_SIGACTION
583 struct sigaction old_winch;
585 memset (&old_winch, 0, sizeof (old_winch));
586 old_winch.sa_handler = &tui_sigwinch_handler;
587 #ifdef SA_RESTART
588 old_winch.sa_flags = SA_RESTART;
589 #endif
590 sigaction (SIGWINCH, &old_winch, NULL);
591 #else
592 signal (SIGWINCH, &tui_sigwinch_handler);
593 #endif
595 #endif
599 static void
600 tui_scroll_forward_command (const char *arg, int from_tty)
602 int num_to_scroll = 1;
603 struct tui_win_info *win_to_scroll;
605 /* Make sure the curses mode is enabled. */
606 tui_enable ();
607 if (arg == NULL)
608 parse_scrolling_args (arg, &win_to_scroll, NULL);
609 else
610 parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
611 win_to_scroll->forward_scroll (num_to_scroll);
615 static void
616 tui_scroll_backward_command (const char *arg, int from_tty)
618 int num_to_scroll = 1;
619 struct tui_win_info *win_to_scroll;
621 /* Make sure the curses mode is enabled. */
622 tui_enable ();
623 if (arg == NULL)
624 parse_scrolling_args (arg, &win_to_scroll, NULL);
625 else
626 parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
627 win_to_scroll->backward_scroll (num_to_scroll);
631 static void
632 tui_scroll_left_command (const char *arg, int from_tty)
634 int num_to_scroll;
635 struct tui_win_info *win_to_scroll;
637 /* Make sure the curses mode is enabled. */
638 tui_enable ();
639 parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
640 win_to_scroll->left_scroll (num_to_scroll);
644 static void
645 tui_scroll_right_command (const char *arg, int from_tty)
647 int num_to_scroll;
648 struct tui_win_info *win_to_scroll;
650 /* Make sure the curses mode is enabled. */
651 tui_enable ();
652 parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
653 win_to_scroll->right_scroll (num_to_scroll);
657 /* Answer the window represented by name. */
658 static struct tui_win_info *
659 tui_partial_win_by_name (std::string_view name)
661 struct tui_win_info *best = nullptr;
663 for (tui_win_info *item : all_tui_windows ())
665 const char *cur_name = item->name ();
667 if (name == cur_name)
668 return item;
669 if (startswith (cur_name, name))
671 if (best != nullptr)
672 error (_("Window name \"%*s\" is ambiguous"),
673 (int) name.size (), name.data ());
674 best = item;
678 return best;
681 /* Set focus to the window named by 'arg'. */
682 static void
683 tui_set_focus_command (const char *arg, int from_tty)
685 tui_enable ();
687 if (arg == NULL)
688 error_no_arg (_("name of window to focus"));
690 struct tui_win_info *win_info = NULL;
692 if (startswith ("next", arg))
693 win_info = tui_next_win (tui_win_with_focus ());
694 else if (startswith ("prev", arg))
695 win_info = tui_prev_win (tui_win_with_focus ());
696 else
697 win_info = tui_partial_win_by_name (arg);
699 if (win_info == nullptr)
701 /* When WIN_INFO is nullptr this can either mean that the window name
702 is unknown to GDB, or that the window is not in the current
703 layout. To try and help the user, give a different error
704 depending on which of these is the case. */
705 std::string matching_window_name;
706 bool is_ambiguous = false;
708 for (const std::string &name : all_known_window_names ())
710 /* Look through all windows in the current layout, if the window
711 is in the current layout then we're not interested is it. */
712 for (tui_win_info *item : all_tui_windows ())
713 if (item->name () == name)
714 continue;
716 if (startswith (name, arg))
718 if (matching_window_name.empty ())
719 matching_window_name = name;
720 else
721 is_ambiguous = true;
725 if (!matching_window_name.empty ())
727 if (is_ambiguous)
728 error (_("No windows matching \"%s\" in the current layout"),
729 arg);
730 else
731 error (_("Window \"%s\" is not in the current layout"),
732 matching_window_name.c_str ());
734 else
735 error (_("Unrecognized window name \"%s\""), arg);
738 /* If a window is part of the current layout then it will have a
739 tui_win_info associated with it and be visible, otherwise, there will
740 be no tui_win_info and the above error will have been raised. */
741 gdb_assert (win_info->is_visible ());
743 if (!win_info->can_focus ())
744 error (_("Window \"%s\" cannot be focused"), arg);
746 tui_set_win_focus_to (win_info);
747 gdb_printf (_("Focus set to %s window.\n"),
748 tui_win_with_focus ()->name ());
751 static void
752 tui_all_windows_info (const char *arg, int from_tty)
754 if (!tui_active)
756 gdb_printf (_("The TUI is not active.\n"));
757 return;
760 struct tui_win_info *win_with_focus = tui_win_with_focus ();
761 struct ui_out *uiout = current_uiout;
763 ui_out_emit_table table_emitter (uiout, 4, -1, "tui-windows");
764 uiout->table_header (10, ui_left, "name", "Name");
765 uiout->table_header (5, ui_right, "lines", "Lines");
766 uiout->table_header (7, ui_right, "columns", "Columns");
767 uiout->table_header (10, ui_left, "focus", "Focus");
768 uiout->table_body ();
770 for (tui_win_info *win_info : all_tui_windows ())
771 if (win_info->is_visible ())
773 ui_out_emit_tuple tuple_emitter (uiout, nullptr);
775 uiout->field_string ("name", win_info->name ());
776 uiout->field_signed ("lines", win_info->height);
777 uiout->field_signed ("columns", win_info->width);
778 if (win_with_focus == win_info)
779 uiout->field_string ("focus", _("(has focus)"));
780 else
781 uiout->field_skip ("focus");
782 uiout->text ("\n");
787 static void
788 tui_refresh_all_command (const char *arg, int from_tty)
790 /* Make sure the curses mode is enabled. */
791 tui_enable ();
793 tui_refresh_all_win ();
796 #define DEFAULT_TAB_LEN 8
798 /* The tab width that should be used by the TUI. */
800 unsigned int tui_tab_width = DEFAULT_TAB_LEN;
802 /* The tab width as set by the user. */
804 static unsigned int internal_tab_width = DEFAULT_TAB_LEN;
806 /* After the tab width is set, call this to update the relevant
807 windows. */
809 static void
810 update_tab_width ()
812 for (tui_win_info *win_info : all_tui_windows ())
814 if (win_info->is_visible ())
815 win_info->update_tab_width ();
819 /* Callback for "set tui tab-width". */
821 static void
822 tui_set_tab_width (const char *ignore,
823 int from_tty, struct cmd_list_element *c)
825 if (internal_tab_width == 0)
827 internal_tab_width = tui_tab_width;
828 error (_("Tab width must not be 0"));
831 tui_tab_width = internal_tab_width;
832 update_tab_width ();
835 /* Callback for "show tui tab-width". */
837 static void
838 tui_show_tab_width (struct ui_file *file, int from_tty,
839 struct cmd_list_element *c, const char *value)
841 gdb_printf (file, _("TUI tab width is %s spaces.\n"), value);
845 /* See tui-win.h. */
847 bool compact_source = false;
849 /* Callback for "set tui compact-source". */
851 static void
852 tui_set_compact_source (const char *ignore, int from_tty,
853 struct cmd_list_element *c)
855 if (tui_src_win () != nullptr)
856 tui_src_win ()->refill ();
859 /* Callback for "show tui compact-source". */
861 static void
862 tui_show_compact_source (struct ui_file *file, int from_tty,
863 struct cmd_list_element *c, const char *value)
865 gdb_printf (file, _("TUI source window compactness is %s.\n"), value);
868 bool tui_enable_mouse = true;
870 /* Implement 'show tui mouse-events'. */
872 static void
873 show_tui_mouse_events (struct ui_file *file, int from_tty,
874 struct cmd_list_element *c, const char *value)
876 gdb_printf (file, _("TUI mouse events are %s.\n"), value);
879 /* Set the tab width of the specified window. */
880 static void
881 tui_set_tab_width_command (const char *arg, int from_tty)
883 /* Make sure the curses mode is enabled. */
884 tui_enable ();
885 if (arg != NULL)
887 int ts;
889 ts = atoi (arg);
890 if (ts <= 0)
891 warning (_("Tab widths greater than 0 must be specified."));
892 else
894 internal_tab_width = ts;
895 tui_tab_width = ts;
897 update_tab_width ();
902 /* Helper function for the user commands to adjust a window's width or
903 height. The ARG string contains the command line arguments from the
904 user, which should give the name of a window, and how to adjust the
905 size.
907 When SET_WIDTH_P is true the width of the window is adjusted based on
908 ARG, and when SET_WIDTH_P is false, the height of the window is adjusted
909 based on ARG.
911 On invalid input, or if the size can't be adjusted as requested, then an
912 error is thrown, otherwise, the window sizes are adjusted, and the
913 windows redrawn. */
915 static void
916 tui_set_win_size (const char *arg, bool set_width_p)
918 /* Make sure the curses mode is enabled. */
919 tui_enable ();
920 if (arg == NULL)
921 error_no_arg (_("name of window"));
923 const char *buf = arg;
924 const char *buf_ptr = buf;
925 int new_size;
926 struct tui_win_info *win_info;
928 buf_ptr = skip_to_space (buf_ptr);
930 /* Validate the window name. */
931 std::string_view wname (buf, buf_ptr - buf);
932 win_info = tui_partial_win_by_name (wname);
934 if (win_info == NULL)
935 error (_("Unrecognized window name \"%s\""), arg);
936 if (!win_info->is_visible ())
937 error (_("Window \"%s\" is not visible"), arg);
939 /* Process the size. */
940 buf_ptr = skip_spaces (buf_ptr);
942 if (*buf_ptr != '\0')
944 bool negate = false;
945 bool fixed_size = true;
946 int input_no;;
948 if (*buf_ptr == '+' || *buf_ptr == '-')
950 if (*buf_ptr == '-')
951 negate = true;
952 fixed_size = false;
953 buf_ptr++;
955 input_no = atoi (buf_ptr);
956 if (input_no > 0)
958 if (negate)
959 input_no *= (-1);
960 if (fixed_size)
961 new_size = input_no;
962 else
964 int curr_size;
965 if (set_width_p)
966 curr_size = win_info->width;
967 else
968 curr_size = win_info->height;
969 new_size = curr_size + input_no;
972 /* Now change the window's height, and adjust
973 all other windows around it. */
974 if (set_width_p)
975 tui_adjust_window_width (win_info, new_size);
976 else
977 tui_adjust_window_height (win_info, new_size);
978 tui_update_gdb_sizes ();
980 else
982 if (set_width_p)
983 error (_("Invalid window width specified"));
984 else
985 error (_("Invalid window height specified"));
990 /* Implement the 'tui window height' command (alias 'winheight'). */
992 static void
993 tui_set_win_height_command (const char *arg, int from_tty)
995 /* Pass false as the final argument to set the height. */
996 tui_set_win_size (arg, false);
999 /* Implement the 'tui window width' command (alias 'winwidth'). */
1001 static void
1002 tui_set_win_width_command (const char *arg, int from_tty)
1004 /* Pass true as the final argument to set the width. */
1005 tui_set_win_size (arg, true);
1008 /* See tui-data.h. */
1011 tui_win_info::max_height () const
1013 return tui_term_height ();
1016 /* See tui-data.h. */
1019 tui_win_info::max_width () const
1021 return tui_term_width ();
1024 static void
1025 parse_scrolling_args (const char *arg,
1026 struct tui_win_info **win_to_scroll,
1027 int *num_to_scroll)
1029 if (num_to_scroll)
1030 *num_to_scroll = 0;
1031 *win_to_scroll = tui_win_with_focus ();
1033 /* First set up the default window to scroll, in case there is no
1034 window name arg. */
1035 if (arg != NULL)
1037 char *buf_ptr;
1039 /* Process the number of lines to scroll. */
1040 std::string copy = arg;
1041 buf_ptr = &copy[0];
1042 if (isdigit (*buf_ptr))
1044 char *num_str;
1046 num_str = buf_ptr;
1047 buf_ptr = strchr (buf_ptr, ' ');
1048 if (buf_ptr != NULL)
1050 *buf_ptr = '\0';
1051 if (num_to_scroll)
1052 *num_to_scroll = atoi (num_str);
1053 buf_ptr++;
1055 else if (num_to_scroll)
1056 *num_to_scroll = atoi (num_str);
1059 /* Process the window name if one is specified. */
1060 if (buf_ptr != NULL)
1062 const char *wname;
1064 wname = skip_spaces (buf_ptr);
1066 if (*wname != '\0')
1068 *win_to_scroll = tui_partial_win_by_name (wname);
1070 if (*win_to_scroll == NULL)
1071 error (_("Unrecognized window `%s'"), wname);
1072 if (!(*win_to_scroll)->is_visible ())
1073 error (_("Window is not visible"));
1074 else if (*win_to_scroll == tui_cmd_win ())
1075 *win_to_scroll = *(tui_source_windows ().begin ());
1081 /* The list of 'tui window' sub-commands. */
1083 static cmd_list_element *tui_window_cmds = nullptr;
1085 /* Called to implement 'tui window'. */
1087 static void
1088 tui_window_command (const char *args, int from_tty)
1090 help_list (tui_window_cmds, "tui window ", all_commands, gdb_stdout);
1093 /* See tui-win.h. */
1095 bool tui_left_margin_verbose = false;
1097 /* Function to initialize gdb commands, for tui window
1098 manipulation. */
1100 void _initialize_tui_win ();
1101 void
1102 _initialize_tui_win ()
1104 static struct cmd_list_element *tui_setlist;
1105 static struct cmd_list_element *tui_showlist;
1107 /* Define the classes of commands.
1108 They will appear in the help list in the reverse of this order. */
1109 add_setshow_prefix_cmd ("tui", class_tui,
1110 _("TUI configuration variables."),
1111 _("TUI configuration variables."),
1112 &tui_setlist, &tui_showlist,
1113 &setlist, &showlist);
1115 cmd_list_element *refresh_cmd
1116 = add_cmd ("refresh", class_tui, tui_refresh_all_command,
1117 _("Refresh the terminal display."),
1118 tui_get_cmd_list ());
1119 add_com_alias ("refresh", refresh_cmd, class_tui, 0);
1121 cmd_list_element *tabset_cmd
1122 = add_com ("tabset", class_tui, tui_set_tab_width_command, _("\
1123 Set the width (in characters) of tab stops.\n\
1124 Usage: tabset N"));
1125 deprecate_cmd (tabset_cmd, "set tui tab-width");
1127 /* Setup the 'tui window' list of command. */
1128 add_prefix_cmd ("window", class_tui, tui_window_command,
1129 _("Text User Interface window commands."),
1130 &tui_window_cmds, 1, tui_get_cmd_list ());
1132 cmd_list_element *winheight_cmd
1133 = add_cmd ("height", class_tui, tui_set_win_height_command, _("\
1134 Set or modify the height of a specified window.\n\
1135 Usage: tui window height WINDOW-NAME [+ | -] NUM-LINES\n\
1136 Use \"info win\" to see the names of the windows currently being displayed."),
1137 &tui_window_cmds);
1138 add_com_alias ("winheight", winheight_cmd, class_tui, 0);
1139 add_com_alias ("wh", winheight_cmd, class_tui, 0);
1140 set_cmd_completer (winheight_cmd, winheight_completer);
1142 cmd_list_element *winwidth_cmd
1143 = add_cmd ("width", class_tui, tui_set_win_width_command, _("\
1144 Set or modify the width of a specified window.\n\
1145 Usage: tui window width WINDOW-NAME [+ | -] NUM-LINES\n\
1146 Use \"info win\" to see the names of the windows currently being displayed."),
1147 &tui_window_cmds);
1148 add_com_alias ("winwidth", winwidth_cmd, class_tui, 0);
1149 set_cmd_completer (winwidth_cmd, winheight_completer);
1151 add_info ("win", tui_all_windows_info,
1152 _("List of all displayed windows.\n\
1153 Usage: info win"));
1154 cmd_list_element *focus_cmd
1155 = add_cmd ("focus", class_tui, tui_set_focus_command, _("\
1156 Set focus to named window or next/prev window.\n\
1157 Usage: tui focus [WINDOW-NAME | next | prev]\n\
1158 Use \"info win\" to see the names of the windows currently being displayed."),
1159 tui_get_cmd_list ());
1160 add_com_alias ("focus", focus_cmd, class_tui, 0);
1161 add_com_alias ("fs", focus_cmd, class_tui, 0);
1162 set_cmd_completer (focus_cmd, focus_completer);
1163 add_com ("+", class_tui, tui_scroll_forward_command, _("\
1164 Scroll window forward.\n\
1165 Usage: + [N] [WIN]\n\
1166 Scroll window WIN N lines forwards. Both WIN and N are optional, N\n\
1167 defaults to 1, and WIN defaults to the currently focused window."));
1168 add_com ("-", class_tui, tui_scroll_backward_command, _("\
1169 Scroll window backward.\n\
1170 Usage: - [N] [WIN]\n\
1171 Scroll window WIN N lines backwards. Both WIN and N are optional, N\n\
1172 defaults to 1, and WIN defaults to the currently focused window."));
1173 add_com ("<", class_tui, tui_scroll_left_command, _("\
1174 Scroll window text to the left.\n\
1175 Usage: < [N] [WIN]\n\
1176 Scroll window WIN N characters left. Both WIN and N are optional, N\n\
1177 defaults to 1, and WIN defaults to the currently focused window."));
1178 add_com (">", class_tui, tui_scroll_right_command, _("\
1179 Scroll window text to the right.\n\
1180 Usage: > [N] [WIN]\n\
1181 Scroll window WIN N characters right. Both WIN and N are optional, N\n\
1182 defaults to 1, and WIN defaults to the currently focused window."));
1184 /* Define the tui control variables. */
1185 add_setshow_enum_cmd ("border-kind", no_class, tui_border_kind_enums,
1186 &tui_border_kind, _("\
1187 Set the kind of border for TUI windows."), _("\
1188 Show the kind of border for TUI windows."), _("\
1189 This variable controls the border of TUI windows:\n\
1190 space use a white space\n\
1191 ascii use ascii characters + - | for the border\n\
1192 acs use the Alternate Character Set"),
1193 tui_set_var_cmd,
1194 show_tui_border_kind,
1195 &tui_setlist, &tui_showlist);
1197 const std::string help_attribute_mode (_("\
1198 normal normal display\n\
1199 standout use highlight mode of terminal\n\
1200 reverse use reverse video mode\n\
1201 half use half bright\n\
1202 half-standout use half bright and standout mode\n\
1203 bold use extra bright or bold\n\
1204 bold-standout use extra bright or bold with standout mode"));
1206 const std::string help_tui_border_mode
1207 = (_("\
1208 This variable controls the attributes to use for the window borders:\n")
1209 + help_attribute_mode);
1211 add_setshow_enum_cmd ("border-mode", no_class, tui_border_mode_enums,
1212 &tui_border_mode, _("\
1213 Set the attribute mode to use for the TUI window borders."), _("\
1214 Show the attribute mode to use for the TUI window borders."),
1215 help_tui_border_mode.c_str (),
1216 tui_set_var_cmd,
1217 show_tui_border_mode,
1218 &tui_setlist, &tui_showlist);
1220 const std::string help_tui_active_border_mode
1221 = (_("\
1222 This variable controls the attributes to use for the active window borders:\n")
1223 + help_attribute_mode);
1225 add_setshow_enum_cmd ("active-border-mode", no_class, tui_border_mode_enums,
1226 &tui_active_border_mode, _("\
1227 Set the attribute mode to use for the active TUI window border."), _("\
1228 Show the attribute mode to use for the active TUI window border."),
1229 help_tui_active_border_mode.c_str (),
1230 tui_set_var_cmd,
1231 show_tui_active_border_mode,
1232 &tui_setlist, &tui_showlist);
1234 add_setshow_zuinteger_cmd ("tab-width", no_class,
1235 &internal_tab_width, _("\
1236 Set the tab width, in characters, for the TUI."), _("\
1237 Show the tab width, in characters, for the TUI."), _("\
1238 This variable controls how many spaces are used to display a tab character."),
1239 tui_set_tab_width, tui_show_tab_width,
1240 &tui_setlist, &tui_showlist);
1242 add_setshow_boolean_cmd ("tui-resize-message", class_maintenance,
1243 &resize_message, _("\
1244 Set TUI resize messaging."), _("\
1245 Show TUI resize messaging."), _("\
1246 When enabled GDB will print a message when the terminal is resized."),
1247 nullptr,
1248 show_tui_resize_message,
1249 &maintenance_set_cmdlist,
1250 &maintenance_show_cmdlist);
1252 add_setshow_boolean_cmd ("compact-source", class_tui,
1253 &compact_source, _("\
1254 Set whether the TUI source window is compact."), _("\
1255 Show whether the TUI source window is compact."), _("\
1256 This variable controls whether the TUI source window is shown\n\
1257 in a compact form. The compact form uses less horizontal space."),
1258 tui_set_compact_source, tui_show_compact_source,
1259 &tui_setlist, &tui_showlist);
1261 add_setshow_boolean_cmd ("mouse-events", class_tui,
1262 &tui_enable_mouse, _("\
1263 Set whether TUI mode handles mouse clicks."), _("\
1264 Show whether TUI mode handles mouse clicks."), _("\
1265 When on (default), mouse clicks control the TUI and can be accessed by Python\n\
1266 extensions. When off, mouse clicks are handled by the terminal, enabling\n\
1267 terminal-native text selection."),
1268 nullptr,
1269 show_tui_mouse_events,
1270 &tui_setlist, &tui_showlist);
1272 add_setshow_boolean_cmd ("tui-current-position", class_maintenance,
1273 &style_tui_current_position, _("\
1274 Set whether to style text highlighted by the TUI's current position indicator."),
1275 _("\
1276 Show whether to style text highlighted by the TUI's current position indicator."),
1277 _("\
1278 When enabled, the source and assembly code highlighted by the TUI's current\n\
1279 position indicator is styled."),
1280 set_style_tui_current_position,
1281 show_style_tui_current_position,
1282 &style_set_list,
1283 &style_show_list);
1285 add_setshow_boolean_cmd ("tui-left-margin-verbose", class_maintenance,
1286 &tui_left_margin_verbose, _("\
1287 Set whether the left margin should use '_' and '0' instead of spaces."),
1288 _("\
1289 Show whether the left margin should use '_' and '0' instead of spaces."),
1290 _("\
1291 When enabled, the left margin will use '_' and '0' instead of spaces."),
1292 nullptr,
1293 nullptr,
1294 &maintenance_set_cmdlist,
1295 &maintenance_show_cmdlist);
1297 tui_border_style.changed.attach (tui_rehighlight_all, "tui-win");
1298 tui_active_border_style.changed.attach (tui_rehighlight_all, "tui-win");