Imported from ../bash-3.2.tar.gz.
[platform/upstream/bash.git] / lib / readline / terminal.c
1 /* terminal.c -- controlling the terminal with termcap. */
2
3 /* Copyright (C) 1996-2006 Free Software Foundation, Inc.
4
5    This file is part of the GNU Readline Library, a library for
6    reading lines of text with interactive input and history editing.
7
8    The GNU Readline Library is free software; you can redistribute it
9    and/or modify it under the terms of the GNU General Public License
10    as published by the Free Software Foundation; either version 2, or
11    (at your option) any later version.
12
13    The GNU Readline Library is distributed in the hope that it will be
14    useful, but WITHOUT ANY WARRANTY; without even the implied warranty
15    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    The GNU General Public License is often shipped with GNU software, and
19    is generally kept in a file called COPYING or LICENSE.  If you do not
20    have a copy of the license, write to the Free Software Foundation,
21    59 Temple Place, Suite 330, Boston, MA 02111 USA. */
22 #define READLINE_LIBRARY
23
24 #if defined (HAVE_CONFIG_H)
25 #  include <config.h>
26 #endif
27
28 #include <sys/types.h>
29 #include "posixstat.h"
30 #include <fcntl.h>
31 #if defined (HAVE_SYS_FILE_H)
32 #  include <sys/file.h>
33 #endif /* HAVE_SYS_FILE_H */
34
35 #if defined (HAVE_UNISTD_H)
36 #  include <unistd.h>
37 #endif /* HAVE_UNISTD_H */
38
39 #if defined (HAVE_STDLIB_H)
40 #  include <stdlib.h>
41 #else
42 #  include "ansi_stdlib.h"
43 #endif /* HAVE_STDLIB_H */
44
45 #if defined (HAVE_LOCALE_H)
46 #  include <locale.h>
47 #endif
48
49 #include <stdio.h>
50
51 /* System-specific feature definitions and include files. */
52 #include "rldefs.h"
53
54 #if defined (GWINSZ_IN_SYS_IOCTL) && !defined (TIOCGWINSZ)
55 #  include <sys/ioctl.h>
56 #endif /* GWINSZ_IN_SYS_IOCTL && !TIOCGWINSZ */
57
58 #include "rltty.h"
59 #include "tcap.h"
60
61 /* Some standard library routines. */
62 #include "readline.h"
63 #include "history.h"
64
65 #include "rlprivate.h"
66 #include "rlshell.h"
67 #include "xmalloc.h"
68
69 #if defined (__MINGW32__)
70 #  include <windows.h>
71 #  include <wincon.h>
72
73 static void _win_get_screensize PARAMS((int *, int *));
74 #endif
75
76 #if defined (__EMX__)
77 static void _emx_get_screensize PARAMS((int *, int *));
78 #endif
79
80 #define CUSTOM_REDISPLAY_FUNC() (rl_redisplay_function != rl_redisplay)
81 #define CUSTOM_INPUT_FUNC() (rl_getc_function != rl_getc)
82
83 /*  If the calling application sets this to a non-zero value, readline will
84     use the $LINES and $COLUMNS environment variables to set its idea of the
85     window size before interrogating the kernel. */
86 int rl_prefer_env_winsize = 0;
87
88 /* **************************************************************** */
89 /*                                                                  */
90 /*                      Terminal and Termcap                        */
91 /*                                                                  */
92 /* **************************************************************** */
93
94 static char *term_buffer = (char *)NULL;
95 static char *term_string_buffer = (char *)NULL;
96
97 static int tcap_initialized;
98
99 #if !defined (__linux__)
100 #  if defined (__EMX__) || defined (NEED_EXTERN_PC)
101 extern 
102 #  endif /* __EMX__ || NEED_EXTERN_PC */
103 char PC, *BC, *UP;
104 #endif /* __linux__ */
105
106 /* Some strings to control terminal actions.  These are output by tputs (). */
107 char *_rl_term_clreol;
108 char *_rl_term_clrpag;
109 char *_rl_term_cr;
110 char *_rl_term_backspace;
111 char *_rl_term_goto;
112 char *_rl_term_pc;
113
114 /* Non-zero if we determine that the terminal can do character insertion. */
115 int _rl_terminal_can_insert = 0;
116
117 /* How to insert characters. */
118 char *_rl_term_im;
119 char *_rl_term_ei;
120 char *_rl_term_ic;
121 char *_rl_term_ip;
122 char *_rl_term_IC;
123
124 /* How to delete characters. */
125 char *_rl_term_dc;
126 char *_rl_term_DC;
127
128 char *_rl_term_forward_char;
129
130 /* How to go up a line. */
131 char *_rl_term_up;
132
133 /* A visible bell; char if the terminal can be made to flash the screen. */
134 static char *_rl_visible_bell;
135
136 /* Non-zero means the terminal can auto-wrap lines. */
137 int _rl_term_autowrap = -1;
138
139 /* Non-zero means that this terminal has a meta key. */
140 static int term_has_meta;
141
142 /* The sequences to write to turn on and off the meta key, if this
143    terminal has one. */
144 static char *_rl_term_mm;
145 static char *_rl_term_mo;
146
147 /* The key sequences output by the arrow keys, if this terminal has any. */
148 static char *_rl_term_ku;
149 static char *_rl_term_kd;
150 static char *_rl_term_kr;
151 static char *_rl_term_kl;
152
153 /* How to initialize and reset the arrow keys, if this terminal has any. */
154 static char *_rl_term_ks;
155 static char *_rl_term_ke;
156
157 /* The key sequences sent by the Home and End keys, if any. */
158 static char *_rl_term_kh;
159 static char *_rl_term_kH;
160 static char *_rl_term_at7;      /* @7 */
161
162 /* Delete key */
163 static char *_rl_term_kD;
164
165 /* Insert key */
166 static char *_rl_term_kI;
167
168 /* Cursor control */
169 static char *_rl_term_vs;       /* very visible */
170 static char *_rl_term_ve;       /* normal */
171
172 static void bind_termcap_arrow_keys PARAMS((Keymap));
173
174 /* Variables that hold the screen dimensions, used by the display code. */
175 int _rl_screenwidth, _rl_screenheight, _rl_screenchars;
176
177 /* Non-zero means the user wants to enable the keypad. */
178 int _rl_enable_keypad;
179
180 /* Non-zero means the user wants to enable a meta key. */
181 int _rl_enable_meta = 1;
182
183 #if defined (__EMX__)
184 static void
185 _emx_get_screensize (swp, shp)
186      int *swp, *shp;
187 {
188   int sz[2];
189
190   _scrsize (sz);
191
192   if (swp)
193     *swp = sz[0];
194   if (shp)
195     *shp = sz[1];
196 }
197 #endif
198
199 #if defined (__MINGW32__)
200 static void
201 _win_get_screensize (swp, shp)
202      int *swp, *shp;
203 {
204   HANDLE hConOut;
205   CONSOLE_SCREEN_BUFFER_INFO scr;
206
207   hConOut = GetStdHandle (STD_OUTPUT_HANDLE);
208   if (hConOut != INVALID_HANDLE_VALUE)
209     {
210       if (GetConsoleScreenBufferInfo (hConOut, &scr))
211         {
212           *swp = scr.dwSize.X;
213           *shp = scr.srWindow.Bottom - scr.srWindow.Top + 1;
214         }
215     }
216 }
217 #endif
218
219 /* Get readline's idea of the screen size.  TTY is a file descriptor open
220    to the terminal.  If IGNORE_ENV is true, we do not pay attention to the
221    values of $LINES and $COLUMNS.  The tests for TERM_STRING_BUFFER being
222    non-null serve to check whether or not we have initialized termcap. */
223 void
224 _rl_get_screen_size (tty, ignore_env)
225      int tty, ignore_env;
226 {
227   char *ss;
228 #if defined (TIOCGWINSZ)
229   struct winsize window_size;
230 #endif /* TIOCGWINSZ */
231   int wr, wc;
232
233   wr = wc = -1;
234 #if defined (TIOCGWINSZ)
235   if (ioctl (tty, TIOCGWINSZ, &window_size) == 0)
236     {
237       wc = (int) window_size.ws_col;
238       wr = (int) window_size.ws_row;
239     }
240 #endif /* TIOCGWINSZ */
241
242 #if defined (__EMX__)
243   _emx_get_screensize (&wc, &wr);
244 #elif defined (__MINGW32__)
245   _win_get_screensize (&wc, &wr);
246 #endif
247
248   if (ignore_env || rl_prefer_env_winsize == 0)
249     {
250       _rl_screenwidth = wc;
251       _rl_screenheight = wr;
252     }
253   else
254     _rl_screenwidth = _rl_screenheight = -1;
255
256   /* Environment variable COLUMNS overrides setting of "co" if IGNORE_ENV
257      is unset.  If we prefer the environment, check it first before
258      assigning the value returned by the kernel. */
259   if (_rl_screenwidth <= 0)
260     {
261       if (ignore_env == 0 && (ss = sh_get_env_value ("COLUMNS")))
262         _rl_screenwidth = atoi (ss);
263
264       if (_rl_screenwidth <= 0)
265         _rl_screenwidth = wc;
266
267 #if !defined (__DJGPP__)
268       if (_rl_screenwidth <= 0 && term_string_buffer)
269         _rl_screenwidth = tgetnum ("co");
270 #endif
271     }
272
273   /* Environment variable LINES overrides setting of "li" if IGNORE_ENV
274      is unset. */
275   if (_rl_screenheight <= 0)
276     {
277       if (ignore_env == 0 && (ss = sh_get_env_value ("LINES")))
278         _rl_screenheight = atoi (ss);
279
280       if (_rl_screenheight <= 0)
281         _rl_screenheight = wr;
282
283 #if !defined (__DJGPP__)
284       if (_rl_screenheight <= 0 && term_string_buffer)
285         _rl_screenheight = tgetnum ("li");
286 #endif
287     }
288
289   /* If all else fails, default to 80x24 terminal. */
290   if (_rl_screenwidth <= 1)
291     _rl_screenwidth = 80;
292
293   if (_rl_screenheight <= 0)
294     _rl_screenheight = 24;
295
296   /* If we're being compiled as part of bash, set the environment
297      variables $LINES and $COLUMNS to new values.  Otherwise, just
298      do a pair of putenv () or setenv () calls. */
299   sh_set_lines_and_columns (_rl_screenheight, _rl_screenwidth);
300
301   if (_rl_term_autowrap == 0)
302     _rl_screenwidth--;
303
304   _rl_screenchars = _rl_screenwidth * _rl_screenheight;
305 }
306
307 void
308 _rl_set_screen_size (rows, cols)
309      int rows, cols;
310 {
311   if (_rl_term_autowrap == -1)
312     _rl_init_terminal_io (rl_terminal_name);
313
314   if (rows > 0)
315     _rl_screenheight = rows;
316   if (cols > 0)
317     {
318       _rl_screenwidth = cols;
319       if (_rl_term_autowrap == 0)
320         _rl_screenwidth--;
321     }
322
323   if (rows > 0 || cols > 0)
324     _rl_screenchars = _rl_screenwidth * _rl_screenheight;
325 }
326
327 void
328 rl_set_screen_size (rows, cols)
329      int rows, cols;
330 {
331   _rl_set_screen_size (rows, cols);
332 }
333
334 void
335 rl_get_screen_size (rows, cols)
336      int *rows, *cols;
337 {
338   if (rows)
339     *rows = _rl_screenheight;
340   if (cols)
341     *cols = _rl_screenwidth;
342 }
343
344 void
345 rl_reset_screen_size ()
346 {
347   _rl_get_screen_size (fileno (rl_instream), 0);
348 }
349      
350 void
351 rl_resize_terminal ()
352 {
353   if (readline_echoing_p)
354     {
355       _rl_get_screen_size (fileno (rl_instream), 1);
356       if (CUSTOM_REDISPLAY_FUNC ())
357         rl_forced_update_display ();
358       else
359         _rl_redisplay_after_sigwinch ();
360     }
361 }
362
363 struct _tc_string {
364      const char *tc_var;
365      char **tc_value;
366 };
367
368 /* This should be kept sorted, just in case we decide to change the
369    search algorithm to something smarter. */
370 static struct _tc_string tc_strings[] =
371 {
372   { "@7", &_rl_term_at7 },
373   { "DC", &_rl_term_DC },
374   { "IC", &_rl_term_IC },
375   { "ce", &_rl_term_clreol },
376   { "cl", &_rl_term_clrpag },
377   { "cr", &_rl_term_cr },
378   { "dc", &_rl_term_dc },
379   { "ei", &_rl_term_ei },
380   { "ic", &_rl_term_ic },
381   { "im", &_rl_term_im },
382   { "kD", &_rl_term_kD },       /* delete */
383   { "kH", &_rl_term_kH },       /* home down ?? */
384   { "kI", &_rl_term_kI },       /* insert */
385   { "kd", &_rl_term_kd },
386   { "ke", &_rl_term_ke },       /* end keypad mode */
387   { "kh", &_rl_term_kh },       /* home */
388   { "kl", &_rl_term_kl },
389   { "kr", &_rl_term_kr },
390   { "ks", &_rl_term_ks },       /* start keypad mode */
391   { "ku", &_rl_term_ku },
392   { "le", &_rl_term_backspace },
393   { "mm", &_rl_term_mm },
394   { "mo", &_rl_term_mo },
395   { "nd", &_rl_term_forward_char },
396   { "pc", &_rl_term_pc },
397   { "up", &_rl_term_up },
398   { "vb", &_rl_visible_bell },
399   { "vs", &_rl_term_vs },
400   { "ve", &_rl_term_ve },
401 };
402
403 #define NUM_TC_STRINGS (sizeof (tc_strings) / sizeof (struct _tc_string))
404
405 /* Read the desired terminal capability strings into BP.  The capabilities
406    are described in the TC_STRINGS table. */
407 static void
408 get_term_capabilities (bp)
409      char **bp;
410 {
411 #if !defined (__DJGPP__)        /* XXX - doesn't DJGPP have a termcap library? */
412   register int i;
413
414   for (i = 0; i < NUM_TC_STRINGS; i++)
415     *(tc_strings[i].tc_value) = tgetstr ((char *)tc_strings[i].tc_var, bp);
416 #endif
417   tcap_initialized = 1;
418 }
419
420 int
421 _rl_init_terminal_io (terminal_name)
422      const char *terminal_name;
423 {
424   const char *term;
425   char *buffer;
426   int tty, tgetent_ret;
427
428   term = terminal_name ? terminal_name : sh_get_env_value ("TERM");
429   _rl_term_clrpag = _rl_term_cr = _rl_term_clreol = (char *)NULL;
430   tty = rl_instream ? fileno (rl_instream) : 0;
431
432   if (term == 0)
433     term = "dumb";
434
435   /* I've separated this out for later work on not calling tgetent at all
436      if the calling application has supplied a custom redisplay function,
437      (and possibly if the application has supplied a custom input function). */
438   if (CUSTOM_REDISPLAY_FUNC())
439     {
440       tgetent_ret = -1;
441     }
442   else
443     {
444       if (term_string_buffer == 0)
445         term_string_buffer = (char *)xmalloc(2032);
446
447       if (term_buffer == 0)
448         term_buffer = (char *)xmalloc(4080);
449
450       buffer = term_string_buffer;
451
452       tgetent_ret = tgetent (term_buffer, term);
453     }
454
455   if (tgetent_ret <= 0)
456     {
457       FREE (term_string_buffer);
458       FREE (term_buffer);
459       buffer = term_buffer = term_string_buffer = (char *)NULL;
460
461       _rl_term_autowrap = 0;    /* used by _rl_get_screen_size */
462
463       /* Allow calling application to set default height and width, using
464          rl_set_screen_size */
465       if (_rl_screenwidth <= 0 || _rl_screenheight <= 0)
466         {
467 #if defined (__EMX__)
468           _emx_get_screensize (&_rl_screenwidth, &_rl_screenheight);
469           _rl_screenwidth--;
470 #else /* !__EMX__ */
471           _rl_get_screen_size (tty, 0);
472 #endif /* !__EMX__ */
473         }
474
475       /* Defaults. */
476       if (_rl_screenwidth <= 0 || _rl_screenheight <= 0)
477         {
478           _rl_screenwidth = 79;
479           _rl_screenheight = 24;
480         }
481
482       /* Everything below here is used by the redisplay code (tputs). */
483       _rl_screenchars = _rl_screenwidth * _rl_screenheight;
484       _rl_term_cr = "\r";
485       _rl_term_im = _rl_term_ei = _rl_term_ic = _rl_term_IC = (char *)NULL;
486       _rl_term_up = _rl_term_dc = _rl_term_DC = _rl_visible_bell = (char *)NULL;
487       _rl_term_ku = _rl_term_kd = _rl_term_kl = _rl_term_kr = (char *)NULL;
488       _rl_term_kh = _rl_term_kH = _rl_term_kI = _rl_term_kD = (char *)NULL;
489       _rl_term_ks = _rl_term_ke = _rl_term_at7 = (char *)NULL;
490       _rl_term_mm = _rl_term_mo = (char *)NULL;
491       _rl_term_ve = _rl_term_vs = (char *)NULL;
492       _rl_term_forward_char = (char *)NULL;
493       _rl_terminal_can_insert = term_has_meta = 0;
494
495       /* Reasonable defaults for tgoto().  Readline currently only uses
496          tgoto if _rl_term_IC or _rl_term_DC is defined, but just in case we
497          change that later... */
498       PC = '\0';
499       BC = _rl_term_backspace = "\b";
500       UP = _rl_term_up;
501
502       return 0;
503     }
504
505   get_term_capabilities (&buffer);
506
507   /* Set up the variables that the termcap library expects the application
508      to provide. */
509   PC = _rl_term_pc ? *_rl_term_pc : 0;
510   BC = _rl_term_backspace;
511   UP = _rl_term_up;
512
513   if (!_rl_term_cr)
514     _rl_term_cr = "\r";
515
516   _rl_term_autowrap = tgetflag ("am") && tgetflag ("xn");
517
518   /* Allow calling application to set default height and width, using
519      rl_set_screen_size */
520   if (_rl_screenwidth <= 0 || _rl_screenheight <= 0)
521     _rl_get_screen_size (tty, 0);
522
523   /* "An application program can assume that the terminal can do
524       character insertion if *any one of* the capabilities `IC',
525       `im', `ic' or `ip' is provided."  But we can't do anything if
526       only `ip' is provided, so... */
527   _rl_terminal_can_insert = (_rl_term_IC || _rl_term_im || _rl_term_ic);
528
529   /* Check to see if this terminal has a meta key and clear the capability
530      variables if there is none. */
531   term_has_meta = (tgetflag ("km") || tgetflag ("MT"));
532   if (!term_has_meta)
533     _rl_term_mm = _rl_term_mo = (char *)NULL;
534
535   /* Attempt to find and bind the arrow keys.  Do not override already
536      bound keys in an overzealous attempt, however. */
537
538   bind_termcap_arrow_keys (emacs_standard_keymap);
539
540 #if defined (VI_MODE)
541   bind_termcap_arrow_keys (vi_movement_keymap);
542   bind_termcap_arrow_keys (vi_insertion_keymap);
543 #endif /* VI_MODE */
544
545   return 0;
546 }
547
548 /* Bind the arrow key sequences from the termcap description in MAP. */
549 static void
550 bind_termcap_arrow_keys (map)
551      Keymap map;
552 {
553   Keymap xkeymap;
554
555   xkeymap = _rl_keymap;
556   _rl_keymap = map;
557
558   rl_bind_keyseq_if_unbound (_rl_term_ku, rl_get_previous_history);
559   rl_bind_keyseq_if_unbound (_rl_term_kd, rl_get_next_history);
560   rl_bind_keyseq_if_unbound (_rl_term_kr, rl_forward_char);
561   rl_bind_keyseq_if_unbound (_rl_term_kl, rl_backward_char);
562
563   rl_bind_keyseq_if_unbound (_rl_term_kh, rl_beg_of_line);      /* Home */
564   rl_bind_keyseq_if_unbound (_rl_term_at7, rl_end_of_line);     /* End */
565
566   rl_bind_keyseq_if_unbound (_rl_term_kD, rl_delete);
567
568   _rl_keymap = xkeymap;
569 }
570
571 char *
572 rl_get_termcap (cap)
573      const char *cap;
574 {
575   register int i;
576
577   if (tcap_initialized == 0)
578     return ((char *)NULL);
579   for (i = 0; i < NUM_TC_STRINGS; i++)
580     {
581       if (tc_strings[i].tc_var[0] == cap[0] && strcmp (tc_strings[i].tc_var, cap) == 0)
582         return *(tc_strings[i].tc_value);
583     }
584   return ((char *)NULL);
585 }
586
587 /* Re-initialize the terminal considering that the TERM/TERMCAP variable
588    has changed. */
589 int
590 rl_reset_terminal (terminal_name)
591      const char *terminal_name;
592 {
593   _rl_screenwidth = _rl_screenheight = 0;
594   _rl_init_terminal_io (terminal_name);
595   return 0;
596 }
597
598 /* A function for the use of tputs () */
599 #ifdef _MINIX
600 void
601 _rl_output_character_function (c)
602      int c;
603 {
604   putc (c, _rl_out_stream);
605 }
606 #else /* !_MINIX */
607 int
608 _rl_output_character_function (c)
609      int c;
610 {
611   return putc (c, _rl_out_stream);
612 }
613 #endif /* !_MINIX */
614
615 /* Write COUNT characters from STRING to the output stream. */
616 void
617 _rl_output_some_chars (string, count)
618      const char *string;
619      int count;
620 {
621   fwrite (string, 1, count, _rl_out_stream);
622 }
623
624 /* Move the cursor back. */
625 int
626 _rl_backspace (count)
627      int count;
628 {
629   register int i;
630
631   if (_rl_term_backspace)
632     for (i = 0; i < count; i++)
633       tputs (_rl_term_backspace, 1, _rl_output_character_function);
634   else
635     for (i = 0; i < count; i++)
636       putc ('\b', _rl_out_stream);
637   return 0;
638 }
639
640 /* Move to the start of the next line. */
641 int
642 rl_crlf ()
643 {
644 #if defined (NEW_TTY_DRIVER)
645   if (_rl_term_cr)
646     tputs (_rl_term_cr, 1, _rl_output_character_function);
647 #endif /* NEW_TTY_DRIVER */
648   putc ('\n', _rl_out_stream);
649   return 0;
650 }
651
652 /* Ring the terminal bell. */
653 int
654 rl_ding ()
655 {
656   if (readline_echoing_p)
657     {
658       switch (_rl_bell_preference)
659         {
660         case NO_BELL:
661         default:
662           break;
663         case VISIBLE_BELL:
664           if (_rl_visible_bell)
665             {
666               tputs (_rl_visible_bell, 1, _rl_output_character_function);
667               break;
668             }
669           /* FALLTHROUGH */
670         case AUDIBLE_BELL:
671           fprintf (stderr, "\007");
672           fflush (stderr);
673           break;
674         }
675       return (0);
676     }
677   return (-1);
678 }
679
680 /* **************************************************************** */
681 /*                                                                  */
682 /*              Controlling the Meta Key and Keypad                 */
683 /*                                                                  */
684 /* **************************************************************** */
685
686 void
687 _rl_enable_meta_key ()
688 {
689 #if !defined (__DJGPP__)
690   if (term_has_meta && _rl_term_mm)
691     tputs (_rl_term_mm, 1, _rl_output_character_function);
692 #endif
693 }
694
695 void
696 _rl_control_keypad (on)
697      int on;
698 {
699 #if !defined (__DJGPP__)
700   if (on && _rl_term_ks)
701     tputs (_rl_term_ks, 1, _rl_output_character_function);
702   else if (!on && _rl_term_ke)
703     tputs (_rl_term_ke, 1, _rl_output_character_function);
704 #endif
705 }
706
707 /* **************************************************************** */
708 /*                                                                  */
709 /*                      Controlling the Cursor                      */
710 /*                                                                  */
711 /* **************************************************************** */
712
713 /* Set the cursor appropriately depending on IM, which is one of the
714    insert modes (insert or overwrite).  Insert mode gets the normal
715    cursor.  Overwrite mode gets a very visible cursor.  Only does
716    anything if we have both capabilities. */
717 void
718 _rl_set_cursor (im, force)
719      int im, force;
720 {
721   if (_rl_term_ve && _rl_term_vs)
722     {
723       if (force || im != rl_insert_mode)
724         {
725           if (im == RL_IM_OVERWRITE)
726             tputs (_rl_term_vs, 1, _rl_output_character_function);
727           else
728             tputs (_rl_term_ve, 1, _rl_output_character_function);
729         }
730     }
731 }