terminal.c revision 136758
1136758Speter/* $FreeBSD: head/contrib/libreadline/terminal.c 136758 2004-10-21 20:02:02Z peter $ */
2136758Speter
321308Sache/* terminal.c -- controlling the terminal with termcap. */
421308Sache
521308Sache/* Copyright (C) 1996 Free Software Foundation, Inc.
621308Sache
721308Sache   This file is part of the GNU Readline Library, a library for
821308Sache   reading lines of text with interactive input and history editing.
921308Sache
1021308Sache   The GNU Readline Library is free software; you can redistribute it
1121308Sache   and/or modify it under the terms of the GNU General Public License
1258314Sache   as published by the Free Software Foundation; either version 2, or
1321308Sache   (at your option) any later version.
1421308Sache
1521308Sache   The GNU Readline Library is distributed in the hope that it will be
1621308Sache   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
1721308Sache   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1821308Sache   GNU General Public License for more details.
1921308Sache
2021308Sache   The GNU General Public License is often shipped with GNU software, and
2121308Sache   is generally kept in a file called COPYING or LICENSE.  If you do not
2221308Sache   have a copy of the license, write to the Free Software Foundation,
2358314Sache   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
2421308Sache#define READLINE_LIBRARY
2521308Sache
2621308Sache#if defined (HAVE_CONFIG_H)
2721308Sache#  include <config.h>
2821308Sache#endif
2921308Sache
3021308Sache#include <sys/types.h>
3121308Sache#include "posixstat.h"
3221308Sache#include <fcntl.h>
3321308Sache#if defined (HAVE_SYS_FILE_H)
3421308Sache#  include <sys/file.h>
3521308Sache#endif /* HAVE_SYS_FILE_H */
3621308Sache
3721308Sache#if defined (HAVE_UNISTD_H)
3821308Sache#  include <unistd.h>
3921308Sache#endif /* HAVE_UNISTD_H */
4021308Sache
4121308Sache#if defined (HAVE_STDLIB_H)
4221308Sache#  include <stdlib.h>
4321308Sache#else
4421308Sache#  include "ansi_stdlib.h"
4521308Sache#endif /* HAVE_STDLIB_H */
4621308Sache
4721308Sache#if defined (HAVE_LOCALE_H)
4821308Sache#  include <locale.h>
4921308Sache#endif
5021308Sache
5121308Sache#include <stdio.h>
5221308Sache
5321308Sache/* System-specific feature definitions and include files. */
5421308Sache#include "rldefs.h"
5521308Sache
5626497Sache#if defined (GWINSZ_IN_SYS_IOCTL) && !defined (TIOCGWINSZ)
5726497Sache#  include <sys/ioctl.h>
5826497Sache#endif /* GWINSZ_IN_SYS_IOCTL && !TIOCGWINSZ */
5926497Sache
6026497Sache#include "rltty.h"
6121308Sache#include "tcap.h"
6221308Sache
6321308Sache/* Some standard library routines. */
6421308Sache#include "readline.h"
6521308Sache#include "history.h"
6621308Sache
6758314Sache#include "rlprivate.h"
6858314Sache#include "rlshell.h"
69119614Sache#include "xmalloc.h"
7021308Sache
71119614Sache#define CUSTOM_REDISPLAY_FUNC() (rl_redisplay_function != rl_redisplay)
72119614Sache#define CUSTOM_INPUT_FUNC() (rl_getc_function != rl_getc)
73119614Sache
7421308Sache/* **************************************************************** */
7521308Sache/*								    */
7621308Sache/*			Terminal and Termcap			    */
7721308Sache/*								    */
7821308Sache/* **************************************************************** */
7921308Sache
8021308Sachestatic char *term_buffer = (char *)NULL;
8121308Sachestatic char *term_string_buffer = (char *)NULL;
8221308Sache
8321308Sachestatic int tcap_initialized;
8421308Sache
8521308Sache#if !defined (__linux__)
8626497Sache#  if defined (__EMX__) || defined (NEED_EXTERN_PC)
8726497Sacheextern
8826497Sache#  endif /* __EMX__ || NEED_EXTERN_PC */
8926497Sachechar PC, *BC, *UP;
9021308Sache#endif /* __linux__ */
9121308Sache
9221308Sache/* Some strings to control terminal actions.  These are output by tputs (). */
9375409Sachechar *_rl_term_clreol;
9475409Sachechar *_rl_term_clrpag;
9575409Sachechar *_rl_term_cr;
9675409Sachechar *_rl_term_backspace;
9775409Sachechar *_rl_term_goto;
9875409Sachechar *_rl_term_pc;
9921308Sache
10021308Sache/* Non-zero if we determine that the terminal can do character insertion. */
10175409Sacheint _rl_terminal_can_insert = 0;
10221308Sache
10321308Sache/* How to insert characters. */
10475409Sachechar *_rl_term_im;
10575409Sachechar *_rl_term_ei;
10675409Sachechar *_rl_term_ic;
10775409Sachechar *_rl_term_ip;
10875409Sachechar *_rl_term_IC;
10921308Sache
11021308Sache/* How to delete characters. */
11175409Sachechar *_rl_term_dc;
11275409Sachechar *_rl_term_DC;
11321308Sache
11421308Sache#if defined (HACK_TERMCAP_MOTION)
11575409Sachechar *_rl_term_forward_char;
11621308Sache#endif  /* HACK_TERMCAP_MOTION */
11721308Sache
11821308Sache/* How to go up a line. */
11975409Sachechar *_rl_term_up;
12021308Sache
12175409Sache/* A visible bell; char if the terminal can be made to flash the screen. */
12275409Sachestatic char *_rl_visible_bell;
12321308Sache
12421308Sache/* Non-zero means the terminal can auto-wrap lines. */
12521308Sacheint _rl_term_autowrap;
12621308Sache
12721308Sache/* Non-zero means that this terminal has a meta key. */
12821308Sachestatic int term_has_meta;
12921308Sache
13021308Sache/* The sequences to write to turn on and off the meta key, if this
13175409Sache   terminal has one. */
13275409Sachestatic char *_rl_term_mm;
13375409Sachestatic char *_rl_term_mo;
13421308Sache
13521308Sache/* The key sequences output by the arrow keys, if this terminal has any. */
13675409Sachestatic char *_rl_term_ku;
13775409Sachestatic char *_rl_term_kd;
13875409Sachestatic char *_rl_term_kr;
13975409Sachestatic char *_rl_term_kl;
14021308Sache
14121308Sache/* How to initialize and reset the arrow keys, if this terminal has any. */
14275409Sachestatic char *_rl_term_ks;
14375409Sachestatic char *_rl_term_ke;
14421308Sache
14521308Sache/* The key sequences sent by the Home and End keys, if any. */
14675409Sachestatic char *_rl_term_kh;
14775409Sachestatic char *_rl_term_kH;
148119614Sachestatic char *_rl_term_at7;	/* @7 */
14921308Sache
150119614Sache/* Insert key */
151119614Sachestatic char *_rl_term_kI;
152119614Sache
153119614Sache/* Cursor control */
154119614Sachestatic char *_rl_term_vs;	/* very visible */
155119614Sachestatic char *_rl_term_ve;	/* normal */
156119614Sache
157119614Sachestatic void bind_termcap_arrow_keys PARAMS((Keymap));
158119614Sache
15921308Sache/* Variables that hold the screen dimensions, used by the display code. */
16075409Sacheint _rl_screenwidth, _rl_screenheight, _rl_screenchars;
16121308Sache
16221308Sache/* Non-zero means the user wants to enable the keypad. */
16321308Sacheint _rl_enable_keypad;
16421308Sache
16521308Sache/* Non-zero means the user wants to enable a meta key. */
16621308Sacheint _rl_enable_meta = 1;
16721308Sache
16858314Sache#if defined (__EMX__)
16958314Sachestatic void
17058314Sache_emx_get_screensize (swp, shp)
17158314Sache     int *swp, *shp;
17258314Sache{
17358314Sache  int sz[2];
17458314Sache
17558314Sache  _scrsize (sz);
17658314Sache
17758314Sache  if (swp)
17858314Sache    *swp = sz[0];
17958314Sache  if (shp)
18058314Sache    *shp = sz[1];
18158314Sache}
18258314Sache#endif
18358314Sache
18421308Sache/* Get readline's idea of the screen size.  TTY is a file descriptor open
18521308Sache   to the terminal.  If IGNORE_ENV is true, we do not pay attention to the
18621308Sache   values of $LINES and $COLUMNS.  The tests for TERM_STRING_BUFFER being
18721308Sache   non-null serve to check whether or not we have initialized termcap. */
18821308Sachevoid
18921308Sache_rl_get_screen_size (tty, ignore_env)
19021308Sache     int tty, ignore_env;
19121308Sache{
19221308Sache  char *ss;
19321308Sache#if defined (TIOCGWINSZ)
19421308Sache  struct winsize window_size;
19521308Sache#endif /* TIOCGWINSZ */
19621308Sache
19721308Sache#if defined (TIOCGWINSZ)
19821308Sache  if (ioctl (tty, TIOCGWINSZ, &window_size) == 0)
19921308Sache    {
20075409Sache      _rl_screenwidth = (int) window_size.ws_col;
20175409Sache      _rl_screenheight = (int) window_size.ws_row;
20221308Sache    }
20321308Sache#endif /* TIOCGWINSZ */
20421308Sache
20526497Sache#if defined (__EMX__)
20675409Sache  _emx_get_screensize (&_rl_screenwidth, &_rl_screenheight);
20726497Sache#endif
20826497Sache
20921308Sache  /* Environment variable COLUMNS overrides setting of "co" if IGNORE_ENV
21021308Sache     is unset. */
21175409Sache  if (_rl_screenwidth <= 0)
21221308Sache    {
21375409Sache      if (ignore_env == 0 && (ss = sh_get_env_value ("COLUMNS")))
21475409Sache	_rl_screenwidth = atoi (ss);
21521308Sache
21658314Sache#if !defined (__DJGPP__)
21775409Sache      if (_rl_screenwidth <= 0 && term_string_buffer)
21875409Sache	_rl_screenwidth = tgetnum ("co");
21958314Sache#endif
22021308Sache    }
22121308Sache
22221308Sache  /* Environment variable LINES overrides setting of "li" if IGNORE_ENV
22321308Sache     is unset. */
22475409Sache  if (_rl_screenheight <= 0)
22521308Sache    {
22675409Sache      if (ignore_env == 0 && (ss = sh_get_env_value ("LINES")))
22775409Sache	_rl_screenheight = atoi (ss);
22821308Sache
22958314Sache#if !defined (__DJGPP__)
23075409Sache      if (_rl_screenheight <= 0 && term_string_buffer)
23175409Sache	_rl_screenheight = tgetnum ("li");
23258314Sache#endif
23321308Sache    }
23421308Sache
23521308Sache  /* If all else fails, default to 80x24 terminal. */
23675409Sache  if (_rl_screenwidth <= 1)
23775409Sache    _rl_screenwidth = 80;
23821308Sache
23975409Sache  if (_rl_screenheight <= 0)
24075409Sache    _rl_screenheight = 24;
24121308Sache
24221308Sache  /* If we're being compiled as part of bash, set the environment
24321308Sache     variables $LINES and $COLUMNS to new values.  Otherwise, just
24421308Sache     do a pair of putenv () or setenv () calls. */
24575409Sache  sh_set_lines_and_columns (_rl_screenheight, _rl_screenwidth);
24621308Sache
24758314Sache  if (_rl_term_autowrap == 0)
24875409Sache    _rl_screenwidth--;
24921308Sache
25075409Sache  _rl_screenchars = _rl_screenwidth * _rl_screenheight;
25121308Sache}
25221308Sache
25321308Sachevoid
25421308Sache_rl_set_screen_size (rows, cols)
25521308Sache     int rows, cols;
25621308Sache{
25775409Sache  if (rows == 0 || cols == 0)
25875409Sache    return;
25921308Sache
26075409Sache  _rl_screenheight = rows;
26175409Sache  _rl_screenwidth = cols;
26275409Sache
26321308Sache  if (_rl_term_autowrap == 0)
26475409Sache    _rl_screenwidth--;
26521308Sache
26675409Sache  _rl_screenchars = _rl_screenwidth * _rl_screenheight;
26721308Sache}
26821308Sache
26947558Sachevoid
27075409Sacherl_set_screen_size (rows, cols)
27175409Sache     int rows, cols;
27275409Sache{
27375409Sache  _rl_set_screen_size (rows, cols);
27475409Sache}
27575409Sache
27675409Sachevoid
27775409Sacherl_get_screen_size (rows, cols)
27875409Sache     int *rows, *cols;
27975409Sache{
28075409Sache  if (rows)
28175409Sache    *rows = _rl_screenheight;
28275409Sache  if (cols)
28375409Sache    *cols = _rl_screenwidth;
28475409Sache}
28575409Sache
28675409Sachevoid
28747558Sacherl_resize_terminal ()
28847558Sache{
28947558Sache  if (readline_echoing_p)
29047558Sache    {
29147558Sache      _rl_get_screen_size (fileno (rl_instream), 1);
292119614Sache      if (CUSTOM_REDISPLAY_FUNC ())
293119614Sache	rl_forced_update_display ();
294119614Sache      else
295119614Sache	_rl_redisplay_after_sigwinch ();
29647558Sache    }
29747558Sache}
29847558Sache
29921308Sachestruct _tc_string {
30075409Sache     const char *tc_var;
30121308Sache     char **tc_value;
30221308Sache};
30321308Sache
30421308Sache/* This should be kept sorted, just in case we decide to change the
30521308Sache   search algorithm to something smarter. */
30621308Sachestatic struct _tc_string tc_strings[] =
30721308Sache{
308119614Sache  { "@7", &_rl_term_at7 },
30975409Sache  { "DC", &_rl_term_DC },
31075409Sache  { "IC", &_rl_term_IC },
31175409Sache  { "ce", &_rl_term_clreol },
31275409Sache  { "cl", &_rl_term_clrpag },
31375409Sache  { "cr", &_rl_term_cr },
31475409Sache  { "dc", &_rl_term_dc },
31575409Sache  { "ei", &_rl_term_ei },
31675409Sache  { "ic", &_rl_term_ic },
31775409Sache  { "im", &_rl_term_im },
318119614Sache  { "kH", &_rl_term_kH },	/* home down ?? */
319119614Sache  { "kI", &_rl_term_kI },	/* insert */
32075409Sache  { "kd", &_rl_term_kd },
321119614Sache  { "ke", &_rl_term_ke },	/* end keypad mode */
32275409Sache  { "kh", &_rl_term_kh },	/* home */
32375409Sache  { "kl", &_rl_term_kl },
32475409Sache  { "kr", &_rl_term_kr },
325119614Sache  { "ks", &_rl_term_ks },	/* start keypad mode */
32675409Sache  { "ku", &_rl_term_ku },
32775409Sache  { "le", &_rl_term_backspace },
32875409Sache  { "mm", &_rl_term_mm },
32975409Sache  { "mo", &_rl_term_mo },
33021308Sache#if defined (HACK_TERMCAP_MOTION)
33175409Sache  { "nd", &_rl_term_forward_char },
33221308Sache#endif
33375409Sache  { "pc", &_rl_term_pc },
33475409Sache  { "up", &_rl_term_up },
33575409Sache  { "vb", &_rl_visible_bell },
336119614Sache  { "vs", &_rl_term_vs },
337119614Sache  { "ve", &_rl_term_ve },
33821308Sache};
33921308Sache
34021308Sache#define NUM_TC_STRINGS (sizeof (tc_strings) / sizeof (struct _tc_string))
34121308Sache
34221308Sache/* Read the desired terminal capability strings into BP.  The capabilities
34321308Sache   are described in the TC_STRINGS table. */
34421308Sachestatic void
34521308Sacheget_term_capabilities (bp)
34621308Sache     char **bp;
34721308Sache{
34858314Sache#if !defined (__DJGPP__)	/* XXX - doesn't DJGPP have a termcap library? */
34921308Sache  register int i;
35021308Sache
35121308Sache  for (i = 0; i < NUM_TC_STRINGS; i++)
352119614Sache    *(tc_strings[i].tc_value) = tgetstr ((char *)tc_strings[i].tc_var, bp);
35358314Sache#endif
35421308Sache  tcap_initialized = 1;
35521308Sache}
35621308Sache
35721308Sacheint
35821308Sache_rl_init_terminal_io (terminal_name)
35975409Sache     const char *terminal_name;
36021308Sache{
36175409Sache  const char *term;
36275409Sache  char *buffer;
36358314Sache  int tty, tgetent_ret;
36421308Sache
36575409Sache  term = terminal_name ? terminal_name : sh_get_env_value ("TERM");
36675409Sache  _rl_term_clrpag = _rl_term_cr = _rl_term_clreol = (char *)NULL;
36758314Sache  tty = rl_instream ? fileno (rl_instream) : 0;
36875409Sache  _rl_screenwidth = _rl_screenheight = 0;
36921308Sache
37058314Sache  if (term == 0)
37158314Sache    term = "dumb";
37221308Sache
37358314Sache  /* I've separated this out for later work on not calling tgetent at all
37458314Sache     if the calling application has supplied a custom redisplay function,
37558314Sache     (and possibly if the application has supplied a custom input function). */
37658314Sache  if (CUSTOM_REDISPLAY_FUNC())
37758314Sache    {
37858314Sache      tgetent_ret = -1;
37958314Sache    }
38058314Sache  else
38158314Sache    {
38258314Sache      if (term_string_buffer == 0)
383119614Sache	term_string_buffer = (char *)xmalloc(2032);
38421308Sache
38558314Sache      if (term_buffer == 0)
386119614Sache	term_buffer = (char *)xmalloc(4080);
38721308Sache
38858314Sache      buffer = term_string_buffer;
38921308Sache
39058314Sache      tgetent_ret = tgetent (term_buffer, term);
39158314Sache    }
39221308Sache
39358314Sache  if (tgetent_ret <= 0)
39421308Sache    {
39558314Sache      FREE (term_string_buffer);
39658314Sache      FREE (term_buffer);
39758314Sache      buffer = term_buffer = term_string_buffer = (char *)NULL;
39858314Sache
39958314Sache      _rl_term_autowrap = 0;	/* used by _rl_get_screen_size */
40058314Sache
40158314Sache#if defined (__EMX__)
40275409Sache      _emx_get_screensize (&_rl_screenwidth, &_rl_screenheight);
40375409Sache      _rl_screenwidth--;
40458314Sache#else /* !__EMX__ */
40558314Sache      _rl_get_screen_size (tty, 0);
40658314Sache#endif /* !__EMX__ */
40758314Sache
40858314Sache      /* Defaults. */
40975409Sache      if (_rl_screenwidth <= 0 || _rl_screenheight <= 0)
41058314Sache        {
41175409Sache	  _rl_screenwidth = 79;
41275409Sache	  _rl_screenheight = 24;
41358314Sache        }
41458314Sache
41558314Sache      /* Everything below here is used by the redisplay code (tputs). */
41675409Sache      _rl_screenchars = _rl_screenwidth * _rl_screenheight;
41775409Sache      _rl_term_cr = "\r";
41875409Sache      _rl_term_im = _rl_term_ei = _rl_term_ic = _rl_term_IC = (char *)NULL;
41975409Sache      _rl_term_up = _rl_term_dc = _rl_term_DC = _rl_visible_bell = (char *)NULL;
42075409Sache      _rl_term_ku = _rl_term_kd = _rl_term_kl = _rl_term_kr = (char *)NULL;
421119614Sache      _rl_term_kh = _rl_term_kH = _rl_term_kI = (char *)NULL;
422119614Sache      _rl_term_ks = _rl_term_ke = _rl_term_at7 = (char *)NULL;
42375409Sache      _rl_term_mm = _rl_term_mo = (char *)NULL;
424119614Sache      _rl_term_ve = _rl_term_vs = (char *)NULL;
42521308Sache#if defined (HACK_TERMCAP_MOTION)
42621308Sache      term_forward_char = (char *)NULL;
42721308Sache#endif
42875409Sache      _rl_terminal_can_insert = term_has_meta = 0;
42958314Sache
43058314Sache      /* Reasonable defaults for tgoto().  Readline currently only uses
43175409Sache         tgoto if _rl_term_IC or _rl_term_DC is defined, but just in case we
43258314Sache         change that later... */
43358314Sache      PC = '\0';
43475409Sache      BC = _rl_term_backspace = "\b";
43575409Sache      UP = _rl_term_up;
43658314Sache
43721308Sache      return 0;
43821308Sache    }
43921308Sache
44021308Sache  get_term_capabilities (&buffer);
44121308Sache
44221308Sache  /* Set up the variables that the termcap library expects the application
44321308Sache     to provide. */
44475409Sache  PC = _rl_term_pc ? *_rl_term_pc : 0;
44575409Sache  BC = _rl_term_backspace;
44675409Sache  UP = _rl_term_up;
44721308Sache
44875409Sache  if (!_rl_term_cr)
44975409Sache    _rl_term_cr = "\r";
45021308Sache
45121308Sache  _rl_term_autowrap = tgetflag ("am") && tgetflag ("xn");
45221308Sache
45321308Sache  _rl_get_screen_size (tty, 0);
45421308Sache
45521308Sache  /* "An application program can assume that the terminal can do
45621308Sache      character insertion if *any one of* the capabilities `IC',
45721308Sache      `im', `ic' or `ip' is provided."  But we can't do anything if
45821308Sache      only `ip' is provided, so... */
45975409Sache  _rl_terminal_can_insert = (_rl_term_IC || _rl_term_im || _rl_term_ic);
46021308Sache
46121308Sache  /* Check to see if this terminal has a meta key and clear the capability
46221308Sache     variables if there is none. */
46321308Sache  term_has_meta = (tgetflag ("km") || tgetflag ("MT"));
46421308Sache  if (!term_has_meta)
46575409Sache    _rl_term_mm = _rl_term_mo = (char *)NULL;
46621308Sache
46721308Sache  /* Attempt to find and bind the arrow keys.  Do not override already
46821308Sache     bound keys in an overzealous attempt, however. */
46921308Sache
470119614Sache  bind_termcap_arrow_keys (emacs_standard_keymap);
47121308Sache
472119614Sache#if defined (VI_MODE)
473119614Sache  bind_termcap_arrow_keys (vi_movement_keymap);
474119614Sache  bind_termcap_arrow_keys (vi_insertion_keymap);
475119614Sache#endif /* VI_MODE */
47621308Sache
477119614Sache  return 0;
478119614Sache}
479119614Sache
480119614Sache/* Bind the arrow key sequences from the termcap description in MAP. */
481119614Sachestatic void
482119614Sachebind_termcap_arrow_keys (map)
483119614Sache     Keymap map;
484119614Sache{
485119614Sache  Keymap xkeymap;
486119614Sache
487119614Sache  xkeymap = _rl_keymap;
488119614Sache  _rl_keymap = map;
489119614Sache
490136758Speter  rl_bind_keyseq_if_unbound (_rl_term_ku, rl_get_previous_history);
491136758Speter  rl_bind_keyseq_if_unbound (_rl_term_kd, rl_get_next_history);
492136758Speter  rl_bind_keyseq_if_unbound (_rl_term_kr, rl_forward_char);
493136758Speter  rl_bind_keyseq_if_unbound (_rl_term_kl, rl_backward_char);
49421308Sache
495136758Speter  rl_bind_keyseq_if_unbound (_rl_term_kh, rl_beg_of_line);	/* Home */
496136758Speter  rl_bind_keyseq_if_unbound (_rl_term_at7, rl_end_of_line);	/* End */
49721308Sache
49821308Sache  _rl_keymap = xkeymap;
49921308Sache}
50021308Sache
50121308Sachechar *
50221308Sacherl_get_termcap (cap)
50375409Sache     const char *cap;
50421308Sache{
50521308Sache  register int i;
50621308Sache
50721308Sache  if (tcap_initialized == 0)
50821308Sache    return ((char *)NULL);
50921308Sache  for (i = 0; i < NUM_TC_STRINGS; i++)
51021308Sache    {
51121308Sache      if (tc_strings[i].tc_var[0] == cap[0] && strcmp (tc_strings[i].tc_var, cap) == 0)
51221308Sache        return *(tc_strings[i].tc_value);
51321308Sache    }
51421308Sache  return ((char *)NULL);
51521308Sache}
51621308Sache
51726497Sache/* Re-initialize the terminal considering that the TERM/TERMCAP variable
51826497Sache   has changed. */
51926497Sacheint
52026497Sacherl_reset_terminal (terminal_name)
52175409Sache     const char *terminal_name;
52226497Sache{
52326497Sache  _rl_init_terminal_io (terminal_name);
52426497Sache  return 0;
52526497Sache}
52626497Sache
52721308Sache/* A function for the use of tputs () */
52835486Sache#ifdef _MINIX
52935486Sachevoid
53035486Sache_rl_output_character_function (c)
53135486Sache     int c;
53235486Sache{
53335486Sache  putc (c, _rl_out_stream);
53435486Sache}
53535486Sache#else /* !_MINIX */
53621308Sacheint
53721308Sache_rl_output_character_function (c)
53821308Sache     int c;
53921308Sache{
54021308Sache  return putc (c, _rl_out_stream);
54121308Sache}
54235486Sache#endif /* !_MINIX */
54358314Sache
54421308Sache/* Write COUNT characters from STRING to the output stream. */
54521308Sachevoid
54621308Sache_rl_output_some_chars (string, count)
54775409Sache     const char *string;
54821308Sache     int count;
54921308Sache{
55021308Sache  fwrite (string, 1, count, _rl_out_stream);
55121308Sache}
55221308Sache
55321308Sache/* Move the cursor back. */
55421308Sacheint
55521308Sache_rl_backspace (count)
55621308Sache     int count;
55721308Sache{
55821308Sache  register int i;
55921308Sache
56075409Sache  if (_rl_term_backspace)
56121308Sache    for (i = 0; i < count; i++)
56275409Sache      tputs (_rl_term_backspace, 1, _rl_output_character_function);
56321308Sache  else
56421308Sache    for (i = 0; i < count; i++)
56521308Sache      putc ('\b', _rl_out_stream);
56621308Sache  return 0;
56721308Sache}
56821308Sache
56921308Sache/* Move to the start of the next line. */
57021308Sacheint
57175409Sacherl_crlf ()
57221308Sache{
57321308Sache#if defined (NEW_TTY_DRIVER)
57475409Sache  if (_rl_term_cr)
57575409Sache    tputs (_rl_term_cr, 1, _rl_output_character_function);
57621308Sache#endif /* NEW_TTY_DRIVER */
57721308Sache  putc ('\n', _rl_out_stream);
57821308Sache  return 0;
57921308Sache}
58021308Sache
58121308Sache/* Ring the terminal bell. */
58221308Sacheint
58375409Sacherl_ding ()
58421308Sache{
58521308Sache  if (readline_echoing_p)
58621308Sache    {
58721308Sache      switch (_rl_bell_preference)
58821308Sache        {
58921308Sache	case NO_BELL:
59021308Sache	default:
59121308Sache	  break;
59221308Sache	case VISIBLE_BELL:
59375409Sache	  if (_rl_visible_bell)
59421308Sache	    {
59575409Sache	      tputs (_rl_visible_bell, 1, _rl_output_character_function);
59621308Sache	      break;
59721308Sache	    }
59821308Sache	  /* FALLTHROUGH */
59921308Sache	case AUDIBLE_BELL:
60021308Sache	  fprintf (stderr, "\007");
60121308Sache	  fflush (stderr);
60221308Sache	  break;
60321308Sache        }
60421308Sache      return (0);
60521308Sache    }
60621308Sache  return (-1);
60721308Sache}
60821308Sache
60921308Sache/* **************************************************************** */
61021308Sache/*								    */
61121308Sache/*	 	Controlling the Meta Key and Keypad		    */
61221308Sache/*								    */
61321308Sache/* **************************************************************** */
61421308Sache
61526497Sachevoid
61621308Sache_rl_enable_meta_key ()
61721308Sache{
61858314Sache#if !defined (__DJGPP__)
61975409Sache  if (term_has_meta && _rl_term_mm)
62075409Sache    tputs (_rl_term_mm, 1, _rl_output_character_function);
62158314Sache#endif
62221308Sache}
62321308Sache
62421308Sachevoid
62521308Sache_rl_control_keypad (on)
62621308Sache     int on;
62721308Sache{
62858314Sache#if !defined (__DJGPP__)
62975409Sache  if (on && _rl_term_ks)
63075409Sache    tputs (_rl_term_ks, 1, _rl_output_character_function);
63175409Sache  else if (!on && _rl_term_ke)
63275409Sache    tputs (_rl_term_ke, 1, _rl_output_character_function);
63358314Sache#endif
63421308Sache}
635119614Sache
636119614Sache/* **************************************************************** */
637119614Sache/*								    */
638119614Sache/*	 		Controlling the Cursor			    */
639119614Sache/*								    */
640119614Sache/* **************************************************************** */
641119614Sache
642119614Sache/* Set the cursor appropriately depending on IM, which is one of the
643119614Sache   insert modes (insert or overwrite).  Insert mode gets the normal
644119614Sache   cursor.  Overwrite mode gets a very visible cursor.  Only does
645119614Sache   anything if we have both capabilities. */
646119614Sachevoid
647119614Sache_rl_set_cursor (im, force)
648119614Sache     int im, force;
649119614Sache{
650119614Sache  if (_rl_term_ve && _rl_term_vs)
651119614Sache    {
652119614Sache      if (force || im != rl_insert_mode)
653119614Sache	{
654119614Sache	  if (im == RL_IM_OVERWRITE)
655119614Sache	    tputs (_rl_term_vs, 1, _rl_output_character_function);
656119614Sache	  else
657119614Sache	    tputs (_rl_term_ve, 1, _rl_output_character_function);
658119614Sache	}
659119614Sache    }
660119614Sache}
661