1 /* TUI support I/O functions.
2 Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
3 Contributed by Hewlett-Packard Company.
5 This file is part of GDB.
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 2 of the License, or
10 (at your option) any later version.
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.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* If we need <curses.h>, we must include it before we get "bfd.h". */
36 #include "event-loop.h"
39 #include "readline/readline.h"
43 #include "tuiCommand.h"
45 #include "tuiGeneralWin.h"
52 /* This file controls the IO interactions between gdb and curses.
53 When the TUI is enabled, gdb has two modes a curses and a standard
56 In curses mode, the gdb outputs are made in a curses command window.
57 For this, the gdb_stdout and gdb_stderr are redirected to the specific
58 ui_file implemented by TUI. The output is handled by tui_puts().
59 The input is also controlled by curses with tui_getc(). The readline
60 library uses this function to get its input. Several readline hooks
61 are installed to redirect readline output to the TUI (see also the
64 In normal mode, the gdb outputs are restored to their origin, that
65 is as if TUI is not used. Readline also uses its original getc()
68 Note: the current readline is not clean in its management of the output.
69 Even if we install a redisplay handler, it sometimes writes on a stdout
70 file. It is important to redirect every output produced by readline,
71 otherwise the curses window will be garbled. This is implemented with
72 a pipe that TUI reads and readline writes to. A gdb input handler
73 is created so that reading the pipe is handled automatically.
74 This will probably not work on non-Unix platforms. The best fix is
75 to make readline clean enougth so that is never write on stdout. */
77 /* TUI output files. */
78 static struct ui_file
*tui_stdout
;
79 static struct ui_file
*tui_stderr
;
80 static struct ui_out
*tui_out
;
82 /* GDB output files in non-curses mode. */
83 static struct ui_file
*tui_old_stdout
;
84 static struct ui_file
*tui_old_stderr
;
85 static struct ui_out
*tui_old_uiout
;
87 /* Readline previous hooks. */
88 static Function
*tui_old_rl_getc_function
;
89 static VFunction
*tui_old_rl_redisplay_function
;
90 static VFunction
*tui_old_rl_prep_terminal
;
91 static VFunction
*tui_old_rl_deprep_terminal
;
92 static int tui_old_readline_echoing_p
;
94 /* Readline output stream.
95 Should be removed when readline is clean. */
96 static FILE *tui_rl_outstream
;
97 static FILE *tui_old_rl_outstream
;
98 static int tui_readline_pipe
[2];
100 static unsigned int _tuiHandleResizeDuringIO (unsigned int);
103 /* Print the string in the curses command window. */
105 tui_puts (const char *string
)
107 static int tui_skip_line
= -1;
111 w
= cmdWin
->generic
.handle
;
112 while ((c
= *string
++) != 0)
114 /* Catch annotation and discard them. We need two \032 and
115 discard until a \n is seen. */
120 else if (tui_skip_line
!= 1)
128 getyx (w
, cmdWin
->detail
.commandInfo
.curLine
,
129 cmdWin
->detail
.commandInfo
.curch
);
130 cmdWin
->detail
.commandInfo
.start_line
= cmdWin
->detail
.commandInfo
.curLine
;
132 /* We could defer the following. */
137 /* Readline callback.
138 Redisplay the command line with its prompt after readline has
139 changed the edited text. */
141 tui_redisplay_readline (void)
153 prompt
= get_prompt ();
157 w
= cmdWin
->generic
.handle
;
158 start_line
= cmdWin
->detail
.commandInfo
.start_line
;
159 wmove (w
, start_line
, 0);
162 for (in
= 0; prompt
&& prompt
[in
]; in
++)
164 waddch (w
, prompt
[in
]);
165 getyx (w
, line
, col
);
170 for (in
= 0; in
< rl_end
; in
++)
174 c
= (unsigned char) rl_line_buffer
[in
];
177 getyx (w
, c_line
, c_pos
);
180 if (CTRL_CHAR (c
) || c
== RUBOUT
)
183 waddch (w
, CTRL_CHAR (c
) ? UNCTRL (c
) : '?');
191 getyx (w
, cmdWin
->detail
.commandInfo
.start_line
,
192 cmdWin
->detail
.commandInfo
.curch
);
194 getyx (w
, line
, col
);
200 getyx (w
, cmdWin
->detail
.commandInfo
.start_line
,
201 cmdWin
->detail
.commandInfo
.curch
);
204 wmove (w
, c_line
, c_pos
);
205 cmdWin
->detail
.commandInfo
.curLine
= c_line
;
206 cmdWin
->detail
.commandInfo
.curch
= c_pos
;
208 cmdWin
->detail
.commandInfo
.start_line
-= height
- 1;
214 /* Readline callback to prepare the terminal. It is called once
215 each time we enter readline. There is nothing to do in curses mode. */
217 tui_prep_terminal (void)
221 /* Readline callback to restore the terminal. It is called once
222 each time we leave readline. There is nothing to do in curses mode. */
224 tui_deprep_terminal (void)
228 /* Read readline output pipe and feed the command window with it.
229 Should be removed when readline is clean. */
231 tui_readline_output (int code
, gdb_client_data data
)
236 size
= read (tui_readline_pipe
[0], buf
, sizeof (buf
) - 1);
237 if (size
> 0 && tui_active
)
244 /* Setup the IO for curses or non-curses mode.
245 - In non-curses mode, readline and gdb use the standard input and
246 standard output/error directly.
247 - In curses mode, the standard output/error is controlled by TUI
248 with the tui_stdout and tui_stderr. The output is redirected in
249 the curses command window. Several readline callbacks are installed
250 so that readline asks for its input to the curses command window
253 tui_setup_io (int mode
)
255 extern int readline_echoing_p
;
259 /* Redirect readline to TUI. */
260 tui_old_rl_redisplay_function
= rl_redisplay_function
;
261 tui_old_rl_deprep_terminal
= rl_deprep_term_function
;
262 tui_old_rl_prep_terminal
= rl_prep_term_function
;
263 tui_old_rl_getc_function
= rl_getc_function
;
264 tui_old_rl_outstream
= rl_outstream
;
265 tui_old_readline_echoing_p
= readline_echoing_p
;
266 rl_redisplay_function
= tui_redisplay_readline
;
267 rl_deprep_term_function
= tui_deprep_terminal
;
268 rl_prep_term_function
= tui_prep_terminal
;
269 rl_getc_function
= tui_getc
;
270 readline_echoing_p
= 0;
271 rl_outstream
= tui_rl_outstream
;
274 /* Keep track of previous gdb output. */
275 tui_old_stdout
= gdb_stdout
;
276 tui_old_stderr
= gdb_stderr
;
277 tui_old_uiout
= uiout
;
279 /* Reconfigure gdb output. */
280 gdb_stdout
= tui_stdout
;
281 gdb_stderr
= tui_stderr
;
282 gdb_stdlog
= gdb_stdout
; /* for moment */
283 gdb_stdtarg
= gdb_stderr
; /* for moment */
286 /* Save tty for SIGCONT. */
291 /* Restore gdb output. */
292 gdb_stdout
= tui_old_stdout
;
293 gdb_stderr
= tui_old_stderr
;
294 gdb_stdlog
= gdb_stdout
; /* for moment */
295 gdb_stdtarg
= gdb_stderr
; /* for moment */
296 uiout
= tui_old_uiout
;
298 /* Restore readline. */
299 rl_redisplay_function
= tui_old_rl_redisplay_function
;
300 rl_deprep_term_function
= tui_old_rl_deprep_terminal
;
301 rl_prep_term_function
= tui_old_rl_prep_terminal
;
302 rl_getc_function
= tui_old_rl_getc_function
;
303 rl_outstream
= tui_old_rl_outstream
;
304 readline_echoing_p
= tui_old_readline_echoing_p
;
306 /* Save tty for SIGCONT. */
312 /* Catch SIGCONT to restore the terminal and refresh the screen. */
314 tui_cont_sig (int sig
)
318 /* Restore the terminal setting because another process (shell)
319 might have changed it. */
322 /* Force a refresh of the screen. */
325 /* Update cursor position on the screen. */
326 wmove (cmdWin
->generic
.handle
,
327 cmdWin
->detail
.commandInfo
.start_line
,
328 cmdWin
->detail
.commandInfo
.curch
);
329 wrefresh (cmdWin
->generic
.handle
);
331 signal (sig
, tui_cont_sig
);
335 /* Initialize the IO for gdb in curses mode. */
340 signal (SIGCONT
, tui_cont_sig
);
343 /* Create tui output streams. */
344 tui_stdout
= tui_fileopen (stdout
);
345 tui_stderr
= tui_fileopen (stderr
);
346 tui_out
= tui_out_new (tui_stdout
);
348 /* Create the default UI. It is not created because we installed
350 uiout
= cli_out_new (gdb_stdout
);
352 /* Temporary solution for readline writing to stdout:
353 redirect readline output in a pipe, read that pipe and
354 output the content in the curses command window. */
355 if (pipe (tui_readline_pipe
) != 0)
357 fprintf_unfiltered (gdb_stderr
, "Cannot create pipe for readline");
360 tui_rl_outstream
= fdopen (tui_readline_pipe
[1], "w");
361 if (tui_rl_outstream
== 0)
363 fprintf_unfiltered (gdb_stderr
, "Cannot redirect readline output");
366 setlinebuf (tui_rl_outstream
);
369 (void) fcntl (tui_readline_pipe
[0], F_SETFL
, O_NONBLOCK
);
372 (void) fcntl (tui_readline_pipe
[0], F_SETFL
, O_NDELAY
);
376 add_file_handler (tui_readline_pipe
[0], tui_readline_output
, 0);
379 /* Get a character from the command window. This is called from the readline
387 w
= cmdWin
->generic
.handle
;
389 /* Flush readline output. */
390 tui_readline_output (GDB_READABLE
, 0);
393 ch
= _tuiHandleResizeDuringIO (ch
);
395 /* The \n must be echoed because it will not be printed by readline. */
398 /* When hitting return with an empty input, gdb executes the last
399 command. If we emit a newline, this fills up the command window
400 with empty lines with gdb prompt at beginning. Instead of that,
401 stay on the same line but provide a visual effect to show the
402 user we recognized the command. */
405 wmove (w
, cmdWin
->detail
.commandInfo
.curLine
, 0);
407 /* Clear the line. This will blink the gdb prompt since
408 it will be redrawn at the same line. */
415 wmove (w
, cmdWin
->detail
.commandInfo
.curLine
,
416 cmdWin
->detail
.commandInfo
.curch
);
421 if (m_isCommandChar (ch
))
422 { /* Handle prev/next/up/down here */
423 ch
= tuiDispatchCtrlChar (ch
);
426 if (ch
== '\n' || ch
== '\r' || ch
== '\f')
427 cmdWin
->detail
.commandInfo
.curch
= 0;
430 tuiIncrCommandCharCountBy (1);
432 if (ch
== KEY_BACKSPACE
)
439 /* Cleanup when a resize has occured.
440 Returns the character that must be processed. */
442 _tuiHandleResizeDuringIO (unsigned int originalCh
)
444 if (tuiWinResized ())
448 tuiSetWinResizedTo (FALSE
);