]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/tui/tuiIO.c
* gdb.threads/killed.exp, gdb.threads/killed.c: New test.
[thirdparty/binutils-gdb.git] / gdb / tui / tuiIO.c
CommitLineData
f377b406 1/* TUI support I/O functions.
f33c6cbf
AC
2
3 Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation,
4 Inc.
5
f377b406
SC
6 Contributed by Hewlett-Packard Company.
7
8 This file is part of GDB.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA. */
c906108c 24
f33c6cbf
AC
25/* FIXME: cagney/2002-02-28: The GDB coding standard indicates that
26 "defs.h" should be included first. Unfortunatly some systems
27 (currently Debian GNU/Linux) include the <stdbool.h> via <curses.h>
28 and they clash with "bfd.h"'s definiton of true/false. The correct
29 fix is to remove true/false from "bfd.h", however, until that
30 happens, hack around it by including "config.h" and <curses.h>
31 first. */
32
4e8f7a8b
DJ
33#include "config.h"
34#ifdef HAVE_NCURSES_H
35#include <ncurses.h>
36#else
37#ifdef HAVE_CURSES_H
38#include <curses.h>
39#endif
40#endif
41
c906108c
SS
42#include <stdio.h>
43#include "defs.h"
44#include "terminal.h"
a198b876
SC
45#include "target.h"
46#include "event-loop.h"
e09d2eba 47#include "event-top.h"
a198b876
SC
48#include "command.h"
49#include "top.h"
50#include "readline/readline.h"
c906108c
SS
51#include "tui.h"
52#include "tuiData.h"
53#include "tuiIO.h"
54#include "tuiCommand.h"
55#include "tuiWin.h"
a198b876
SC
56#include "tuiGeneralWin.h"
57#include "tui-file.h"
58#include "ui-out.h"
59#include "cli-out.h"
60#include <fcntl.h>
9d876a16 61#include <signal.h>
a198b876 62
ec6f8892
SC
63/* Use definition from readline 4.3. */
64#undef CTRL_CHAR
65#define CTRL_CHAR(c) ((c) < control_character_threshold && (((c) & 0x80) == 0))
66
a198b876
SC
67/* This file controls the IO interactions between gdb and curses.
68 When the TUI is enabled, gdb has two modes a curses and a standard
69 mode.
70
71 In curses mode, the gdb outputs are made in a curses command window.
72 For this, the gdb_stdout and gdb_stderr are redirected to the specific
73 ui_file implemented by TUI. The output is handled by tui_puts().
74 The input is also controlled by curses with tui_getc(). The readline
75 library uses this function to get its input. Several readline hooks
76 are installed to redirect readline output to the TUI (see also the
77 note below).
78
79 In normal mode, the gdb outputs are restored to their origin, that
80 is as if TUI is not used. Readline also uses its original getc()
81 function with stdin.
82
83 Note: the current readline is not clean in its management of the output.
84 Even if we install a redisplay handler, it sometimes writes on a stdout
85 file. It is important to redirect every output produced by readline,
86 otherwise the curses window will be garbled. This is implemented with
87 a pipe that TUI reads and readline writes to. A gdb input handler
88 is created so that reading the pipe is handled automatically.
89 This will probably not work on non-Unix platforms. The best fix is
90 to make readline clean enougth so that is never write on stdout. */
91
92/* TUI output files. */
93static struct ui_file *tui_stdout;
94static struct ui_file *tui_stderr;
95static struct ui_out *tui_out;
96
97/* GDB output files in non-curses mode. */
98static struct ui_file *tui_old_stdout;
99static struct ui_file *tui_old_stderr;
100static struct ui_out *tui_old_uiout;
101
102/* Readline previous hooks. */
103static Function *tui_old_rl_getc_function;
104static VFunction *tui_old_rl_redisplay_function;
105static VFunction *tui_old_rl_prep_terminal;
106static VFunction *tui_old_rl_deprep_terminal;
107static int tui_old_readline_echoing_p;
108
109/* Readline output stream.
110 Should be removed when readline is clean. */
111static FILE *tui_rl_outstream;
112static FILE *tui_old_rl_outstream;
113static int tui_readline_pipe[2];
c906108c 114
a14ed312 115static unsigned int _tuiHandleResizeDuringIO (unsigned int);
c906108c
SS
116
117
a198b876 118/* Print the string in the curses command window. */
c906108c 119void
a198b876 120tui_puts (const char *string)
c906108c 121{
a198b876
SC
122 static int tui_skip_line = -1;
123 char c;
124 WINDOW *w;
c906108c 125
a198b876
SC
126 w = cmdWin->generic.handle;
127 while ((c = *string++) != 0)
c906108c 128 {
a198b876
SC
129 /* Catch annotation and discard them. We need two \032 and
130 discard until a \n is seen. */
131 if (c == '\032')
132 {
133 tui_skip_line++;
134 }
135 else if (tui_skip_line != 1)
136 {
137 tui_skip_line = -1;
138 waddch (w, c);
139 }
140 else if (c == '\n')
141 tui_skip_line = -1;
142 }
143 getyx (w, cmdWin->detail.commandInfo.curLine,
144 cmdWin->detail.commandInfo.curch);
d75e970c 145 cmdWin->detail.commandInfo.start_line = cmdWin->detail.commandInfo.curLine;
a198b876
SC
146
147 /* We could defer the following. */
148 wrefresh (w);
149 fflush (stdout);
150}
151
152/* Readline callback.
153 Redisplay the command line with its prompt after readline has
154 changed the edited text. */
e09d2eba 155void
a198b876
SC
156tui_redisplay_readline (void)
157{
158 int prev_col;
159 int height;
160 int col, line;
161 int c_pos;
162 int c_line;
163 int in;
164 WINDOW *w;
165 char *prompt;
166 int start_line;
167
e09d2eba
SC
168 if (tui_current_key_mode == tui_single_key_mode)
169 prompt = "";
170 else
171 prompt = get_prompt ();
a198b876
SC
172
173 c_pos = -1;
174 c_line = -1;
175 w = cmdWin->generic.handle;
d75e970c 176 start_line = cmdWin->detail.commandInfo.start_line;
a198b876
SC
177 wmove (w, start_line, 0);
178 prev_col = 0;
179 height = 1;
180 for (in = 0; prompt && prompt[in]; in++)
181 {
182 waddch (w, prompt[in]);
183 getyx (w, line, col);
184 if (col < prev_col)
185 height++;
186 prev_col = col;
187 }
188 for (in = 0; in < rl_end; in++)
189 {
190 unsigned char c;
191
192 c = (unsigned char) rl_line_buffer[in];
193 if (in == rl_point)
194 {
195 getyx (w, c_line, c_pos);
196 }
197
198 if (CTRL_CHAR (c) || c == RUBOUT)
199 {
200 waddch (w, '^');
201 waddch (w, CTRL_CHAR (c) ? UNCTRL (c) : '?');
202 }
c906108c
SS
203 else
204 {
a198b876 205 waddch (w, c);
c906108c 206 }
a198b876
SC
207 if (c == '\n')
208 {
d75e970c 209 getyx (w, cmdWin->detail.commandInfo.start_line,
a198b876
SC
210 cmdWin->detail.commandInfo.curch);
211 }
212 getyx (w, line, col);
213 if (col < prev_col)
214 height++;
215 prev_col = col;
c906108c 216 }
a198b876 217 wclrtobot (w);
d75e970c 218 getyx (w, cmdWin->detail.commandInfo.start_line,
a198b876
SC
219 cmdWin->detail.commandInfo.curch);
220 if (c_line >= 0)
d75e970c
SC
221 {
222 wmove (w, c_line, c_pos);
223 cmdWin->detail.commandInfo.curLine = c_line;
224 cmdWin->detail.commandInfo.curch = c_pos;
225 }
226 cmdWin->detail.commandInfo.start_line -= height - 1;
a198b876 227
a198b876
SC
228 wrefresh (w);
229 fflush(stdout);
230}
231
232/* Readline callback to prepare the terminal. It is called once
233 each time we enter readline. There is nothing to do in curses mode. */
234static void
235tui_prep_terminal (void)
c906108c 236{
a198b876 237}
c906108c 238
a198b876
SC
239/* Readline callback to restore the terminal. It is called once
240 each time we leave readline. There is nothing to do in curses mode. */
241static void
242tui_deprep_terminal (void)
243{
244}
c906108c 245
a198b876
SC
246/* Read readline output pipe and feed the command window with it.
247 Should be removed when readline is clean. */
248static void
249tui_readline_output (int code, gdb_client_data data)
250{
251 int size;
252 char buf[256];
c906108c 253
a198b876
SC
254 size = read (tui_readline_pipe[0], buf, sizeof (buf) - 1);
255 if (size > 0 && tui_active)
c906108c 256 {
a198b876
SC
257 buf[size] = 0;
258 tui_puts (buf);
c906108c 259 }
a198b876
SC
260}
261
262/* Setup the IO for curses or non-curses mode.
263 - In non-curses mode, readline and gdb use the standard input and
264 standard output/error directly.
265 - In curses mode, the standard output/error is controlled by TUI
266 with the tui_stdout and tui_stderr. The output is redirected in
267 the curses command window. Several readline callbacks are installed
268 so that readline asks for its input to the curses command window
269 with wgetch(). */
270void
271tui_setup_io (int mode)
272{
273 extern int readline_echoing_p;
274
275 if (mode)
c906108c 276 {
a198b876
SC
277 /* Redirect readline to TUI. */
278 tui_old_rl_redisplay_function = rl_redisplay_function;
279 tui_old_rl_deprep_terminal = rl_deprep_term_function;
280 tui_old_rl_prep_terminal = rl_prep_term_function;
281 tui_old_rl_getc_function = rl_getc_function;
282 tui_old_rl_outstream = rl_outstream;
283 tui_old_readline_echoing_p = readline_echoing_p;
284 rl_redisplay_function = tui_redisplay_readline;
285 rl_deprep_term_function = tui_deprep_terminal;
286 rl_prep_term_function = tui_prep_terminal;
287 rl_getc_function = tui_getc;
288 readline_echoing_p = 0;
289 rl_outstream = tui_rl_outstream;
290 rl_prompt = 0;
291
292 /* Keep track of previous gdb output. */
293 tui_old_stdout = gdb_stdout;
294 tui_old_stderr = gdb_stderr;
295 tui_old_uiout = uiout;
296
297 /* Reconfigure gdb output. */
298 gdb_stdout = tui_stdout;
299 gdb_stderr = tui_stderr;
300 gdb_stdlog = gdb_stdout; /* for moment */
301 gdb_stdtarg = gdb_stderr; /* for moment */
302 uiout = tui_out;
9d876a16
SC
303
304 /* Save tty for SIGCONT. */
305 savetty ();
c906108c 306 }
a198b876 307 else
c906108c 308 {
a198b876
SC
309 /* Restore gdb output. */
310 gdb_stdout = tui_old_stdout;
311 gdb_stderr = tui_old_stderr;
312 gdb_stdlog = gdb_stdout; /* for moment */
313 gdb_stdtarg = gdb_stderr; /* for moment */
314 uiout = tui_old_uiout;
315
316 /* Restore readline. */
317 rl_redisplay_function = tui_old_rl_redisplay_function;
318 rl_deprep_term_function = tui_old_rl_deprep_terminal;
319 rl_prep_term_function = tui_old_rl_prep_terminal;
320 rl_getc_function = tui_old_rl_getc_function;
321 rl_outstream = tui_old_rl_outstream;
322 readline_echoing_p = tui_old_readline_echoing_p;
9d876a16
SC
323
324 /* Save tty for SIGCONT. */
325 savetty ();
326 }
327}
328
329#ifdef SIGCONT
330/* Catch SIGCONT to restore the terminal and refresh the screen. */
331static void
332tui_cont_sig (int sig)
333{
334 if (tui_active)
335 {
336 /* Restore the terminal setting because another process (shell)
337 might have changed it. */
338 resetty ();
339
340 /* Force a refresh of the screen. */
341 tuiRefreshAll ();
d75e970c
SC
342
343 /* Update cursor position on the screen. */
344 wmove (cmdWin->generic.handle,
345 cmdWin->detail.commandInfo.start_line,
346 cmdWin->detail.commandInfo.curch);
347 wrefresh (cmdWin->generic.handle);
c906108c 348 }
9d876a16 349 signal (sig, tui_cont_sig);
a198b876 350}
9d876a16 351#endif
c906108c 352
a198b876
SC
353/* Initialize the IO for gdb in curses mode. */
354void
355tui_initialize_io ()
356{
9d876a16
SC
357#ifdef SIGCONT
358 signal (SIGCONT, tui_cont_sig);
359#endif
360
a198b876
SC
361 /* Create tui output streams. */
362 tui_stdout = tui_fileopen (stdout);
363 tui_stderr = tui_fileopen (stderr);
364 tui_out = tui_out_new (tui_stdout);
365
366 /* Create the default UI. It is not created because we installed
367 a init_ui_hook. */
368 uiout = cli_out_new (gdb_stdout);
369
370 /* Temporary solution for readline writing to stdout:
371 redirect readline output in a pipe, read that pipe and
372 output the content in the curses command window. */
373 if (pipe (tui_readline_pipe) != 0)
c906108c 374 {
a198b876
SC
375 fprintf_unfiltered (gdb_stderr, "Cannot create pipe for readline");
376 exit (1);
c906108c 377 }
a198b876
SC
378 tui_rl_outstream = fdopen (tui_readline_pipe[1], "w");
379 if (tui_rl_outstream == 0)
c906108c 380 {
a198b876
SC
381 fprintf_unfiltered (gdb_stderr, "Cannot redirect readline output");
382 exit (1);
c906108c 383 }
a198b876 384 setlinebuf (tui_rl_outstream);
c906108c 385
a198b876
SC
386#ifdef O_NONBLOCK
387 (void) fcntl (tui_readline_pipe[0], F_SETFL, O_NONBLOCK);
c906108c 388#else
a198b876
SC
389#ifdef O_NDELAY
390 (void) fcntl (tui_readline_pipe[0], F_SETFL, O_NDELAY);
c906108c 391#endif
a198b876
SC
392#endif
393
394 add_file_handler (tui_readline_pipe[0], tui_readline_output, 0);
395}
396
397/* Get a character from the command window. This is called from the readline
398 package. */
399int
400tui_getc (FILE *fp)
401{
402 int ch;
403 WINDOW *w;
404
405 w = cmdWin->generic.handle;
406
407 /* Flush readline output. */
408 tui_readline_output (GDB_READABLE, 0);
409
410 ch = wgetch (w);
c906108c
SS
411 ch = _tuiHandleResizeDuringIO (ch);
412
a198b876
SC
413 /* The \n must be echoed because it will not be printed by readline. */
414 if (ch == '\n')
415 {
416 /* When hitting return with an empty input, gdb executes the last
417 command. If we emit a newline, this fills up the command window
418 with empty lines with gdb prompt at beginning. Instead of that,
419 stay on the same line but provide a visual effect to show the
420 user we recognized the command. */
421 if (rl_end == 0)
422 {
423 wmove (w, cmdWin->detail.commandInfo.curLine, 0);
424
425 /* Clear the line. This will blink the gdb prompt since
426 it will be redrawn at the same line. */
427 wclrtoeol (w);
428 wrefresh (w);
429 napms (20);
430 }
431 else
432 {
433 wmove (w, cmdWin->detail.commandInfo.curLine,
434 cmdWin->detail.commandInfo.curch);
435 waddch (w, ch);
436 }
437 }
438
c906108c
SS
439 if (m_isCommandChar (ch))
440 { /* Handle prev/next/up/down here */
c906108c 441 ch = tuiDispatchCtrlChar (ch);
c906108c 442 }
a198b876 443
c906108c
SS
444 if (ch == '\n' || ch == '\r' || ch == '\f')
445 cmdWin->detail.commandInfo.curch = 0;
a198b876 446#if 0
c906108c
SS
447 else
448 tuiIncrCommandCharCountBy (1);
a198b876
SC
449#endif
450 if (ch == KEY_BACKSPACE)
451 return '\b';
452
c906108c 453 return ch;
a198b876 454}
c906108c 455
c906108c 456
a198b876
SC
457/* Cleanup when a resize has occured.
458 Returns the character that must be processed. */
c906108c 459static unsigned int
eca6576c 460_tuiHandleResizeDuringIO (unsigned int originalCh)
c906108c
SS
461{
462 if (tuiWinResized ())
463 {
e8b915dc 464 tuiRefreshAll ();
c906108c
SS
465 dont_repeat ();
466 tuiSetWinResizedTo (FALSE);
c906108c
SS
467 return '\n';
468 }
469 else
470 return originalCh;
a198b876 471}