OSDN Git Service

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