tui-win.c revision 1.10 1 /* TUI window generic functions.
2
3 Copyright (C) 1998-2023 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 gdb_printf (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 gdb_printf (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 gdb_printf (file, _("The kind of border for TUI windows is \"%s\".\n"),
218 value);
219 }
220
221 /* Implementation of the "set/show style tui-current-position" commands. */
222
223 bool style_tui_current_position = false;
224
225 static void
226 show_style_tui_current_position (ui_file *file,
227 int from_tty,
228 cmd_list_element *c,
229 const char *value)
230 {
231 gdb_printf (file, _("\
232 Styling the text highlighted by the TUI's current position indicator is %s.\n"),
233 value);
234 }
235
236 static void
237 set_style_tui_current_position (const char *ignore, int from_tty,
238 cmd_list_element *c)
239 {
240 if (TUI_SRC_WIN != nullptr)
241 TUI_SRC_WIN->refill ();
242 if (TUI_DISASM_WIN != nullptr)
243 TUI_DISASM_WIN->refill ();
244 }
245
246 /* Tui internal configuration variables. These variables are updated
247 by tui_update_variables to reflect the tui configuration
248 variables. */
249 chtype tui_border_vline;
250 chtype tui_border_hline;
251 chtype tui_border_ulcorner;
252 chtype tui_border_urcorner;
253 chtype tui_border_llcorner;
254 chtype tui_border_lrcorner;
255
256 int tui_border_attrs;
257 int tui_active_border_attrs;
258
259 /* Identify the item in the translation table.
260 When the item is not recognized, use the default entry. */
261 static struct tui_translate *
262 translate (const char *name, struct tui_translate *table)
263 {
264 while (table->name)
265 {
266 if (name && strcmp (table->name, name) == 0)
267 return table;
268 table++;
269 }
270
271 /* Not found, return default entry. */
272 table++;
273 return table;
274 }
275
276 /* Update the tui internal configuration according to gdb settings.
277 Returns 1 if the configuration has changed and the screen should
278 be redrawn. */
279 bool
280 tui_update_variables ()
281 {
282 bool need_redraw = false;
283 struct tui_translate *entry;
284
285 entry = translate (tui_border_mode, tui_border_mode_translate);
286 if (tui_border_attrs != entry->value)
287 {
288 tui_border_attrs = entry->value;
289 need_redraw = true;
290 }
291 entry = translate (tui_active_border_mode, tui_border_mode_translate);
292 if (tui_active_border_attrs != entry->value)
293 {
294 tui_active_border_attrs = entry->value;
295 need_redraw = true;
296 }
297
298 /* If one corner changes, all characters are changed.
299 Only check the first one. The ACS characters are determined at
300 run time by curses terminal management. */
301 entry = translate (tui_border_kind, tui_border_kind_translate_lrcorner);
302 if (tui_border_lrcorner != (chtype) entry->value)
303 {
304 tui_border_lrcorner = (entry->value < 0) ? ACS_LRCORNER : entry->value;
305 need_redraw = true;
306 }
307 entry = translate (tui_border_kind, tui_border_kind_translate_llcorner);
308 tui_border_llcorner = (entry->value < 0) ? ACS_LLCORNER : entry->value;
309
310 entry = translate (tui_border_kind, tui_border_kind_translate_ulcorner);
311 tui_border_ulcorner = (entry->value < 0) ? ACS_ULCORNER : entry->value;
312
313 entry = translate (tui_border_kind, tui_border_kind_translate_urcorner);
314 tui_border_urcorner = (entry->value < 0) ? ACS_URCORNER : entry->value;
315
316 entry = translate (tui_border_kind, tui_border_kind_translate_hline);
317 tui_border_hline = (entry->value < 0) ? ACS_HLINE : entry->value;
318
319 entry = translate (tui_border_kind, tui_border_kind_translate_vline);
320 tui_border_vline = (entry->value < 0) ? ACS_VLINE : entry->value;
321
322 return need_redraw;
323 }
324
325 static struct cmd_list_element *tuilist;
326
327 struct cmd_list_element **
328 tui_get_cmd_list (void)
329 {
330 if (tuilist == 0)
331 add_basic_prefix_cmd ("tui", class_tui,
332 _("Text User Interface commands."),
333 &tuilist, 0, &cmdlist);
334 return &tuilist;
335 }
336
337 /* The set_func hook of "set tui ..." commands that affect the window
338 borders on the TUI display. */
339
340 static void
341 tui_set_var_cmd (const char *null_args,
342 int from_tty, struct cmd_list_element *c)
343 {
344 if (tui_update_variables () && tui_active)
345 tui_rehighlight_all ();
346 }
347
348
349
351 /* True if TUI resizes should print a message. This is used by the
352 test suite. */
353
354 static bool resize_message;
355
356 static void
357 show_tui_resize_message (struct ui_file *file, int from_tty,
358 struct cmd_list_element *c, const char *value)
359 {
360 gdb_printf (file, _("TUI resize messaging is %s.\n"), value);
361 }
362
363
364
366 /* Generic window name completion function. Complete window name pointed
367 to by TEXT and WORD. If INCLUDE_NEXT_PREV_P is true then the special
368 window names 'next' and 'prev' will also be considered as possible
369 completions of the window name. */
370
371 static void
372 window_name_completer (completion_tracker &tracker,
373 int include_next_prev_p,
374 const char *text, const char *word)
375 {
376 std::vector<const char *> completion_name_vec;
377
378 for (tui_win_info *win_info : all_tui_windows ())
379 {
380 const char *completion_name = NULL;
381
382 /* We can't focus on an invisible window. */
383 if (!win_info->is_visible ())
384 continue;
385
386 completion_name = win_info->name ();
387 gdb_assert (completion_name != NULL);
388 completion_name_vec.push_back (completion_name);
389 }
390
391 /* If no windows are considered visible then the TUI has not yet been
392 initialized. But still "focus src" and "focus cmd" will work because
393 invoking the focus command will entail initializing the TUI which sets the
394 default layout to "src". */
395 if (completion_name_vec.empty ())
396 {
397 completion_name_vec.push_back (SRC_NAME);
398 completion_name_vec.push_back (CMD_NAME);
399 }
400
401 if (include_next_prev_p)
402 {
403 completion_name_vec.push_back ("next");
404 completion_name_vec.push_back ("prev");
405 }
406
407
408 completion_name_vec.push_back (NULL);
409 complete_on_enum (tracker, completion_name_vec.data (), text, word);
410 }
411
412 /* Complete possible window names to focus on. TEXT is the complete text
413 entered so far, WORD is the word currently being completed. */
414
415 static void
416 focus_completer (struct cmd_list_element *ignore,
417 completion_tracker &tracker,
418 const char *text, const char *word)
419 {
420 window_name_completer (tracker, 1, text, word);
421 }
422
423 /* Complete possible window names for winheight command. TEXT is the
424 complete text entered so far, WORD is the word currently being
425 completed. */
426
427 static void
428 winheight_completer (struct cmd_list_element *ignore,
429 completion_tracker &tracker,
430 const char *text, const char *word)
431 {
432 /* The first word is the window name. That we can complete. Subsequent
433 words can't be completed. */
434 if (word != text)
435 return;
436
437 window_name_completer (tracker, 0, text, word);
438 }
439
440 /* Update gdb's knowledge of the terminal size. */
441 void
442 tui_update_gdb_sizes (void)
443 {
444 int width, height;
445
446 if (tui_active)
447 {
448 width = TUI_CMD_WIN->width;
449 height = TUI_CMD_WIN->height;
450 }
451 else
452 {
453 width = tui_term_width ();
454 height = tui_term_height ();
455 }
456
457 set_screen_width_and_height (width, height);
458 }
459
460
461 void
462 tui_win_info::forward_scroll (int num_to_scroll)
463 {
464 if (num_to_scroll == 0)
465 num_to_scroll = height - 3;
466
467 do_scroll_vertical (num_to_scroll);
468 }
469
470 void
471 tui_win_info::backward_scroll (int num_to_scroll)
472 {
473 if (num_to_scroll == 0)
474 num_to_scroll = height - 3;
475
476 do_scroll_vertical (-num_to_scroll);
477 }
478
479
480 void
481 tui_win_info::left_scroll (int num_to_scroll)
482 {
483 if (num_to_scroll == 0)
484 num_to_scroll = 1;
485
486 do_scroll_horizontal (num_to_scroll);
487 }
488
489
490 void
491 tui_win_info::right_scroll (int num_to_scroll)
492 {
493 if (num_to_scroll == 0)
494 num_to_scroll = 1;
495
496 do_scroll_horizontal (-num_to_scroll);
497 }
498
499
500 void
501 tui_refresh_all_win (void)
502 {
503 clearok (curscr, TRUE);
504 tui_refresh_all ();
505 }
506
507 void
508 tui_rehighlight_all (void)
509 {
510 for (tui_win_info *win_info : all_tui_windows ())
511 win_info->check_and_display_highlight_if_needed ();
512 }
513
514 /* Resize all the windows based on the terminal size. This function
515 gets called from within the readline SIGWINCH handler. */
516 void
517 tui_resize_all (void)
518 {
519 int height_diff, width_diff;
520 int screenheight, screenwidth;
521
522 rl_get_screen_size (&screenheight, &screenwidth);
523 width_diff = screenwidth - tui_term_width ();
524 height_diff = screenheight - tui_term_height ();
525 if (height_diff || width_diff)
526 {
527 #ifdef HAVE_RESIZE_TERM
528 resize_term (screenheight, screenwidth);
529 #endif
530 /* Turn keypad off while we resize. */
531 keypad (TUI_CMD_WIN->handle.get (), FALSE);
532 tui_update_gdb_sizes ();
533 tui_set_term_height_to (screenheight);
534 tui_set_term_width_to (screenwidth);
535
536 /* erase + clearok are used instead of a straightforward clear as
537 AIX 5.3 does not define clear. */
538 erase ();
539 clearok (curscr, TRUE);
540 /* Apply the current layout. The 'false' here allows the command
541 window to resize proportionately with containing terminal, rather
542 than maintaining a fixed size. */
543 tui_apply_current_layout (false); /* Turn keypad back on. */
544 keypad (TUI_CMD_WIN->handle.get (), TRUE);
545 }
546 }
547
548 #ifdef SIGWINCH
549 /* Token for use by TUI's asynchronous SIGWINCH handler. */
550 static struct async_signal_handler *tui_sigwinch_token;
551
552 /* TUI's SIGWINCH signal handler. */
553 static void
554 tui_sigwinch_handler (int signal)
555 {
556 mark_async_signal_handler (tui_sigwinch_token);
557 tui_set_win_resized_to (true);
558 }
559
560 /* Callback for asynchronously resizing TUI following a SIGWINCH signal. */
561 static void
562 tui_async_resize_screen (gdb_client_data arg)
563 {
564 rl_resize_terminal ();
565
566 if (!tui_active)
567 {
568 int screen_height, screen_width;
569
570 rl_get_screen_size (&screen_height, &screen_width);
571 set_screen_width_and_height (screen_width, screen_height);
572
573 /* win_resized is left set so that the next call to tui_enable()
574 resizes the TUI windows. */
575 }
576 else
577 {
578 tui_set_win_resized_to (false);
579 tui_resize_all ();
580 tui_refresh_all_win ();
581 tui_update_gdb_sizes ();
582 if (resize_message)
583 {
584 static int count;
585 printf_unfiltered ("@@ resize done %d, size = %dx%d\n", count,
586 tui_term_width (), tui_term_height ());
587 ++count;
588 }
589 tui_redisplay_readline ();
590 }
591 }
592 #endif
593
594 /* Initialize TUI's SIGWINCH signal handler. Note that the handler is not
595 uninstalled when we exit TUI, so the handler should not assume that TUI is
596 always active. */
597 void
598 tui_initialize_win (void)
599 {
600 #ifdef SIGWINCH
601 tui_sigwinch_token
602 = create_async_signal_handler (tui_async_resize_screen, NULL,
603 "tui-sigwinch");
604
605 {
606 #ifdef HAVE_SIGACTION
607 struct sigaction old_winch;
608
609 memset (&old_winch, 0, sizeof (old_winch));
610 old_winch.sa_handler = &tui_sigwinch_handler;
611 #ifdef SA_RESTART
612 old_winch.sa_flags = SA_RESTART;
613 #endif
614 sigaction (SIGWINCH, &old_winch, NULL);
615 #else
616 signal (SIGWINCH, &tui_sigwinch_handler);
617 #endif
618 }
619 #endif
620 }
621
622
623 static void
624 tui_scroll_forward_command (const char *arg, int from_tty)
625 {
626 int num_to_scroll = 1;
627 struct tui_win_info *win_to_scroll;
628
629 /* Make sure the curses mode is enabled. */
630 tui_enable ();
631 if (arg == NULL)
632 parse_scrolling_args (arg, &win_to_scroll, NULL);
633 else
634 parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
635 win_to_scroll->forward_scroll (num_to_scroll);
636 }
637
638
639 static void
640 tui_scroll_backward_command (const char *arg, int from_tty)
641 {
642 int num_to_scroll = 1;
643 struct tui_win_info *win_to_scroll;
644
645 /* Make sure the curses mode is enabled. */
646 tui_enable ();
647 if (arg == NULL)
648 parse_scrolling_args (arg, &win_to_scroll, NULL);
649 else
650 parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
651 win_to_scroll->backward_scroll (num_to_scroll);
652 }
653
654
655 static void
656 tui_scroll_left_command (const char *arg, int from_tty)
657 {
658 int num_to_scroll;
659 struct tui_win_info *win_to_scroll;
660
661 /* Make sure the curses mode is enabled. */
662 tui_enable ();
663 parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
664 win_to_scroll->left_scroll (num_to_scroll);
665 }
666
667
668 static void
669 tui_scroll_right_command (const char *arg, int from_tty)
670 {
671 int num_to_scroll;
672 struct tui_win_info *win_to_scroll;
673
674 /* Make sure the curses mode is enabled. */
675 tui_enable ();
676 parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
677 win_to_scroll->right_scroll (num_to_scroll);
678 }
679
680
681 /* Answer the window represented by name. */
682 static struct tui_win_info *
683 tui_partial_win_by_name (gdb::string_view name)
684 {
685 struct tui_win_info *best = nullptr;
686
687 for (tui_win_info *item : all_tui_windows ())
688 {
689 const char *cur_name = item->name ();
690
691 if (name == cur_name)
692 return item;
693 if (startswith (cur_name, name))
694 {
695 if (best != nullptr)
696 error (_("Window name \"%*s\" is ambiguous"),
697 (int) name.size (), name.data ());
698 best = item;
699 }
700 }
701
702 return best;
703 }
704
705 /* Set focus to the window named by 'arg'. */
706 static void
707 tui_set_focus_command (const char *arg, int from_tty)
708 {
709 tui_enable ();
710
711 if (arg == NULL)
712 error_no_arg (_("name of window to focus"));
713
714 struct tui_win_info *win_info = NULL;
715
716 if (startswith ("next", arg))
717 win_info = tui_next_win (tui_win_with_focus ());
718 else if (startswith ("prev", arg))
719 win_info = tui_prev_win (tui_win_with_focus ());
720 else
721 win_info = tui_partial_win_by_name (arg);
722
723 if (win_info == NULL)
724 error (_("Unrecognized window name \"%s\""), arg);
725 if (!win_info->is_visible ())
726 error (_("Window \"%s\" is not visible"), arg);
727
728 tui_set_win_focus_to (win_info);
729 gdb_printf (_("Focus set to %s window.\n"),
730 tui_win_with_focus ()->name ());
731 }
732
733 static void
734 tui_all_windows_info (const char *arg, int from_tty)
735 {
736 if (!tui_active)
737 {
738 gdb_printf (_("The TUI is not active.\n"));
739 return;
740 }
741
742 struct tui_win_info *win_with_focus = tui_win_with_focus ();
743 struct ui_out *uiout = current_uiout;
744
745 ui_out_emit_table table_emitter (uiout, 4, -1, "tui-windows");
746 uiout->table_header (10, ui_left, "name", "Name");
747 uiout->table_header (5, ui_right, "lines", "Lines");
748 uiout->table_header (7, ui_right, "columns", "Columns");
749 uiout->table_header (10, ui_left, "focus", "Focus");
750 uiout->table_body ();
751
752 for (tui_win_info *win_info : all_tui_windows ())
753 if (win_info->is_visible ())
754 {
755 ui_out_emit_tuple tuple_emitter (uiout, nullptr);
756
757 uiout->field_string ("name", win_info->name ());
758 uiout->field_signed ("lines", win_info->height);
759 uiout->field_signed ("columns", win_info->width);
760 if (win_with_focus == win_info)
761 uiout->field_string ("focus", _("(has focus)"));
762 else
763 uiout->field_skip ("focus");
764 uiout->text ("\n");
765 }
766 }
767
768
769 static void
770 tui_refresh_all_command (const char *arg, int from_tty)
771 {
772 /* Make sure the curses mode is enabled. */
773 tui_enable ();
774
775 tui_refresh_all_win ();
776 }
777
778 #define DEFAULT_TAB_LEN 8
779
780 /* The tab width that should be used by the TUI. */
781
782 unsigned int tui_tab_width = DEFAULT_TAB_LEN;
783
784 /* The tab width as set by the user. */
785
786 static unsigned int internal_tab_width = DEFAULT_TAB_LEN;
787
788 /* After the tab width is set, call this to update the relevant
789 windows. */
790
791 static void
792 update_tab_width ()
793 {
794 for (tui_win_info *win_info : all_tui_windows ())
795 {
796 if (win_info->is_visible ())
797 win_info->update_tab_width ();
798 }
799 }
800
801 /* Callback for "set tui tab-width". */
802
803 static void
804 tui_set_tab_width (const char *ignore,
805 int from_tty, struct cmd_list_element *c)
806 {
807 if (internal_tab_width == 0)
808 {
809 internal_tab_width = tui_tab_width;
810 error (_("Tab width must not be 0"));
811 }
812
813 tui_tab_width = internal_tab_width;
814 update_tab_width ();
815 }
816
817 /* Callback for "show tui tab-width". */
818
819 static void
820 tui_show_tab_width (struct ui_file *file, int from_tty,
821 struct cmd_list_element *c, const char *value)
822 {
823 gdb_printf (file, _("TUI tab width is %s spaces.\n"), value);
824
825 }
826
827 /* See tui-win.h. */
828
829 bool compact_source = false;
830
831 /* Callback for "set tui compact-source". */
832
833 static void
834 tui_set_compact_source (const char *ignore, int from_tty,
835 struct cmd_list_element *c)
836 {
837 if (TUI_SRC_WIN != nullptr)
838 TUI_SRC_WIN->refill ();
839 }
840
841 /* Callback for "show tui compact-source". */
842
843 static void
844 tui_show_compact_source (struct ui_file *file, int from_tty,
845 struct cmd_list_element *c, const char *value)
846 {
847 gdb_printf (file, _("TUI source window compactness is %s.\n"), value);
848 }
849
850 /* Set the tab width of the specified window. */
851 static void
852 tui_set_tab_width_command (const char *arg, int from_tty)
853 {
854 /* Make sure the curses mode is enabled. */
855 tui_enable ();
856 if (arg != NULL)
857 {
858 int ts;
859
860 ts = atoi (arg);
861 if (ts <= 0)
862 warning (_("Tab widths greater than 0 must be specified."));
863 else
864 {
865 internal_tab_width = ts;
866 tui_tab_width = ts;
867
868 update_tab_width ();
869 }
870 }
871 }
872
873 /* Helper function for the user commands to adjust a window's width or
874 height. The ARG string contains the command line arguments from the
875 user, which should give the name of a window, and how to adjust the
876 size.
877
878 When SET_WIDTH_P is true the width of the window is adjusted based on
879 ARG, and when SET_WIDTH_P is false, the height of the window is adjusted
880 based on ARG.
881
882 On invalid input, or if the size can't be adjusted as requested, then an
883 error is thrown, otherwise, the window sizes are adjusted, and the
884 windows redrawn. */
885
886 static void
887 tui_set_win_size (const char *arg, bool set_width_p)
888 {
889 /* Make sure the curses mode is enabled. */
890 tui_enable ();
891 if (arg == NULL)
892 error_no_arg (_("name of window"));
893
894 const char *buf = arg;
895 const char *buf_ptr = buf;
896 int new_size;
897 struct tui_win_info *win_info;
898
899 buf_ptr = skip_to_space (buf_ptr);
900
901 /* Validate the window name. */
902 gdb::string_view wname (buf, buf_ptr - buf);
903 win_info = tui_partial_win_by_name (wname);
904
905 if (win_info == NULL)
906 error (_("Unrecognized window name \"%s\""), arg);
907 if (!win_info->is_visible ())
908 error (_("Window \"%s\" is not visible"), arg);
909
910 /* Process the size. */
911 buf_ptr = skip_spaces (buf_ptr);
912
913 if (*buf_ptr != '\0')
914 {
915 bool negate = false;
916 bool fixed_size = true;
917 int input_no;;
918
919 if (*buf_ptr == '+' || *buf_ptr == '-')
920 {
921 if (*buf_ptr == '-')
922 negate = true;
923 fixed_size = false;
924 buf_ptr++;
925 }
926 input_no = atoi (buf_ptr);
927 if (input_no > 0)
928 {
929 if (negate)
930 input_no *= (-1);
931 if (fixed_size)
932 new_size = input_no;
933 else
934 {
935 int curr_size;
936 if (set_width_p)
937 curr_size = win_info->width;
938 else
939 curr_size = win_info->height;
940 new_size = curr_size + input_no;
941 }
942
943 /* Now change the window's height, and adjust
944 all other windows around it. */
945 if (set_width_p)
946 tui_adjust_window_width (win_info, new_size);
947 else
948 tui_adjust_window_height (win_info, new_size);
949 tui_update_gdb_sizes ();
950 }
951 else
952 {
953 if (set_width_p)
954 error (_("Invalid window width specified"));
955 else
956 error (_("Invalid window height specified"));
957 }
958 }
959 }
960
961 /* Implement the 'tui window height' command (alias 'winheight'). */
962
963 static void
964 tui_set_win_height_command (const char *arg, int from_tty)
965 {
966 /* Pass false as the final argument to set the height. */
967 tui_set_win_size (arg, false);
968 }
969
970 /* Implement the 'tui window width' command (alias 'winwidth'). */
971
972 static void
973 tui_set_win_width_command (const char *arg, int from_tty)
974 {
975 /* Pass true as the final argument to set the width. */
976 tui_set_win_size (arg, true);
977 }
978
979 /* See tui-data.h. */
980
981 int
982 tui_win_info::max_height () const
983 {
984 return tui_term_height ();
985 }
986
987 /* See tui-data.h. */
988
989 int
990 tui_win_info::max_width () const
991 {
992 return tui_term_width ();
993 }
994
995 static void
996 parse_scrolling_args (const char *arg,
997 struct tui_win_info **win_to_scroll,
998 int *num_to_scroll)
999 {
1000 if (num_to_scroll)
1001 *num_to_scroll = 0;
1002 *win_to_scroll = tui_win_with_focus ();
1003
1004 /* First set up the default window to scroll, in case there is no
1005 window name arg. */
1006 if (arg != NULL)
1007 {
1008 char *buf_ptr;
1009
1010 /* Process the number of lines to scroll. */
1011 std::string copy = arg;
1012 buf_ptr = ©[0];
1013 if (isdigit (*buf_ptr))
1014 {
1015 char *num_str;
1016
1017 num_str = buf_ptr;
1018 buf_ptr = strchr (buf_ptr, ' ');
1019 if (buf_ptr != NULL)
1020 {
1021 *buf_ptr = '\0';
1022 if (num_to_scroll)
1023 *num_to_scroll = atoi (num_str);
1024 buf_ptr++;
1025 }
1026 else if (num_to_scroll)
1027 *num_to_scroll = atoi (num_str);
1028 }
1029
1030 /* Process the window name if one is specified. */
1031 if (buf_ptr != NULL)
1032 {
1033 const char *wname;
1034
1035 wname = skip_spaces (buf_ptr);
1036
1037 if (*wname != '\0')
1038 {
1039 *win_to_scroll = tui_partial_win_by_name (wname);
1040
1041 if (*win_to_scroll == NULL)
1042 error (_("Unrecognized window `%s'"), wname);
1043 if (!(*win_to_scroll)->is_visible ())
1044 error (_("Window is not visible"));
1045 else if (*win_to_scroll == TUI_CMD_WIN)
1046 *win_to_scroll = *(tui_source_windows ().begin ());
1047 }
1048 }
1049 }
1050 }
1051
1052 /* The list of 'tui window' sub-commands. */
1053
1054 static cmd_list_element *tui_window_cmds = nullptr;
1055
1056 /* Called to implement 'tui window'. */
1057
1058 static void
1059 tui_window_command (const char *args, int from_tty)
1060 {
1061 help_list (tui_window_cmds, "tui window ", all_commands, gdb_stdout);
1062 }
1063
1064 /* Function to initialize gdb commands, for tui window
1065 manipulation. */
1066
1067 void _initialize_tui_win ();
1068 void
1069 _initialize_tui_win ()
1070 {
1071 static struct cmd_list_element *tui_setlist;
1072 static struct cmd_list_element *tui_showlist;
1073
1074 /* Define the classes of commands.
1075 They will appear in the help list in the reverse of this order. */
1076 add_setshow_prefix_cmd ("tui", class_tui,
1077 _("TUI configuration variables."),
1078 _("TUI configuration variables."),
1079 &tui_setlist, &tui_showlist,
1080 &setlist, &showlist);
1081
1082 cmd_list_element *refresh_cmd
1083 = add_cmd ("refresh", class_tui, tui_refresh_all_command,
1084 _("Refresh the terminal display."),
1085 tui_get_cmd_list ());
1086 add_com_alias ("refresh", refresh_cmd, class_tui, 0);
1087
1088 cmd_list_element *tabset_cmd
1089 = add_com ("tabset", class_tui, tui_set_tab_width_command, _("\
1090 Set the width (in characters) of tab stops.\n\
1091 Usage: tabset N"));
1092 deprecate_cmd (tabset_cmd, "set tui tab-width");
1093
1094 /* Setup the 'tui window' list of command. */
1095 add_prefix_cmd ("window", class_tui, tui_window_command,
1096 _("Text User Interface window commands."),
1097 &tui_window_cmds, 1, tui_get_cmd_list ());
1098
1099 cmd_list_element *winheight_cmd
1100 = add_cmd ("height", class_tui, tui_set_win_height_command, _("\
1101 Set or modify the height of a specified window.\n\
1102 Usage: tui window height WINDOW-NAME [+ | -] NUM-LINES\n\
1103 Use \"info win\" to see the names of the windows currently being displayed."),
1104 &tui_window_cmds);
1105 add_com_alias ("winheight", winheight_cmd, class_tui, 0);
1106 add_com_alias ("wh", winheight_cmd, class_tui, 0);
1107 set_cmd_completer (winheight_cmd, winheight_completer);
1108
1109 cmd_list_element *winwidth_cmd
1110 = add_cmd ("width", class_tui, tui_set_win_width_command, _("\
1111 Set or modify the width of a specified window.\n\
1112 Usage: tui window width WINDOW-NAME [+ | -] NUM-LINES\n\
1113 Use \"info win\" to see the names of the windows currently being displayed."),
1114 &tui_window_cmds);
1115 add_com_alias ("winwidth", winwidth_cmd, class_tui, 0);
1116 set_cmd_completer (winwidth_cmd, winheight_completer);
1117
1118 add_info ("win", tui_all_windows_info,
1119 _("List of all displayed windows.\n\
1120 Usage: info win"));
1121 cmd_list_element *focus_cmd
1122 = add_cmd ("focus", class_tui, tui_set_focus_command, _("\
1123 Set focus to named window or next/prev window.\n\
1124 Usage: tui focus [WINDOW-NAME | next | prev]\n\
1125 Use \"info win\" to see the names of the windows currently being displayed."),
1126 tui_get_cmd_list ());
1127 add_com_alias ("focus", focus_cmd, class_tui, 0);
1128 add_com_alias ("fs", focus_cmd, class_tui, 0);
1129 set_cmd_completer (focus_cmd, focus_completer);
1130 add_com ("+", class_tui, tui_scroll_forward_command, _("\
1131 Scroll window forward.\n\
1132 Usage: + [N] [WIN]\n\
1133 Scroll window WIN N lines forwards. Both WIN and N are optional, N\n\
1134 defaults to 1, and WIN defaults to the currently focused window."));
1135 add_com ("-", class_tui, tui_scroll_backward_command, _("\
1136 Scroll window backward.\n\
1137 Usage: - [N] [WIN]\n\
1138 Scroll window WIN N lines backwards. Both WIN and N are optional, N\n\
1139 defaults to 1, and WIN defaults to the currently focused window."));
1140 add_com ("<", class_tui, tui_scroll_left_command, _("\
1141 Scroll window text to the left.\n\
1142 Usage: < [N] [WIN]\n\
1143 Scroll window WIN N characters left. Both WIN and N are optional, N\n\
1144 defaults to 1, and WIN defaults to the currently focused window."));
1145 add_com (">", class_tui, tui_scroll_right_command, _("\
1146 Scroll window text to the right.\n\
1147 Usage: > [N] [WIN]\n\
1148 Scroll window WIN N characters right. Both WIN and N are optional, N\n\
1149 defaults to 1, and WIN defaults to the currently focused window."));
1150
1151 /* Define the tui control variables. */
1152 add_setshow_enum_cmd ("border-kind", no_class, tui_border_kind_enums,
1153 &tui_border_kind, _("\
1154 Set the kind of border for TUI windows."), _("\
1155 Show the kind of border for TUI windows."), _("\
1156 This variable controls the border of TUI windows:\n\
1157 space use a white space\n\
1158 ascii use ascii characters + - | for the border\n\
1159 acs use the Alternate Character Set"),
1160 tui_set_var_cmd,
1161 show_tui_border_kind,
1162 &tui_setlist, &tui_showlist);
1163
1164 add_setshow_enum_cmd ("border-mode", no_class, tui_border_mode_enums,
1165 &tui_border_mode, _("\
1166 Set the attribute mode to use for the TUI window borders."), _("\
1167 Show the attribute mode to use for the TUI window borders."), _("\
1168 This variable controls the attributes to use for the window borders:\n\
1169 normal normal display\n\
1170 standout use highlight mode of terminal\n\
1171 reverse use reverse video mode\n\
1172 half use half bright\n\
1173 half-standout use half bright and standout mode\n\
1174 bold use extra bright or bold\n\
1175 bold-standout use extra bright or bold with standout mode"),
1176 tui_set_var_cmd,
1177 show_tui_border_mode,
1178 &tui_setlist, &tui_showlist);
1179
1180 add_setshow_enum_cmd ("active-border-mode", no_class, tui_border_mode_enums,
1181 &tui_active_border_mode, _("\
1182 Set the attribute mode to use for the active TUI window border."), _("\
1183 Show the attribute mode to use for the active TUI window border."), _("\
1184 This variable controls the attributes to use for the active window border:\n\
1185 normal normal display\n\
1186 standout use highlight mode of terminal\n\
1187 reverse use reverse video mode\n\
1188 half use half bright\n\
1189 half-standout use half bright and standout mode\n\
1190 bold use extra bright or bold\n\
1191 bold-standout use extra bright or bold with standout mode"),
1192 tui_set_var_cmd,
1193 show_tui_active_border_mode,
1194 &tui_setlist, &tui_showlist);
1195
1196 add_setshow_zuinteger_cmd ("tab-width", no_class,
1197 &internal_tab_width, _("\
1198 Set the tab width, in characters, for the TUI."), _("\
1199 Show the tab witdh, in characters, for the TUI."), _("\
1200 This variable controls how many spaces are used to display a tab character."),
1201 tui_set_tab_width, tui_show_tab_width,
1202 &tui_setlist, &tui_showlist);
1203
1204 add_setshow_boolean_cmd ("tui-resize-message", class_maintenance,
1205 &resize_message, _("\
1206 Set TUI resize messaging."), _("\
1207 Show TUI resize messaging."), _("\
1208 When enabled GDB will print a message when the terminal is resized."),
1209 nullptr,
1210 show_tui_resize_message,
1211 &maintenance_set_cmdlist,
1212 &maintenance_show_cmdlist);
1213
1214 add_setshow_boolean_cmd ("compact-source", class_tui,
1215 &compact_source, _("\
1216 Set whether the TUI source window is compact."), _("\
1217 Show whether the TUI source window is compact."), _("\
1218 This variable controls whether the TUI source window is shown\n\
1219 in a compact form. The compact form puts the source closer to\n\
1220 the line numbers and uses less horizontal space."),
1221 tui_set_compact_source, tui_show_compact_source,
1222 &tui_setlist, &tui_showlist);
1223
1224 add_setshow_boolean_cmd ("tui-current-position", class_maintenance,
1225 &style_tui_current_position, _("\
1226 Set whether to style text highlighted by the TUI's current position indicator."),
1227 _("\
1228 Show whether to style text highlighted by the TUI's current position indicator."),
1229 _("\
1230 When enabled, the source and assembly code highlighted by the TUI's current\n\
1231 position indicator is styled."),
1232 set_style_tui_current_position,
1233 show_style_tui_current_position,
1234 &style_set_list,
1235 &style_show_list);
1236
1237 tui_border_style.changed.attach (tui_rehighlight_all, "tui-win");
1238 tui_active_border_style.changed.attach (tui_rehighlight_all, "tui-win");
1239 }
1240