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