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