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