xref: /openbsd-src/gnu/usr.bin/binutils/gdb/tui/tui-io.c (revision 11efff7f3ac2b3cfeff0c0cddc14294d9b3aca4f)
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