1 /* TUI Interpreter definitions for GDB, the GNU debugger. 2 3 Copyright (C) 2003-2024 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20 #include "cli/cli-interp.h" 21 #include "interps.h" 22 #include "ui.h" 23 #include "event-top.h" 24 #include "gdbsupport/event-loop.h" 25 #include "ui-out.h" 26 #include "cli-out.h" 27 #include "tui/tui-data.h" 28 #include "tui/tui-win.h" 29 #include "tui/tui.h" 30 #include "tui/tui-io.h" 31 #include "infrun.h" 32 #include "observable.h" 33 #include "gdbthread.h" 34 #include "inferior.h" 35 #include "main.h" 36 37 /* Set to true when the TUI mode must be activated when we first start 38 gdb. */ 39 static bool tui_start_enabled = false; 40 41 class tui_interp final : public cli_interp_base 42 { 43 public: tui_interp(const char * name)44 explicit tui_interp (const char *name) 45 : cli_interp_base (name) 46 {} 47 48 void init (bool top_level) override; 49 void resume () override; 50 void suspend () override; 51 void exec (const char *command_str) override; 52 ui_out *interp_ui_out () override; 53 supports_new_ui()54 bool supports_new_ui () const override 55 { return false; } 56 }; 57 58 /* Cleanup the tui before exiting. */ 59 60 static void tui_exit(void)61tui_exit (void) 62 { 63 /* Disable the tui. Curses mode is left leaving the screen in a 64 clean state (see endwin()). */ 65 tui_disable (); 66 } 67 68 /* These implement the TUI interpreter. */ 69 70 void init(bool top_level)71tui_interp::init (bool top_level) 72 { 73 /* Install exit handler to leave the screen in a good shape. */ 74 atexit (tui_exit); 75 76 tui_initialize_io (); 77 if (gdb_stdout->isatty ()) 78 { 79 tui_ensure_readline_initialized (); 80 81 /* This installs the SIGWINCH signal handler. The handler needs to do 82 readline calls (to rl_resize_terminal), so it must not be installed 83 unless readline is properly initialized. */ 84 tui_initialize_win (); 85 } 86 } 87 88 /* Used as the command handler for the tui. */ 89 90 static void tui_command_line_handler(gdb::unique_xmalloc_ptr<char> && rl)91tui_command_line_handler (gdb::unique_xmalloc_ptr<char> &&rl) 92 { 93 /* When a tui enabled GDB is running in either tui mode or cli mode then 94 it is always the tui interpreter that is in use. As a result we end 95 up in here even in standard cli mode. 96 97 We only need to do any special actions when the tui is in use 98 though. When the tui is active the users return is not echoed to the 99 screen as a result the display will not automatically move us to the 100 next line. Here we manually insert a newline character and move the 101 cursor. */ 102 if (tui_active) 103 tui_inject_newline_into_command_window (); 104 105 /* Now perform GDB's standard CLI command line handling. */ 106 command_line_handler (std::move (rl)); 107 } 108 109 void resume()110tui_interp::resume () 111 { 112 struct ui *ui = current_ui; 113 struct ui_file *stream; 114 115 /* gdb_setup_readline will change gdb_stdout. If the TUI was 116 previously writing to gdb_stdout, then set it to the new 117 gdb_stdout afterwards. */ 118 119 stream = tui_old_uiout->set_stream (gdb_stdout); 120 if (stream != gdb_stdout) 121 { 122 tui_old_uiout->set_stream (stream); 123 stream = NULL; 124 } 125 126 gdb_setup_readline (1); 127 128 ui->input_handler = tui_command_line_handler; 129 130 if (stream != NULL) 131 tui_old_uiout->set_stream (gdb_stdout); 132 133 if (tui_start_enabled) 134 tui_enable (); 135 } 136 137 void suspend()138tui_interp::suspend () 139 { 140 gdb_disable_readline (); 141 tui_start_enabled = tui_active; 142 tui_disable (); 143 } 144 145 ui_out * interp_ui_out()146tui_interp::interp_ui_out () 147 { 148 if (tui_active) 149 return tui_out; 150 else 151 return tui_old_uiout; 152 } 153 154 void exec(const char * command_str)155tui_interp::exec (const char *command_str) 156 { 157 internal_error (_("tui_exec called")); 158 } 159 160 161 /* Factory for TUI interpreters. */ 162 163 static struct interp * tui_interp_factory(const char * name)164tui_interp_factory (const char *name) 165 { 166 return new tui_interp (name); 167 } 168 169 void _initialize_tui_interp (); 170 void _initialize_tui_interp()171_initialize_tui_interp () 172 { 173 interp_factory_register (INTERP_TUI, tui_interp_factory); 174 175 if (interpreter_p == INTERP_TUI) 176 tui_start_enabled = true; 177 178 if (interpreter_p == INTERP_CONSOLE) 179 interpreter_p = INTERP_TUI; 180 181 /* There are no observers here because the CLI interpreter's 182 observers work for the TUI interpreter as well. See 183 cli-interp.c. */ 184 } 185