1136758Speter/* $FreeBSD$ */
221308Sache/* terminal.c -- controlling the terminal with termcap. */
321308Sache
4165675Sache/* Copyright (C) 1996-2006 Free Software Foundation, Inc.
521308Sache
621308Sache   This file is part of the GNU Readline Library, a library for
721308Sache   reading lines of text with interactive input and history editing.
821308Sache
921308Sache   The GNU Readline Library is free software; you can redistribute it
1021308Sache   and/or modify it under the terms of the GNU General Public License
1158314Sache   as published by the Free Software Foundation; either version 2, or
1221308Sache   (at your option) any later version.
1321308Sache
1421308Sache   The GNU Readline Library is distributed in the hope that it will be
1521308Sache   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
1621308Sache   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1721308Sache   GNU General Public License for more details.
1821308Sache
1921308Sache   The GNU General Public License is often shipped with GNU software, and
2021308Sache   is generally kept in a file called COPYING or LICENSE.  If you do not
2121308Sache   have a copy of the license, write to the Free Software Foundation,
2258314Sache   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
2321308Sache#define READLINE_LIBRARY
2421308Sache
2521308Sache#if defined (HAVE_CONFIG_H)
2621308Sache#  include <config.h>
2721308Sache#endif
2821308Sache
2921308Sache#include <sys/types.h>
3021308Sache#include "posixstat.h"
3121308Sache#include <fcntl.h>
3221308Sache#if defined (HAVE_SYS_FILE_H)
3321308Sache#  include <sys/file.h>
3421308Sache#endif /* HAVE_SYS_FILE_H */
3521308Sache
3621308Sache#if defined (HAVE_UNISTD_H)
3721308Sache#  include <unistd.h>
3821308Sache#endif /* HAVE_UNISTD_H */
3921308Sache
4021308Sache#if defined (HAVE_STDLIB_H)
4121308Sache#  include <stdlib.h>
4221308Sache#else
4321308Sache#  include "ansi_stdlib.h"
4421308Sache#endif /* HAVE_STDLIB_H */
4521308Sache
4621308Sache#if defined (HAVE_LOCALE_H)
4721308Sache#  include <locale.h>
4821308Sache#endif
4921308Sache
5021308Sache#include <stdio.h>
5121308Sache
5221308Sache/* System-specific feature definitions and include files. */
5321308Sache#include "rldefs.h"
5421308Sache
5526497Sache#if defined (GWINSZ_IN_SYS_IOCTL) && !defined (TIOCGWINSZ)
5626497Sache#  include <sys/ioctl.h>
5726497Sache#endif /* GWINSZ_IN_SYS_IOCTL && !TIOCGWINSZ */
5826497Sache
5926497Sache#include "rltty.h"
6021308Sache#include "tcap.h"
6121308Sache
6221308Sache/* Some standard library routines. */
6321308Sache#include "readline.h"
6421308Sache#include "history.h"
6521308Sache
6658314Sache#include "rlprivate.h"
6758314Sache#include "rlshell.h"
68119614Sache#include "xmalloc.h"
6921308Sache
70165675Sache#if defined (__MINGW32__)
71165675Sache#  include <windows.h>
72165675Sache#  include <wincon.h>
73165675Sache
74165675Sachestatic void _win_get_screensize PARAMS((int *, int *));
75165675Sache#endif
76165675Sache
77165675Sache#if defined (__EMX__)
78165675Sachestatic void _emx_get_screensize PARAMS((int *, int *));
79165675Sache#endif
80165675Sache
81119614Sache#define CUSTOM_REDISPLAY_FUNC() (rl_redisplay_function != rl_redisplay)
82119614Sache#define CUSTOM_INPUT_FUNC() (rl_getc_function != rl_getc)
83119614Sache
84165675Sache/*  If the calling application sets this to a non-zero value, readline will
85165675Sache    use the $LINES and $COLUMNS environment variables to set its idea of the
86165675Sache    window size before interrogating the kernel. */
87165675Sacheint rl_prefer_env_winsize = 0;
88157188Sache
8921308Sache/* **************************************************************** */
9021308Sache/*								    */
9121308Sache/*			Terminal and Termcap			    */
9221308Sache/*								    */
9321308Sache/* **************************************************************** */
9421308Sache
9521308Sachestatic char *term_buffer = (char *)NULL;
9621308Sachestatic char *term_string_buffer = (char *)NULL;
9721308Sache
9821308Sachestatic int tcap_initialized;
9921308Sache
10021308Sache#if !defined (__linux__)
10126497Sache#  if defined (__EMX__) || defined (NEED_EXTERN_PC)
10226497Sacheextern
10326497Sache#  endif /* __EMX__ || NEED_EXTERN_PC */
10426497Sachechar PC, *BC, *UP;
10521308Sache#endif /* __linux__ */
10621308Sache
10721308Sache/* Some strings to control terminal actions.  These are output by tputs (). */
10875409Sachechar *_rl_term_clreol;
10975409Sachechar *_rl_term_clrpag;
11075409Sachechar *_rl_term_cr;
11175409Sachechar *_rl_term_backspace;
11275409Sachechar *_rl_term_goto;
11375409Sachechar *_rl_term_pc;
11421308Sache
11521308Sache/* Non-zero if we determine that the terminal can do character insertion. */
11675409Sacheint _rl_terminal_can_insert = 0;
11721308Sache
11821308Sache/* How to insert characters. */
11975409Sachechar *_rl_term_im;
12075409Sachechar *_rl_term_ei;
12175409Sachechar *_rl_term_ic;
12275409Sachechar *_rl_term_ip;
12375409Sachechar *_rl_term_IC;
12421308Sache
12521308Sache/* How to delete characters. */
12675409Sachechar *_rl_term_dc;
12775409Sachechar *_rl_term_DC;
12821308Sache
12975409Sachechar *_rl_term_forward_char;
13021308Sache
13121308Sache/* How to go up a line. */
13275409Sachechar *_rl_term_up;
13321308Sache
13475409Sache/* A visible bell; char if the terminal can be made to flash the screen. */
13575409Sachestatic char *_rl_visible_bell;
13621308Sache
13721308Sache/* Non-zero means the terminal can auto-wrap lines. */
138157195Sacheint _rl_term_autowrap = -1;
13921308Sache
14021308Sache/* Non-zero means that this terminal has a meta key. */
14121308Sachestatic int term_has_meta;
14221308Sache
14321308Sache/* The sequences to write to turn on and off the meta key, if this
14475409Sache   terminal has one. */
14575409Sachestatic char *_rl_term_mm;
14675409Sachestatic char *_rl_term_mo;
14721308Sache
14821308Sache/* The key sequences output by the arrow keys, if this terminal has any. */
14975409Sachestatic char *_rl_term_ku;
15075409Sachestatic char *_rl_term_kd;
15175409Sachestatic char *_rl_term_kr;
15275409Sachestatic char *_rl_term_kl;
15321308Sache
15421308Sache/* How to initialize and reset the arrow keys, if this terminal has any. */
15575409Sachestatic char *_rl_term_ks;
15675409Sachestatic char *_rl_term_ke;
15721308Sache
15821308Sache/* The key sequences sent by the Home and End keys, if any. */
15975409Sachestatic char *_rl_term_kh;
16075409Sachestatic char *_rl_term_kH;
161119614Sachestatic char *_rl_term_at7;	/* @7 */
16221308Sache
163157188Sache/* Delete key */
164157188Sachestatic char *_rl_term_kD;
165157188Sache
166119614Sache/* Insert key */
167119614Sachestatic char *_rl_term_kI;
168119614Sache
169119614Sache/* Cursor control */
170119614Sachestatic char *_rl_term_vs;	/* very visible */
171119614Sachestatic char *_rl_term_ve;	/* normal */
172119614Sache
173119614Sachestatic void bind_termcap_arrow_keys PARAMS((Keymap));
174119614Sache
17521308Sache/* Variables that hold the screen dimensions, used by the display code. */
17675409Sacheint _rl_screenwidth, _rl_screenheight, _rl_screenchars;
17721308Sache
17821308Sache/* Non-zero means the user wants to enable the keypad. */
17921308Sacheint _rl_enable_keypad;
18021308Sache
18121308Sache/* Non-zero means the user wants to enable a meta key. */
18221308Sacheint _rl_enable_meta = 1;
18321308Sache
18458314Sache#if defined (__EMX__)
18558314Sachestatic void
18658314Sache_emx_get_screensize (swp, shp)
18758314Sache     int *swp, *shp;
18858314Sache{
18958314Sache  int sz[2];
19058314Sache
19158314Sache  _scrsize (sz);
19258314Sache
19358314Sache  if (swp)
19458314Sache    *swp = sz[0];
19558314Sache  if (shp)
19658314Sache    *shp = sz[1];
19758314Sache}
19858314Sache#endif
19958314Sache
200165675Sache#if defined (__MINGW32__)
201165675Sachestatic void
202165675Sache_win_get_screensize (swp, shp)
203165675Sache     int *swp, *shp;
204165675Sache{
205165675Sache  HANDLE hConOut;
206165675Sache  CONSOLE_SCREEN_BUFFER_INFO scr;
207165675Sache
208165675Sache  hConOut = GetStdHandle (STD_OUTPUT_HANDLE);
209165675Sache  if (hConOut != INVALID_HANDLE_VALUE)
210165675Sache    {
211165675Sache      if (GetConsoleScreenBufferInfo (hConOut, &scr))
212165675Sache	{
213165675Sache	  *swp = scr.dwSize.X;
214165675Sache	  *shp = scr.srWindow.Bottom - scr.srWindow.Top + 1;
215165675Sache	}
216165675Sache    }
217165675Sache}
218165675Sache#endif
219165675Sache
22021308Sache/* Get readline's idea of the screen size.  TTY is a file descriptor open
22121308Sache   to the terminal.  If IGNORE_ENV is true, we do not pay attention to the
22221308Sache   values of $LINES and $COLUMNS.  The tests for TERM_STRING_BUFFER being
22321308Sache   non-null serve to check whether or not we have initialized termcap. */
22421308Sachevoid
22521308Sache_rl_get_screen_size (tty, ignore_env)
22621308Sache     int tty, ignore_env;
22721308Sache{
22821308Sache  char *ss;
22921308Sache#if defined (TIOCGWINSZ)
23021308Sache  struct winsize window_size;
23121308Sache#endif /* TIOCGWINSZ */
232157188Sache  int wr, wc;
23321308Sache
234157188Sache  wr = wc = -1;
23521308Sache#if defined (TIOCGWINSZ)
23621308Sache  if (ioctl (tty, TIOCGWINSZ, &window_size) == 0)
23721308Sache    {
238157188Sache      wc = (int) window_size.ws_col;
239157188Sache      wr = (int) window_size.ws_row;
24021308Sache    }
24121308Sache#endif /* TIOCGWINSZ */
24221308Sache
24326497Sache#if defined (__EMX__)
244165675Sache  _emx_get_screensize (&wc, &wr);
245165675Sache#elif defined (__MINGW32__)
246165675Sache  _win_get_screensize (&wc, &wr);
24726497Sache#endif
24826497Sache
249157188Sache  if (ignore_env || rl_prefer_env_winsize == 0)
250157188Sache    {
251157188Sache      _rl_screenwidth = wc;
252157188Sache      _rl_screenheight = wr;
253157188Sache    }
254157188Sache  else
255157188Sache    _rl_screenwidth = _rl_screenheight = -1;
256157188Sache
25721308Sache  /* Environment variable COLUMNS overrides setting of "co" if IGNORE_ENV
258157188Sache     is unset.  If we prefer the environment, check it first before
259157188Sache     assigning the value returned by the kernel. */
26075409Sache  if (_rl_screenwidth <= 0)
26121308Sache    {
26275409Sache      if (ignore_env == 0 && (ss = sh_get_env_value ("COLUMNS")))
26375409Sache	_rl_screenwidth = atoi (ss);
26421308Sache
265157188Sache      if (_rl_screenwidth <= 0)
266157188Sache        _rl_screenwidth = wc;
267157188Sache
26858314Sache#if !defined (__DJGPP__)
26975409Sache      if (_rl_screenwidth <= 0 && term_string_buffer)
27075409Sache	_rl_screenwidth = tgetnum ("co");
27158314Sache#endif
27221308Sache    }
27321308Sache
27421308Sache  /* Environment variable LINES overrides setting of "li" if IGNORE_ENV
27521308Sache     is unset. */
27675409Sache  if (_rl_screenheight <= 0)
27721308Sache    {
27875409Sache      if (ignore_env == 0 && (ss = sh_get_env_value ("LINES")))
27975409Sache	_rl_screenheight = atoi (ss);
28021308Sache
281157188Sache      if (_rl_screenheight <= 0)
282157188Sache        _rl_screenheight = wr;
283157188Sache
28458314Sache#if !defined (__DJGPP__)
28575409Sache      if (_rl_screenheight <= 0 && term_string_buffer)
28675409Sache	_rl_screenheight = tgetnum ("li");
28758314Sache#endif
28821308Sache    }
28921308Sache
29021308Sache  /* If all else fails, default to 80x24 terminal. */
29175409Sache  if (_rl_screenwidth <= 1)
29275409Sache    _rl_screenwidth = 80;
29321308Sache
29475409Sache  if (_rl_screenheight <= 0)
29575409Sache    _rl_screenheight = 24;
29621308Sache
29721308Sache  /* If we're being compiled as part of bash, set the environment
29821308Sache     variables $LINES and $COLUMNS to new values.  Otherwise, just
29921308Sache     do a pair of putenv () or setenv () calls. */
30075409Sache  sh_set_lines_and_columns (_rl_screenheight, _rl_screenwidth);
30121308Sache
30258314Sache  if (_rl_term_autowrap == 0)
30375409Sache    _rl_screenwidth--;
30421308Sache
30575409Sache  _rl_screenchars = _rl_screenwidth * _rl_screenheight;
30621308Sache}
30721308Sache
30821308Sachevoid
30921308Sache_rl_set_screen_size (rows, cols)
31021308Sache     int rows, cols;
31121308Sache{
312157195Sache  if (_rl_term_autowrap == -1)
313157195Sache    _rl_init_terminal_io (rl_terminal_name);
314157195Sache
315157188Sache  if (rows > 0)
316157188Sache    _rl_screenheight = rows;
317157188Sache  if (cols > 0)
318157188Sache    {
319157188Sache      _rl_screenwidth = cols;
320157188Sache      if (_rl_term_autowrap == 0)
321157188Sache	_rl_screenwidth--;
322157188Sache    }
32321308Sache
324157188Sache  if (rows > 0 || cols > 0)
325157188Sache    _rl_screenchars = _rl_screenwidth * _rl_screenheight;
32621308Sache}
32721308Sache
32847558Sachevoid
32975409Sacherl_set_screen_size (rows, cols)
33075409Sache     int rows, cols;
33175409Sache{
33275409Sache  _rl_set_screen_size (rows, cols);
33375409Sache}
33475409Sache
33575409Sachevoid
33675409Sacherl_get_screen_size (rows, cols)
33775409Sache     int *rows, *cols;
33875409Sache{
33975409Sache  if (rows)
34075409Sache    *rows = _rl_screenheight;
34175409Sache  if (cols)
34275409Sache    *cols = _rl_screenwidth;
34375409Sache}
344157188Sache
345157188Sachevoid
346157188Sacherl_reset_screen_size ()
347157188Sache{
348157188Sache  _rl_get_screen_size (fileno (rl_instream), 0);
349157188Sache}
35075409Sache
35175409Sachevoid
35247558Sacherl_resize_terminal ()
35347558Sache{
35447558Sache  if (readline_echoing_p)
35547558Sache    {
35647558Sache      _rl_get_screen_size (fileno (rl_instream), 1);
357119614Sache      if (CUSTOM_REDISPLAY_FUNC ())
358119614Sache	rl_forced_update_display ();
359119614Sache      else
360119614Sache	_rl_redisplay_after_sigwinch ();
36147558Sache    }
36247558Sache}
36347558Sache
36421308Sachestruct _tc_string {
36575409Sache     const char *tc_var;
36621308Sache     char **tc_value;
36721308Sache};
36821308Sache
36921308Sache/* This should be kept sorted, just in case we decide to change the
37021308Sache   search algorithm to something smarter. */
37121308Sachestatic struct _tc_string tc_strings[] =
37221308Sache{
373119614Sache  { "@7", &_rl_term_at7 },
37475409Sache  { "DC", &_rl_term_DC },
37575409Sache  { "IC", &_rl_term_IC },
37675409Sache  { "ce", &_rl_term_clreol },
37775409Sache  { "cl", &_rl_term_clrpag },
37875409Sache  { "cr", &_rl_term_cr },
37975409Sache  { "dc", &_rl_term_dc },
38075409Sache  { "ei", &_rl_term_ei },
38175409Sache  { "ic", &_rl_term_ic },
38275409Sache  { "im", &_rl_term_im },
383157188Sache  { "kD", &_rl_term_kD },	/* delete */
384119614Sache  { "kH", &_rl_term_kH },	/* home down ?? */
385119614Sache  { "kI", &_rl_term_kI },	/* insert */
38675409Sache  { "kd", &_rl_term_kd },
387119614Sache  { "ke", &_rl_term_ke },	/* end keypad mode */
38875409Sache  { "kh", &_rl_term_kh },	/* home */
38975409Sache  { "kl", &_rl_term_kl },
39075409Sache  { "kr", &_rl_term_kr },
391119614Sache  { "ks", &_rl_term_ks },	/* start keypad mode */
39275409Sache  { "ku", &_rl_term_ku },
39375409Sache  { "le", &_rl_term_backspace },
39475409Sache  { "mm", &_rl_term_mm },
39575409Sache  { "mo", &_rl_term_mo },
39675409Sache  { "nd", &_rl_term_forward_char },
39775409Sache  { "pc", &_rl_term_pc },
39875409Sache  { "up", &_rl_term_up },
39975409Sache  { "vb", &_rl_visible_bell },
400119614Sache  { "vs", &_rl_term_vs },
401119614Sache  { "ve", &_rl_term_ve },
40221308Sache};
40321308Sache
40421308Sache#define NUM_TC_STRINGS (sizeof (tc_strings) / sizeof (struct _tc_string))
40521308Sache
40621308Sache/* Read the desired terminal capability strings into BP.  The capabilities
40721308Sache   are described in the TC_STRINGS table. */
40821308Sachestatic void
40921308Sacheget_term_capabilities (bp)
41021308Sache     char **bp;
41121308Sache{
41258314Sache#if !defined (__DJGPP__)	/* XXX - doesn't DJGPP have a termcap library? */
41321308Sache  register int i;
41421308Sache
41521308Sache  for (i = 0; i < NUM_TC_STRINGS; i++)
416119614Sache    *(tc_strings[i].tc_value) = tgetstr ((char *)tc_strings[i].tc_var, bp);
41758314Sache#endif
41821308Sache  tcap_initialized = 1;
41921308Sache}
42021308Sache
42121308Sacheint
42221308Sache_rl_init_terminal_io (terminal_name)
42375409Sache     const char *terminal_name;
42421308Sache{
42575409Sache  const char *term;
42675409Sache  char *buffer;
42758314Sache  int tty, tgetent_ret;
42821308Sache
42975409Sache  term = terminal_name ? terminal_name : sh_get_env_value ("TERM");
43075409Sache  _rl_term_clrpag = _rl_term_cr = _rl_term_clreol = (char *)NULL;
43158314Sache  tty = rl_instream ? fileno (rl_instream) : 0;
43221308Sache
43358314Sache  if (term == 0)
43458314Sache    term = "dumb";
43521308Sache
43658314Sache  /* I've separated this out for later work on not calling tgetent at all
43758314Sache     if the calling application has supplied a custom redisplay function,
43858314Sache     (and possibly if the application has supplied a custom input function). */
43958314Sache  if (CUSTOM_REDISPLAY_FUNC())
44058314Sache    {
44158314Sache      tgetent_ret = -1;
44258314Sache    }
44358314Sache  else
44458314Sache    {
44558314Sache      if (term_string_buffer == 0)
446119614Sache	term_string_buffer = (char *)xmalloc(2032);
44721308Sache
44858314Sache      if (term_buffer == 0)
449119614Sache	term_buffer = (char *)xmalloc(4080);
45021308Sache
45158314Sache      buffer = term_string_buffer;
45221308Sache
45358314Sache      tgetent_ret = tgetent (term_buffer, term);
45458314Sache    }
45521308Sache
45658314Sache  if (tgetent_ret <= 0)
45721308Sache    {
45858314Sache      FREE (term_string_buffer);
45958314Sache      FREE (term_buffer);
46058314Sache      buffer = term_buffer = term_string_buffer = (char *)NULL;
46158314Sache
46258314Sache      _rl_term_autowrap = 0;	/* used by _rl_get_screen_size */
46358314Sache
464157188Sache      /* Allow calling application to set default height and width, using
465157188Sache	 rl_set_screen_size */
466157188Sache      if (_rl_screenwidth <= 0 || _rl_screenheight <= 0)
467157188Sache	{
46858314Sache#if defined (__EMX__)
469157188Sache	  _emx_get_screensize (&_rl_screenwidth, &_rl_screenheight);
470157188Sache	  _rl_screenwidth--;
47158314Sache#else /* !__EMX__ */
472157188Sache	  _rl_get_screen_size (tty, 0);
47358314Sache#endif /* !__EMX__ */
474157188Sache	}
47558314Sache
47658314Sache      /* Defaults. */
47775409Sache      if (_rl_screenwidth <= 0 || _rl_screenheight <= 0)
47858314Sache        {
47975409Sache	  _rl_screenwidth = 79;
48075409Sache	  _rl_screenheight = 24;
48158314Sache        }
48258314Sache
48358314Sache      /* Everything below here is used by the redisplay code (tputs). */
48475409Sache      _rl_screenchars = _rl_screenwidth * _rl_screenheight;
48575409Sache      _rl_term_cr = "\r";
48675409Sache      _rl_term_im = _rl_term_ei = _rl_term_ic = _rl_term_IC = (char *)NULL;
48775409Sache      _rl_term_up = _rl_term_dc = _rl_term_DC = _rl_visible_bell = (char *)NULL;
48875409Sache      _rl_term_ku = _rl_term_kd = _rl_term_kl = _rl_term_kr = (char *)NULL;
489157188Sache      _rl_term_kh = _rl_term_kH = _rl_term_kI = _rl_term_kD = (char *)NULL;
490119614Sache      _rl_term_ks = _rl_term_ke = _rl_term_at7 = (char *)NULL;
49175409Sache      _rl_term_mm = _rl_term_mo = (char *)NULL;
492119614Sache      _rl_term_ve = _rl_term_vs = (char *)NULL;
493165675Sache      _rl_term_forward_char = (char *)NULL;
49475409Sache      _rl_terminal_can_insert = term_has_meta = 0;
49558314Sache
49658314Sache      /* Reasonable defaults for tgoto().  Readline currently only uses
49775409Sache         tgoto if _rl_term_IC or _rl_term_DC is defined, but just in case we
49858314Sache         change that later... */
49958314Sache      PC = '\0';
50075409Sache      BC = _rl_term_backspace = "\b";
50175409Sache      UP = _rl_term_up;
50258314Sache
50321308Sache      return 0;
50421308Sache    }
50521308Sache
50621308Sache  get_term_capabilities (&buffer);
50721308Sache
50821308Sache  /* Set up the variables that the termcap library expects the application
50921308Sache     to provide. */
51075409Sache  PC = _rl_term_pc ? *_rl_term_pc : 0;
51175409Sache  BC = _rl_term_backspace;
51275409Sache  UP = _rl_term_up;
51321308Sache
51475409Sache  if (!_rl_term_cr)
51575409Sache    _rl_term_cr = "\r";
51621308Sache
51721308Sache  _rl_term_autowrap = tgetflag ("am") && tgetflag ("xn");
51821308Sache
519157188Sache  /* Allow calling application to set default height and width, using
520157188Sache     rl_set_screen_size */
521157188Sache  if (_rl_screenwidth <= 0 || _rl_screenheight <= 0)
522157188Sache    _rl_get_screen_size (tty, 0);
52321308Sache
52421308Sache  /* "An application program can assume that the terminal can do
52521308Sache      character insertion if *any one of* the capabilities `IC',
52621308Sache      `im', `ic' or `ip' is provided."  But we can't do anything if
52721308Sache      only `ip' is provided, so... */
52875409Sache  _rl_terminal_can_insert = (_rl_term_IC || _rl_term_im || _rl_term_ic);
52921308Sache
53021308Sache  /* Check to see if this terminal has a meta key and clear the capability
53121308Sache     variables if there is none. */
53221308Sache  term_has_meta = (tgetflag ("km") || tgetflag ("MT"));
53321308Sache  if (!term_has_meta)
53475409Sache    _rl_term_mm = _rl_term_mo = (char *)NULL;
53521308Sache
53621308Sache  /* Attempt to find and bind the arrow keys.  Do not override already
53721308Sache     bound keys in an overzealous attempt, however. */
53821308Sache
539119614Sache  bind_termcap_arrow_keys (emacs_standard_keymap);
54021308Sache
541119614Sache#if defined (VI_MODE)
542119614Sache  bind_termcap_arrow_keys (vi_movement_keymap);
543119614Sache  bind_termcap_arrow_keys (vi_insertion_keymap);
544119614Sache#endif /* VI_MODE */
54521308Sache
546119614Sache  return 0;
547119614Sache}
548119614Sache
549119614Sache/* Bind the arrow key sequences from the termcap description in MAP. */
550119614Sachestatic void
551119614Sachebind_termcap_arrow_keys (map)
552119614Sache     Keymap map;
553119614Sache{
554119614Sache  Keymap xkeymap;
555119614Sache
556119614Sache  xkeymap = _rl_keymap;
557119614Sache  _rl_keymap = map;
558119614Sache
559136758Speter  rl_bind_keyseq_if_unbound (_rl_term_ku, rl_get_previous_history);
560136758Speter  rl_bind_keyseq_if_unbound (_rl_term_kd, rl_get_next_history);
561136758Speter  rl_bind_keyseq_if_unbound (_rl_term_kr, rl_forward_char);
562136758Speter  rl_bind_keyseq_if_unbound (_rl_term_kl, rl_backward_char);
56321308Sache
564136758Speter  rl_bind_keyseq_if_unbound (_rl_term_kh, rl_beg_of_line);	/* Home */
565136758Speter  rl_bind_keyseq_if_unbound (_rl_term_at7, rl_end_of_line);	/* End */
56621308Sache
567157188Sache  rl_bind_keyseq_if_unbound (_rl_term_kD, rl_delete);
568157188Sache
56921308Sache  _rl_keymap = xkeymap;
57021308Sache}
57121308Sache
57221308Sachechar *
57321308Sacherl_get_termcap (cap)
57475409Sache     const char *cap;
57521308Sache{
57621308Sache  register int i;
57721308Sache
57821308Sache  if (tcap_initialized == 0)
57921308Sache    return ((char *)NULL);
58021308Sache  for (i = 0; i < NUM_TC_STRINGS; i++)
58121308Sache    {
58221308Sache      if (tc_strings[i].tc_var[0] == cap[0] && strcmp (tc_strings[i].tc_var, cap) == 0)
58321308Sache        return *(tc_strings[i].tc_value);
58421308Sache    }
58521308Sache  return ((char *)NULL);
58621308Sache}
58721308Sache
58826497Sache/* Re-initialize the terminal considering that the TERM/TERMCAP variable
58926497Sache   has changed. */
59026497Sacheint
59126497Sacherl_reset_terminal (terminal_name)
59275409Sache     const char *terminal_name;
59326497Sache{
594157188Sache  _rl_screenwidth = _rl_screenheight = 0;
59526497Sache  _rl_init_terminal_io (terminal_name);
59626497Sache  return 0;
59726497Sache}
59826497Sache
59921308Sache/* A function for the use of tputs () */
60035486Sache#ifdef _MINIX
60135486Sachevoid
60235486Sache_rl_output_character_function (c)
60335486Sache     int c;
60435486Sache{
60535486Sache  putc (c, _rl_out_stream);
60635486Sache}
60735486Sache#else /* !_MINIX */
60821308Sacheint
60921308Sache_rl_output_character_function (c)
61021308Sache     int c;
61121308Sache{
61221308Sache  return putc (c, _rl_out_stream);
61321308Sache}
61435486Sache#endif /* !_MINIX */
61558314Sache
61621308Sache/* Write COUNT characters from STRING to the output stream. */
61721308Sachevoid
61821308Sache_rl_output_some_chars (string, count)
61975409Sache     const char *string;
62021308Sache     int count;
62121308Sache{
62221308Sache  fwrite (string, 1, count, _rl_out_stream);
62321308Sache}
62421308Sache
62521308Sache/* Move the cursor back. */
62621308Sacheint
62721308Sache_rl_backspace (count)
62821308Sache     int count;
62921308Sache{
63021308Sache  register int i;
63121308Sache
63275409Sache  if (_rl_term_backspace)
63321308Sache    for (i = 0; i < count; i++)
63475409Sache      tputs (_rl_term_backspace, 1, _rl_output_character_function);
63521308Sache  else
63621308Sache    for (i = 0; i < count; i++)
63721308Sache      putc ('\b', _rl_out_stream);
63821308Sache  return 0;
63921308Sache}
64021308Sache
64121308Sache/* Move to the start of the next line. */
64221308Sacheint
64375409Sacherl_crlf ()
64421308Sache{
64521308Sache#if defined (NEW_TTY_DRIVER)
64675409Sache  if (_rl_term_cr)
64775409Sache    tputs (_rl_term_cr, 1, _rl_output_character_function);
64821308Sache#endif /* NEW_TTY_DRIVER */
64921308Sache  putc ('\n', _rl_out_stream);
65021308Sache  return 0;
65121308Sache}
65221308Sache
65321308Sache/* Ring the terminal bell. */
65421308Sacheint
65575409Sacherl_ding ()
65621308Sache{
65721308Sache  if (readline_echoing_p)
65821308Sache    {
65921308Sache      switch (_rl_bell_preference)
66021308Sache        {
66121308Sache	case NO_BELL:
66221308Sache	default:
66321308Sache	  break;
66421308Sache	case VISIBLE_BELL:
66575409Sache	  if (_rl_visible_bell)
66621308Sache	    {
66775409Sache	      tputs (_rl_visible_bell, 1, _rl_output_character_function);
66821308Sache	      break;
66921308Sache	    }
67021308Sache	  /* FALLTHROUGH */
67121308Sache	case AUDIBLE_BELL:
67221308Sache	  fprintf (stderr, "\007");
67321308Sache	  fflush (stderr);
67421308Sache	  break;
67521308Sache        }
67621308Sache      return (0);
67721308Sache    }
67821308Sache  return (-1);
67921308Sache}
68021308Sache
68121308Sache/* **************************************************************** */
68221308Sache/*								    */
68321308Sache/*	 	Controlling the Meta Key and Keypad		    */
68421308Sache/*								    */
68521308Sache/* **************************************************************** */
68621308Sache
68726497Sachevoid
68821308Sache_rl_enable_meta_key ()
68921308Sache{
69058314Sache#if !defined (__DJGPP__)
69175409Sache  if (term_has_meta && _rl_term_mm)
69275409Sache    tputs (_rl_term_mm, 1, _rl_output_character_function);
69358314Sache#endif
69421308Sache}
69521308Sache
69621308Sachevoid
69721308Sache_rl_control_keypad (on)
69821308Sache     int on;
69921308Sache{
70058314Sache#if !defined (__DJGPP__)
70175409Sache  if (on && _rl_term_ks)
70275409Sache    tputs (_rl_term_ks, 1, _rl_output_character_function);
70375409Sache  else if (!on && _rl_term_ke)
70475409Sache    tputs (_rl_term_ke, 1, _rl_output_character_function);
70558314Sache#endif
70621308Sache}
707119614Sache
708119614Sache/* **************************************************************** */
709119614Sache/*								    */
710119614Sache/*	 		Controlling the Cursor			    */
711119614Sache/*								    */
712119614Sache/* **************************************************************** */
713119614Sache
714119614Sache/* Set the cursor appropriately depending on IM, which is one of the
715119614Sache   insert modes (insert or overwrite).  Insert mode gets the normal
716119614Sache   cursor.  Overwrite mode gets a very visible cursor.  Only does
717119614Sache   anything if we have both capabilities. */
718119614Sachevoid
719119614Sache_rl_set_cursor (im, force)
720119614Sache     int im, force;
721119614Sache{
722119614Sache  if (_rl_term_ve && _rl_term_vs)
723119614Sache    {
724119614Sache      if (force || im != rl_insert_mode)
725119614Sache	{
726119614Sache	  if (im == RL_IM_OVERWRITE)
727119614Sache	    tputs (_rl_term_vs, 1, _rl_output_character_function);
728119614Sache	  else
729119614Sache	    tputs (_rl_term_ve, 1, _rl_output_character_function);
730119614Sache	}
731119614Sache    }
732119614Sache}
733