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