1130803Smarcel/* TUI support I/O functions.
2130803Smarcel
3130803Smarcel   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
4130803Smarcel   Foundation, Inc.
5130803Smarcel
6130803Smarcel   Contributed by Hewlett-Packard Company.
7130803Smarcel
8130803Smarcel   This file is part of GDB.
9130803Smarcel
10130803Smarcel   This program is free software; you can redistribute it and/or modify
11130803Smarcel   it under the terms of the GNU General Public License as published by
12130803Smarcel   the Free Software Foundation; either version 2 of the License, or
13130803Smarcel   (at your option) any later version.
14130803Smarcel
15130803Smarcel   This program is distributed in the hope that it will be useful,
16130803Smarcel   but WITHOUT ANY WARRANTY; without even the implied warranty of
17130803Smarcel   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18130803Smarcel   GNU General Public License for more details.
19130803Smarcel
20130803Smarcel   You should have received a copy of the GNU General Public License
21130803Smarcel   along with this program; if not, write to the Free Software
22130803Smarcel   Foundation, Inc., 59 Temple Place - Suite 330,
23130803Smarcel   Boston, MA 02111-1307, USA.  */
24130803Smarcel
25130803Smarcel#include "defs.h"
26130803Smarcel#include "terminal.h"
27130803Smarcel#include "target.h"
28130803Smarcel#include "event-loop.h"
29130803Smarcel#include "event-top.h"
30130803Smarcel#include "command.h"
31130803Smarcel#include "top.h"
32130803Smarcel#include "readline/readline.h"
33130803Smarcel#include "tui/tui.h"
34130803Smarcel#include "tui/tui-data.h"
35130803Smarcel#include "tui/tui-io.h"
36130803Smarcel#include "tui/tui-command.h"
37130803Smarcel#include "tui/tui-win.h"
38130803Smarcel#include "tui/tui-wingeneral.h"
39130803Smarcel#include "tui/tui-file.h"
40130803Smarcel#include "ui-out.h"
41130803Smarcel#include "cli-out.h"
42130803Smarcel#include <fcntl.h>
43130803Smarcel#include <signal.h>
44130803Smarcel#include <stdio.h>
45130803Smarcel
46130803Smarcel#include "gdb_curses.h"
47130803Smarcel
48130803Smarcelint
49130803Smarcelkey_is_start_sequence (int ch)
50130803Smarcel{
51130803Smarcel  return (ch == 27);
52130803Smarcel}
53130803Smarcel
54130803Smarcelint
55130803Smarcelkey_is_end_sequence (int ch)
56130803Smarcel{
57130803Smarcel  return (ch == 126);
58130803Smarcel}
59130803Smarcel
60130803Smarcelint
61130803Smarcelkey_is_backspace (int ch)
62130803Smarcel{
63130803Smarcel  return (ch == 8);
64130803Smarcel}
65130803Smarcel
66130803Smarcelint
67130803Smarcelkey_is_command_char (int ch)
68130803Smarcel{
69130803Smarcel  return ((ch == KEY_NPAGE) || (ch == KEY_PPAGE)
70130803Smarcel	  || (ch == KEY_LEFT) || (ch == KEY_RIGHT)
71130803Smarcel	  || (ch == KEY_UP) || (ch == KEY_DOWN)
72130803Smarcel	  || (ch == KEY_SF) || (ch == KEY_SR)
73130803Smarcel	  || (ch == (int)'\f') || key_is_start_sequence (ch));
74130803Smarcel}
75130803Smarcel
76130803Smarcel/* Use definition from readline 4.3.  */
77130803Smarcel#undef CTRL_CHAR
78130803Smarcel#define CTRL_CHAR(c) ((c) < control_character_threshold && (((c) & 0x80) == 0))
79130803Smarcel
80130803Smarcel/* This file controls the IO interactions between gdb and curses.
81130803Smarcel   When the TUI is enabled, gdb has two modes a curses and a standard
82130803Smarcel   mode.
83130803Smarcel
84130803Smarcel   In curses mode, the gdb outputs are made in a curses command window.
85130803Smarcel   For this, the gdb_stdout and gdb_stderr are redirected to the specific
86130803Smarcel   ui_file implemented by TUI.  The output is handled by tui_puts().
87130803Smarcel   The input is also controlled by curses with tui_getc().  The readline
88130803Smarcel   library uses this function to get its input.  Several readline hooks
89130803Smarcel   are installed to redirect readline output to the TUI (see also the
90130803Smarcel   note below).
91130803Smarcel
92130803Smarcel   In normal mode, the gdb outputs are restored to their origin, that
93130803Smarcel   is as if TUI is not used.  Readline also uses its original getc()
94130803Smarcel   function with stdin.
95130803Smarcel
96130803Smarcel   Note SCz/2001-07-21: the current readline is not clean in its management of
97130803Smarcel   the output.  Even if we install a redisplay handler, it sometimes writes on
98130803Smarcel   a stdout file.  It is important to redirect every output produced by
99130803Smarcel   readline, otherwise the curses window will be garbled.  This is implemented
100130803Smarcel   with a pipe that TUI reads and readline writes to.  A gdb input handler
101130803Smarcel   is created so that reading the pipe is handled automatically.
102130803Smarcel   This will probably not work on non-Unix platforms.  The best fix is
103130803Smarcel   to make readline clean enougth so that is never write on stdout.
104130803Smarcel
105130803Smarcel   Note SCz/2002-09-01: we now use more readline hooks and it seems that
106130803Smarcel   with them we don't need the pipe anymore (verified by creating the pipe
107130803Smarcel   and closing its end so that write causes a SIGPIPE).  The old pipe code
108130803Smarcel   is still there and can be conditionally removed by
109130803Smarcel   #undef TUI_USE_PIPE_FOR_READLINE.  */
110130803Smarcel
111130803Smarcel/* For gdb 5.3, prefer to continue the pipe hack as a backup wheel.  */
112130803Smarcel#define TUI_USE_PIPE_FOR_READLINE
113130803Smarcel/*#undef TUI_USE_PIPE_FOR_READLINE*/
114130803Smarcel
115130803Smarcel/* TUI output files.  */
116130803Smarcelstatic struct ui_file *tui_stdout;
117130803Smarcelstatic struct ui_file *tui_stderr;
118130803Smarcelstruct ui_out *tui_out;
119130803Smarcel
120130803Smarcel/* GDB output files in non-curses mode.  */
121130803Smarcelstatic struct ui_file *tui_old_stdout;
122130803Smarcelstatic struct ui_file *tui_old_stderr;
123130803Smarcelstruct ui_out *tui_old_uiout;
124130803Smarcel
125130803Smarcel/* Readline previous hooks.  */
126130803Smarcelstatic Function *tui_old_rl_getc_function;
127130803Smarcelstatic VFunction *tui_old_rl_redisplay_function;
128130803Smarcelstatic VFunction *tui_old_rl_prep_terminal;
129130803Smarcelstatic VFunction *tui_old_rl_deprep_terminal;
130130803Smarcelstatic int tui_old_readline_echoing_p;
131130803Smarcel
132130803Smarcel/* Readline output stream.
133130803Smarcel   Should be removed when readline is clean.  */
134130803Smarcelstatic FILE *tui_rl_outstream;
135130803Smarcelstatic FILE *tui_old_rl_outstream;
136130803Smarcel#ifdef TUI_USE_PIPE_FOR_READLINE
137130803Smarcelstatic int tui_readline_pipe[2];
138130803Smarcel#endif
139130803Smarcel
140130803Smarcel/* The last gdb prompt that was registered in readline.
141130803Smarcel   This may be the main gdb prompt or a secondary prompt.  */
142130803Smarcelstatic char *tui_rl_saved_prompt;
143130803Smarcel
144130803Smarcelstatic unsigned int tui_handle_resize_during_io (unsigned int);
145130803Smarcel
146130803Smarcelstatic void
147130803Smarceltui_putc (char c)
148130803Smarcel{
149130803Smarcel  char buf[2];
150130803Smarcel
151130803Smarcel  buf[0] = c;
152130803Smarcel  buf[1] = 0;
153130803Smarcel  tui_puts (buf);
154130803Smarcel}
155130803Smarcel
156130803Smarcel/* Print the string in the curses command window.  */
157130803Smarcelvoid
158130803Smarceltui_puts (const char *string)
159130803Smarcel{
160130803Smarcel  static int tui_skip_line = -1;
161130803Smarcel  char c;
162130803Smarcel  WINDOW *w;
163130803Smarcel
164130803Smarcel  w = TUI_CMD_WIN->generic.handle;
165130803Smarcel  while ((c = *string++) != 0)
166130803Smarcel    {
167130803Smarcel      /* Catch annotation and discard them.  We need two \032 and
168130803Smarcel         discard until a \n is seen.  */
169130803Smarcel      if (c == '\032')
170130803Smarcel        {
171130803Smarcel          tui_skip_line++;
172130803Smarcel        }
173130803Smarcel      else if (tui_skip_line != 1)
174130803Smarcel        {
175130803Smarcel          tui_skip_line = -1;
176130803Smarcel          waddch (w, c);
177130803Smarcel        }
178130803Smarcel      else if (c == '\n')
179130803Smarcel        tui_skip_line = -1;
180130803Smarcel    }
181130803Smarcel  getyx (w, TUI_CMD_WIN->detail.command_info.cur_line,
182130803Smarcel         TUI_CMD_WIN->detail.command_info.curch);
183130803Smarcel  TUI_CMD_WIN->detail.command_info.start_line = TUI_CMD_WIN->detail.command_info.cur_line;
184130803Smarcel
185130803Smarcel  /* We could defer the following.  */
186130803Smarcel  wrefresh (w);
187130803Smarcel  fflush (stdout);
188130803Smarcel}
189130803Smarcel
190130803Smarcel/* Readline callback.
191130803Smarcel   Redisplay the command line with its prompt after readline has
192130803Smarcel   changed the edited text.  */
193130803Smarcelvoid
194130803Smarceltui_redisplay_readline (void)
195130803Smarcel{
196130803Smarcel  int prev_col;
197130803Smarcel  int height;
198130803Smarcel  int col, line;
199130803Smarcel  int c_pos;
200130803Smarcel  int c_line;
201130803Smarcel  int in;
202130803Smarcel  WINDOW *w;
203130803Smarcel  char *prompt;
204130803Smarcel  int start_line;
205130803Smarcel
206130803Smarcel  /* Detect when we temporarily left SingleKey and now the readline
207130803Smarcel     edit buffer is empty, automatically restore the SingleKey mode.  */
208130803Smarcel  if (tui_current_key_mode == TUI_ONE_COMMAND_MODE && rl_end == 0)
209130803Smarcel    tui_set_key_mode (TUI_SINGLE_KEY_MODE);
210130803Smarcel
211130803Smarcel  if (tui_current_key_mode == TUI_SINGLE_KEY_MODE)
212130803Smarcel    prompt = "";
213130803Smarcel  else
214130803Smarcel    prompt = tui_rl_saved_prompt;
215130803Smarcel
216130803Smarcel  c_pos = -1;
217130803Smarcel  c_line = -1;
218130803Smarcel  w = TUI_CMD_WIN->generic.handle;
219130803Smarcel  start_line = TUI_CMD_WIN->detail.command_info.start_line;
220130803Smarcel  wmove (w, start_line, 0);
221130803Smarcel  prev_col = 0;
222130803Smarcel  height = 1;
223130803Smarcel  for (in = 0; prompt && prompt[in]; in++)
224130803Smarcel    {
225130803Smarcel      waddch (w, prompt[in]);
226130803Smarcel      getyx (w, line, col);
227130803Smarcel      if (col < prev_col)
228130803Smarcel        height++;
229130803Smarcel      prev_col = col;
230130803Smarcel    }
231130803Smarcel  for (in = 0; in < rl_end; in++)
232130803Smarcel    {
233130803Smarcel      unsigned char c;
234130803Smarcel
235130803Smarcel      c = (unsigned char) rl_line_buffer[in];
236130803Smarcel      if (in == rl_point)
237130803Smarcel	{
238130803Smarcel          getyx (w, c_line, c_pos);
239130803Smarcel	}
240130803Smarcel
241130803Smarcel      if (CTRL_CHAR (c) || c == RUBOUT)
242130803Smarcel	{
243130803Smarcel          waddch (w, '^');
244130803Smarcel          waddch (w, CTRL_CHAR (c) ? UNCTRL (c) : '?');
245130803Smarcel	}
246130803Smarcel      else
247130803Smarcel	{
248130803Smarcel          waddch (w, c);
249130803Smarcel	}
250130803Smarcel      if (c == '\n')
251130803Smarcel        {
252130803Smarcel          getyx (w, TUI_CMD_WIN->detail.command_info.start_line,
253130803Smarcel                 TUI_CMD_WIN->detail.command_info.curch);
254130803Smarcel        }
255130803Smarcel      getyx (w, line, col);
256130803Smarcel      if (col < prev_col)
257130803Smarcel        height++;
258130803Smarcel      prev_col = col;
259130803Smarcel    }
260130803Smarcel  wclrtobot (w);
261130803Smarcel  getyx (w, TUI_CMD_WIN->detail.command_info.start_line,
262130803Smarcel         TUI_CMD_WIN->detail.command_info.curch);
263130803Smarcel  if (c_line >= 0)
264130803Smarcel    {
265130803Smarcel      wmove (w, c_line, c_pos);
266130803Smarcel      TUI_CMD_WIN->detail.command_info.cur_line = c_line;
267130803Smarcel      TUI_CMD_WIN->detail.command_info.curch = c_pos;
268130803Smarcel    }
269130803Smarcel  TUI_CMD_WIN->detail.command_info.start_line -= height - 1;
270130803Smarcel
271130803Smarcel  wrefresh (w);
272130803Smarcel  fflush(stdout);
273130803Smarcel}
274130803Smarcel
275130803Smarcel/* Readline callback to prepare the terminal.  It is called once
276130803Smarcel   each time we enter readline.  Terminal is already setup in curses mode.  */
277130803Smarcelstatic void
278130803Smarceltui_prep_terminal (int notused1)
279130803Smarcel{
280130803Smarcel  /* Save the prompt registered in readline to correctly display it.
281130803Smarcel     (we can't use gdb_prompt() due to secondary prompts and can't use
282130803Smarcel     rl_prompt because it points to an alloca buffer).  */
283130803Smarcel  xfree (tui_rl_saved_prompt);
284130803Smarcel  tui_rl_saved_prompt = xstrdup (rl_prompt);
285130803Smarcel}
286130803Smarcel
287130803Smarcel/* Readline callback to restore the terminal.  It is called once
288130803Smarcel   each time we leave readline.  There is nothing to do in curses mode.  */
289130803Smarcelstatic void
290130803Smarceltui_deprep_terminal (void)
291130803Smarcel{
292130803Smarcel}
293130803Smarcel
294130803Smarcel#ifdef TUI_USE_PIPE_FOR_READLINE
295130803Smarcel/* Read readline output pipe and feed the command window with it.
296130803Smarcel   Should be removed when readline is clean.  */
297130803Smarcelstatic void
298130803Smarceltui_readline_output (int code, gdb_client_data data)
299130803Smarcel{
300130803Smarcel  int size;
301130803Smarcel  char buf[256];
302130803Smarcel
303130803Smarcel  size = read (tui_readline_pipe[0], buf, sizeof (buf) - 1);
304130803Smarcel  if (size > 0 && tui_active)
305130803Smarcel    {
306130803Smarcel      buf[size] = 0;
307130803Smarcel      tui_puts (buf);
308130803Smarcel    }
309130803Smarcel}
310130803Smarcel#endif
311130803Smarcel
312130803Smarcel/* Return the portion of PATHNAME that should be output when listing
313130803Smarcel   possible completions.  If we are hacking filename completion, we
314130803Smarcel   are only interested in the basename, the portion following the
315130803Smarcel   final slash.  Otherwise, we return what we were passed.
316130803Smarcel
317130803Smarcel   Comes from readline/complete.c  */
318130803Smarcelstatic char *
319130803Smarcelprintable_part (char *pathname)
320130803Smarcel{
321130803Smarcel  char *temp;
322130803Smarcel
323130803Smarcel  temp = rl_filename_completion_desired ? strrchr (pathname, '/') : (char *)NULL;
324130803Smarcel#if defined (__MSDOS__)
325130803Smarcel  if (rl_filename_completion_desired && temp == 0 && isalpha (pathname[0]) && pathname[1] == ':')
326130803Smarcel    temp = pathname + 1;
327130803Smarcel#endif
328130803Smarcel  return (temp ? ++temp : pathname);
329130803Smarcel}
330130803Smarcel
331130803Smarcel/* Output TO_PRINT to rl_outstream.  If VISIBLE_STATS is defined and we
332130803Smarcel   are using it, check for and output a single character for `special'
333130803Smarcel   filenames.  Return the number of characters we output. */
334130803Smarcel
335130803Smarcel#define PUTX(c) \
336130803Smarcel    do { \
337130803Smarcel      if (CTRL_CHAR (c)) \
338130803Smarcel        { \
339130803Smarcel          tui_puts ("^"); \
340130803Smarcel          tui_putc (UNCTRL (c)); \
341130803Smarcel          printed_len += 2; \
342130803Smarcel        } \
343130803Smarcel      else if (c == RUBOUT) \
344130803Smarcel	{ \
345130803Smarcel	  tui_puts ("^?"); \
346130803Smarcel	  printed_len += 2; \
347130803Smarcel	} \
348130803Smarcel      else \
349130803Smarcel	{ \
350130803Smarcel	  tui_putc (c); \
351130803Smarcel	  printed_len++; \
352130803Smarcel	} \
353130803Smarcel    } while (0)
354130803Smarcel
355130803Smarcelstatic int
356130803Smarcelprint_filename (char *to_print, char *full_pathname)
357130803Smarcel{
358130803Smarcel  int printed_len = 0;
359130803Smarcel  char *s;
360130803Smarcel
361130803Smarcel  for (s = to_print; *s; s++)
362130803Smarcel    {
363130803Smarcel      PUTX (*s);
364130803Smarcel    }
365130803Smarcel  return printed_len;
366130803Smarcel}
367130803Smarcel
368130803Smarcel/* The user must press "y" or "n".  Non-zero return means "y" pressed.
369130803Smarcel   Comes from readline/complete.c  */
370130803Smarcelstatic int
371130803Smarcelget_y_or_n (void)
372130803Smarcel{
373130803Smarcel  extern int _rl_abort_internal ();
374130803Smarcel  int c;
375130803Smarcel
376130803Smarcel  for (;;)
377130803Smarcel    {
378130803Smarcel      c = rl_read_key ();
379130803Smarcel      if (c == 'y' || c == 'Y' || c == ' ')
380130803Smarcel	return (1);
381130803Smarcel      if (c == 'n' || c == 'N' || c == RUBOUT)
382130803Smarcel	return (0);
383130803Smarcel      if (c == ABORT_CHAR)
384130803Smarcel	_rl_abort_internal ();
385130803Smarcel      beep ();
386130803Smarcel    }
387130803Smarcel}
388130803Smarcel
389130803Smarcel/* A convenience function for displaying a list of strings in
390130803Smarcel   columnar format on readline's output stream.  MATCHES is the list
391130803Smarcel   of strings, in argv format, LEN is the number of strings in MATCHES,
392130803Smarcel   and MAX is the length of the longest string in MATCHES.
393130803Smarcel
394130803Smarcel   Comes from readline/complete.c and modified to write in
395130803Smarcel   the TUI command window using tui_putc/tui_puts.  */
396130803Smarcelstatic void
397130803Smarceltui_rl_display_match_list (char **matches, int len, int max)
398130803Smarcel{
399130803Smarcel  typedef int QSFUNC (const void *, const void *);
400130803Smarcel  extern int _rl_qsort_string_compare (const void*, const void*);
401130803Smarcel  extern int _rl_print_completions_horizontally;
402130803Smarcel
403130803Smarcel  int count, limit, printed_len;
404130803Smarcel  int i, j, k, l;
405130803Smarcel  char *temp;
406130803Smarcel
407130803Smarcel  /* Screen dimension correspond to the TUI command window.  */
408130803Smarcel  int screenwidth = TUI_CMD_WIN->generic.width;
409130803Smarcel
410130803Smarcel  /* If there are many items, then ask the user if she really wants to
411130803Smarcel     see them all. */
412130803Smarcel  if (len >= rl_completion_query_items)
413130803Smarcel    {
414130803Smarcel      char msg[256];
415130803Smarcel
416130803Smarcel      sprintf (msg, "\nDisplay all %d possibilities? (y or n)", len);
417130803Smarcel      tui_puts (msg);
418130803Smarcel      if (get_y_or_n () == 0)
419130803Smarcel	{
420130803Smarcel	  tui_puts ("\n");
421130803Smarcel	  return;
422130803Smarcel	}
423130803Smarcel    }
424130803Smarcel
425130803Smarcel  /* How many items of MAX length can we fit in the screen window? */
426130803Smarcel  max += 2;
427130803Smarcel  limit = screenwidth / max;
428130803Smarcel  if (limit != 1 && (limit * max == screenwidth))
429130803Smarcel    limit--;
430130803Smarcel
431130803Smarcel  /* Avoid a possible floating exception.  If max > screenwidth,
432130803Smarcel     limit will be 0 and a divide-by-zero fault will result. */
433130803Smarcel  if (limit == 0)
434130803Smarcel    limit = 1;
435130803Smarcel
436130803Smarcel  /* How many iterations of the printing loop? */
437130803Smarcel  count = (len + (limit - 1)) / limit;
438130803Smarcel
439130803Smarcel  /* Watch out for special case.  If LEN is less than LIMIT, then
440130803Smarcel     just do the inner printing loop.
441130803Smarcel	   0 < len <= limit  implies  count = 1. */
442130803Smarcel
443130803Smarcel  /* Sort the items if they are not already sorted. */
444130803Smarcel  if (rl_ignore_completion_duplicates == 0)
445130803Smarcel    qsort (matches + 1, len, sizeof (char *),
446130803Smarcel           (QSFUNC *)_rl_qsort_string_compare);
447130803Smarcel
448130803Smarcel  tui_putc ('\n');
449130803Smarcel
450130803Smarcel  if (_rl_print_completions_horizontally == 0)
451130803Smarcel    {
452130803Smarcel      /* Print the sorted items, up-and-down alphabetically, like ls. */
453130803Smarcel      for (i = 1; i <= count; i++)
454130803Smarcel	{
455130803Smarcel	  for (j = 0, l = i; j < limit; j++)
456130803Smarcel	    {
457130803Smarcel	      if (l > len || matches[l] == 0)
458130803Smarcel		break;
459130803Smarcel	      else
460130803Smarcel		{
461130803Smarcel		  temp = printable_part (matches[l]);
462130803Smarcel		  printed_len = print_filename (temp, matches[l]);
463130803Smarcel
464130803Smarcel		  if (j + 1 < limit)
465130803Smarcel		    for (k = 0; k < max - printed_len; k++)
466130803Smarcel		      tui_putc (' ');
467130803Smarcel		}
468130803Smarcel	      l += count;
469130803Smarcel	    }
470130803Smarcel	  tui_putc ('\n');
471130803Smarcel	}
472130803Smarcel    }
473130803Smarcel  else
474130803Smarcel    {
475130803Smarcel      /* Print the sorted items, across alphabetically, like ls -x. */
476130803Smarcel      for (i = 1; matches[i]; i++)
477130803Smarcel	{
478130803Smarcel	  temp = printable_part (matches[i]);
479130803Smarcel	  printed_len = print_filename (temp, matches[i]);
480130803Smarcel	  /* Have we reached the end of this line? */
481130803Smarcel	  if (matches[i+1])
482130803Smarcel	    {
483130803Smarcel	      if (i && (limit > 1) && (i % limit) == 0)
484130803Smarcel		tui_putc ('\n');
485130803Smarcel	      else
486130803Smarcel		for (k = 0; k < max - printed_len; k++)
487130803Smarcel		  tui_putc (' ');
488130803Smarcel	    }
489130803Smarcel	}
490130803Smarcel      tui_putc ('\n');
491130803Smarcel    }
492130803Smarcel}
493130803Smarcel
494130803Smarcel/* Setup the IO for curses or non-curses mode.
495130803Smarcel   - In non-curses mode, readline and gdb use the standard input and
496130803Smarcel   standard output/error directly.
497130803Smarcel   - In curses mode, the standard output/error is controlled by TUI
498130803Smarcel   with the tui_stdout and tui_stderr.  The output is redirected in
499130803Smarcel   the curses command window.  Several readline callbacks are installed
500130803Smarcel   so that readline asks for its input to the curses command window
501130803Smarcel   with wgetch().  */
502130803Smarcelvoid
503130803Smarceltui_setup_io (int mode)
504130803Smarcel{
505130803Smarcel  extern int readline_echoing_p;
506130803Smarcel
507130803Smarcel  if (mode)
508130803Smarcel    {
509130803Smarcel      /* Redirect readline to TUI.  */
510130803Smarcel      tui_old_rl_redisplay_function = rl_redisplay_function;
511130803Smarcel      tui_old_rl_deprep_terminal = rl_deprep_term_function;
512130803Smarcel      tui_old_rl_prep_terminal = rl_prep_term_function;
513130803Smarcel      tui_old_rl_getc_function = rl_getc_function;
514130803Smarcel      tui_old_rl_outstream = rl_outstream;
515130803Smarcel      tui_old_readline_echoing_p = readline_echoing_p;
516130803Smarcel      rl_redisplay_function = tui_redisplay_readline;
517130803Smarcel      rl_deprep_term_function = tui_deprep_terminal;
518130803Smarcel      rl_prep_term_function = tui_prep_terminal;
519130803Smarcel      rl_getc_function = tui_getc;
520130803Smarcel      readline_echoing_p = 0;
521130803Smarcel      rl_outstream = tui_rl_outstream;
522130803Smarcel      rl_prompt = 0;
523130803Smarcel      rl_completion_display_matches_hook = tui_rl_display_match_list;
524130803Smarcel      rl_already_prompted = 0;
525130803Smarcel
526130803Smarcel      /* Keep track of previous gdb output.  */
527130803Smarcel      tui_old_stdout = gdb_stdout;
528130803Smarcel      tui_old_stderr = gdb_stderr;
529130803Smarcel      tui_old_uiout = uiout;
530130803Smarcel
531130803Smarcel      /* Reconfigure gdb output.  */
532130803Smarcel      gdb_stdout = tui_stdout;
533130803Smarcel      gdb_stderr = tui_stderr;
534130803Smarcel      gdb_stdlog = gdb_stdout;	/* for moment */
535130803Smarcel      gdb_stdtarg = gdb_stderr;	/* for moment */
536130803Smarcel      uiout = tui_out;
537130803Smarcel
538130803Smarcel      /* Save tty for SIGCONT.  */
539130803Smarcel      savetty ();
540130803Smarcel    }
541130803Smarcel  else
542130803Smarcel    {
543130803Smarcel      /* Restore gdb output.  */
544130803Smarcel      gdb_stdout = tui_old_stdout;
545130803Smarcel      gdb_stderr = tui_old_stderr;
546130803Smarcel      gdb_stdlog = gdb_stdout;	/* for moment */
547130803Smarcel      gdb_stdtarg = gdb_stderr;	/* for moment */
548130803Smarcel      uiout = tui_old_uiout;
549130803Smarcel
550130803Smarcel      /* Restore readline.  */
551130803Smarcel      rl_redisplay_function = tui_old_rl_redisplay_function;
552130803Smarcel      rl_deprep_term_function = tui_old_rl_deprep_terminal;
553130803Smarcel      rl_prep_term_function = tui_old_rl_prep_terminal;
554130803Smarcel      rl_getc_function = tui_old_rl_getc_function;
555130803Smarcel      rl_outstream = tui_old_rl_outstream;
556130803Smarcel      rl_completion_display_matches_hook = 0;
557130803Smarcel      readline_echoing_p = tui_old_readline_echoing_p;
558130803Smarcel      rl_already_prompted = 0;
559130803Smarcel
560130803Smarcel      /* Save tty for SIGCONT.  */
561130803Smarcel      savetty ();
562130803Smarcel    }
563130803Smarcel}
564130803Smarcel
565130803Smarcel#ifdef SIGCONT
566130803Smarcel/* Catch SIGCONT to restore the terminal and refresh the screen.  */
567130803Smarcelstatic void
568130803Smarceltui_cont_sig (int sig)
569130803Smarcel{
570130803Smarcel  if (tui_active)
571130803Smarcel    {
572130803Smarcel      /* Restore the terminal setting because another process (shell)
573130803Smarcel         might have changed it.  */
574130803Smarcel      resetty ();
575130803Smarcel
576130803Smarcel      /* Force a refresh of the screen.  */
577130803Smarcel      tui_refresh_all_win ();
578130803Smarcel
579130803Smarcel      /* Update cursor position on the screen.  */
580130803Smarcel      wmove (TUI_CMD_WIN->generic.handle,
581130803Smarcel             TUI_CMD_WIN->detail.command_info.start_line,
582130803Smarcel             TUI_CMD_WIN->detail.command_info.curch);
583130803Smarcel      wrefresh (TUI_CMD_WIN->generic.handle);
584130803Smarcel    }
585130803Smarcel  signal (sig, tui_cont_sig);
586130803Smarcel}
587130803Smarcel#endif
588130803Smarcel
589130803Smarcel/* Initialize the IO for gdb in curses mode.  */
590130803Smarcelvoid
591130803Smarceltui_initialize_io (void)
592130803Smarcel{
593130803Smarcel#ifdef SIGCONT
594130803Smarcel  signal (SIGCONT, tui_cont_sig);
595130803Smarcel#endif
596130803Smarcel
597130803Smarcel  /* Create tui output streams.  */
598130803Smarcel  tui_stdout = tui_fileopen (stdout);
599130803Smarcel  tui_stderr = tui_fileopen (stderr);
600130803Smarcel  tui_out = tui_out_new (tui_stdout);
601130803Smarcel
602130803Smarcel  /* Create the default UI.  It is not created because we installed
603130803Smarcel     a init_ui_hook.  */
604130803Smarcel  tui_old_uiout = uiout = cli_out_new (gdb_stdout);
605130803Smarcel
606130803Smarcel#ifdef TUI_USE_PIPE_FOR_READLINE
607130803Smarcel  /* Temporary solution for readline writing to stdout:
608130803Smarcel     redirect readline output in a pipe, read that pipe and
609130803Smarcel     output the content in the curses command window.  */
610130803Smarcel  if (pipe (tui_readline_pipe) != 0)
611130803Smarcel    {
612130803Smarcel      fprintf_unfiltered (gdb_stderr, "Cannot create pipe for readline");
613130803Smarcel      exit (1);
614130803Smarcel    }
615130803Smarcel  tui_rl_outstream = fdopen (tui_readline_pipe[1], "w");
616130803Smarcel  if (tui_rl_outstream == 0)
617130803Smarcel    {
618130803Smarcel      fprintf_unfiltered (gdb_stderr, "Cannot redirect readline output");
619130803Smarcel      exit (1);
620130803Smarcel    }
621130803Smarcel  setvbuf (tui_rl_outstream, (char*) NULL, _IOLBF, 0);
622130803Smarcel
623130803Smarcel#ifdef O_NONBLOCK
624130803Smarcel  (void) fcntl (tui_readline_pipe[0], F_SETFL, O_NONBLOCK);
625130803Smarcel#else
626130803Smarcel#ifdef O_NDELAY
627130803Smarcel  (void) fcntl (tui_readline_pipe[0], F_SETFL, O_NDELAY);
628130803Smarcel#endif
629130803Smarcel#endif
630130803Smarcel  add_file_handler (tui_readline_pipe[0], tui_readline_output, 0);
631130803Smarcel#else
632130803Smarcel  tui_rl_outstream = stdout;
633130803Smarcel#endif
634130803Smarcel}
635130803Smarcel
636130803Smarcel/* Get a character from the command window.  This is called from the readline
637130803Smarcel   package.  */
638130803Smarcelint
639130803Smarceltui_getc (FILE *fp)
640130803Smarcel{
641130803Smarcel  int ch;
642130803Smarcel  WINDOW *w;
643130803Smarcel
644130803Smarcel  w = TUI_CMD_WIN->generic.handle;
645130803Smarcel
646130803Smarcel#ifdef TUI_USE_PIPE_FOR_READLINE
647130803Smarcel  /* Flush readline output.  */
648130803Smarcel  tui_readline_output (GDB_READABLE, 0);
649130803Smarcel#endif
650130803Smarcel
651130803Smarcel  ch = wgetch (w);
652130803Smarcel  ch = tui_handle_resize_during_io (ch);
653130803Smarcel
654130803Smarcel  /* The \n must be echoed because it will not be printed by readline.  */
655130803Smarcel  if (ch == '\n')
656130803Smarcel    {
657130803Smarcel      /* When hitting return with an empty input, gdb executes the last
658130803Smarcel         command.  If we emit a newline, this fills up the command window
659130803Smarcel         with empty lines with gdb prompt at beginning.  Instead of that,
660130803Smarcel         stay on the same line but provide a visual effect to show the
661130803Smarcel         user we recognized the command.  */
662130803Smarcel      if (rl_end == 0)
663130803Smarcel        {
664130803Smarcel          wmove (w, TUI_CMD_WIN->detail.command_info.cur_line, 0);
665130803Smarcel
666130803Smarcel          /* Clear the line.  This will blink the gdb prompt since
667130803Smarcel             it will be redrawn at the same line.  */
668130803Smarcel          wclrtoeol (w);
669130803Smarcel          wrefresh (w);
670130803Smarcel          napms (20);
671130803Smarcel        }
672130803Smarcel      else
673130803Smarcel        {
674130803Smarcel          wmove (w, TUI_CMD_WIN->detail.command_info.cur_line,
675130803Smarcel                 TUI_CMD_WIN->detail.command_info.curch);
676130803Smarcel          waddch (w, ch);
677130803Smarcel        }
678130803Smarcel    }
679130803Smarcel
680130803Smarcel  if (key_is_command_char (ch))
681130803Smarcel    {				/* Handle prev/next/up/down here */
682130803Smarcel      ch = tui_dispatch_ctrl_char (ch);
683130803Smarcel    }
684130803Smarcel
685130803Smarcel  if (ch == '\n' || ch == '\r' || ch == '\f')
686130803Smarcel    TUI_CMD_WIN->detail.command_info.curch = 0;
687130803Smarcel  if (ch == KEY_BACKSPACE)
688130803Smarcel    return '\b';
689130803Smarcel
690130803Smarcel  return ch;
691130803Smarcel}
692130803Smarcel
693130803Smarcel
694130803Smarcel/* Cleanup when a resize has occured.
695130803Smarcel   Returns the character that must be processed.  */
696130803Smarcelstatic unsigned int
697130803Smarceltui_handle_resize_during_io (unsigned int original_ch)
698130803Smarcel{
699130803Smarcel  if (tui_win_resized ())
700130803Smarcel    {
701130803Smarcel      tui_refresh_all_win ();
702130803Smarcel      dont_repeat ();
703130803Smarcel      tui_set_win_resized_to (FALSE);
704130803Smarcel      return '\n';
705130803Smarcel    }
706130803Smarcel  else
707130803Smarcel    return original_ch;
708130803Smarcel}
709