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