xref: /openbsd-src/gnu/lib/libreadline/terminal.c (revision 146f3f6add7a0e0ba8ccf4c59ad3beea87957093)
11acd27e7Smillert /* terminal.c -- controlling the terminal with termcap. */
21acd27e7Smillert 
31acd27e7Smillert /* Copyright (C) 1996 Free Software Foundation, Inc.
41acd27e7Smillert 
51acd27e7Smillert    This file is part of the GNU Readline Library, a library for
61acd27e7Smillert    reading lines of text with interactive input and history editing.
71acd27e7Smillert 
81acd27e7Smillert    The GNU Readline Library is free software; you can redistribute it
91acd27e7Smillert    and/or modify it under the terms of the GNU General Public License
101acd27e7Smillert    as published by the Free Software Foundation; either version 2, or
111acd27e7Smillert    (at your option) any later version.
121acd27e7Smillert 
131acd27e7Smillert    The GNU Readline Library is distributed in the hope that it will be
141acd27e7Smillert    useful, but WITHOUT ANY WARRANTY; without even the implied warranty
151acd27e7Smillert    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
161acd27e7Smillert    GNU General Public License for more details.
171acd27e7Smillert 
181acd27e7Smillert    The GNU General Public License is often shipped with GNU software, and
191acd27e7Smillert    is generally kept in a file called COPYING or LICENSE.  If you do not
201acd27e7Smillert    have a copy of the license, write to the Free Software Foundation,
211acd27e7Smillert    59 Temple Place, Suite 330, Boston, MA 02111 USA. */
221acd27e7Smillert #define READLINE_LIBRARY
231acd27e7Smillert 
241acd27e7Smillert #if defined (HAVE_CONFIG_H)
251acd27e7Smillert #  include <config.h>
261acd27e7Smillert #endif
271acd27e7Smillert 
281acd27e7Smillert #include <sys/types.h>
291acd27e7Smillert #include "posixstat.h"
301acd27e7Smillert #include <fcntl.h>
311acd27e7Smillert #if defined (HAVE_SYS_FILE_H)
321acd27e7Smillert #  include <sys/file.h>
331acd27e7Smillert #endif /* HAVE_SYS_FILE_H */
341acd27e7Smillert 
351acd27e7Smillert #if defined (HAVE_UNISTD_H)
361acd27e7Smillert #  include <unistd.h>
371acd27e7Smillert #endif /* HAVE_UNISTD_H */
381acd27e7Smillert 
391acd27e7Smillert #if defined (HAVE_STDLIB_H)
401acd27e7Smillert #  include <stdlib.h>
411acd27e7Smillert #else
421acd27e7Smillert #  include "ansi_stdlib.h"
431acd27e7Smillert #endif /* HAVE_STDLIB_H */
441acd27e7Smillert 
451acd27e7Smillert #if defined (HAVE_LOCALE_H)
461acd27e7Smillert #  include <locale.h>
471acd27e7Smillert #endif
481acd27e7Smillert 
491acd27e7Smillert #include <stdio.h>
501acd27e7Smillert 
511acd27e7Smillert /* System-specific feature definitions and include files. */
521acd27e7Smillert #include "rldefs.h"
531acd27e7Smillert 
541acd27e7Smillert #  include <sys/ioctl.h>
551acd27e7Smillert 
561acd27e7Smillert #include "rltty.h"
571acd27e7Smillert #include "tcap.h"
581acd27e7Smillert 
591acd27e7Smillert /* Some standard library routines. */
601acd27e7Smillert #include "readline.h"
611acd27e7Smillert #include "history.h"
621acd27e7Smillert 
631acd27e7Smillert #include "rlprivate.h"
641acd27e7Smillert #include "rlshell.h"
65*af70c2dfSkettenis #include "xmalloc.h"
66*af70c2dfSkettenis 
67*af70c2dfSkettenis #define CUSTOM_REDISPLAY_FUNC() (rl_redisplay_function != rl_redisplay)
68*af70c2dfSkettenis #define CUSTOM_INPUT_FUNC() (rl_getc_function != rl_getc)
691acd27e7Smillert 
701acd27e7Smillert /* **************************************************************** */
711acd27e7Smillert /*								    */
721acd27e7Smillert /*			Terminal and Termcap			    */
731acd27e7Smillert /*								    */
741acd27e7Smillert /* **************************************************************** */
751acd27e7Smillert 
761acd27e7Smillert static char *term_buffer = (char *)NULL;
771acd27e7Smillert static char *term_string_buffer = (char *)NULL;
781acd27e7Smillert 
791acd27e7Smillert static int tcap_initialized;
801acd27e7Smillert 
811acd27e7Smillert #if !defined (__linux__)
821acd27e7Smillert #  if defined (__EMX__) || defined (NEED_EXTERN_PC)
831acd27e7Smillert extern
841acd27e7Smillert #  endif /* __EMX__ || NEED_EXTERN_PC */
851acd27e7Smillert char PC, *BC, *UP;
861acd27e7Smillert #endif /* __linux__ */
871acd27e7Smillert 
881acd27e7Smillert /* Some strings to control terminal actions.  These are output by tputs (). */
89*af70c2dfSkettenis char *_rl_term_clreol;
90*af70c2dfSkettenis char *_rl_term_clrpag;
91*af70c2dfSkettenis char *_rl_term_cr;
92*af70c2dfSkettenis char *_rl_term_backspace;
93*af70c2dfSkettenis char *_rl_term_goto;
94*af70c2dfSkettenis char *_rl_term_pc;
951acd27e7Smillert 
961acd27e7Smillert /* Non-zero if we determine that the terminal can do character insertion. */
97*af70c2dfSkettenis int _rl_terminal_can_insert = 0;
981acd27e7Smillert 
991acd27e7Smillert /* How to insert characters. */
100*af70c2dfSkettenis char *_rl_term_im;
101*af70c2dfSkettenis char *_rl_term_ei;
102*af70c2dfSkettenis char *_rl_term_ic;
103*af70c2dfSkettenis char *_rl_term_ip;
104*af70c2dfSkettenis char *_rl_term_IC;
1051acd27e7Smillert 
1061acd27e7Smillert /* How to delete characters. */
107*af70c2dfSkettenis char *_rl_term_dc;
108*af70c2dfSkettenis char *_rl_term_DC;
1091acd27e7Smillert 
1101acd27e7Smillert #if defined (HACK_TERMCAP_MOTION)
111*af70c2dfSkettenis char *_rl_term_forward_char;
1121acd27e7Smillert #endif  /* HACK_TERMCAP_MOTION */
1131acd27e7Smillert 
1141acd27e7Smillert /* How to go up a line. */
115*af70c2dfSkettenis char *_rl_term_up;
1161acd27e7Smillert 
117*af70c2dfSkettenis /* A visible bell; char if the terminal can be made to flash the screen. */
118*af70c2dfSkettenis static char *_rl_visible_bell;
1191acd27e7Smillert 
1201acd27e7Smillert /* Non-zero means the terminal can auto-wrap lines. */
1211acd27e7Smillert int _rl_term_autowrap;
1221acd27e7Smillert 
1231acd27e7Smillert /* Non-zero means that this terminal has a meta key. */
1241acd27e7Smillert static int term_has_meta;
1251acd27e7Smillert 
1261acd27e7Smillert /* The sequences to write to turn on and off the meta key, if this
1271acd27e7Smillert    terminal has one. */
128*af70c2dfSkettenis static char *_rl_term_mm;
129*af70c2dfSkettenis static char *_rl_term_mo;
1301acd27e7Smillert 
1311acd27e7Smillert /* The key sequences output by the arrow keys, if this terminal has any. */
132*af70c2dfSkettenis static char *_rl_term_ku;
133*af70c2dfSkettenis static char *_rl_term_kd;
134*af70c2dfSkettenis static char *_rl_term_kr;
135*af70c2dfSkettenis static char *_rl_term_kl;
1361acd27e7Smillert 
1371acd27e7Smillert /* How to initialize and reset the arrow keys, if this terminal has any. */
138*af70c2dfSkettenis static char *_rl_term_ks;
139*af70c2dfSkettenis static char *_rl_term_ke;
1401acd27e7Smillert 
1411acd27e7Smillert /* The key sequences sent by the Home and End keys, if any. */
142*af70c2dfSkettenis static char *_rl_term_kh;
143*af70c2dfSkettenis static char *_rl_term_kH;
144*af70c2dfSkettenis static char *_rl_term_at7;	/* @7 */
145*af70c2dfSkettenis 
146*af70c2dfSkettenis /* Insert key */
147*af70c2dfSkettenis static char *_rl_term_kI;
148*af70c2dfSkettenis 
149*af70c2dfSkettenis /* Cursor control */
150*af70c2dfSkettenis static char *_rl_term_vs;	/* very visible */
151*af70c2dfSkettenis static char *_rl_term_ve;	/* normal */
152*af70c2dfSkettenis 
153*af70c2dfSkettenis static void bind_termcap_arrow_keys PARAMS((Keymap));
1541acd27e7Smillert 
1551acd27e7Smillert /* Variables that hold the screen dimensions, used by the display code. */
156*af70c2dfSkettenis int _rl_screenwidth, _rl_screenheight, _rl_screenchars;
1571acd27e7Smillert 
1581acd27e7Smillert /* Non-zero means the user wants to enable the keypad. */
1591acd27e7Smillert int _rl_enable_keypad;
1601acd27e7Smillert 
1611acd27e7Smillert /* Non-zero means the user wants to enable a meta key. */
1621acd27e7Smillert int _rl_enable_meta = 1;
1631acd27e7Smillert 
1641acd27e7Smillert #if defined (__EMX__)
1651acd27e7Smillert static void
_emx_get_screensize(swp,shp)1661acd27e7Smillert _emx_get_screensize (swp, shp)
1671acd27e7Smillert      int *swp, *shp;
1681acd27e7Smillert {
1691acd27e7Smillert   int sz[2];
1701acd27e7Smillert 
1711acd27e7Smillert   _scrsize (sz);
1721acd27e7Smillert 
1731acd27e7Smillert   if (swp)
1741acd27e7Smillert     *swp = sz[0];
1751acd27e7Smillert   if (shp)
1761acd27e7Smillert     *shp = sz[1];
1771acd27e7Smillert }
1781acd27e7Smillert #endif
1791acd27e7Smillert 
1801acd27e7Smillert /* Get readline's idea of the screen size.  TTY is a file descriptor open
1811acd27e7Smillert    to the terminal.  If IGNORE_ENV is true, we do not pay attention to the
1821acd27e7Smillert    values of $LINES and $COLUMNS.  The tests for TERM_STRING_BUFFER being
1831acd27e7Smillert    non-null serve to check whether or not we have initialized termcap. */
1841acd27e7Smillert void
_rl_get_screen_size(tty,ignore_env)1851acd27e7Smillert _rl_get_screen_size (tty, ignore_env)
1861acd27e7Smillert      int tty, ignore_env;
1871acd27e7Smillert {
1881acd27e7Smillert   char *ss;
1891acd27e7Smillert #if defined (TIOCGWINSZ)
1901acd27e7Smillert   struct winsize window_size;
1911acd27e7Smillert #endif /* TIOCGWINSZ */
1921acd27e7Smillert 
1931acd27e7Smillert #if defined (TIOCGWINSZ)
1941acd27e7Smillert   if (ioctl (tty, TIOCGWINSZ, &window_size) == 0)
1951acd27e7Smillert     {
196*af70c2dfSkettenis       _rl_screenwidth = (int) window_size.ws_col;
197*af70c2dfSkettenis       _rl_screenheight = (int) window_size.ws_row;
1981acd27e7Smillert     }
1991acd27e7Smillert #endif /* TIOCGWINSZ */
2001acd27e7Smillert 
2011acd27e7Smillert #if defined (__EMX__)
202*af70c2dfSkettenis   _emx_get_screensize (&_rl_screenwidth, &_rl_screenheight);
2031acd27e7Smillert #endif
2041acd27e7Smillert 
2051acd27e7Smillert   /* Environment variable COLUMNS overrides setting of "co" if IGNORE_ENV
2061acd27e7Smillert      is unset. */
207*af70c2dfSkettenis   if (_rl_screenwidth <= 0)
2081acd27e7Smillert     {
209*af70c2dfSkettenis       if (ignore_env == 0 && (ss = sh_get_env_value ("COLUMNS")) && *ss != '\0')
210*af70c2dfSkettenis 	_rl_screenwidth = atoi (ss);
2111acd27e7Smillert 
2121acd27e7Smillert #if !defined (__DJGPP__)
213*af70c2dfSkettenis       if (_rl_screenwidth <= 0 && term_string_buffer)
214*af70c2dfSkettenis 	_rl_screenwidth = tgetnum ("co");
2151acd27e7Smillert #endif
2161acd27e7Smillert     }
2171acd27e7Smillert 
2181acd27e7Smillert   /* Environment variable LINES overrides setting of "li" if IGNORE_ENV
2191acd27e7Smillert      is unset. */
220*af70c2dfSkettenis   if (_rl_screenheight <= 0)
2211acd27e7Smillert     {
222*af70c2dfSkettenis       if (ignore_env == 0 && (ss = sh_get_env_value ("LINES")) && *ss != '\0')
223*af70c2dfSkettenis 	_rl_screenheight = atoi (ss);
2241acd27e7Smillert 
2251acd27e7Smillert #if !defined (__DJGPP__)
226*af70c2dfSkettenis       if (_rl_screenheight <= 0 && term_string_buffer)
227*af70c2dfSkettenis 	_rl_screenheight = tgetnum ("li");
2281acd27e7Smillert #endif
2291acd27e7Smillert     }
2301acd27e7Smillert 
2311acd27e7Smillert   /* If all else fails, default to 80x24 terminal. */
232*af70c2dfSkettenis   if (_rl_screenwidth <= 1)
233*af70c2dfSkettenis     _rl_screenwidth = 80;
2341acd27e7Smillert 
235*af70c2dfSkettenis   if (_rl_screenheight <= 0)
236*af70c2dfSkettenis     _rl_screenheight = 24;
2371acd27e7Smillert 
2381acd27e7Smillert   /* If we're being compiled as part of bash, set the environment
2391acd27e7Smillert      variables $LINES and $COLUMNS to new values.  Otherwise, just
2401acd27e7Smillert      do a pair of putenv () or setenv () calls. */
241*af70c2dfSkettenis   sh_set_lines_and_columns (_rl_screenheight, _rl_screenwidth);
2421acd27e7Smillert 
2431acd27e7Smillert   if (_rl_term_autowrap == 0)
244*af70c2dfSkettenis     _rl_screenwidth--;
2451acd27e7Smillert 
246*af70c2dfSkettenis   _rl_screenchars = _rl_screenwidth * _rl_screenheight;
2471acd27e7Smillert }
2481acd27e7Smillert 
2491acd27e7Smillert void
_rl_set_screen_size(rows,cols)2501acd27e7Smillert _rl_set_screen_size (rows, cols)
2511acd27e7Smillert      int rows, cols;
2521acd27e7Smillert {
253*af70c2dfSkettenis   if (rows == 0 || cols == 0)
254*af70c2dfSkettenis     return;
255*af70c2dfSkettenis 
256*af70c2dfSkettenis   _rl_screenheight = rows;
257*af70c2dfSkettenis   _rl_screenwidth = cols;
2581acd27e7Smillert 
2591acd27e7Smillert   if (_rl_term_autowrap == 0)
260*af70c2dfSkettenis     _rl_screenwidth--;
2611acd27e7Smillert 
262*af70c2dfSkettenis   _rl_screenchars = _rl_screenwidth * _rl_screenheight;
263*af70c2dfSkettenis }
264*af70c2dfSkettenis 
265*af70c2dfSkettenis void
rl_set_screen_size(rows,cols)266*af70c2dfSkettenis rl_set_screen_size (rows, cols)
267*af70c2dfSkettenis      int rows, cols;
268*af70c2dfSkettenis {
269*af70c2dfSkettenis   _rl_set_screen_size (rows, cols);
270*af70c2dfSkettenis }
271*af70c2dfSkettenis 
272*af70c2dfSkettenis void
rl_get_screen_size(rows,cols)273*af70c2dfSkettenis rl_get_screen_size (rows, cols)
274*af70c2dfSkettenis      int *rows, *cols;
275*af70c2dfSkettenis {
276*af70c2dfSkettenis   if (rows)
277*af70c2dfSkettenis     *rows = _rl_screenheight;
278*af70c2dfSkettenis   if (cols)
279*af70c2dfSkettenis     *cols = _rl_screenwidth;
2801acd27e7Smillert }
2811acd27e7Smillert 
2821acd27e7Smillert void
rl_resize_terminal()2831acd27e7Smillert rl_resize_terminal ()
2841acd27e7Smillert {
2851acd27e7Smillert   if (readline_echoing_p)
2861acd27e7Smillert     {
2871acd27e7Smillert       _rl_get_screen_size (fileno (rl_instream), 1);
288*af70c2dfSkettenis       if (CUSTOM_REDISPLAY_FUNC ())
289*af70c2dfSkettenis 	rl_forced_update_display ();
290*af70c2dfSkettenis       else
2911acd27e7Smillert 	_rl_redisplay_after_sigwinch ();
2921acd27e7Smillert     }
2931acd27e7Smillert }
2941acd27e7Smillert 
2951acd27e7Smillert struct _tc_string {
296*af70c2dfSkettenis      const char *tc_var;
2971acd27e7Smillert      char **tc_value;
2981acd27e7Smillert };
2991acd27e7Smillert 
3001acd27e7Smillert /* This should be kept sorted, just in case we decide to change the
3011acd27e7Smillert    search algorithm to something smarter. */
3021acd27e7Smillert static struct _tc_string tc_strings[] =
3031acd27e7Smillert {
304*af70c2dfSkettenis   { "@7", &_rl_term_at7 },
305*af70c2dfSkettenis   { "DC", &_rl_term_DC },
306*af70c2dfSkettenis   { "IC", &_rl_term_IC },
307*af70c2dfSkettenis   { "ce", &_rl_term_clreol },
308*af70c2dfSkettenis   { "cl", &_rl_term_clrpag },
309*af70c2dfSkettenis   { "cr", &_rl_term_cr },
310*af70c2dfSkettenis   { "dc", &_rl_term_dc },
311*af70c2dfSkettenis   { "ei", &_rl_term_ei },
312*af70c2dfSkettenis   { "ic", &_rl_term_ic },
313*af70c2dfSkettenis   { "im", &_rl_term_im },
314*af70c2dfSkettenis   { "kH", &_rl_term_kH },	/* home down ?? */
315*af70c2dfSkettenis   { "kI", &_rl_term_kI },	/* insert */
316*af70c2dfSkettenis   { "kd", &_rl_term_kd },
317*af70c2dfSkettenis   { "ke", &_rl_term_ke },	/* end keypad mode */
318*af70c2dfSkettenis   { "kh", &_rl_term_kh },	/* home */
319*af70c2dfSkettenis   { "kl", &_rl_term_kl },
320*af70c2dfSkettenis   { "kr", &_rl_term_kr },
321*af70c2dfSkettenis   { "ks", &_rl_term_ks },	/* start keypad mode */
322*af70c2dfSkettenis   { "ku", &_rl_term_ku },
323*af70c2dfSkettenis   { "le", &_rl_term_backspace },
324*af70c2dfSkettenis   { "mm", &_rl_term_mm },
325*af70c2dfSkettenis   { "mo", &_rl_term_mo },
3261acd27e7Smillert #if defined (HACK_TERMCAP_MOTION)
327*af70c2dfSkettenis   { "nd", &_rl_term_forward_char },
3281acd27e7Smillert #endif
329*af70c2dfSkettenis   { "pc", &_rl_term_pc },
330*af70c2dfSkettenis   { "up", &_rl_term_up },
331*af70c2dfSkettenis   { "vb", &_rl_visible_bell },
332*af70c2dfSkettenis   { "vs", &_rl_term_vs },
333*af70c2dfSkettenis   { "ve", &_rl_term_ve },
3341acd27e7Smillert };
3351acd27e7Smillert 
3361acd27e7Smillert #define NUM_TC_STRINGS (sizeof (tc_strings) / sizeof (struct _tc_string))
3371acd27e7Smillert 
3381acd27e7Smillert /* Read the desired terminal capability strings into BP.  The capabilities
3391acd27e7Smillert    are described in the TC_STRINGS table. */
3401acd27e7Smillert static void
get_term_capabilities(bp)3411acd27e7Smillert get_term_capabilities (bp)
3421acd27e7Smillert      char **bp;
3431acd27e7Smillert {
3441acd27e7Smillert #if !defined (__DJGPP__)	/* XXX - doesn't DJGPP have a termcap library? */
3451acd27e7Smillert   register int i;
3461acd27e7Smillert 
3471acd27e7Smillert   for (i = 0; i < NUM_TC_STRINGS; i++)
348*af70c2dfSkettenis #  ifdef __LCC__
349*af70c2dfSkettenis     *(tc_strings[i].tc_value) = tgetstr ((char *)tc_strings[i].tc_var, bp);
350*af70c2dfSkettenis #  else
3511acd27e7Smillert     *(tc_strings[i].tc_value) = tgetstr (tc_strings[i].tc_var, bp);
3521acd27e7Smillert #  endif
353*af70c2dfSkettenis #endif
3541acd27e7Smillert   tcap_initialized = 1;
3551acd27e7Smillert }
3561acd27e7Smillert 
3571acd27e7Smillert int
_rl_init_terminal_io(terminal_name)3581acd27e7Smillert _rl_init_terminal_io (terminal_name)
359*af70c2dfSkettenis      const char *terminal_name;
3601acd27e7Smillert {
361*af70c2dfSkettenis   const char *term;
362*af70c2dfSkettenis   char *buffer;
3631acd27e7Smillert   int tty, tgetent_ret;
3641acd27e7Smillert 
365*af70c2dfSkettenis   term = terminal_name ? terminal_name : sh_get_env_value ("TERM");
366*af70c2dfSkettenis   _rl_term_clrpag = _rl_term_cr = _rl_term_clreol = (char *)NULL;
3671acd27e7Smillert   tty = rl_instream ? fileno (rl_instream) : 0;
368*af70c2dfSkettenis   _rl_screenwidth = _rl_screenheight = 0;
3691acd27e7Smillert 
37094bc1d69Smillert   if (term == 0 || *term == '\0')
3711acd27e7Smillert     term = "dumb";
3721acd27e7Smillert 
3731acd27e7Smillert   /* I've separated this out for later work on not calling tgetent at all
3741acd27e7Smillert      if the calling application has supplied a custom redisplay function,
3751acd27e7Smillert      (and possibly if the application has supplied a custom input function). */
3761acd27e7Smillert   if (CUSTOM_REDISPLAY_FUNC())
3771acd27e7Smillert     {
3781acd27e7Smillert       tgetent_ret = -1;
3791acd27e7Smillert     }
3801acd27e7Smillert   else
3811acd27e7Smillert     {
3821acd27e7Smillert       if (term_string_buffer == 0)
383*af70c2dfSkettenis 	term_string_buffer = (char *)xmalloc(2032);
3841acd27e7Smillert 
3851acd27e7Smillert       if (term_buffer == 0)
386*af70c2dfSkettenis 	term_buffer = (char *)xmalloc(4080);
3871acd27e7Smillert 
3881acd27e7Smillert       buffer = term_string_buffer;
3891acd27e7Smillert 
3901acd27e7Smillert       tgetent_ret = tgetent (term_buffer, term);
3911acd27e7Smillert     }
3921acd27e7Smillert 
3931acd27e7Smillert   if (tgetent_ret <= 0)
3941acd27e7Smillert     {
3951acd27e7Smillert       FREE (term_string_buffer);
3961acd27e7Smillert       FREE (term_buffer);
3971acd27e7Smillert       buffer = term_buffer = term_string_buffer = (char *)NULL;
3981acd27e7Smillert 
3991acd27e7Smillert       _rl_term_autowrap = 0;	/* used by _rl_get_screen_size */
4001acd27e7Smillert 
4011acd27e7Smillert #if defined (__EMX__)
402*af70c2dfSkettenis       _emx_get_screensize (&_rl_screenwidth, &_rl_screenheight);
403*af70c2dfSkettenis       _rl_screenwidth--;
4041acd27e7Smillert #else /* !__EMX__ */
4051acd27e7Smillert       _rl_get_screen_size (tty, 0);
4061acd27e7Smillert #endif /* !__EMX__ */
4071acd27e7Smillert 
4081acd27e7Smillert       /* Defaults. */
409*af70c2dfSkettenis       if (_rl_screenwidth <= 0 || _rl_screenheight <= 0)
4101acd27e7Smillert         {
411*af70c2dfSkettenis 	  _rl_screenwidth = 79;
412*af70c2dfSkettenis 	  _rl_screenheight = 24;
4131acd27e7Smillert         }
4141acd27e7Smillert 
4151acd27e7Smillert       /* Everything below here is used by the redisplay code (tputs). */
416*af70c2dfSkettenis       _rl_screenchars = _rl_screenwidth * _rl_screenheight;
417*af70c2dfSkettenis       _rl_term_cr = "\r";
418*af70c2dfSkettenis       _rl_term_im = _rl_term_ei = _rl_term_ic = _rl_term_IC = (char *)NULL;
419*af70c2dfSkettenis       _rl_term_up = _rl_term_dc = _rl_term_DC = _rl_visible_bell = (char *)NULL;
420*af70c2dfSkettenis       _rl_term_ku = _rl_term_kd = _rl_term_kl = _rl_term_kr = (char *)NULL;
421*af70c2dfSkettenis       _rl_term_kh = _rl_term_kH = _rl_term_kI = (char *)NULL;
422*af70c2dfSkettenis       _rl_term_ks = _rl_term_ke = _rl_term_at7 = (char *)NULL;
423*af70c2dfSkettenis       _rl_term_mm = _rl_term_mo = (char *)NULL;
424*af70c2dfSkettenis       _rl_term_ve = _rl_term_vs = (char *)NULL;
4251acd27e7Smillert #if defined (HACK_TERMCAP_MOTION)
4261acd27e7Smillert       term_forward_char = (char *)NULL;
4271acd27e7Smillert #endif
428*af70c2dfSkettenis       _rl_terminal_can_insert = term_has_meta = 0;
4291acd27e7Smillert 
4301acd27e7Smillert       /* Reasonable defaults for tgoto().  Readline currently only uses
431*af70c2dfSkettenis          tgoto if _rl_term_IC or _rl_term_DC is defined, but just in case we
4321acd27e7Smillert          change that later... */
4331acd27e7Smillert       PC = '\0';
434*af70c2dfSkettenis       BC = _rl_term_backspace = "\b";
435*af70c2dfSkettenis       UP = _rl_term_up;
4361acd27e7Smillert 
4371acd27e7Smillert       return 0;
4381acd27e7Smillert     }
4391acd27e7Smillert 
4401acd27e7Smillert   get_term_capabilities (&buffer);
4411acd27e7Smillert 
4421acd27e7Smillert   /* Set up the variables that the termcap library expects the application
4431acd27e7Smillert      to provide. */
444*af70c2dfSkettenis   PC = _rl_term_pc ? *_rl_term_pc : 0;
445*af70c2dfSkettenis   BC = _rl_term_backspace;
446*af70c2dfSkettenis   UP = _rl_term_up;
4471acd27e7Smillert 
448*af70c2dfSkettenis   if (!_rl_term_cr)
449*af70c2dfSkettenis     _rl_term_cr = "\r";
4501acd27e7Smillert 
4511acd27e7Smillert   _rl_term_autowrap = tgetflag ("am") && tgetflag ("xn");
4521acd27e7Smillert 
4531acd27e7Smillert   _rl_get_screen_size (tty, 0);
4541acd27e7Smillert 
4551acd27e7Smillert   /* "An application program can assume that the terminal can do
4561acd27e7Smillert       character insertion if *any one of* the capabilities `IC',
4571acd27e7Smillert       `im', `ic' or `ip' is provided."  But we can't do anything if
4581acd27e7Smillert       only `ip' is provided, so... */
459*af70c2dfSkettenis   _rl_terminal_can_insert = (_rl_term_IC || _rl_term_im || _rl_term_ic);
4601acd27e7Smillert 
4611acd27e7Smillert   /* Check to see if this terminal has a meta key and clear the capability
4621acd27e7Smillert      variables if there is none. */
4631acd27e7Smillert   term_has_meta = (tgetflag ("km") || tgetflag ("MT"));
4641acd27e7Smillert   if (!term_has_meta)
465*af70c2dfSkettenis     _rl_term_mm = _rl_term_mo = (char *)NULL;
4661acd27e7Smillert 
4671acd27e7Smillert   /* Attempt to find and bind the arrow keys.  Do not override already
4681acd27e7Smillert      bound keys in an overzealous attempt, however. */
4691acd27e7Smillert 
470*af70c2dfSkettenis   bind_termcap_arrow_keys (emacs_standard_keymap);
4711acd27e7Smillert 
4721acd27e7Smillert #if defined (VI_MODE)
473*af70c2dfSkettenis   bind_termcap_arrow_keys (vi_movement_keymap);
474*af70c2dfSkettenis   bind_termcap_arrow_keys (vi_insertion_keymap);
4751acd27e7Smillert #endif /* VI_MODE */
4761acd27e7Smillert 
4771acd27e7Smillert   return 0;
4781acd27e7Smillert }
4791acd27e7Smillert 
480*af70c2dfSkettenis /* Bind the arrow key sequences from the termcap description in MAP. */
481*af70c2dfSkettenis static void
bind_termcap_arrow_keys(map)482*af70c2dfSkettenis bind_termcap_arrow_keys (map)
483*af70c2dfSkettenis      Keymap map;
484*af70c2dfSkettenis {
485*af70c2dfSkettenis   Keymap xkeymap;
486*af70c2dfSkettenis 
487*af70c2dfSkettenis   xkeymap = _rl_keymap;
488*af70c2dfSkettenis   _rl_keymap = map;
489*af70c2dfSkettenis 
490*af70c2dfSkettenis   _rl_bind_if_unbound (_rl_term_ku, rl_get_previous_history);
491*af70c2dfSkettenis   _rl_bind_if_unbound (_rl_term_kd, rl_get_next_history);
492*af70c2dfSkettenis   _rl_bind_if_unbound (_rl_term_kr, rl_forward);
493*af70c2dfSkettenis   _rl_bind_if_unbound (_rl_term_kl, rl_backward);
494*af70c2dfSkettenis 
495*af70c2dfSkettenis   _rl_bind_if_unbound (_rl_term_kh, rl_beg_of_line);	/* Home */
496*af70c2dfSkettenis   _rl_bind_if_unbound (_rl_term_at7, rl_end_of_line);	/* End */
497*af70c2dfSkettenis 
498*af70c2dfSkettenis   _rl_keymap = xkeymap;
499*af70c2dfSkettenis }
500*af70c2dfSkettenis 
5011acd27e7Smillert char *
rl_get_termcap(cap)5021acd27e7Smillert rl_get_termcap (cap)
503*af70c2dfSkettenis      const char *cap;
5041acd27e7Smillert {
5051acd27e7Smillert   register int i;
5061acd27e7Smillert 
5071acd27e7Smillert   if (tcap_initialized == 0)
5081acd27e7Smillert     return ((char *)NULL);
5091acd27e7Smillert   for (i = 0; i < NUM_TC_STRINGS; i++)
5101acd27e7Smillert     {
5111acd27e7Smillert       if (tc_strings[i].tc_var[0] == cap[0] && strcmp (tc_strings[i].tc_var, cap) == 0)
5121acd27e7Smillert         return *(tc_strings[i].tc_value);
5131acd27e7Smillert     }
5141acd27e7Smillert   return ((char *)NULL);
5151acd27e7Smillert }
5161acd27e7Smillert 
5171acd27e7Smillert /* Re-initialize the terminal considering that the TERM/TERMCAP variable
5181acd27e7Smillert    has changed. */
5191acd27e7Smillert int
rl_reset_terminal(terminal_name)5201acd27e7Smillert rl_reset_terminal (terminal_name)
521*af70c2dfSkettenis      const char *terminal_name;
5221acd27e7Smillert {
5231acd27e7Smillert   _rl_init_terminal_io (terminal_name);
5241acd27e7Smillert   return 0;
5251acd27e7Smillert }
5261acd27e7Smillert 
5271acd27e7Smillert /* A function for the use of tputs () */
5281acd27e7Smillert #ifdef _MINIX
5291acd27e7Smillert void
_rl_output_character_function(c)5301acd27e7Smillert _rl_output_character_function (c)
5311acd27e7Smillert      int c;
5321acd27e7Smillert {
5331acd27e7Smillert   putc (c, _rl_out_stream);
5341acd27e7Smillert }
5351acd27e7Smillert #else /* !_MINIX */
5361acd27e7Smillert int
_rl_output_character_function(c)5371acd27e7Smillert _rl_output_character_function (c)
5381acd27e7Smillert      int c;
5391acd27e7Smillert {
5401acd27e7Smillert   return putc (c, _rl_out_stream);
5411acd27e7Smillert }
5421acd27e7Smillert #endif /* !_MINIX */
5431acd27e7Smillert 
5441acd27e7Smillert /* Write COUNT characters from STRING to the output stream. */
5451acd27e7Smillert void
_rl_output_some_chars(string,count)5461acd27e7Smillert _rl_output_some_chars (string, count)
547*af70c2dfSkettenis      const char *string;
5481acd27e7Smillert      int count;
5491acd27e7Smillert {
5501acd27e7Smillert   fwrite (string, 1, count, _rl_out_stream);
5511acd27e7Smillert }
5521acd27e7Smillert 
5531acd27e7Smillert /* Move the cursor back. */
5541acd27e7Smillert int
_rl_backspace(count)5551acd27e7Smillert _rl_backspace (count)
5561acd27e7Smillert      int count;
5571acd27e7Smillert {
5581acd27e7Smillert   register int i;
5591acd27e7Smillert 
560*af70c2dfSkettenis   if (_rl_term_backspace)
5611acd27e7Smillert     for (i = 0; i < count; i++)
562*af70c2dfSkettenis       tputs (_rl_term_backspace, 1, _rl_output_character_function);
5631acd27e7Smillert   else
5641acd27e7Smillert     for (i = 0; i < count; i++)
5651acd27e7Smillert       putc ('\b', _rl_out_stream);
5661acd27e7Smillert   return 0;
5671acd27e7Smillert }
5681acd27e7Smillert 
5691acd27e7Smillert /* Move to the start of the next line. */
5701acd27e7Smillert int
rl_crlf()571*af70c2dfSkettenis rl_crlf ()
5721acd27e7Smillert {
5731acd27e7Smillert #if defined (NEW_TTY_DRIVER)
574*af70c2dfSkettenis   if (_rl_term_cr)
575*af70c2dfSkettenis     tputs (_rl_term_cr, 1, _rl_output_character_function);
5761acd27e7Smillert #endif /* NEW_TTY_DRIVER */
5771acd27e7Smillert   putc ('\n', _rl_out_stream);
5781acd27e7Smillert   return 0;
5791acd27e7Smillert }
5801acd27e7Smillert 
5811acd27e7Smillert /* Ring the terminal bell. */
5821acd27e7Smillert int
rl_ding()583*af70c2dfSkettenis rl_ding ()
5841acd27e7Smillert {
5851acd27e7Smillert   if (readline_echoing_p)
5861acd27e7Smillert     {
5871acd27e7Smillert       switch (_rl_bell_preference)
5881acd27e7Smillert         {
5891acd27e7Smillert 	case NO_BELL:
5901acd27e7Smillert 	default:
5911acd27e7Smillert 	  break;
5921acd27e7Smillert 	case VISIBLE_BELL:
593*af70c2dfSkettenis 	  if (_rl_visible_bell)
5941acd27e7Smillert 	    {
595*af70c2dfSkettenis 	      tputs (_rl_visible_bell, 1, _rl_output_character_function);
5961acd27e7Smillert 	      break;
5971acd27e7Smillert 	    }
5981acd27e7Smillert 	  /* FALLTHROUGH */
5991acd27e7Smillert 	case AUDIBLE_BELL:
6001acd27e7Smillert 	  fprintf (stderr, "\007");
6011acd27e7Smillert 	  fflush (stderr);
6021acd27e7Smillert 	  break;
6031acd27e7Smillert         }
6041acd27e7Smillert       return (0);
6051acd27e7Smillert     }
6061acd27e7Smillert   return (-1);
6071acd27e7Smillert }
6081acd27e7Smillert 
6091acd27e7Smillert /* **************************************************************** */
6101acd27e7Smillert /*								    */
6111acd27e7Smillert /*		Controlling the Meta Key and Keypad		    */
6121acd27e7Smillert /*								    */
6131acd27e7Smillert /* **************************************************************** */
6141acd27e7Smillert 
6151acd27e7Smillert void
_rl_enable_meta_key()6161acd27e7Smillert _rl_enable_meta_key ()
6171acd27e7Smillert {
6181acd27e7Smillert #if !defined (__DJGPP__)
619*af70c2dfSkettenis   if (term_has_meta && _rl_term_mm)
620*af70c2dfSkettenis     tputs (_rl_term_mm, 1, _rl_output_character_function);
6211acd27e7Smillert #endif
6221acd27e7Smillert }
6231acd27e7Smillert 
6241acd27e7Smillert void
_rl_control_keypad(on)6251acd27e7Smillert _rl_control_keypad (on)
6261acd27e7Smillert      int on;
6271acd27e7Smillert {
6281acd27e7Smillert #if !defined (__DJGPP__)
629*af70c2dfSkettenis   if (on && _rl_term_ks)
630*af70c2dfSkettenis     tputs (_rl_term_ks, 1, _rl_output_character_function);
631*af70c2dfSkettenis   else if (!on && _rl_term_ke)
632*af70c2dfSkettenis     tputs (_rl_term_ke, 1, _rl_output_character_function);
6331acd27e7Smillert #endif
6341acd27e7Smillert }
635*af70c2dfSkettenis 
636*af70c2dfSkettenis /* **************************************************************** */
637*af70c2dfSkettenis /*								    */
638*af70c2dfSkettenis /*			Controlling the Cursor			    */
639*af70c2dfSkettenis /*								    */
640*af70c2dfSkettenis /* **************************************************************** */
641*af70c2dfSkettenis 
642*af70c2dfSkettenis /* Set the cursor appropriately depending on IM, which is one of the
643*af70c2dfSkettenis    insert modes (insert or overwrite).  Insert mode gets the normal
644*af70c2dfSkettenis    cursor.  Overwrite mode gets a very visible cursor.  Only does
645*af70c2dfSkettenis    anything if we have both capabilities. */
646*af70c2dfSkettenis void
_rl_set_cursor(im,force)647*af70c2dfSkettenis _rl_set_cursor (im, force)
648*af70c2dfSkettenis      int im, force;
649*af70c2dfSkettenis {
650*af70c2dfSkettenis   if (_rl_term_ve && _rl_term_vs)
651*af70c2dfSkettenis     {
652*af70c2dfSkettenis       if (force || im != rl_insert_mode)
653*af70c2dfSkettenis 	{
654*af70c2dfSkettenis 	  if (im == RL_IM_OVERWRITE)
655*af70c2dfSkettenis 	    tputs (_rl_term_vs, 1, _rl_output_character_function);
656*af70c2dfSkettenis 	  else
657*af70c2dfSkettenis 	    tputs (_rl_term_ve, 1, _rl_output_character_function);
658*af70c2dfSkettenis 	}
659*af70c2dfSkettenis     }
660*af70c2dfSkettenis }
661