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