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