1 /* TUI support I/O functions.
3 Copyright (C) 1998-2022 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/>. */
24 #include "gdbsupport/event-loop.h"
25 #include "event-top.h"
29 #include "tui/tui-data.h"
30 #include "tui/tui-io.h"
31 #include "tui/tui-command.h"
32 #include "tui/tui-win.h"
33 #include "tui/tui-wingeneral.h"
34 #include "tui/tui-file.h"
35 #include "tui/tui-out.h"
43 #include "gdbsupport/filestuff.h"
44 #include "completer.h"
45 #include "gdb_curses.h"
49 /* This redefines CTRL if it is not already defined, so it must come
50 after terminal state releated include files like <term.h> and
52 #include "readline/readline.h"
55 static SHORT ncurses_norm_attr
;
58 static int tui_getc (FILE *fp
);
61 key_is_start_sequence (int ch
)
66 /* Use definition from readline 4.3. */
68 #define CTRL_CHAR(c) \
69 ((c) < control_character_threshold && (((c) & 0x80) == 0))
71 /* This file controls the IO interactions between gdb and curses.
72 When the TUI is enabled, gdb has two modes a curses and a standard
75 In curses mode, the gdb outputs are made in a curses command
76 window. For this, the gdb_stdout and gdb_stderr are redirected to
77 the specific ui_file implemented by TUI. The output is handled by
78 tui_puts(). The input is also controlled by curses with
79 tui_getc(). The readline library uses this function to get its
80 input. Several readline hooks are installed to redirect readline
81 output to the TUI (see also the note below).
83 In normal mode, the gdb outputs are restored to their origin, that
84 is as if TUI is not used. Readline also uses its original getc()
87 Note SCz/2001-07-21: the current readline is not clean in its
88 management of the output. Even if we install a redisplay handler,
89 it sometimes writes on a stdout file. It is important to redirect
90 every output produced by readline, otherwise the curses window will
91 be garbled. This is implemented with a pipe that TUI reads and
92 readline writes to. A gdb input handler is created so that reading
93 the pipe is handled automatically. This will probably not work on
94 non-Unix platforms. The best fix is to make readline clean enough
95 so that is never write on stdout.
97 Note SCz/2002-09-01: we now use more readline hooks and it seems
98 that with them we don't need the pipe anymore (verified by creating
99 the pipe and closing its end so that write causes a SIGPIPE). The
100 old pipe code is still there and can be conditionally removed by
101 #undef TUI_USE_PIPE_FOR_READLINE. */
103 /* For gdb 5.3, prefer to continue the pipe hack as a backup wheel. */
105 #define TUI_USE_PIPE_FOR_READLINE
107 /* #undef TUI_USE_PIPE_FOR_READLINE */
109 /* TUI output files. */
110 static struct ui_file
*tui_stdout
;
111 static struct ui_file
*tui_stderr
;
112 static struct ui_file
*tui_stdlog
;
113 struct ui_out
*tui_out
;
115 /* GDB output files in non-curses mode. */
116 static struct ui_file
*tui_old_stdout
;
117 static struct ui_file
*tui_old_stderr
;
118 static struct ui_file
*tui_old_stdlog
;
119 cli_ui_out
*tui_old_uiout
;
121 /* Readline previous hooks. */
122 static rl_getc_func_t
*tui_old_rl_getc_function
;
123 static rl_voidfunc_t
*tui_old_rl_redisplay_function
;
124 static rl_vintfunc_t
*tui_old_rl_prep_terminal
;
125 static rl_voidfunc_t
*tui_old_rl_deprep_terminal
;
126 static rl_compdisp_func_t
*tui_old_rl_display_matches_hook
;
127 static int tui_old_rl_echoing_p
;
129 /* Readline output stream.
130 Should be removed when readline is clean. */
131 static FILE *tui_rl_outstream
;
132 static FILE *tui_old_rl_outstream
;
133 #ifdef TUI_USE_PIPE_FOR_READLINE
134 static int tui_readline_pipe
[2];
137 /* Print a character in the curses command window. The output is
138 buffered. It is up to the caller to refresh the screen if
142 do_tui_putc (WINDOW
*w
, char c
)
144 /* Expand TABs, since ncurses on MS-Windows doesn't. */
155 while ((col
% 8) != 0);
161 /* Update the cached value of the command window's start line based on
162 the window's current Y coordinate. */
165 update_cmdwin_start_line ()
167 TUI_CMD_WIN
->start_line
= getcury (TUI_CMD_WIN
->handle
.get ());
170 /* Print a character in the curses command window. The output is
171 buffered. It is up to the caller to refresh the screen if
177 do_tui_putc (TUI_CMD_WIN
->handle
.get (), c
);
178 update_cmdwin_start_line ();
181 /* This maps colors to their corresponding color index. */
183 static std::map
<ui_file_style::color
, int> color_map
;
185 /* This holds a pair of colors and is used to track the mapping
186 between a color pair index and the actual colors. */
193 bool operator< (const color_pair
&o
) const
195 return fg
< o
.fg
|| (fg
== o
.fg
&& bg
< o
.bg
);
199 /* This maps pairs of colors to their corresponding color pair
202 static std::map
<color_pair
, int> color_pair_map
;
204 /* This is indexed by ANSI color offset from the base color, and holds
205 the corresponding curses color constant. */
207 static const int curses_colors
[] = {
218 /* Given a color, find its index. */
221 get_color (const ui_file_style::color
&color
, int *result
)
223 if (color
.is_none ())
225 else if (color
.is_basic ())
226 *result
= curses_colors
[color
.get_value ()];
229 auto it
= color_map
.find (color
);
230 if (it
== color_map
.end ())
232 /* The first 8 colors are standard. */
233 int next
= color_map
.size () + 8;
238 /* We store RGB as 0..255, but curses wants 0..1000. */
239 if (init_color (next
, rgb
[0] * 1000 / 255, rgb
[1] * 1000 / 255,
240 rgb
[2] * 1000 / 255) == ERR
)
242 color_map
[color
] = next
;
246 *result
= it
->second
;
251 /* The most recently emitted color pair. */
253 static int last_color_pair
= -1;
255 /* The most recently applied style. */
257 static ui_file_style last_style
;
259 /* If true, we're highlighting the current source line in reverse
261 static bool reverse_mode_p
= false;
263 /* The background/foreground colors before we entered reverse
265 static ui_file_style::color
reverse_save_bg (ui_file_style::NONE
);
266 static ui_file_style::color
reverse_save_fg (ui_file_style::NONE
);
268 /* Given two colors, return their color pair index; making a new one
272 get_color_pair (int fg
, int bg
)
274 color_pair c
= { fg
, bg
};
275 auto it
= color_pair_map
.find (c
);
276 if (it
== color_pair_map
.end ())
278 /* Color pair 0 is our default color, so new colors start at
280 int next
= color_pair_map
.size () + 1;
281 /* Curses has a limited number of available color pairs. Fall
282 back to the default if we've used too many. */
283 if (next
>= COLOR_PAIRS
)
285 init_pair (next
, fg
, bg
);
286 color_pair_map
[c
] = next
;
292 /* Apply STYLE to W. */
295 tui_apply_style (WINDOW
*w
, ui_file_style style
)
298 wattron (w
, A_NORMAL
);
299 wattroff (w
, A_BOLD
);
301 wattroff (w
, A_REVERSE
);
302 if (last_color_pair
!= -1)
303 wattroff (w
, COLOR_PAIR (last_color_pair
));
304 wattron (w
, COLOR_PAIR (0));
306 const ui_file_style::color
&fg
= style
.get_foreground ();
307 const ui_file_style::color
&bg
= style
.get_background ();
308 if (!fg
.is_none () || !bg
.is_none ())
311 if (get_color (fg
, &fgi
) && get_color (bg
, &bgi
))
314 /* MS-Windows port of ncurses doesn't support implicit
315 default foreground and background colors, so we must
316 specify them explicitly when needed, using the colors we
319 fgi
= ncurses_norm_attr
& 15;
321 bgi
= (ncurses_norm_attr
>> 4) & 15;
323 int pair
= get_color_pair (fgi
, bgi
);
324 if (last_color_pair
!= -1)
325 wattroff (w
, COLOR_PAIR (last_color_pair
));
326 wattron (w
, COLOR_PAIR (pair
));
327 last_color_pair
= pair
;
331 switch (style
.get_intensity ())
333 case ui_file_style::NORMAL
:
336 case ui_file_style::BOLD
:
340 case ui_file_style::DIM
:
345 gdb_assert_not_reached ("invalid intensity");
348 if (style
.is_reverse ())
349 wattron (w
, A_REVERSE
);
354 /* Apply an ANSI escape sequence from BUF to W. BUF must start with
355 the ESC character. If BUF does not start with an ANSI escape,
356 return 0. Otherwise, apply the sequence if it is recognized, or
357 simply ignore it if not. In this case, the number of bytes read
358 from BUF is returned. */
361 apply_ansi_escape (WINDOW
*w
, const char *buf
)
363 ui_file_style style
= last_style
;
366 if (!style
.parse (buf
, &n_read
))
371 /* We want to reverse _only_ the default foreground/background
372 colors. If the foreground color is not the default (because
373 the text was styled), we want to leave it as is. If e.g.,
374 the terminal is fg=BLACK, and bg=WHITE, and the style wants
375 to print text in RED, we want to reverse the background color
376 (print in BLACK), but still print the text in RED. To do
377 that, we enable the A_REVERSE attribute, and re-reverse the
378 parsed-style's fb/bg colors.
380 Notes on the approach:
382 - there's no portable way to know which colors the default
385 - this approach does the right thing even if you change the
386 terminal colors while GDB is running -- the reversed
387 colors automatically adapt.
389 if (!style
.is_default ())
391 ui_file_style::color bg
= style
.get_background ();
392 ui_file_style::color fg
= style
.get_foreground ();
397 /* Enable A_REVERSE. */
398 style
.set_reverse (true);
401 tui_apply_style (w
, style
);
408 tui_set_reverse_mode (WINDOW
*w
, bool reverse
)
410 ui_file_style style
= last_style
;
412 reverse_mode_p
= reverse
;
413 style
.set_reverse (reverse
);
417 reverse_save_bg
= style
.get_background ();
418 reverse_save_fg
= style
.get_foreground ();
422 style
.set_bg (reverse_save_bg
);
423 style
.set_fg (reverse_save_fg
);
426 tui_apply_style (w
, style
);
429 /* Print LENGTH characters from the buffer pointed to by BUF to the
430 curses command window. The output is buffered. It is up to the
431 caller to refresh the screen if necessary. */
434 tui_write (const char *buf
, size_t length
)
436 /* We need this to be \0-terminated for the regexp matching. */
437 std::string
copy (buf
, length
);
438 tui_puts (copy
.c_str ());
441 /* Print a string in the curses command window. The output is
442 buffered. It is up to the caller to refresh the screen if
446 tui_puts (const char *string
, WINDOW
*w
)
449 w
= TUI_CMD_WIN
->handle
.get ();
453 const char *next
= strpbrk (string
, "\n\1\2\033\t");
455 /* Print the plain text prefix. */
456 size_t n_chars
= next
== nullptr ? strlen (string
) : next
- string
;
458 waddnstr (w
, string
, n_chars
);
469 /* Ignore these, they are readline escape-marking
482 size_t bytes_read
= apply_ansi_escape (w
, next
);
487 /* Just drop the escape. */
494 gdb_assert_not_reached ("missing case in tui_puts");
500 if (TUI_CMD_WIN
!= nullptr && w
== TUI_CMD_WIN
->handle
.get ())
501 update_cmdwin_start_line ();
505 tui_puts_internal (WINDOW
*w
, const char *string
, int *height
)
511 while ((c
= *string
++) != 0)
516 if (c
== '\1' || c
== '\2')
518 /* Ignore these, they are readline escape-marking
525 size_t bytes_read
= apply_ansi_escape (w
, string
- 1);
528 string
= string
+ bytes_read
- 1;
534 if (height
!= nullptr)
536 int col
= getcurx (w
);
543 if (TUI_CMD_WIN
!= nullptr && w
== TUI_CMD_WIN
->handle
.get ())
544 update_cmdwin_start_line ();
549 /* Readline callback.
550 Redisplay the command line with its prompt after readline has
551 changed the edited text. */
553 tui_redisplay_readline (void)
565 /* Detect when we temporarily left SingleKey and now the readline
566 edit buffer is empty, automatically restore the SingleKey
567 mode. The restore must only be done if the command has finished.
568 The command could call prompt_for_continue and we must not
569 restore SingleKey so that the prompt and normal keymap are used. */
570 if (tui_current_key_mode
== TUI_ONE_COMMAND_MODE
&& rl_end
== 0
571 && !gdb_in_secondary_prompt_p (current_ui
))
572 tui_set_key_mode (TUI_SINGLE_KEY_MODE
);
574 if (tui_current_key_mode
== TUI_SINGLE_KEY_MODE
)
577 prompt
= rl_display_prompt
;
581 w
= TUI_CMD_WIN
->handle
.get ();
582 start_line
= TUI_CMD_WIN
->start_line
;
583 wmove (w
, start_line
, 0);
586 if (prompt
!= nullptr)
587 tui_puts_internal (w
, prompt
, &height
);
589 prev_col
= getcurx (w
);
590 for (in
= 0; in
<= rl_end
; in
++)
596 getyx (w
, c_line
, c_pos
);
602 c
= (unsigned char) rl_line_buffer
[in
];
603 if (CTRL_CHAR (c
) || c
== RUBOUT
)
606 waddch (w
, CTRL_CHAR (c
) ? UNCTRL (c
) : '?');
610 /* Expand TABs, since ncurses on MS-Windows doesn't. */
616 } while ((col
% 8) != 0);
623 TUI_CMD_WIN
->start_line
= getcury (w
);
630 TUI_CMD_WIN
->start_line
= getcury (w
);
632 wmove (w
, c_line
, c_pos
);
633 TUI_CMD_WIN
->start_line
-= height
- 1;
639 /* Readline callback to prepare the terminal. It is called once each
640 time we enter readline. Terminal is already setup in curses
643 tui_prep_terminal (int notused1
)
645 #ifdef NCURSES_MOUSE_VERSION
646 mousemask (ALL_MOUSE_EVENTS
, NULL
);
650 /* Readline callback to restore the terminal. It is called once each
651 time we leave readline. There is nothing to do in curses mode. */
653 tui_deprep_terminal (void)
655 #ifdef NCURSES_MOUSE_VERSION
660 #ifdef TUI_USE_PIPE_FOR_READLINE
661 /* Read readline output pipe and feed the command window with it.
662 Should be removed when readline is clean. */
664 tui_readline_output (int error
, gdb_client_data data
)
669 size
= read (tui_readline_pipe
[0], buf
, sizeof (buf
) - 1);
670 if (size
> 0 && tui_active
)
678 /* TUI version of displayer.crlf. */
681 tui_mld_crlf (const struct match_list_displayer
*displayer
)
686 /* TUI version of displayer.putch. */
689 tui_mld_putch (const struct match_list_displayer
*displayer
, int ch
)
694 /* TUI version of displayer.puts. */
697 tui_mld_puts (const struct match_list_displayer
*displayer
, const char *s
)
702 /* TUI version of displayer.flush. */
705 tui_mld_flush (const struct match_list_displayer
*displayer
)
707 wrefresh (TUI_CMD_WIN
->handle
.get ());
710 /* TUI version of displayer.erase_entire_line. */
713 tui_mld_erase_entire_line (const struct match_list_displayer
*displayer
)
715 WINDOW
*w
= TUI_CMD_WIN
->handle
.get ();
716 int cur_y
= getcury (w
);
723 /* TUI version of displayer.beep. */
726 tui_mld_beep (const struct match_list_displayer
*displayer
)
731 /* A wrapper for wgetch that enters nonl mode. We We normally want
732 curses' "nl" mode, but when reading from the user, we'd like to
733 differentiate between C-j and C-m, because some users bind these
734 keys differently in their .inputrc. So, put curses into nonl mode
735 just when reading from the user. See PR tui/20819. */
738 gdb_wgetch (WINDOW
*win
)
741 int r
= wgetch (win
);
746 /* Helper function for tui_mld_read_key.
747 This temporarily replaces tui_getc for use during tab-completion
748 match list display. */
751 tui_mld_getc (FILE *fp
)
753 WINDOW
*w
= TUI_CMD_WIN
->handle
.get ();
754 int c
= gdb_wgetch (w
);
759 /* TUI version of displayer.read_key. */
762 tui_mld_read_key (const struct match_list_displayer
*displayer
)
764 rl_getc_func_t
*prev
= rl_getc_function
;
767 /* We can't use tui_getc as we need NEWLINE to not get emitted. */
768 rl_getc_function
= tui_mld_getc
;
770 rl_getc_function
= prev
;
774 /* TUI version of rl_completion_display_matches_hook.
775 See gdb_display_match_list for a description of the arguments. */
778 tui_rl_display_match_list (char **matches
, int len
, int max
)
780 struct match_list_displayer displayer
;
782 rl_get_screen_size (&displayer
.height
, &displayer
.width
);
783 displayer
.crlf
= tui_mld_crlf
;
784 displayer
.putch
= tui_mld_putch
;
785 displayer
.puts
= tui_mld_puts
;
786 displayer
.flush
= tui_mld_flush
;
787 displayer
.erase_entire_line
= tui_mld_erase_entire_line
;
788 displayer
.beep
= tui_mld_beep
;
789 displayer
.read_key
= tui_mld_read_key
;
791 gdb_display_match_list (matches
, len
, max
, &displayer
);
794 /* Setup the IO for curses or non-curses mode.
795 - In non-curses mode, readline and gdb use the standard input and
796 standard output/error directly.
797 - In curses mode, the standard output/error is controlled by TUI
798 with the tui_stdout and tui_stderr. The output is redirected in
799 the curses command window. Several readline callbacks are installed
800 so that readline asks for its input to the curses command window
803 tui_setup_io (int mode
)
805 extern int _rl_echoing_p
;
809 /* Ensure that readline has been initialized before saving any
811 tui_ensure_readline_initialized ();
813 /* Redirect readline to TUI. */
814 tui_old_rl_redisplay_function
= rl_redisplay_function
;
815 tui_old_rl_deprep_terminal
= rl_deprep_term_function
;
816 tui_old_rl_prep_terminal
= rl_prep_term_function
;
817 tui_old_rl_getc_function
= rl_getc_function
;
818 tui_old_rl_display_matches_hook
= rl_completion_display_matches_hook
;
819 tui_old_rl_outstream
= rl_outstream
;
820 tui_old_rl_echoing_p
= _rl_echoing_p
;
821 rl_redisplay_function
= tui_redisplay_readline
;
822 rl_deprep_term_function
= tui_deprep_terminal
;
823 rl_prep_term_function
= tui_prep_terminal
;
824 rl_getc_function
= tui_getc
;
826 rl_outstream
= tui_rl_outstream
;
828 rl_completion_display_matches_hook
= tui_rl_display_match_list
;
829 rl_already_prompted
= 0;
831 /* Keep track of previous gdb output. */
832 tui_old_stdout
= gdb_stdout
;
833 tui_old_stderr
= gdb_stderr
;
834 tui_old_stdlog
= gdb_stdlog
;
835 tui_old_uiout
= dynamic_cast<cli_ui_out
*> (current_uiout
);
836 gdb_assert (tui_old_uiout
!= nullptr);
838 /* Reconfigure gdb output. */
839 gdb_stdout
= tui_stdout
;
840 gdb_stderr
= tui_stderr
;
841 gdb_stdlog
= tui_stdlog
;
842 gdb_stdtarg
= gdb_stderr
; /* for moment */
843 gdb_stdtargerr
= gdb_stderr
; /* for moment */
844 current_uiout
= tui_out
;
846 /* Save tty for SIGCONT. */
851 /* Restore gdb output. */
852 gdb_stdout
= tui_old_stdout
;
853 gdb_stderr
= tui_old_stderr
;
854 gdb_stdlog
= tui_old_stdlog
;
855 gdb_stdtarg
= gdb_stderr
; /* for moment */
856 gdb_stdtargerr
= gdb_stderr
; /* for moment */
857 current_uiout
= tui_old_uiout
;
859 /* Restore readline. */
860 rl_redisplay_function
= tui_old_rl_redisplay_function
;
861 rl_deprep_term_function
= tui_old_rl_deprep_terminal
;
862 rl_prep_term_function
= tui_old_rl_prep_terminal
;
863 rl_getc_function
= tui_old_rl_getc_function
;
864 rl_completion_display_matches_hook
= tui_old_rl_display_matches_hook
;
865 rl_outstream
= tui_old_rl_outstream
;
866 _rl_echoing_p
= tui_old_rl_echoing_p
;
867 rl_already_prompted
= 0;
869 /* Save tty for SIGCONT. */
872 /* Clean up color information. */
873 last_color_pair
= -1;
874 last_style
= ui_file_style ();
876 color_pair_map
.clear ();
881 /* Catch SIGCONT to restore the terminal and refresh the screen. */
883 tui_cont_sig (int sig
)
887 /* Restore the terminal setting because another process (shell)
888 might have changed it. */
891 /* Force a refresh of the screen. */
892 tui_refresh_all_win ();
894 signal (sig
, tui_cont_sig
);
898 /* Initialize the IO for gdb in curses mode. */
900 tui_initialize_io (void)
903 signal (SIGCONT
, tui_cont_sig
);
906 /* Create tui output streams. */
907 tui_stdout
= new pager_file (new tui_file (stdout
));
908 tui_stderr
= new tui_file (stderr
);
909 tui_stdlog
= new timestamped_file (tui_stderr
);
910 tui_out
= tui_out_new (tui_stdout
);
912 /* Create the default UI. */
913 tui_old_uiout
= cli_out_new (gdb_stdout
);
915 #ifdef TUI_USE_PIPE_FOR_READLINE
916 /* Temporary solution for readline writing to stdout: redirect
917 readline output in a pipe, read that pipe and output the content
918 in the curses command window. */
919 if (gdb_pipe_cloexec (tui_readline_pipe
) != 0)
920 error (_("Cannot create pipe for readline"));
922 tui_rl_outstream
= fdopen (tui_readline_pipe
[1], "w");
923 if (tui_rl_outstream
== 0)
924 error (_("Cannot redirect readline output"));
926 setvbuf (tui_rl_outstream
, NULL
, _IOLBF
, 0);
929 (void) fcntl (tui_readline_pipe
[0], F_SETFL
, O_NONBLOCK
);
932 (void) fcntl (tui_readline_pipe
[0], F_SETFL
, O_NDELAY
);
935 add_file_handler (tui_readline_pipe
[0], tui_readline_output
, 0, "tui");
937 tui_rl_outstream
= stdout
;
941 /* MS-Windows port of ncurses doesn't support default foreground and
942 background colors, so we must record the default colors at startup. */
943 HANDLE hstdout
= (HANDLE
)_get_osfhandle (fileno (stdout
));
945 CONSOLE_SCREEN_BUFFER_INFO csbi
;
947 if (hstdout
!= INVALID_HANDLE_VALUE
948 && GetConsoleMode (hstdout
, &cmode
) != 0
949 && GetConsoleScreenBufferInfo (hstdout
, &csbi
))
950 ncurses_norm_attr
= csbi
.wAttributes
;
954 /* Dispatch the correct tui function based upon the mouse event. */
956 #ifdef NCURSES_MOUSE_VERSION
959 tui_dispatch_mouse_event ()
962 if (getmouse (&mev
) != OK
)
965 for (tui_win_info
*wi
: all_tui_windows ())
966 if (mev
.x
> wi
->x
&& mev
.x
< wi
->x
+ wi
->width
- 1
967 && mev
.y
> wi
->y
&& mev
.y
< wi
->y
+ wi
->height
- 1)
969 if ((mev
.bstate
& BUTTON1_CLICKED
) != 0
970 || (mev
.bstate
& BUTTON2_CLICKED
) != 0
971 || (mev
.bstate
& BUTTON3_CLICKED
) != 0)
973 int button
= (mev
.bstate
& BUTTON1_CLICKED
) != 0 ? 1
974 : ((mev
.bstate
& BUTTON2_CLICKED
) != 0 ? 2
976 wi
->click (mev
.x
- wi
->x
- 1, mev
.y
- wi
->y
- 1, button
);
978 #ifdef BUTTON5_PRESSED
979 else if ((mev
.bstate
& BUTTON4_PRESSED
) != 0)
980 wi
->backward_scroll (3);
981 else if ((mev
.bstate
& BUTTON5_PRESSED
) != 0)
982 wi
->forward_scroll (3);
990 /* Dispatch the correct tui function based upon the control
993 tui_dispatch_ctrl_char (unsigned int ch
)
995 struct tui_win_info
*win_info
= tui_win_with_focus ();
997 /* If no window has the focus, or if the focus window can't scroll,
998 just pass the character through. */
999 if (win_info
== NULL
|| !win_info
->can_scroll ())
1005 win_info
->forward_scroll (0);
1008 win_info
->backward_scroll (0);
1012 win_info
->forward_scroll (1);
1016 win_info
->backward_scroll (1);
1019 win_info
->left_scroll (1);
1022 win_info
->right_scroll (1);
1025 /* We didn't recognize the character as a control character, so pass it
1030 /* We intercepted the control character, so return 0 (which readline
1031 will interpret as a no-op). */
1038 tui_inject_newline_into_command_window ()
1040 gdb_assert (tui_active
);
1042 WINDOW
*w
= TUI_CMD_WIN
->handle
.get ();
1044 /* When hitting return with an empty input, gdb executes the last
1045 command. If we emit a newline, this fills up the command window
1046 with empty lines with gdb prompt at beginning. Instead of that,
1047 stay on the same line but provide a visual effect to show the
1048 user we recognized the command. */
1049 if (rl_end
== 0 && !gdb_in_secondary_prompt_p (current_ui
))
1051 wmove (w
, getcury (w
), 0);
1053 /* Clear the line. This will blink the gdb prompt since
1054 it will be redrawn at the same line. */
1061 /* Move cursor to the end of the command line before emitting the
1062 newline. We need to do so because when ncurses outputs a newline
1063 it truncates any text that appears past the end of the cursor. */
1066 px
+= rl_end
- rl_point
;
1067 py
+= px
/ TUI_CMD_WIN
->width
;
1068 px
%= TUI_CMD_WIN
->width
;
1074 /* If we're passing an escape sequence to readline, this points to a
1075 string holding the remaining characters of the sequence to pass.
1076 We advance the pointer one character at a time until '\0' is
1078 static const char *cur_seq
= nullptr;
1080 /* Set CUR_SEQ to point at the current sequence to pass to readline,
1081 setup to call the input handler again so we complete the sequence
1082 shortly, and return the first character to start the sequence. */
1085 start_sequence (const char *seq
)
1087 call_stdin_event_handler_again_p
= 1;
1092 /* Main worker for tui_getc. Get a character from the command window.
1093 This is called from the readline package, but wrapped in a
1094 try/catch by tui_getc. */
1097 tui_getc_1 (FILE *fp
)
1102 w
= TUI_CMD_WIN
->handle
.get ();
1104 #ifdef TUI_USE_PIPE_FOR_READLINE
1105 /* Flush readline output. */
1106 tui_readline_output (0, 0);
1109 /* We enable keypad mode so that curses's wgetch processes mouse
1110 escape sequences. In keypad mode, wgetch also processes the
1111 escape sequences for keys such as up/down etc. and returns KEY_UP
1112 / KEY_DOWN etc. When we have the focus on the command window
1113 though, we want to pass the raw up/down etc. escape codes to
1114 readline so readline understands them. */
1115 if (cur_seq
!= nullptr)
1119 /* If we've reached the end of the string, we're done with the
1120 sequence. Otherwise, setup to get back here again for
1121 another character. */
1122 if (*cur_seq
== '\0')
1125 call_stdin_event_handler_again_p
= 1;
1129 ch
= gdb_wgetch (w
);
1131 /* Handle prev/next/up/down here. */
1132 ch
= tui_dispatch_ctrl_char (ch
);
1134 #ifdef NCURSES_MOUSE_VERSION
1135 if (ch
== KEY_MOUSE
)
1137 tui_dispatch_mouse_event ();
1142 /* Translate curses keys back to escape sequences so that readline
1143 can understand them. We do this irrespective of which window has
1144 the focus. If e.g., we're focused on a non-command window, then
1145 the up/down keys will already have been filtered by
1146 tui_dispatch_ctrl_char. Keys that haven't been intercepted will
1147 be passed down to readline. */
1148 if (current_ui
->command_editing
)
1150 /* For the standard arrow keys + home/end, hardcode sequences
1151 readline understands. See bind_arrow_keys_internal in
1152 readline/readline.c. */
1156 return start_sequence ("\033[A");
1158 return start_sequence ("\033[B");
1160 return start_sequence ("\033[C");
1162 return start_sequence ("\033[D");
1164 return start_sequence ("\033[H");
1166 return start_sequence ("\033[F");
1168 /* del and ins are unfortunately not hardcoded in readline for
1171 case KEY_DC
: /* del */
1173 return start_sequence ("\340S");
1175 return start_sequence ("\033[3~");
1178 case KEY_IC
: /* ins */
1179 #if defined __MINGW32__
1180 return start_sequence ("\340R");
1182 return start_sequence ("\033[2~");
1186 /* Keycodes above KEY_MAX are not garanteed to be stable.
1187 Compare keyname instead. */
1190 auto name
= gdb::string_view (keyname (ch
));
1192 /* The following sequences are hardcoded in readline as
1195 /* ctrl-arrow keys */
1196 if (name
== "kLFT5") /* ctrl-left */
1197 return start_sequence ("\033[1;5D");
1198 else if (name
== "kRIT5") /* ctrl-right */
1199 return start_sequence ("\033[1;5C");
1200 else if (name
== "kDC5") /* ctrl-del */
1201 return start_sequence ("\033[3;5~");
1203 /* alt-arrow keys */
1204 else if (name
== "kLFT3") /* alt-left */
1205 return start_sequence ("\033[1;3D");
1206 else if (name
== "kRIT3") /* alt-right */
1207 return start_sequence ("\033[1;3C");
1211 /* Handle the CTRL-L refresh for each window. */
1214 tui_refresh_all_win ();
1218 if (ch
== KEY_BACKSPACE
)
1221 if (current_ui
->command_editing
&& key_is_start_sequence (ch
))
1226 ch_pending
= gdb_wgetch (w
);
1229 /* If we have pending input following a start sequence, call the stdin
1230 event handler again because ncurses may have already read and stored
1231 the input into its internal buffer, meaning that we won't get an stdin
1232 event for it. If we don't compensate for this missed stdin event, key
1233 sequences as Alt_F (^[f) will not behave promptly.
1235 (We only compensates for the missed 2nd byte of a key sequence because
1236 2-byte sequences are by far the most commonly used. ncurses may have
1237 buffered a larger, 3+-byte key sequence though it remains to be seen
1238 whether it is useful to compensate for all the bytes of such
1240 if (ch_pending
!= ERR
)
1242 ungetch (ch_pending
);
1243 call_stdin_event_handler_again_p
= 1;
1249 /* Readline doesn't understand non-8-bit curses keys, filter
1257 /* Get a character from the command window. This is called from the
1258 readline package. */
1265 return tui_getc_1 (fp
);
1267 catch (const gdb_exception
&ex
)
1269 /* Just in case, don't ever let an exception escape to readline.
1270 This shouldn't ever happen, but if it does, print the
1271 exception instead of just crashing GDB. */
1272 exception_print (gdb_stderr
, ex
);
1274 /* If we threw an exception, it's because we recognized the