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