* tuiStack.h (tuiClearLocatorDisplay): Don't declare.
[deliverable/binutils-gdb.git] / gdb / tui / tuiIO.c
1 /* TUI support I/O functions.
2
3 Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation,
4 Inc.
5
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. */
24
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
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
42 #include <stdio.h>
43 #include "defs.h"
44 #include "terminal.h"
45 #include "target.h"
46 #include "event-loop.h"
47 #include "command.h"
48 #include "top.h"
49 #include "readline/readline.h"
50 #include "tui.h"
51 #include "tuiData.h"
52 #include "tuiIO.h"
53 #include "tuiCommand.h"
54 #include "tuiWin.h"
55 #include "tuiGeneralWin.h"
56 #include "tui-file.h"
57 #include "ui-out.h"
58 #include "cli-out.h"
59 #include <fcntl.h>
60 #include <signal.h>
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. */
88 static struct ui_file *tui_stdout;
89 static struct ui_file *tui_stderr;
90 static struct ui_out *tui_out;
91
92 /* GDB output files in non-curses mode. */
93 static struct ui_file *tui_old_stdout;
94 static struct ui_file *tui_old_stderr;
95 static struct ui_out *tui_old_uiout;
96
97 /* Readline previous hooks. */
98 static Function *tui_old_rl_getc_function;
99 static VFunction *tui_old_rl_redisplay_function;
100 static VFunction *tui_old_rl_prep_terminal;
101 static VFunction *tui_old_rl_deprep_terminal;
102 static int tui_old_readline_echoing_p;
103
104 /* Readline output stream.
105 Should be removed when readline is clean. */
106 static FILE *tui_rl_outstream;
107 static FILE *tui_old_rl_outstream;
108 static int tui_readline_pipe[2];
109
110 static unsigned int _tuiHandleResizeDuringIO (unsigned int);
111
112
113 /* Print the string in the curses command window. */
114 void
115 tui_puts (const char *string)
116 {
117 static int tui_skip_line = -1;
118 char c;
119 WINDOW *w;
120
121 w = cmdWin->generic.handle;
122 while ((c = *string++) != 0)
123 {
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);
140 cmdWin->detail.commandInfo.start_line = cmdWin->detail.commandInfo.curLine;
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. */
150 static void
151 tui_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;
168 start_line = cmdWin->detail.commandInfo.start_line;
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 }
195 else
196 {
197 waddch (w, c);
198 }
199 if (c == '\n')
200 {
201 getyx (w, cmdWin->detail.commandInfo.start_line,
202 cmdWin->detail.commandInfo.curch);
203 }
204 getyx (w, line, col);
205 if (col < prev_col)
206 height++;
207 prev_col = col;
208 }
209 wclrtobot (w);
210 getyx (w, cmdWin->detail.commandInfo.start_line,
211 cmdWin->detail.commandInfo.curch);
212 if (c_line >= 0)
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;
219
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. */
226 static void
227 tui_prep_terminal (void)
228 {
229 }
230
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. */
233 static void
234 tui_deprep_terminal (void)
235 {
236 }
237
238 /* Read readline output pipe and feed the command window with it.
239 Should be removed when readline is clean. */
240 static void
241 tui_readline_output (int code, gdb_client_data data)
242 {
243 int size;
244 char buf[256];
245
246 size = read (tui_readline_pipe[0], buf, sizeof (buf) - 1);
247 if (size > 0 && tui_active)
248 {
249 buf[size] = 0;
250 tui_puts (buf);
251 }
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(). */
262 void
263 tui_setup_io (int mode)
264 {
265 extern int readline_echoing_p;
266
267 if (mode)
268 {
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;
295
296 /* Save tty for SIGCONT. */
297 savetty ();
298 }
299 else
300 {
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;
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. */
323 static void
324 tui_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 ();
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);
340 }
341 signal (sig, tui_cont_sig);
342 }
343 #endif
344
345 /* Initialize the IO for gdb in curses mode. */
346 void
347 tui_initialize_io ()
348 {
349 #ifdef SIGCONT
350 signal (SIGCONT, tui_cont_sig);
351 #endif
352
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)
366 {
367 fprintf_unfiltered (gdb_stderr, "Cannot create pipe for readline");
368 exit (1);
369 }
370 tui_rl_outstream = fdopen (tui_readline_pipe[1], "w");
371 if (tui_rl_outstream == 0)
372 {
373 fprintf_unfiltered (gdb_stderr, "Cannot redirect readline output");
374 exit (1);
375 }
376 setlinebuf (tui_rl_outstream);
377
378 #ifdef O_NONBLOCK
379 (void) fcntl (tui_readline_pipe[0], F_SETFL, O_NONBLOCK);
380 #else
381 #ifdef O_NDELAY
382 (void) fcntl (tui_readline_pipe[0], F_SETFL, O_NDELAY);
383 #endif
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. */
391 int
392 tui_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);
403 ch = _tuiHandleResizeDuringIO (ch);
404
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
431 if (m_isCommandChar (ch))
432 { /* Handle prev/next/up/down here */
433 ch = tuiDispatchCtrlChar (ch);
434 }
435
436 if (ch == '\n' || ch == '\r' || ch == '\f')
437 cmdWin->detail.commandInfo.curch = 0;
438 #if 0
439 else
440 tuiIncrCommandCharCountBy (1);
441 #endif
442 if (ch == KEY_BACKSPACE)
443 return '\b';
444
445 return ch;
446 }
447
448
449 /* Cleanup when a resize has occured.
450 Returns the character that must be processed. */
451 static unsigned int
452 _tuiHandleResizeDuringIO (unsigned int originalCh)
453 {
454 if (tuiWinResized ())
455 {
456 tuiRefreshAll ();
457 dont_repeat ();
458 tuiSetWinResizedTo (FALSE);
459 return '\n';
460 }
461 else
462 return originalCh;
463 }
This page took 0.0412940000000001 seconds and 4 git commands to generate.