1b725ae77Skettenis /* TUI support I/O functions.
2b725ae77Skettenis
3b725ae77Skettenis Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
4b725ae77Skettenis Foundation, Inc.
5b725ae77Skettenis
6b725ae77Skettenis Contributed by Hewlett-Packard Company.
7b725ae77Skettenis
8b725ae77Skettenis This file is part of GDB.
9b725ae77Skettenis
10b725ae77Skettenis This program is free software; you can redistribute it and/or modify
11b725ae77Skettenis it under the terms of the GNU General Public License as published by
12b725ae77Skettenis the Free Software Foundation; either version 2 of the License, or
13b725ae77Skettenis (at your option) any later version.
14b725ae77Skettenis
15b725ae77Skettenis This program is distributed in the hope that it will be useful,
16b725ae77Skettenis but WITHOUT ANY WARRANTY; without even the implied warranty of
17b725ae77Skettenis MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18b725ae77Skettenis GNU General Public License for more details.
19b725ae77Skettenis
20b725ae77Skettenis You should have received a copy of the GNU General Public License
21b725ae77Skettenis along with this program; if not, write to the Free Software
22b725ae77Skettenis Foundation, Inc., 59 Temple Place - Suite 330,
23b725ae77Skettenis Boston, MA 02111-1307, USA. */
24b725ae77Skettenis
25b725ae77Skettenis #include "defs.h"
26b725ae77Skettenis #include "terminal.h"
27b725ae77Skettenis #include "target.h"
28b725ae77Skettenis #include "event-loop.h"
29b725ae77Skettenis #include "event-top.h"
30b725ae77Skettenis #include "command.h"
31b725ae77Skettenis #include "top.h"
32b725ae77Skettenis #include "tui/tui.h"
33b725ae77Skettenis #include "tui/tui-data.h"
34b725ae77Skettenis #include "tui/tui-io.h"
35b725ae77Skettenis #include "tui/tui-command.h"
36b725ae77Skettenis #include "tui/tui-win.h"
37b725ae77Skettenis #include "tui/tui-wingeneral.h"
38b725ae77Skettenis #include "tui/tui-file.h"
39b725ae77Skettenis #include "ui-out.h"
40b725ae77Skettenis #include "cli-out.h"
41b725ae77Skettenis #include <fcntl.h>
42b725ae77Skettenis #include <signal.h>
43b725ae77Skettenis #include <stdio.h>
44b725ae77Skettenis
45b725ae77Skettenis #include "gdb_curses.h"
46b725ae77Skettenis
47*11efff7fSkettenis /* This redefines CTRL if it is not already defined, so it must come
48*11efff7fSkettenis after terminal state releated include files like <term.h> and
49*11efff7fSkettenis "gdb_curses.h". */
50*11efff7fSkettenis #include "readline/readline.h"
51*11efff7fSkettenis
52b725ae77Skettenis int
key_is_start_sequence(int ch)53b725ae77Skettenis key_is_start_sequence (int ch)
54b725ae77Skettenis {
55b725ae77Skettenis return (ch == 27);
56b725ae77Skettenis }
57b725ae77Skettenis
58b725ae77Skettenis int
key_is_end_sequence(int ch)59b725ae77Skettenis key_is_end_sequence (int ch)
60b725ae77Skettenis {
61b725ae77Skettenis return (ch == 126);
62b725ae77Skettenis }
63b725ae77Skettenis
64b725ae77Skettenis int
key_is_backspace(int ch)65b725ae77Skettenis key_is_backspace (int ch)
66b725ae77Skettenis {
67b725ae77Skettenis return (ch == 8);
68b725ae77Skettenis }
69b725ae77Skettenis
70b725ae77Skettenis int
key_is_command_char(int ch)71b725ae77Skettenis key_is_command_char (int ch)
72b725ae77Skettenis {
73b725ae77Skettenis return ((ch == KEY_NPAGE) || (ch == KEY_PPAGE)
74b725ae77Skettenis || (ch == KEY_LEFT) || (ch == KEY_RIGHT)
75b725ae77Skettenis || (ch == KEY_UP) || (ch == KEY_DOWN)
76b725ae77Skettenis || (ch == KEY_SF) || (ch == KEY_SR)
77b725ae77Skettenis || (ch == (int)'\f') || key_is_start_sequence (ch));
78b725ae77Skettenis }
79b725ae77Skettenis
80b725ae77Skettenis /* Use definition from readline 4.3. */
81b725ae77Skettenis #undef CTRL_CHAR
82b725ae77Skettenis #define CTRL_CHAR(c) ((c) < control_character_threshold && (((c) & 0x80) == 0))
83b725ae77Skettenis
84b725ae77Skettenis /* This file controls the IO interactions between gdb and curses.
85b725ae77Skettenis When the TUI is enabled, gdb has two modes a curses and a standard
86b725ae77Skettenis mode.
87b725ae77Skettenis
88b725ae77Skettenis In curses mode, the gdb outputs are made in a curses command window.
89b725ae77Skettenis For this, the gdb_stdout and gdb_stderr are redirected to the specific
90b725ae77Skettenis ui_file implemented by TUI. The output is handled by tui_puts().
91b725ae77Skettenis The input is also controlled by curses with tui_getc(). The readline
92b725ae77Skettenis library uses this function to get its input. Several readline hooks
93b725ae77Skettenis are installed to redirect readline output to the TUI (see also the
94b725ae77Skettenis note below).
95b725ae77Skettenis
96b725ae77Skettenis In normal mode, the gdb outputs are restored to their origin, that
97b725ae77Skettenis is as if TUI is not used. Readline also uses its original getc()
98b725ae77Skettenis function with stdin.
99b725ae77Skettenis
100b725ae77Skettenis Note SCz/2001-07-21: the current readline is not clean in its management of
101b725ae77Skettenis the output. Even if we install a redisplay handler, it sometimes writes on
102b725ae77Skettenis a stdout file. It is important to redirect every output produced by
103b725ae77Skettenis readline, otherwise the curses window will be garbled. This is implemented
104b725ae77Skettenis with a pipe that TUI reads and readline writes to. A gdb input handler
105b725ae77Skettenis is created so that reading the pipe is handled automatically.
106b725ae77Skettenis This will probably not work on non-Unix platforms. The best fix is
107b725ae77Skettenis to make readline clean enougth so that is never write on stdout.
108b725ae77Skettenis
109b725ae77Skettenis Note SCz/2002-09-01: we now use more readline hooks and it seems that
110b725ae77Skettenis with them we don't need the pipe anymore (verified by creating the pipe
111b725ae77Skettenis and closing its end so that write causes a SIGPIPE). The old pipe code
112b725ae77Skettenis is still there and can be conditionally removed by
113b725ae77Skettenis #undef TUI_USE_PIPE_FOR_READLINE. */
114b725ae77Skettenis
115b725ae77Skettenis /* For gdb 5.3, prefer to continue the pipe hack as a backup wheel. */
116b725ae77Skettenis #define TUI_USE_PIPE_FOR_READLINE
117b725ae77Skettenis /*#undef TUI_USE_PIPE_FOR_READLINE*/
118b725ae77Skettenis
119b725ae77Skettenis /* TUI output files. */
120b725ae77Skettenis static struct ui_file *tui_stdout;
121b725ae77Skettenis static struct ui_file *tui_stderr;
122b725ae77Skettenis struct ui_out *tui_out;
123b725ae77Skettenis
124b725ae77Skettenis /* GDB output files in non-curses mode. */
125b725ae77Skettenis static struct ui_file *tui_old_stdout;
126b725ae77Skettenis static struct ui_file *tui_old_stderr;
127b725ae77Skettenis struct ui_out *tui_old_uiout;
128b725ae77Skettenis
129b725ae77Skettenis /* Readline previous hooks. */
130b725ae77Skettenis static Function *tui_old_rl_getc_function;
131b725ae77Skettenis static VFunction *tui_old_rl_redisplay_function;
132b725ae77Skettenis static VFunction *tui_old_rl_prep_terminal;
133b725ae77Skettenis static VFunction *tui_old_rl_deprep_terminal;
134b725ae77Skettenis static int tui_old_readline_echoing_p;
135b725ae77Skettenis
136b725ae77Skettenis /* Readline output stream.
137b725ae77Skettenis Should be removed when readline is clean. */
138b725ae77Skettenis static FILE *tui_rl_outstream;
139b725ae77Skettenis static FILE *tui_old_rl_outstream;
140b725ae77Skettenis #ifdef TUI_USE_PIPE_FOR_READLINE
141b725ae77Skettenis static int tui_readline_pipe[2];
142b725ae77Skettenis #endif
143b725ae77Skettenis
144b725ae77Skettenis /* The last gdb prompt that was registered in readline.
145b725ae77Skettenis This may be the main gdb prompt or a secondary prompt. */
146b725ae77Skettenis static char *tui_rl_saved_prompt;
147b725ae77Skettenis
148b725ae77Skettenis static unsigned int tui_handle_resize_during_io (unsigned int);
149b725ae77Skettenis
150b725ae77Skettenis static void
tui_putc(char c)151b725ae77Skettenis tui_putc (char c)
152b725ae77Skettenis {
153b725ae77Skettenis char buf[2];
154b725ae77Skettenis
155b725ae77Skettenis buf[0] = c;
156b725ae77Skettenis buf[1] = 0;
157b725ae77Skettenis tui_puts (buf);
158b725ae77Skettenis }
159b725ae77Skettenis
160b725ae77Skettenis /* Print the string in the curses command window. */
161b725ae77Skettenis void
tui_puts(const char * string)162b725ae77Skettenis tui_puts (const char *string)
163b725ae77Skettenis {
164b725ae77Skettenis static int tui_skip_line = -1;
165b725ae77Skettenis char c;
166b725ae77Skettenis WINDOW *w;
167b725ae77Skettenis
168b725ae77Skettenis w = TUI_CMD_WIN->generic.handle;
169b725ae77Skettenis while ((c = *string++) != 0)
170b725ae77Skettenis {
171b725ae77Skettenis /* Catch annotation and discard them. We need two \032 and
172b725ae77Skettenis discard until a \n is seen. */
173b725ae77Skettenis if (c == '\032')
174b725ae77Skettenis {
175b725ae77Skettenis tui_skip_line++;
176b725ae77Skettenis }
177b725ae77Skettenis else if (tui_skip_line != 1)
178b725ae77Skettenis {
179b725ae77Skettenis tui_skip_line = -1;
180b725ae77Skettenis waddch (w, c);
181b725ae77Skettenis }
182b725ae77Skettenis else if (c == '\n')
183b725ae77Skettenis tui_skip_line = -1;
184b725ae77Skettenis }
185b725ae77Skettenis getyx (w, TUI_CMD_WIN->detail.command_info.cur_line,
186b725ae77Skettenis TUI_CMD_WIN->detail.command_info.curch);
187b725ae77Skettenis TUI_CMD_WIN->detail.command_info.start_line = TUI_CMD_WIN->detail.command_info.cur_line;
188b725ae77Skettenis
189b725ae77Skettenis /* We could defer the following. */
190b725ae77Skettenis wrefresh (w);
191b725ae77Skettenis fflush (stdout);
192b725ae77Skettenis }
193b725ae77Skettenis
194b725ae77Skettenis /* Readline callback.
195b725ae77Skettenis Redisplay the command line with its prompt after readline has
196b725ae77Skettenis changed the edited text. */
197b725ae77Skettenis void
tui_redisplay_readline(void)198b725ae77Skettenis tui_redisplay_readline (void)
199b725ae77Skettenis {
200b725ae77Skettenis int prev_col;
201b725ae77Skettenis int height;
202b725ae77Skettenis int col, line;
203b725ae77Skettenis int c_pos;
204b725ae77Skettenis int c_line;
205b725ae77Skettenis int in;
206b725ae77Skettenis WINDOW *w;
207b725ae77Skettenis char *prompt;
208b725ae77Skettenis int start_line;
209b725ae77Skettenis
210b725ae77Skettenis /* Detect when we temporarily left SingleKey and now the readline
211b725ae77Skettenis edit buffer is empty, automatically restore the SingleKey mode. */
212b725ae77Skettenis if (tui_current_key_mode == TUI_ONE_COMMAND_MODE && rl_end == 0)
213b725ae77Skettenis tui_set_key_mode (TUI_SINGLE_KEY_MODE);
214b725ae77Skettenis
215b725ae77Skettenis if (tui_current_key_mode == TUI_SINGLE_KEY_MODE)
216b725ae77Skettenis prompt = "";
217b725ae77Skettenis else
218b725ae77Skettenis prompt = tui_rl_saved_prompt;
219b725ae77Skettenis
220b725ae77Skettenis c_pos = -1;
221b725ae77Skettenis c_line = -1;
222b725ae77Skettenis w = TUI_CMD_WIN->generic.handle;
223b725ae77Skettenis start_line = TUI_CMD_WIN->detail.command_info.start_line;
224b725ae77Skettenis wmove (w, start_line, 0);
225b725ae77Skettenis prev_col = 0;
226b725ae77Skettenis height = 1;
227b725ae77Skettenis for (in = 0; prompt && prompt[in]; in++)
228b725ae77Skettenis {
229b725ae77Skettenis waddch (w, prompt[in]);
230b725ae77Skettenis getyx (w, line, col);
231b725ae77Skettenis if (col < prev_col)
232b725ae77Skettenis height++;
233b725ae77Skettenis prev_col = col;
234b725ae77Skettenis }
235b725ae77Skettenis for (in = 0; in < rl_end; in++)
236b725ae77Skettenis {
237b725ae77Skettenis unsigned char c;
238b725ae77Skettenis
239b725ae77Skettenis c = (unsigned char) rl_line_buffer[in];
240b725ae77Skettenis if (in == rl_point)
241b725ae77Skettenis {
242b725ae77Skettenis getyx (w, c_line, c_pos);
243b725ae77Skettenis }
244b725ae77Skettenis
245b725ae77Skettenis if (CTRL_CHAR (c) || c == RUBOUT)
246b725ae77Skettenis {
247b725ae77Skettenis waddch (w, '^');
248b725ae77Skettenis waddch (w, CTRL_CHAR (c) ? UNCTRL (c) : '?');
249b725ae77Skettenis }
250b725ae77Skettenis else
251b725ae77Skettenis {
252b725ae77Skettenis waddch (w, c);
253b725ae77Skettenis }
254b725ae77Skettenis if (c == '\n')
255b725ae77Skettenis {
256b725ae77Skettenis getyx (w, TUI_CMD_WIN->detail.command_info.start_line,
257b725ae77Skettenis TUI_CMD_WIN->detail.command_info.curch);
258b725ae77Skettenis }
259b725ae77Skettenis getyx (w, line, col);
260b725ae77Skettenis if (col < prev_col)
261b725ae77Skettenis height++;
262b725ae77Skettenis prev_col = col;
263b725ae77Skettenis }
264b725ae77Skettenis wclrtobot (w);
265b725ae77Skettenis getyx (w, TUI_CMD_WIN->detail.command_info.start_line,
266b725ae77Skettenis TUI_CMD_WIN->detail.command_info.curch);
267b725ae77Skettenis if (c_line >= 0)
268b725ae77Skettenis {
269b725ae77Skettenis wmove (w, c_line, c_pos);
270b725ae77Skettenis TUI_CMD_WIN->detail.command_info.cur_line = c_line;
271b725ae77Skettenis TUI_CMD_WIN->detail.command_info.curch = c_pos;
272b725ae77Skettenis }
273b725ae77Skettenis TUI_CMD_WIN->detail.command_info.start_line -= height - 1;
274b725ae77Skettenis
275b725ae77Skettenis wrefresh (w);
276b725ae77Skettenis fflush(stdout);
277b725ae77Skettenis }
278b725ae77Skettenis
279b725ae77Skettenis /* Readline callback to prepare the terminal. It is called once
280b725ae77Skettenis each time we enter readline. Terminal is already setup in curses mode. */
281b725ae77Skettenis static void
tui_prep_terminal(int notused1)282b725ae77Skettenis tui_prep_terminal (int notused1)
283b725ae77Skettenis {
284b725ae77Skettenis /* Save the prompt registered in readline to correctly display it.
285b725ae77Skettenis (we can't use gdb_prompt() due to secondary prompts and can't use
286b725ae77Skettenis rl_prompt because it points to an alloca buffer). */
287b725ae77Skettenis xfree (tui_rl_saved_prompt);
288b725ae77Skettenis tui_rl_saved_prompt = xstrdup (rl_prompt);
289b725ae77Skettenis }
290b725ae77Skettenis
291b725ae77Skettenis /* Readline callback to restore the terminal. It is called once
292b725ae77Skettenis each time we leave readline. There is nothing to do in curses mode. */
293b725ae77Skettenis static void
tui_deprep_terminal(void)294b725ae77Skettenis tui_deprep_terminal (void)
295b725ae77Skettenis {
296b725ae77Skettenis }
297b725ae77Skettenis
298b725ae77Skettenis #ifdef TUI_USE_PIPE_FOR_READLINE
299b725ae77Skettenis /* Read readline output pipe and feed the command window with it.
300b725ae77Skettenis Should be removed when readline is clean. */
301b725ae77Skettenis static void
tui_readline_output(int code,gdb_client_data data)302b725ae77Skettenis tui_readline_output (int code, gdb_client_data data)
303b725ae77Skettenis {
304b725ae77Skettenis int size;
305b725ae77Skettenis char buf[256];
306b725ae77Skettenis
307b725ae77Skettenis size = read (tui_readline_pipe[0], buf, sizeof (buf) - 1);
308b725ae77Skettenis if (size > 0 && tui_active)
309b725ae77Skettenis {
310b725ae77Skettenis buf[size] = 0;
311b725ae77Skettenis tui_puts (buf);
312b725ae77Skettenis }
313b725ae77Skettenis }
314b725ae77Skettenis #endif
315b725ae77Skettenis
316b725ae77Skettenis /* Return the portion of PATHNAME that should be output when listing
317b725ae77Skettenis possible completions. If we are hacking filename completion, we
318b725ae77Skettenis are only interested in the basename, the portion following the
319b725ae77Skettenis final slash. Otherwise, we return what we were passed.
320b725ae77Skettenis
321b725ae77Skettenis Comes from readline/complete.c */
322b725ae77Skettenis static char *
printable_part(char * pathname)323b725ae77Skettenis printable_part (char *pathname)
324b725ae77Skettenis {
325b725ae77Skettenis char *temp;
326b725ae77Skettenis
327b725ae77Skettenis temp = rl_filename_completion_desired ? strrchr (pathname, '/') : (char *)NULL;
328b725ae77Skettenis #if defined (__MSDOS__)
329b725ae77Skettenis if (rl_filename_completion_desired && temp == 0 && isalpha (pathname[0]) && pathname[1] == ':')
330b725ae77Skettenis temp = pathname + 1;
331b725ae77Skettenis #endif
332b725ae77Skettenis return (temp ? ++temp : pathname);
333b725ae77Skettenis }
334b725ae77Skettenis
335b725ae77Skettenis /* Output TO_PRINT to rl_outstream. If VISIBLE_STATS is defined and we
336b725ae77Skettenis are using it, check for and output a single character for `special'
337b725ae77Skettenis filenames. Return the number of characters we output. */
338b725ae77Skettenis
339b725ae77Skettenis #define PUTX(c) \
340b725ae77Skettenis do { \
341b725ae77Skettenis if (CTRL_CHAR (c)) \
342b725ae77Skettenis { \
343b725ae77Skettenis tui_puts ("^"); \
344b725ae77Skettenis tui_putc (UNCTRL (c)); \
345b725ae77Skettenis printed_len += 2; \
346b725ae77Skettenis } \
347b725ae77Skettenis else if (c == RUBOUT) \
348b725ae77Skettenis { \
349b725ae77Skettenis tui_puts ("^?"); \
350b725ae77Skettenis printed_len += 2; \
351b725ae77Skettenis } \
352b725ae77Skettenis else \
353b725ae77Skettenis { \
354b725ae77Skettenis tui_putc (c); \
355b725ae77Skettenis printed_len++; \
356b725ae77Skettenis } \
357b725ae77Skettenis } while (0)
358b725ae77Skettenis
359b725ae77Skettenis static int
print_filename(char * to_print,char * full_pathname)360b725ae77Skettenis print_filename (char *to_print, char *full_pathname)
361b725ae77Skettenis {
362b725ae77Skettenis int printed_len = 0;
363b725ae77Skettenis char *s;
364b725ae77Skettenis
365b725ae77Skettenis for (s = to_print; *s; s++)
366b725ae77Skettenis {
367b725ae77Skettenis PUTX (*s);
368b725ae77Skettenis }
369b725ae77Skettenis return printed_len;
370b725ae77Skettenis }
371b725ae77Skettenis
372b725ae77Skettenis /* The user must press "y" or "n". Non-zero return means "y" pressed.
373b725ae77Skettenis Comes from readline/complete.c */
374b725ae77Skettenis static int
get_y_or_n(void)375b725ae77Skettenis get_y_or_n (void)
376b725ae77Skettenis {
377b725ae77Skettenis extern int _rl_abort_internal ();
378b725ae77Skettenis int c;
379b725ae77Skettenis
380b725ae77Skettenis for (;;)
381b725ae77Skettenis {
382b725ae77Skettenis c = rl_read_key ();
383b725ae77Skettenis if (c == 'y' || c == 'Y' || c == ' ')
384b725ae77Skettenis return (1);
385b725ae77Skettenis if (c == 'n' || c == 'N' || c == RUBOUT)
386b725ae77Skettenis return (0);
387b725ae77Skettenis if (c == ABORT_CHAR)
388b725ae77Skettenis _rl_abort_internal ();
389b725ae77Skettenis beep ();
390b725ae77Skettenis }
391b725ae77Skettenis }
392b725ae77Skettenis
393b725ae77Skettenis /* A convenience function for displaying a list of strings in
394b725ae77Skettenis columnar format on readline's output stream. MATCHES is the list
395b725ae77Skettenis of strings, in argv format, LEN is the number of strings in MATCHES,
396b725ae77Skettenis and MAX is the length of the longest string in MATCHES.
397b725ae77Skettenis
398b725ae77Skettenis Comes from readline/complete.c and modified to write in
399b725ae77Skettenis the TUI command window using tui_putc/tui_puts. */
400b725ae77Skettenis static void
tui_rl_display_match_list(char ** matches,int len,int max)401b725ae77Skettenis tui_rl_display_match_list (char **matches, int len, int max)
402b725ae77Skettenis {
403b725ae77Skettenis typedef int QSFUNC (const void *, const void *);
404b725ae77Skettenis extern int _rl_qsort_string_compare (const void*, const void*);
405b725ae77Skettenis extern int _rl_print_completions_horizontally;
406b725ae77Skettenis
407b725ae77Skettenis int count, limit, printed_len;
408b725ae77Skettenis int i, j, k, l;
409b725ae77Skettenis char *temp;
410b725ae77Skettenis
411b725ae77Skettenis /* Screen dimension correspond to the TUI command window. */
412b725ae77Skettenis int screenwidth = TUI_CMD_WIN->generic.width;
413b725ae77Skettenis
414b725ae77Skettenis /* If there are many items, then ask the user if she really wants to
415b725ae77Skettenis see them all. */
416b725ae77Skettenis if (len >= rl_completion_query_items)
417b725ae77Skettenis {
418b725ae77Skettenis char msg[256];
419b725ae77Skettenis
420b725ae77Skettenis sprintf (msg, "\nDisplay all %d possibilities? (y or n)", len);
421b725ae77Skettenis tui_puts (msg);
422b725ae77Skettenis if (get_y_or_n () == 0)
423b725ae77Skettenis {
424b725ae77Skettenis tui_puts ("\n");
425b725ae77Skettenis return;
426b725ae77Skettenis }
427b725ae77Skettenis }
428b725ae77Skettenis
429b725ae77Skettenis /* How many items of MAX length can we fit in the screen window? */
430b725ae77Skettenis max += 2;
431b725ae77Skettenis limit = screenwidth / max;
432b725ae77Skettenis if (limit != 1 && (limit * max == screenwidth))
433b725ae77Skettenis limit--;
434b725ae77Skettenis
435b725ae77Skettenis /* Avoid a possible floating exception. If max > screenwidth,
436b725ae77Skettenis limit will be 0 and a divide-by-zero fault will result. */
437b725ae77Skettenis if (limit == 0)
438b725ae77Skettenis limit = 1;
439b725ae77Skettenis
440b725ae77Skettenis /* How many iterations of the printing loop? */
441b725ae77Skettenis count = (len + (limit - 1)) / limit;
442b725ae77Skettenis
443b725ae77Skettenis /* Watch out for special case. If LEN is less than LIMIT, then
444b725ae77Skettenis just do the inner printing loop.
445b725ae77Skettenis 0 < len <= limit implies count = 1. */
446b725ae77Skettenis
447b725ae77Skettenis /* Sort the items if they are not already sorted. */
448b725ae77Skettenis if (rl_ignore_completion_duplicates == 0)
449b725ae77Skettenis qsort (matches + 1, len, sizeof (char *),
450b725ae77Skettenis (QSFUNC *)_rl_qsort_string_compare);
451b725ae77Skettenis
452b725ae77Skettenis tui_putc ('\n');
453b725ae77Skettenis
454b725ae77Skettenis if (_rl_print_completions_horizontally == 0)
455b725ae77Skettenis {
456b725ae77Skettenis /* Print the sorted items, up-and-down alphabetically, like ls. */
457b725ae77Skettenis for (i = 1; i <= count; i++)
458b725ae77Skettenis {
459b725ae77Skettenis for (j = 0, l = i; j < limit; j++)
460b725ae77Skettenis {
461b725ae77Skettenis if (l > len || matches[l] == 0)
462b725ae77Skettenis break;
463b725ae77Skettenis else
464b725ae77Skettenis {
465b725ae77Skettenis temp = printable_part (matches[l]);
466b725ae77Skettenis printed_len = print_filename (temp, matches[l]);
467b725ae77Skettenis
468b725ae77Skettenis if (j + 1 < limit)
469b725ae77Skettenis for (k = 0; k < max - printed_len; k++)
470b725ae77Skettenis tui_putc (' ');
471b725ae77Skettenis }
472b725ae77Skettenis l += count;
473b725ae77Skettenis }
474b725ae77Skettenis tui_putc ('\n');
475b725ae77Skettenis }
476b725ae77Skettenis }
477b725ae77Skettenis else
478b725ae77Skettenis {
479b725ae77Skettenis /* Print the sorted items, across alphabetically, like ls -x. */
480b725ae77Skettenis for (i = 1; matches[i]; i++)
481b725ae77Skettenis {
482b725ae77Skettenis temp = printable_part (matches[i]);
483b725ae77Skettenis printed_len = print_filename (temp, matches[i]);
484b725ae77Skettenis /* Have we reached the end of this line? */
485b725ae77Skettenis if (matches[i+1])
486b725ae77Skettenis {
487b725ae77Skettenis if (i && (limit > 1) && (i % limit) == 0)
488b725ae77Skettenis tui_putc ('\n');
489b725ae77Skettenis else
490b725ae77Skettenis for (k = 0; k < max - printed_len; k++)
491b725ae77Skettenis tui_putc (' ');
492b725ae77Skettenis }
493b725ae77Skettenis }
494b725ae77Skettenis tui_putc ('\n');
495b725ae77Skettenis }
496b725ae77Skettenis }
497b725ae77Skettenis
498b725ae77Skettenis /* Setup the IO for curses or non-curses mode.
499b725ae77Skettenis - In non-curses mode, readline and gdb use the standard input and
500b725ae77Skettenis standard output/error directly.
501b725ae77Skettenis - In curses mode, the standard output/error is controlled by TUI
502b725ae77Skettenis with the tui_stdout and tui_stderr. The output is redirected in
503b725ae77Skettenis the curses command window. Several readline callbacks are installed
504b725ae77Skettenis so that readline asks for its input to the curses command window
505b725ae77Skettenis with wgetch(). */
506b725ae77Skettenis void
tui_setup_io(int mode)507b725ae77Skettenis tui_setup_io (int mode)
508b725ae77Skettenis {
509b725ae77Skettenis extern int readline_echoing_p;
510b725ae77Skettenis
511b725ae77Skettenis if (mode)
512b725ae77Skettenis {
513b725ae77Skettenis /* Redirect readline to TUI. */
514b725ae77Skettenis tui_old_rl_redisplay_function = rl_redisplay_function;
515b725ae77Skettenis tui_old_rl_deprep_terminal = rl_deprep_term_function;
516b725ae77Skettenis tui_old_rl_prep_terminal = rl_prep_term_function;
517b725ae77Skettenis tui_old_rl_getc_function = rl_getc_function;
518b725ae77Skettenis tui_old_rl_outstream = rl_outstream;
519b725ae77Skettenis tui_old_readline_echoing_p = readline_echoing_p;
520b725ae77Skettenis rl_redisplay_function = tui_redisplay_readline;
521b725ae77Skettenis rl_deprep_term_function = tui_deprep_terminal;
522b725ae77Skettenis rl_prep_term_function = tui_prep_terminal;
523b725ae77Skettenis rl_getc_function = tui_getc;
524b725ae77Skettenis readline_echoing_p = 0;
525b725ae77Skettenis rl_outstream = tui_rl_outstream;
526b725ae77Skettenis rl_prompt = 0;
527b725ae77Skettenis rl_completion_display_matches_hook = tui_rl_display_match_list;
528b725ae77Skettenis rl_already_prompted = 0;
529b725ae77Skettenis
530b725ae77Skettenis /* Keep track of previous gdb output. */
531b725ae77Skettenis tui_old_stdout = gdb_stdout;
532b725ae77Skettenis tui_old_stderr = gdb_stderr;
533b725ae77Skettenis tui_old_uiout = uiout;
534b725ae77Skettenis
535b725ae77Skettenis /* Reconfigure gdb output. */
536b725ae77Skettenis gdb_stdout = tui_stdout;
537b725ae77Skettenis gdb_stderr = tui_stderr;
538b725ae77Skettenis gdb_stdlog = gdb_stdout; /* for moment */
539b725ae77Skettenis gdb_stdtarg = gdb_stderr; /* for moment */
540b725ae77Skettenis uiout = tui_out;
541b725ae77Skettenis
542b725ae77Skettenis /* Save tty for SIGCONT. */
543b725ae77Skettenis savetty ();
544b725ae77Skettenis }
545b725ae77Skettenis else
546b725ae77Skettenis {
547b725ae77Skettenis /* Restore gdb output. */
548b725ae77Skettenis gdb_stdout = tui_old_stdout;
549b725ae77Skettenis gdb_stderr = tui_old_stderr;
550b725ae77Skettenis gdb_stdlog = gdb_stdout; /* for moment */
551b725ae77Skettenis gdb_stdtarg = gdb_stderr; /* for moment */
552b725ae77Skettenis uiout = tui_old_uiout;
553b725ae77Skettenis
554b725ae77Skettenis /* Restore readline. */
555b725ae77Skettenis rl_redisplay_function = tui_old_rl_redisplay_function;
556b725ae77Skettenis rl_deprep_term_function = tui_old_rl_deprep_terminal;
557b725ae77Skettenis rl_prep_term_function = tui_old_rl_prep_terminal;
558b725ae77Skettenis rl_getc_function = tui_old_rl_getc_function;
559b725ae77Skettenis rl_outstream = tui_old_rl_outstream;
560b725ae77Skettenis rl_completion_display_matches_hook = 0;
561b725ae77Skettenis readline_echoing_p = tui_old_readline_echoing_p;
562b725ae77Skettenis rl_already_prompted = 0;
563b725ae77Skettenis
564b725ae77Skettenis /* Save tty for SIGCONT. */
565b725ae77Skettenis savetty ();
566b725ae77Skettenis }
567b725ae77Skettenis }
568b725ae77Skettenis
569b725ae77Skettenis #ifdef SIGCONT
570b725ae77Skettenis /* Catch SIGCONT to restore the terminal and refresh the screen. */
571b725ae77Skettenis static void
tui_cont_sig(int sig)572b725ae77Skettenis tui_cont_sig (int sig)
573b725ae77Skettenis {
574b725ae77Skettenis if (tui_active)
575b725ae77Skettenis {
576b725ae77Skettenis /* Restore the terminal setting because another process (shell)
577b725ae77Skettenis might have changed it. */
578b725ae77Skettenis resetty ();
579b725ae77Skettenis
580b725ae77Skettenis /* Force a refresh of the screen. */
581b725ae77Skettenis tui_refresh_all_win ();
582b725ae77Skettenis
583b725ae77Skettenis /* Update cursor position on the screen. */
584b725ae77Skettenis wmove (TUI_CMD_WIN->generic.handle,
585b725ae77Skettenis TUI_CMD_WIN->detail.command_info.start_line,
586b725ae77Skettenis TUI_CMD_WIN->detail.command_info.curch);
587b725ae77Skettenis wrefresh (TUI_CMD_WIN->generic.handle);
588b725ae77Skettenis }
589b725ae77Skettenis signal (sig, tui_cont_sig);
590b725ae77Skettenis }
591b725ae77Skettenis #endif
592b725ae77Skettenis
593b725ae77Skettenis /* Initialize the IO for gdb in curses mode. */
594b725ae77Skettenis void
tui_initialize_io(void)595b725ae77Skettenis tui_initialize_io (void)
596b725ae77Skettenis {
597b725ae77Skettenis #ifdef SIGCONT
598b725ae77Skettenis signal (SIGCONT, tui_cont_sig);
599b725ae77Skettenis #endif
600b725ae77Skettenis
601b725ae77Skettenis /* Create tui output streams. */
602b725ae77Skettenis tui_stdout = tui_fileopen (stdout);
603b725ae77Skettenis tui_stderr = tui_fileopen (stderr);
604b725ae77Skettenis tui_out = tui_out_new (tui_stdout);
605b725ae77Skettenis
606*11efff7fSkettenis /* Create the default UI. It is not created because we installed a
607*11efff7fSkettenis deprecated_init_ui_hook. */
608b725ae77Skettenis tui_old_uiout = uiout = cli_out_new (gdb_stdout);
609b725ae77Skettenis
610b725ae77Skettenis #ifdef TUI_USE_PIPE_FOR_READLINE
611b725ae77Skettenis /* Temporary solution for readline writing to stdout:
612b725ae77Skettenis redirect readline output in a pipe, read that pipe and
613b725ae77Skettenis output the content in the curses command window. */
614b725ae77Skettenis if (pipe (tui_readline_pipe) != 0)
615b725ae77Skettenis {
616b725ae77Skettenis fprintf_unfiltered (gdb_stderr, "Cannot create pipe for readline");
617b725ae77Skettenis exit (1);
618b725ae77Skettenis }
619b725ae77Skettenis tui_rl_outstream = fdopen (tui_readline_pipe[1], "w");
620b725ae77Skettenis if (tui_rl_outstream == 0)
621b725ae77Skettenis {
622b725ae77Skettenis fprintf_unfiltered (gdb_stderr, "Cannot redirect readline output");
623b725ae77Skettenis exit (1);
624b725ae77Skettenis }
625b725ae77Skettenis setvbuf (tui_rl_outstream, (char*) NULL, _IOLBF, 0);
626b725ae77Skettenis
627b725ae77Skettenis #ifdef O_NONBLOCK
628b725ae77Skettenis (void) fcntl (tui_readline_pipe[0], F_SETFL, O_NONBLOCK);
629b725ae77Skettenis #else
630b725ae77Skettenis #ifdef O_NDELAY
631b725ae77Skettenis (void) fcntl (tui_readline_pipe[0], F_SETFL, O_NDELAY);
632b725ae77Skettenis #endif
633b725ae77Skettenis #endif
634b725ae77Skettenis add_file_handler (tui_readline_pipe[0], tui_readline_output, 0);
635b725ae77Skettenis #else
636b725ae77Skettenis tui_rl_outstream = stdout;
637b725ae77Skettenis #endif
638b725ae77Skettenis }
639b725ae77Skettenis
640b725ae77Skettenis /* Get a character from the command window. This is called from the readline
641b725ae77Skettenis package. */
642b725ae77Skettenis int
tui_getc(FILE * fp)643b725ae77Skettenis tui_getc (FILE *fp)
644b725ae77Skettenis {
645b725ae77Skettenis int ch;
646b725ae77Skettenis WINDOW *w;
647b725ae77Skettenis
648b725ae77Skettenis w = TUI_CMD_WIN->generic.handle;
649b725ae77Skettenis
650b725ae77Skettenis #ifdef TUI_USE_PIPE_FOR_READLINE
651b725ae77Skettenis /* Flush readline output. */
652b725ae77Skettenis tui_readline_output (GDB_READABLE, 0);
653b725ae77Skettenis #endif
654b725ae77Skettenis
655b725ae77Skettenis ch = wgetch (w);
656b725ae77Skettenis ch = tui_handle_resize_during_io (ch);
657b725ae77Skettenis
658b725ae77Skettenis /* The \n must be echoed because it will not be printed by readline. */
659b725ae77Skettenis if (ch == '\n')
660b725ae77Skettenis {
661b725ae77Skettenis /* When hitting return with an empty input, gdb executes the last
662b725ae77Skettenis command. If we emit a newline, this fills up the command window
663b725ae77Skettenis with empty lines with gdb prompt at beginning. Instead of that,
664b725ae77Skettenis stay on the same line but provide a visual effect to show the
665b725ae77Skettenis user we recognized the command. */
666b725ae77Skettenis if (rl_end == 0)
667b725ae77Skettenis {
668b725ae77Skettenis wmove (w, TUI_CMD_WIN->detail.command_info.cur_line, 0);
669b725ae77Skettenis
670b725ae77Skettenis /* Clear the line. This will blink the gdb prompt since
671b725ae77Skettenis it will be redrawn at the same line. */
672b725ae77Skettenis wclrtoeol (w);
673b725ae77Skettenis wrefresh (w);
674b725ae77Skettenis napms (20);
675b725ae77Skettenis }
676b725ae77Skettenis else
677b725ae77Skettenis {
678b725ae77Skettenis wmove (w, TUI_CMD_WIN->detail.command_info.cur_line,
679b725ae77Skettenis TUI_CMD_WIN->detail.command_info.curch);
680b725ae77Skettenis waddch (w, ch);
681b725ae77Skettenis }
682b725ae77Skettenis }
683b725ae77Skettenis
684b725ae77Skettenis if (key_is_command_char (ch))
685b725ae77Skettenis { /* Handle prev/next/up/down here */
686b725ae77Skettenis ch = tui_dispatch_ctrl_char (ch);
687b725ae77Skettenis }
688b725ae77Skettenis
689b725ae77Skettenis if (ch == '\n' || ch == '\r' || ch == '\f')
690b725ae77Skettenis TUI_CMD_WIN->detail.command_info.curch = 0;
691b725ae77Skettenis if (ch == KEY_BACKSPACE)
692b725ae77Skettenis return '\b';
693b725ae77Skettenis
694b725ae77Skettenis return ch;
695b725ae77Skettenis }
696b725ae77Skettenis
697b725ae77Skettenis
698b725ae77Skettenis /* Cleanup when a resize has occured.
699b725ae77Skettenis Returns the character that must be processed. */
700b725ae77Skettenis static unsigned int
tui_handle_resize_during_io(unsigned int original_ch)701b725ae77Skettenis tui_handle_resize_during_io (unsigned int original_ch)
702b725ae77Skettenis {
703b725ae77Skettenis if (tui_win_resized ())
704b725ae77Skettenis {
705b725ae77Skettenis tui_refresh_all_win ();
706b725ae77Skettenis dont_repeat ();
707b725ae77Skettenis tui_set_win_resized_to (FALSE);
708b725ae77Skettenis return '\n';
709b725ae77Skettenis }
710b725ae77Skettenis else
711b725ae77Skettenis return original_ch;
712b725ae77Skettenis }
713