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