]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/tui/tui-io.c
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / gdb / tui / tui-io.c
1 /* TUI support I/O functions.
2
3 Copyright (C) 1998-2024 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 #include "defs.h"
23 #include "target.h"
24 #include "gdbsupport/event-loop.h"
25 #include "event-top.h"
26 #include "command.h"
27 #include "top.h"
28 #include "ui.h"
29 #include "tui/tui.h"
30 #include "tui/tui-data.h"
31 #include "tui/tui-io.h"
32 #include "tui/tui-command.h"
33 #include "tui/tui-win.h"
34 #include "tui/tui-wingeneral.h"
35 #include "tui/tui-file.h"
36 #include "tui/tui-out.h"
37 #include "ui-out.h"
38 #include "cli-out.h"
39 #include <fcntl.h>
40 #include <signal.h>
41 #ifdef __MINGW32__
42 #include <windows.h>
43 #endif
44 #include "gdbsupport/filestuff.h"
45 #include "completer.h"
46 #include "gdb_curses.h"
47 #include <map>
48 #include "pager.h"
49 #include "gdbsupport/gdb-checked-static-cast.h"
50
51 /* This redefines CTRL if it is not already defined, so it must come
52 after terminal state releated include files like <term.h> and
53 "gdb_curses.h". */
54 #include "readline/readline.h"
55
56 #ifdef __MINGW32__
57 static SHORT ncurses_norm_attr;
58 #endif
59
60 static int tui_getc (FILE *fp);
61
62 static int
63 key_is_start_sequence (int ch)
64 {
65 return (ch == 27);
66 }
67
68 /* Use definition from readline 4.3. */
69 #undef CTRL_CHAR
70 #define CTRL_CHAR(c) \
71 ((c) < control_character_threshold && (((c) & 0x80) == 0))
72
73 /* This file controls the IO interactions between gdb and curses.
74 When the TUI is enabled, gdb has two modes a curses and a standard
75 mode.
76
77 In curses mode, the gdb outputs are made in a curses command
78 window. For this, the gdb_stdout and gdb_stderr are redirected to
79 the specific ui_file implemented by TUI. The output is handled by
80 tui_puts(). The input is also controlled by curses with
81 tui_getc(). The readline library uses this function to get its
82 input. Several readline hooks are installed to redirect readline
83 output to the TUI (see also the note below).
84
85 In normal mode, the gdb outputs are restored to their origin, that
86 is as if TUI is not used. Readline also uses its original getc()
87 function with stdin.
88
89 Note SCz/2001-07-21: the current readline is not clean in its
90 management of the output. Even if we install a redisplay handler,
91 it sometimes writes on a stdout file. It is important to redirect
92 every output produced by readline, otherwise the curses window will
93 be garbled. This is implemented with a pipe that TUI reads and
94 readline writes to. A gdb input handler is created so that reading
95 the pipe is handled automatically. This will probably not work on
96 non-Unix platforms. The best fix is to make readline clean enough
97 so that is never write on stdout.
98
99 Note SCz/2002-09-01: we now use more readline hooks and it seems
100 that with them we don't need the pipe anymore (verified by creating
101 the pipe and closing its end so that write causes a SIGPIPE). The
102 old pipe code is still there and can be conditionally removed by
103 #undef TUI_USE_PIPE_FOR_READLINE. */
104
105 /* For gdb 5.3, prefer to continue the pipe hack as a backup wheel. */
106 #ifdef HAVE_PIPE
107 #define TUI_USE_PIPE_FOR_READLINE
108 #endif
109 /* #undef TUI_USE_PIPE_FOR_READLINE */
110
111 /* TUI output files. */
112 static struct ui_file *tui_stdout;
113 static struct ui_file *tui_stderr;
114 static struct ui_file *tui_stdlog;
115 struct ui_out *tui_out;
116
117 /* GDB output files in non-curses mode. */
118 static struct ui_file *tui_old_stdout;
119 static struct ui_file *tui_old_stderr;
120 static struct ui_file *tui_old_stdlog;
121 cli_ui_out *tui_old_uiout;
122
123 /* Readline previous hooks. */
124 static rl_getc_func_t *tui_old_rl_getc_function;
125 static rl_voidfunc_t *tui_old_rl_redisplay_function;
126 static rl_vintfunc_t *tui_old_rl_prep_terminal;
127 static rl_voidfunc_t *tui_old_rl_deprep_terminal;
128 static rl_compdisp_func_t *tui_old_rl_display_matches_hook;
129 static int tui_old_rl_echoing_p;
130
131 /* Readline output stream.
132 Should be removed when readline is clean. */
133 static FILE *tui_rl_outstream;
134 static FILE *tui_old_rl_outstream;
135 #ifdef TUI_USE_PIPE_FOR_READLINE
136 static int tui_readline_pipe[2];
137 #endif
138
139 /* Print a character in the curses command window. The output is
140 buffered. It is up to the caller to refresh the screen if
141 necessary. */
142
143 static void
144 do_tui_putc (WINDOW *w, char c)
145 {
146 /* Expand TABs, since ncurses on MS-Windows doesn't. */
147 if (c == '\t')
148 {
149 int col;
150
151 col = getcurx (w);
152 do
153 {
154 waddch (w, ' ');
155 col++;
156 }
157 while ((col % 8) != 0);
158 }
159 else
160 waddch (w, c);
161 }
162
163 /* Update the cached value of the command window's start line based on
164 the window's current Y coordinate. */
165
166 static void
167 update_cmdwin_start_line ()
168 {
169 TUI_CMD_WIN->start_line = getcury (TUI_CMD_WIN->handle.get ());
170 }
171
172 /* Print a character in the curses command window. The output is
173 buffered. It is up to the caller to refresh the screen if
174 necessary. */
175
176 static void
177 tui_putc (char c)
178 {
179 do_tui_putc (TUI_CMD_WIN->handle.get (), c);
180 update_cmdwin_start_line ();
181 }
182
183 /* This maps colors to their corresponding color index. */
184
185 static std::map<ui_file_style::color, int> color_map;
186
187 /* This holds a pair of colors and is used to track the mapping
188 between a color pair index and the actual colors. */
189
190 struct color_pair
191 {
192 int fg;
193 int bg;
194
195 bool operator< (const color_pair &o) const
196 {
197 return fg < o.fg || (fg == o.fg && bg < o.bg);
198 }
199 };
200
201 /* This maps pairs of colors to their corresponding color pair
202 index. */
203
204 static std::map<color_pair, int> color_pair_map;
205
206 /* This is indexed by ANSI color offset from the base color, and holds
207 the corresponding curses color constant. */
208
209 static const int curses_colors[] = {
210 COLOR_BLACK,
211 COLOR_RED,
212 COLOR_GREEN,
213 COLOR_YELLOW,
214 COLOR_BLUE,
215 COLOR_MAGENTA,
216 COLOR_CYAN,
217 COLOR_WHITE
218 };
219
220 /* Given a color, find its index. */
221
222 static bool
223 get_color (const ui_file_style::color &color, int *result)
224 {
225 if (color.is_none ())
226 *result = -1;
227 else if (color.is_basic ())
228 *result = curses_colors[color.get_value ()];
229 else
230 {
231 auto it = color_map.find (color);
232 if (it == color_map.end ())
233 {
234 /* The first 8 colors are standard. */
235 int next = color_map.size () + 8;
236 if (next >= COLORS)
237 return false;
238 uint8_t rgb[3];
239 color.get_rgb (rgb);
240 /* We store RGB as 0..255, but curses wants 0..1000. */
241 if (init_color (next, rgb[0] * 1000 / 255, rgb[1] * 1000 / 255,
242 rgb[2] * 1000 / 255) == ERR)
243 return false;
244 color_map[color] = next;
245 *result = next;
246 }
247 else
248 *result = it->second;
249 }
250 return true;
251 }
252
253 /* The most recently emitted color pair. */
254
255 static int last_color_pair = -1;
256
257 /* The most recently applied style. */
258
259 static ui_file_style last_style;
260
261 /* If true, we're highlighting the current source line in reverse
262 video mode. */
263 static bool reverse_mode_p = false;
264
265 /* The background/foreground colors before we entered reverse
266 mode. */
267 static ui_file_style::color reverse_save_bg (ui_file_style::NONE);
268 static ui_file_style::color reverse_save_fg (ui_file_style::NONE);
269
270 /* Given two colors, return their color pair index; making a new one
271 if necessary. */
272
273 static int
274 get_color_pair (int fg, int bg)
275 {
276 color_pair c = { fg, bg };
277 auto it = color_pair_map.find (c);
278 if (it == color_pair_map.end ())
279 {
280 /* Color pair 0 is our default color, so new colors start at
281 1. */
282 int next = color_pair_map.size () + 1;
283 /* Curses has a limited number of available color pairs. Fall
284 back to the default if we've used too many. */
285 if (next >= COLOR_PAIRS)
286 return 0;
287 init_pair (next, fg, bg);
288 color_pair_map[c] = next;
289 return next;
290 }
291 return it->second;
292 }
293
294 /* Apply STYLE to W. */
295
296 void
297 tui_apply_style (WINDOW *w, ui_file_style style)
298 {
299 /* Reset. */
300 wattron (w, A_NORMAL);
301 wattroff (w, A_BOLD);
302 wattroff (w, A_DIM);
303 wattroff (w, A_REVERSE);
304 if (last_color_pair != -1)
305 wattroff (w, COLOR_PAIR (last_color_pair));
306 wattron (w, COLOR_PAIR (0));
307
308 const ui_file_style::color &fg = style.get_foreground ();
309 const ui_file_style::color &bg = style.get_background ();
310 if (!fg.is_none () || !bg.is_none ())
311 {
312 int fgi, bgi;
313 if (get_color (fg, &fgi) && get_color (bg, &bgi))
314 {
315 #ifdef __MINGW32__
316 /* MS-Windows port of ncurses doesn't support implicit
317 default foreground and background colors, so we must
318 specify them explicitly when needed, using the colors we
319 saw at startup. */
320 if (fgi == -1)
321 fgi = ncurses_norm_attr & 15;
322 if (bgi == -1)
323 bgi = (ncurses_norm_attr >> 4) & 15;
324 #endif
325 int pair = get_color_pair (fgi, bgi);
326 if (last_color_pair != -1)
327 wattroff (w, COLOR_PAIR (last_color_pair));
328 wattron (w, COLOR_PAIR (pair));
329 last_color_pair = pair;
330 }
331 }
332
333 switch (style.get_intensity ())
334 {
335 case ui_file_style::NORMAL:
336 break;
337
338 case ui_file_style::BOLD:
339 wattron (w, A_BOLD);
340 break;
341
342 case ui_file_style::DIM:
343 wattron (w, A_DIM);
344 break;
345
346 default:
347 gdb_assert_not_reached ("invalid intensity");
348 }
349
350 if (style.is_reverse ())
351 wattron (w, A_REVERSE);
352
353 last_style = style;
354 }
355
356 /* Apply an ANSI escape sequence from BUF to W. BUF must start with
357 the ESC character. If BUF does not start with an ANSI escape,
358 return 0. Otherwise, apply the sequence if it is recognized, or
359 simply ignore it if not. In this case, the number of bytes read
360 from BUF is returned. */
361
362 static size_t
363 apply_ansi_escape (WINDOW *w, const char *buf)
364 {
365 ui_file_style style = last_style;
366 size_t n_read;
367
368 if (!style.parse (buf, &n_read))
369 return n_read;
370
371 if (reverse_mode_p)
372 {
373 if (!style_tui_current_position)
374 return n_read;
375
376 /* We want to reverse _only_ the default foreground/background
377 colors. If the foreground color is not the default (because
378 the text was styled), we want to leave it as is. If e.g.,
379 the terminal is fg=BLACK, and bg=WHITE, and the style wants
380 to print text in RED, we want to reverse the background color
381 (print in BLACK), but still print the text in RED. To do
382 that, we enable the A_REVERSE attribute, and re-reverse the
383 parsed-style's fb/bg colors.
384
385 Notes on the approach:
386
387 - there's no portable way to know which colors the default
388 fb/bg colors map to.
389
390 - this approach does the right thing even if you change the
391 terminal colors while GDB is running -- the reversed
392 colors automatically adapt.
393 */
394 if (!style.is_default ())
395 {
396 ui_file_style::color bg = style.get_background ();
397 ui_file_style::color fg = style.get_foreground ();
398 style.set_fg (bg);
399 style.set_bg (fg);
400 }
401
402 /* Enable A_REVERSE. */
403 style.set_reverse (true);
404 }
405
406 tui_apply_style (w, style);
407 return n_read;
408 }
409
410 /* See tui.io.h. */
411
412 void
413 tui_set_reverse_mode (WINDOW *w, bool reverse)
414 {
415 ui_file_style style = last_style;
416
417 reverse_mode_p = reverse;
418
419 if (reverse)
420 {
421 reverse_save_bg = style.get_background ();
422 reverse_save_fg = style.get_foreground ();
423
424 if (!style_tui_current_position)
425 {
426 /* Switch to default style (reversed) while highlighting the
427 current position. */
428 style = {};
429 }
430 }
431 else
432 {
433 style.set_bg (reverse_save_bg);
434 style.set_fg (reverse_save_fg);
435 }
436
437 style.set_reverse (reverse);
438
439 tui_apply_style (w, style);
440 }
441
442 /* Print LENGTH characters from the buffer pointed to by BUF to the
443 curses command window. The output is buffered. It is up to the
444 caller to refresh the screen if necessary. */
445
446 void
447 tui_write (const char *buf, size_t length)
448 {
449 /* We need this to be \0-terminated for the regexp matching. */
450 std::string copy (buf, length);
451 tui_puts (copy.c_str ());
452 }
453
454 /* Print a string in the curses command window. The output is
455 buffered. It is up to the caller to refresh the screen if
456 necessary. */
457
458 void
459 tui_puts (const char *string, WINDOW *w)
460 {
461 if (w == nullptr)
462 w = TUI_CMD_WIN->handle.get ();
463
464 while (true)
465 {
466 const char *next = strpbrk (string, "\n\1\2\033\t");
467
468 /* Print the plain text prefix. */
469 size_t n_chars = next == nullptr ? strlen (string) : next - string;
470 if (n_chars > 0)
471 waddnstr (w, string, n_chars);
472
473 /* We finished. */
474 if (next == nullptr)
475 break;
476
477 char c = *next;
478 switch (c)
479 {
480 case '\1':
481 case '\2':
482 /* Ignore these, they are readline escape-marking
483 sequences. */
484 ++next;
485 break;
486
487 case '\n':
488 case '\t':
489 do_tui_putc (w, c);
490 ++next;
491 break;
492
493 case '\033':
494 {
495 size_t bytes_read = apply_ansi_escape (w, next);
496 if (bytes_read > 0)
497 next += bytes_read;
498 else
499 {
500 /* Just drop the escape. */
501 ++next;
502 }
503 }
504 break;
505
506 default:
507 gdb_assert_not_reached ("missing case in tui_puts");
508 }
509
510 string = next;
511 }
512
513 if (TUI_CMD_WIN != nullptr && w == TUI_CMD_WIN->handle.get ())
514 update_cmdwin_start_line ();
515 }
516
517 static void
518 tui_puts_internal (WINDOW *w, const char *string, int *height)
519 {
520 char c;
521 int prev_col = 0;
522 bool saw_nl = false;
523
524 while ((c = *string++) != 0)
525 {
526 if (c == '\1' || c == '\2')
527 {
528 /* Ignore these, they are readline escape-marking
529 sequences. */
530 continue;
531 }
532
533 if (c == '\033')
534 {
535 size_t bytes_read = apply_ansi_escape (w, string - 1);
536 if (bytes_read > 0)
537 {
538 string = string + bytes_read - 1;
539 continue;
540 }
541 }
542
543 if (c == '\n')
544 saw_nl = true;
545
546 do_tui_putc (w, c);
547
548 if (height != nullptr)
549 {
550 int col = getcurx (w);
551 if (col <= prev_col)
552 ++*height;
553 prev_col = col;
554 }
555 }
556
557 if (TUI_CMD_WIN != nullptr && w == TUI_CMD_WIN->handle.get ())
558 update_cmdwin_start_line ();
559 if (saw_nl)
560 wrefresh (w);
561 }
562
563 /* Readline callback.
564 Redisplay the command line with its prompt after readline has
565 changed the edited text. */
566 void
567 tui_redisplay_readline (void)
568 {
569 int prev_col;
570 int height;
571 int col;
572 int c_pos;
573 int c_line;
574 int in;
575 WINDOW *w;
576 const char *prompt;
577 int start_line;
578
579 /* Detect when we temporarily left SingleKey and now the readline
580 edit buffer is empty, automatically restore the SingleKey
581 mode. The restore must only be done if the command has finished.
582 The command could call prompt_for_continue and we must not
583 restore SingleKey so that the prompt and normal keymap are used. */
584 if (tui_current_key_mode == TUI_ONE_COMMAND_MODE && rl_end == 0
585 && !gdb_in_secondary_prompt_p (current_ui))
586 tui_set_key_mode (TUI_SINGLE_KEY_MODE);
587
588 if (tui_current_key_mode == TUI_SINGLE_KEY_MODE)
589 prompt = "";
590 else
591 prompt = rl_display_prompt;
592
593 c_pos = -1;
594 c_line = -1;
595 w = TUI_CMD_WIN->handle.get ();
596 start_line = TUI_CMD_WIN->start_line;
597 wmove (w, start_line, 0);
598 prev_col = 0;
599 height = 1;
600 if (prompt != nullptr)
601 tui_puts_internal (w, prompt, &height);
602
603 prev_col = getcurx (w);
604 for (in = 0; in <= rl_end; in++)
605 {
606 unsigned char c;
607
608 if (in == rl_point)
609 {
610 getyx (w, c_line, c_pos);
611 }
612
613 if (in == rl_end)
614 break;
615
616 c = (unsigned char) rl_line_buffer[in];
617 if (CTRL_CHAR (c) || c == RUBOUT)
618 {
619 waddch (w, '^');
620 waddch (w, CTRL_CHAR (c) ? UNCTRL (c) : '?');
621 }
622 else if (c == '\t')
623 {
624 /* Expand TABs, since ncurses on MS-Windows doesn't. */
625 col = getcurx (w);
626 do
627 {
628 waddch (w, ' ');
629 col++;
630 } while ((col % 8) != 0);
631 }
632 else
633 {
634 waddch (w, c);
635 }
636 if (c == '\n')
637 TUI_CMD_WIN->start_line = getcury (w);
638 col = getcurx (w);
639 if (col < prev_col)
640 height++;
641 prev_col = col;
642 }
643 wclrtobot (w);
644 TUI_CMD_WIN->start_line = getcury (w);
645 if (c_line >= 0)
646 wmove (w, c_line, c_pos);
647 TUI_CMD_WIN->start_line -= height - 1;
648
649 wrefresh (w);
650 fflush(stdout);
651 }
652
653 /* Readline callback to prepare the terminal. It is called once each
654 time we enter readline. Terminal is already setup in curses
655 mode. */
656 static void
657 tui_prep_terminal (int notused1)
658 {
659 #ifdef NCURSES_MOUSE_VERSION
660 if (tui_enable_mouse)
661 mousemask (ALL_MOUSE_EVENTS, NULL);
662 #endif
663 }
664
665 /* Readline callback to restore the terminal. It is called once each
666 time we leave readline. There is nothing to do in curses mode. */
667 static void
668 tui_deprep_terminal (void)
669 {
670 #ifdef NCURSES_MOUSE_VERSION
671 mousemask (0, NULL);
672 #endif
673 }
674
675 #ifdef TUI_USE_PIPE_FOR_READLINE
676 /* Read readline output pipe and feed the command window with it.
677 Should be removed when readline is clean. */
678 static void
679 tui_readline_output (int error, gdb_client_data data)
680 {
681 int size;
682 char buf[256];
683
684 size = read (tui_readline_pipe[0], buf, sizeof (buf) - 1);
685 if (size > 0 && tui_active)
686 {
687 buf[size] = 0;
688 tui_puts (buf);
689 }
690 }
691 #endif
692
693 /* TUI version of displayer.crlf. */
694
695 static void
696 tui_mld_crlf (const struct match_list_displayer *displayer)
697 {
698 tui_putc ('\n');
699 }
700
701 /* TUI version of displayer.putch. */
702
703 static void
704 tui_mld_putch (const struct match_list_displayer *displayer, int ch)
705 {
706 tui_putc (ch);
707 }
708
709 /* TUI version of displayer.puts. */
710
711 static void
712 tui_mld_puts (const struct match_list_displayer *displayer, const char *s)
713 {
714 tui_puts (s);
715 }
716
717 /* TUI version of displayer.flush. */
718
719 static void
720 tui_mld_flush (const struct match_list_displayer *displayer)
721 {
722 wrefresh (TUI_CMD_WIN->handle.get ());
723 }
724
725 /* TUI version of displayer.erase_entire_line. */
726
727 static void
728 tui_mld_erase_entire_line (const struct match_list_displayer *displayer)
729 {
730 WINDOW *w = TUI_CMD_WIN->handle.get ();
731 int cur_y = getcury (w);
732
733 wmove (w, cur_y, 0);
734 wclrtoeol (w);
735 wmove (w, cur_y, 0);
736 }
737
738 /* TUI version of displayer.beep. */
739
740 static void
741 tui_mld_beep (const struct match_list_displayer *displayer)
742 {
743 beep ();
744 }
745
746 /* A wrapper for wgetch that enters nonl mode. We We normally want
747 curses' "nl" mode, but when reading from the user, we'd like to
748 differentiate between C-j and C-m, because some users bind these
749 keys differently in their .inputrc. So, put curses into nonl mode
750 just when reading from the user. See PR tui/20819. */
751
752 static int
753 gdb_wgetch (WINDOW *win)
754 {
755 nonl ();
756 int r = wgetch (win);
757 nl ();
758 return r;
759 }
760
761 /* Helper function for tui_mld_read_key.
762 This temporarily replaces tui_getc for use during tab-completion
763 match list display. */
764
765 static int
766 tui_mld_getc (FILE *fp)
767 {
768 WINDOW *w = TUI_CMD_WIN->handle.get ();
769 int c = gdb_wgetch (w);
770
771 return c;
772 }
773
774 /* TUI version of displayer.read_key. */
775
776 static int
777 tui_mld_read_key (const struct match_list_displayer *displayer)
778 {
779 /* We can't use tui_getc as we need NEWLINE to not get emitted. */
780 scoped_restore restore_getc_function
781 = make_scoped_restore (&rl_getc_function, tui_mld_getc);
782 return rl_read_key ();
783 }
784
785 /* TUI version of rl_completion_display_matches_hook.
786 See gdb_display_match_list for a description of the arguments. */
787
788 static void
789 tui_rl_display_match_list (char **matches, int len, int max)
790 {
791 struct match_list_displayer displayer;
792
793 rl_get_screen_size (&displayer.height, &displayer.width);
794 displayer.crlf = tui_mld_crlf;
795 displayer.putch = tui_mld_putch;
796 displayer.puts = tui_mld_puts;
797 displayer.flush = tui_mld_flush;
798 displayer.erase_entire_line = tui_mld_erase_entire_line;
799 displayer.beep = tui_mld_beep;
800 displayer.read_key = tui_mld_read_key;
801
802 gdb_display_match_list (matches, len, max, &displayer);
803 }
804
805 /* Setup the IO for curses or non-curses mode.
806 - In non-curses mode, readline and gdb use the standard input and
807 standard output/error directly.
808 - In curses mode, the standard output/error is controlled by TUI
809 with the tui_stdout and tui_stderr. The output is redirected in
810 the curses command window. Several readline callbacks are installed
811 so that readline asks for its input to the curses command window
812 with wgetch(). */
813 void
814 tui_setup_io (int mode)
815 {
816 extern int _rl_echoing_p;
817
818 if (mode)
819 {
820 /* Ensure that readline has been initialized before saving any
821 of its variables. */
822 tui_ensure_readline_initialized ();
823
824 /* Redirect readline to TUI. */
825 tui_old_rl_redisplay_function = rl_redisplay_function;
826 tui_old_rl_deprep_terminal = rl_deprep_term_function;
827 tui_old_rl_prep_terminal = rl_prep_term_function;
828 tui_old_rl_getc_function = rl_getc_function;
829 tui_old_rl_display_matches_hook = rl_completion_display_matches_hook;
830 tui_old_rl_outstream = rl_outstream;
831 tui_old_rl_echoing_p = _rl_echoing_p;
832 rl_redisplay_function = tui_redisplay_readline;
833 rl_deprep_term_function = tui_deprep_terminal;
834 rl_prep_term_function = tui_prep_terminal;
835 rl_getc_function = tui_getc;
836 _rl_echoing_p = 0;
837 rl_outstream = tui_rl_outstream;
838 rl_prompt = 0;
839 rl_completion_display_matches_hook = tui_rl_display_match_list;
840 rl_already_prompted = 0;
841
842 /* Keep track of previous gdb output. */
843 tui_old_stdout = gdb_stdout;
844 tui_old_stderr = gdb_stderr;
845 tui_old_stdlog = gdb_stdlog;
846 tui_old_uiout = gdb::checked_static_cast<cli_ui_out *> (current_uiout);
847
848 /* Reconfigure gdb output. */
849 gdb_stdout = tui_stdout;
850 gdb_stderr = tui_stderr;
851 gdb_stdlog = tui_stdlog;
852 gdb_stdtarg = gdb_stderr;
853 gdb_stdtargerr = gdb_stderr;
854 current_uiout = tui_out;
855
856 /* Save tty for SIGCONT. */
857 savetty ();
858 }
859 else
860 {
861 /* Restore gdb output. */
862 gdb_stdout = tui_old_stdout;
863 gdb_stderr = tui_old_stderr;
864 gdb_stdlog = tui_old_stdlog;
865 gdb_stdtarg = gdb_stderr;
866 gdb_stdtargerr = gdb_stderr;
867 current_uiout = tui_old_uiout;
868
869 /* Restore readline. */
870 rl_redisplay_function = tui_old_rl_redisplay_function;
871 rl_deprep_term_function = tui_old_rl_deprep_terminal;
872 rl_prep_term_function = tui_old_rl_prep_terminal;
873 rl_getc_function = tui_old_rl_getc_function;
874 rl_completion_display_matches_hook = tui_old_rl_display_matches_hook;
875 rl_outstream = tui_old_rl_outstream;
876 _rl_echoing_p = tui_old_rl_echoing_p;
877 rl_already_prompted = 0;
878
879 /* Save tty for SIGCONT. */
880 savetty ();
881
882 /* Clean up color information. */
883 last_color_pair = -1;
884 last_style = ui_file_style ();
885 color_map.clear ();
886 color_pair_map.clear ();
887 }
888 }
889
890 #ifdef SIGCONT
891 /* Catch SIGCONT to restore the terminal and refresh the screen. */
892 static void
893 tui_cont_sig (int sig)
894 {
895 if (tui_active)
896 {
897 /* Restore the terminal setting because another process (shell)
898 might have changed it. */
899 resetty ();
900
901 /* Force a refresh of the screen. */
902 tui_refresh_all_win ();
903 }
904 signal (sig, tui_cont_sig);
905 }
906 #endif
907
908 /* Initialize the IO for gdb in curses mode. */
909 void
910 tui_initialize_io (void)
911 {
912 #ifdef SIGCONT
913 signal (SIGCONT, tui_cont_sig);
914 #endif
915
916 /* Create tui output streams. */
917 tui_stdout = new pager_file (new tui_file (stdout, true));
918 tui_stderr = new tui_file (stderr, false);
919 tui_stdlog = new timestamped_file (tui_stderr);
920 tui_out = new tui_ui_out (tui_stdout);
921
922 /* Create the default UI. */
923 tui_old_uiout = new cli_ui_out (gdb_stdout);
924
925 #ifdef TUI_USE_PIPE_FOR_READLINE
926 /* Temporary solution for readline writing to stdout: redirect
927 readline output in a pipe, read that pipe and output the content
928 in the curses command window. */
929 if (gdb_pipe_cloexec (tui_readline_pipe) != 0)
930 error (_("Cannot create pipe for readline"));
931
932 tui_rl_outstream = fdopen (tui_readline_pipe[1], "w");
933 if (tui_rl_outstream == 0)
934 error (_("Cannot redirect readline output"));
935
936 setvbuf (tui_rl_outstream, NULL, _IOLBF, 0);
937
938 #ifdef O_NONBLOCK
939 (void) fcntl (tui_readline_pipe[0], F_SETFL, O_NONBLOCK);
940 #else
941 #ifdef O_NDELAY
942 (void) fcntl (tui_readline_pipe[0], F_SETFL, O_NDELAY);
943 #endif
944 #endif
945 add_file_handler (tui_readline_pipe[0], tui_readline_output, 0, "tui");
946 #else
947 tui_rl_outstream = stdout;
948 #endif
949
950 #ifdef __MINGW32__
951 /* MS-Windows port of ncurses doesn't support default foreground and
952 background colors, so we must record the default colors at startup. */
953 HANDLE hstdout = (HANDLE)_get_osfhandle (fileno (stdout));
954 DWORD cmode;
955 CONSOLE_SCREEN_BUFFER_INFO csbi;
956
957 if (hstdout != INVALID_HANDLE_VALUE
958 && GetConsoleMode (hstdout, &cmode) != 0
959 && GetConsoleScreenBufferInfo (hstdout, &csbi))
960 ncurses_norm_attr = csbi.wAttributes;
961 #endif
962 }
963
964 /* Dispatch the correct tui function based upon the mouse event. */
965
966 #ifdef NCURSES_MOUSE_VERSION
967
968 static void
969 tui_dispatch_mouse_event ()
970 {
971 MEVENT mev;
972 if (getmouse (&mev) != OK)
973 return;
974
975 for (tui_win_info *wi : all_tui_windows ())
976 if (mev.x > wi->x && mev.x < wi->x + wi->width - 1
977 && mev.y > wi->y && mev.y < wi->y + wi->height - 1)
978 {
979 if ((mev.bstate & BUTTON1_CLICKED) != 0
980 || (mev.bstate & BUTTON2_CLICKED) != 0
981 || (mev.bstate & BUTTON3_CLICKED) != 0)
982 {
983 int button = (mev.bstate & BUTTON1_CLICKED) != 0 ? 1
984 : ((mev.bstate & BUTTON2_CLICKED) != 0 ? 2
985 : 3);
986 wi->click (mev.x - wi->x - 1, mev.y - wi->y - 1, button);
987 }
988 #ifdef BUTTON5_PRESSED
989 else if ((mev.bstate & BUTTON4_PRESSED) != 0)
990 wi->backward_scroll (3);
991 else if ((mev.bstate & BUTTON5_PRESSED) != 0)
992 wi->forward_scroll (3);
993 #endif
994 break;
995 }
996 }
997
998 #endif
999
1000 /* Dispatch the correct tui function based upon the control
1001 character. */
1002 static unsigned int
1003 tui_dispatch_ctrl_char (unsigned int ch)
1004 {
1005 struct tui_win_info *win_info = tui_win_with_focus ();
1006
1007 /* If no window has the focus, or if the focus window can't scroll,
1008 just pass the character through. */
1009 if (win_info == NULL || !win_info->can_scroll ())
1010 return ch;
1011
1012 switch (ch)
1013 {
1014 case KEY_NPAGE:
1015 win_info->forward_scroll (0);
1016 break;
1017 case KEY_PPAGE:
1018 win_info->backward_scroll (0);
1019 break;
1020 case KEY_DOWN:
1021 case KEY_SF:
1022 win_info->forward_scroll (1);
1023 break;
1024 case KEY_UP:
1025 case KEY_SR:
1026 win_info->backward_scroll (1);
1027 break;
1028 case KEY_RIGHT:
1029 win_info->left_scroll (1);
1030 break;
1031 case KEY_LEFT:
1032 win_info->right_scroll (1);
1033 break;
1034 default:
1035 /* We didn't recognize the character as a control character, so pass it
1036 through. */
1037 return ch;
1038 }
1039
1040 /* We intercepted the control character, so return 0 (which readline
1041 will interpret as a no-op). */
1042 return 0;
1043 }
1044
1045 /* See tui-io.h. */
1046
1047 void
1048 tui_inject_newline_into_command_window ()
1049 {
1050 gdb_assert (tui_active);
1051
1052 WINDOW *w = TUI_CMD_WIN->handle.get ();
1053
1054 /* When hitting return with an empty input, gdb executes the last
1055 command. If we emit a newline, this fills up the command window
1056 with empty lines with gdb prompt at beginning. Instead of that,
1057 stay on the same line but provide a visual effect to show the
1058 user we recognized the command. */
1059 if (rl_end == 0 && !gdb_in_secondary_prompt_p (current_ui))
1060 {
1061 wmove (w, getcury (w), 0);
1062
1063 /* Clear the line. This will blink the gdb prompt since
1064 it will be redrawn at the same line. */
1065 wclrtoeol (w);
1066 wrefresh (w);
1067 napms (20);
1068 }
1069 else
1070 {
1071 /* Move cursor to the end of the command line before emitting the
1072 newline. We need to do so because when ncurses outputs a newline
1073 it truncates any text that appears past the end of the cursor. */
1074 int px, py;
1075 getyx (w, py, px);
1076 px += rl_end - rl_point;
1077 py += px / TUI_CMD_WIN->width;
1078 px %= TUI_CMD_WIN->width;
1079 wmove (w, py, px);
1080 tui_putc ('\n');
1081 }
1082 }
1083
1084 /* If we're passing an escape sequence to readline, this points to a
1085 string holding the remaining characters of the sequence to pass.
1086 We advance the pointer one character at a time until '\0' is
1087 reached. */
1088 static const char *cur_seq = nullptr;
1089
1090 /* Set CUR_SEQ to point at the current sequence to pass to readline,
1091 setup to call the input handler again so we complete the sequence
1092 shortly, and return the first character to start the sequence. */
1093
1094 static int
1095 start_sequence (const char *seq)
1096 {
1097 call_stdin_event_handler_again_p = 1;
1098 cur_seq = seq + 1;
1099 return seq[0];
1100 }
1101
1102 /* Main worker for tui_getc. Get a character from the command window.
1103 This is called from the readline package, but wrapped in a
1104 try/catch by tui_getc. */
1105
1106 static int
1107 tui_getc_1 (FILE *fp)
1108 {
1109 int ch;
1110 WINDOW *w;
1111
1112 w = TUI_CMD_WIN->handle.get ();
1113
1114 #ifdef TUI_USE_PIPE_FOR_READLINE
1115 /* Flush readline output. */
1116 tui_readline_output (0, 0);
1117 #endif
1118
1119 /* We enable keypad mode so that curses's wgetch processes mouse
1120 escape sequences. In keypad mode, wgetch also processes the
1121 escape sequences for keys such as up/down etc. and returns KEY_UP
1122 / KEY_DOWN etc. When we have the focus on the command window
1123 though, we want to pass the raw up/down etc. escape codes to
1124 readline so readline understands them. */
1125 if (cur_seq != nullptr)
1126 {
1127 ch = *cur_seq++;
1128
1129 /* If we've reached the end of the string, we're done with the
1130 sequence. Otherwise, setup to get back here again for
1131 another character. */
1132 if (*cur_seq == '\0')
1133 cur_seq = nullptr;
1134 else
1135 call_stdin_event_handler_again_p = 1;
1136 return ch;
1137 }
1138 else
1139 ch = gdb_wgetch (w);
1140
1141 /* Handle prev/next/up/down here. */
1142 ch = tui_dispatch_ctrl_char (ch);
1143
1144 #ifdef NCURSES_MOUSE_VERSION
1145 if (ch == KEY_MOUSE)
1146 {
1147 tui_dispatch_mouse_event ();
1148 return 0;
1149 }
1150 #endif
1151
1152 /* Translate curses keys back to escape sequences so that readline
1153 can understand them. We do this irrespective of which window has
1154 the focus. If e.g., we're focused on a non-command window, then
1155 the up/down keys will already have been filtered by
1156 tui_dispatch_ctrl_char. Keys that haven't been intercepted will
1157 be passed down to readline. */
1158 if (current_ui->command_editing)
1159 {
1160 /* For the standard arrow keys + home/end, hardcode sequences
1161 readline understands. See bind_arrow_keys_internal in
1162 readline/readline.c. */
1163 switch (ch)
1164 {
1165 case KEY_UP:
1166 return start_sequence ("\033[A");
1167 case KEY_DOWN:
1168 return start_sequence ("\033[B");
1169 case KEY_RIGHT:
1170 return start_sequence ("\033[C");
1171 case KEY_LEFT:
1172 return start_sequence ("\033[D");
1173 case KEY_HOME:
1174 return start_sequence ("\033[H");
1175 case KEY_END:
1176 return start_sequence ("\033[F");
1177
1178 /* del and ins are unfortunately not hardcoded in readline for
1179 all systems. */
1180
1181 case KEY_DC: /* del */
1182 #ifdef __MINGW32__
1183 return start_sequence ("\340S");
1184 #else
1185 return start_sequence ("\033[3~");
1186 #endif
1187
1188 case KEY_IC: /* ins */
1189 #if defined __MINGW32__
1190 return start_sequence ("\340R");
1191 #else
1192 return start_sequence ("\033[2~");
1193 #endif
1194 }
1195
1196 /* Keycodes above KEY_MAX are not guaranteed to be stable.
1197 Compare keyname instead. */
1198 if (ch >= KEY_MAX)
1199 {
1200 std::string_view name;
1201 const char *name_str = keyname (ch);
1202 if (name_str != nullptr)
1203 name = std::string_view (name_str);
1204
1205 /* The following sequences are hardcoded in readline as
1206 well. */
1207
1208 /* ctrl-arrow keys */
1209 if (name == "kLFT5") /* ctrl-left */
1210 return start_sequence ("\033[1;5D");
1211 else if (name == "kRIT5") /* ctrl-right */
1212 return start_sequence ("\033[1;5C");
1213 else if (name == "kDC5") /* ctrl-del */
1214 return start_sequence ("\033[3;5~");
1215
1216 /* alt-arrow keys */
1217 else if (name == "kLFT3") /* alt-left */
1218 return start_sequence ("\033[1;3D");
1219 else if (name == "kRIT3") /* alt-right */
1220 return start_sequence ("\033[1;3C");
1221 }
1222 }
1223
1224 /* Handle the CTRL-L refresh for each window. */
1225 if (ch == '\f')
1226 {
1227 tui_refresh_all_win ();
1228 return ch;
1229 }
1230
1231 if (ch == KEY_BACKSPACE)
1232 return '\b';
1233
1234 if (current_ui->command_editing && key_is_start_sequence (ch))
1235 {
1236 int ch_pending;
1237
1238 nodelay (w, TRUE);
1239 ch_pending = gdb_wgetch (w);
1240 nodelay (w, FALSE);
1241
1242 /* If we have pending input following a start sequence, call the stdin
1243 event handler again because ncurses may have already read and stored
1244 the input into its internal buffer, meaning that we won't get an stdin
1245 event for it. If we don't compensate for this missed stdin event, key
1246 sequences as Alt_F (^[f) will not behave promptly.
1247
1248 (We only compensates for the missed 2nd byte of a key sequence because
1249 2-byte sequences are by far the most commonly used. ncurses may have
1250 buffered a larger, 3+-byte key sequence though it remains to be seen
1251 whether it is useful to compensate for all the bytes of such
1252 sequences.) */
1253 if (ch_pending != ERR)
1254 {
1255 ungetch (ch_pending);
1256 call_stdin_event_handler_again_p = 1;
1257 }
1258 }
1259
1260 if (ch > 0xff)
1261 {
1262 /* Readline doesn't understand non-8-bit curses keys, filter
1263 them out. */
1264 return 0;
1265 }
1266
1267 return ch;
1268 }
1269
1270 /* Get a character from the command window. This is called from the
1271 readline package. */
1272
1273 static int
1274 tui_getc (FILE *fp)
1275 {
1276 try
1277 {
1278 return tui_getc_1 (fp);
1279 }
1280 catch (const gdb_exception_forced_quit &ex)
1281 {
1282 /* As noted below, it's not safe to let an exception escape
1283 to newline, so, for this case, reset the quit flag for
1284 later QUIT checking. */
1285 set_force_quit_flag ();
1286 return 0;
1287 }
1288 catch (const gdb_exception &ex)
1289 {
1290 /* Just in case, don't ever let an exception escape to readline.
1291 This shouldn't ever happen, but if it does, print the
1292 exception instead of just crashing GDB. */
1293 exception_print (gdb_stderr, ex);
1294
1295 /* If we threw an exception, it's because we recognized the
1296 character. */
1297 return 0;
1298 }
1299 }