1 /* terminal.c -- controlling the terminal with termcap. */
3 /* Copyright (C) 1996 Free Software Foundation, Inc.
5 This file is part of the GNU Readline Library, a library for
6 reading lines of text with interactive input and history editing.
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.
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.
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
24 #if defined (HAVE_CONFIG_H)
28 #include <sys/types.h>
29 #include "posixstat.h"
31 #if defined (HAVE_SYS_FILE_H)
32 # include <sys/file.h>
33 #endif /* HAVE_SYS_FILE_H */
35 #if defined (HAVE_UNISTD_H)
37 #endif /* HAVE_UNISTD_H */
39 #if defined (HAVE_STDLIB_H)
42 # include "ansi_stdlib.h"
43 #endif /* HAVE_STDLIB_H */
45 #if defined (HAVE_LOCALE_H)
51 /* System-specific feature definitions and include files. */
54 #if defined (GWINSZ_IN_SYS_IOCTL) && !defined (TIOCGWINSZ)
55 # include <sys/ioctl.h>
56 #endif /* GWINSZ_IN_SYS_IOCTL && !TIOCGWINSZ */
65 /* Some standard library routines. */
69 #include "rlprivate.h"
72 /* **************************************************************** */
74 /* Terminal and Termcap */
76 /* **************************************************************** */
79 static char *term_buffer = (char *)NULL;
80 static char *term_string_buffer = (char *)NULL;
82 /* Non-zero means this terminal can't really do anything. */
84 #endif /* !__MSDOS__ */
86 static int tcap_initialized;
88 #if !defined (__linux__)
89 # if defined (__EMX__) || defined (NEED_EXTERN_PC)
91 # endif /* __EMX__ || NEED_EXTERN_PC */
93 #endif /* __linux__ */
95 /* Some strings to control terminal actions. These are output by tputs (). */
96 char *term_goto, *term_clreol, *term_cr, *term_clrpag, *term_backspace;
99 /* Non-zero if we determine that the terminal can do character insertion. */
100 int terminal_can_insert = 0;
102 /* How to insert characters. */
103 char *term_im, *term_ei, *term_ic, *term_ip, *term_IC;
105 /* How to delete characters. */
106 char *term_dc, *term_DC;
108 #if defined (HACK_TERMCAP_MOTION)
109 char *term_forward_char;
110 #endif /* HACK_TERMCAP_MOTION */
112 /* How to go up a line. */
115 /* A visible bell, if the terminal can be made to flash the screen. */
116 static char *visible_bell;
118 /* Non-zero means the terminal can auto-wrap lines. */
119 int _rl_term_autowrap;
121 /* Non-zero means that this terminal has a meta key. */
122 static int term_has_meta;
124 /* The sequences to write to turn on and off the meta key, if this
126 static char *term_mm, *term_mo;
128 /* The key sequences output by the arrow keys, if this terminal has any. */
129 static char *term_ku, *term_kd, *term_kr, *term_kl;
131 /* How to initialize and reset the arrow keys, if this terminal has any. */
132 static char *term_ks, *term_ke;
134 /* The key sequences sent by the Home and End keys, if any. */
135 static char *term_kh, *term_kH;
137 /* Variables that hold the screen dimensions, used by the display code. */
138 int screenwidth, screenheight, screenchars;
140 /* Non-zero means the user wants to enable the keypad. */
141 int _rl_enable_keypad;
143 /* Non-zero means the user wants to enable a meta key. */
144 int _rl_enable_meta = 1;
146 #if defined (__EMX__)
148 _emx_get_screensize (swp, shp)
162 /* Get readline's idea of the screen size. TTY is a file descriptor open
163 to the terminal. If IGNORE_ENV is true, we do not pay attention to the
164 values of $LINES and $COLUMNS. The tests for TERM_STRING_BUFFER being
165 non-null serve to check whether or not we have initialized termcap. */
167 _rl_get_screen_size (tty, ignore_env)
171 #if defined (TIOCGWINSZ)
172 struct winsize window_size;
173 #endif /* TIOCGWINSZ */
175 #if defined (TIOCGWINSZ)
176 if (ioctl (tty, TIOCGWINSZ, &window_size) == 0)
178 screenwidth = (int) window_size.ws_col;
179 screenheight = (int) window_size.ws_row;
181 #endif /* TIOCGWINSZ */
183 #if defined (__EMX__)
184 _emx_get_screensize (&screenwidth, &screenheight);
187 /* Environment variable COLUMNS overrides setting of "co" if IGNORE_ENV
189 if (screenwidth <= 0)
191 if (ignore_env == 0 && (ss = get_env_value ("COLUMNS")))
192 screenwidth = atoi (ss);
194 #if defined (__DJGPP__)
195 if (screenwidth <= 0)
196 screenwidth = ScreenCols ();
198 if (screenwidth <= 0 && term_string_buffer)
199 screenwidth = tgetnum ("co");
203 /* Environment variable LINES overrides setting of "li" if IGNORE_ENV
205 if (screenheight <= 0)
207 if (ignore_env == 0 && (ss = get_env_value ("LINES")))
208 screenheight = atoi (ss);
210 #if defined (__DJGPP__)
211 if (screenheight <= 0)
212 screenheight = ScreenRows ();
214 if (screenheight <= 0 && term_string_buffer)
215 screenheight = tgetnum ("li");
219 /* If all else fails, default to 80x24 terminal. */
220 if (screenwidth <= 1)
223 if (screenheight <= 0)
226 /* If we're being compiled as part of bash, set the environment
227 variables $LINES and $COLUMNS to new values. Otherwise, just
228 do a pair of putenv () or setenv () calls. */
229 set_lines_and_columns (screenheight, screenwidth);
231 if (_rl_term_autowrap == 0)
234 screenchars = screenwidth * screenheight;
238 _rl_set_screen_size (rows, cols)
244 if (_rl_term_autowrap == 0)
247 screenchars = screenwidth * screenheight;
251 rl_resize_terminal ()
253 if (readline_echoing_p)
255 _rl_get_screen_size (fileno (rl_instream), 1);
256 _rl_redisplay_after_sigwinch ();
265 /* This should be kept sorted, just in case we decide to change the
266 search algorithm to something smarter. */
267 static struct _tc_string tc_strings[] =
271 { "ce", &term_clreol },
272 { "cl", &term_clrpag },
279 { "kh", &term_kh }, /* home */
280 { "kH", &term_kH }, /* end */
286 { "le", &term_backspace },
289 #if defined (HACK_TERMCAP_MOTION)
290 { "nd", &term_forward_char },
294 { "vb", &visible_bell },
297 #define NUM_TC_STRINGS (sizeof (tc_strings) / sizeof (struct _tc_string))
299 /* Read the desired terminal capability strings into BP. The capabilities
300 are described in the TC_STRINGS table. */
302 get_term_capabilities (bp)
305 #if !defined (__DJGPP__) /* XXX - doesn't DJGPP have a termcap library? */
308 for (i = 0; i < NUM_TC_STRINGS; i++)
309 *(tc_strings[i].tc_value) = tgetstr (tc_strings[i].tc_var, bp);
311 tcap_initialized = 1;
314 #define CUSTOM_REDISPLAY_FUNC() (rl_redisplay_function != rl_redisplay)
315 #define CUSTOM_INPUT_FUNC() (rl_getc_function != rl_getc)
318 _rl_init_terminal_io (terminal_name)
322 int tty, tgetent_ret;
325 term = terminal_name ? terminal_name : get_env_value ("TERM");
326 term_clrpag = term_cr = term_clreol = (char *)NULL;
327 tty = rl_instream ? fileno (rl_instream) : 0;
328 screenwidth = screenheight = 0;
334 term_im = term_ei = term_ic = term_IC = (char *)NULL;
335 term_up = term_dc = term_DC = visible_bell = (char *)NULL;
336 term_ku = term_kd = term_kl = term_kr = (char *)NULL;
337 term_mm = term_mo = (char *)NULL;
338 terminal_can_insert = term_has_meta = _rl_term_autowrap = 0;
341 _rl_get_screen_size (tty, 0);
342 #else /* !__MSDOS__ */
343 /* I've separated this out for later work on not calling tgetent at all
344 if the calling application has supplied a custom redisplay function,
345 (and possibly if the application has supplied a custom input function). */
346 if (CUSTOM_REDISPLAY_FUNC())
352 if (term_string_buffer == 0)
353 term_string_buffer = xmalloc(2032);
355 if (term_buffer == 0)
356 term_buffer = xmalloc(4080);
358 buffer = term_string_buffer;
360 tgetent_ret = tgetent (term_buffer, term);
363 if (tgetent_ret <= 0)
365 FREE (term_string_buffer);
367 buffer = term_buffer = term_string_buffer = (char *)NULL;
370 _rl_term_autowrap = 0; /* used by _rl_get_screen_size */
372 #if defined (__EMX__)
373 _emx_get_screensize (&screenwidth, &screenheight);
376 _rl_get_screen_size (tty, 0);
377 #endif /* !__EMX__ */
380 if (screenwidth <= 0 || screenheight <= 0)
386 /* Everything below here is used by the redisplay code (tputs). */
387 screenchars = screenwidth * screenheight;
389 term_im = term_ei = term_ic = term_IC = (char *)NULL;
390 term_up = term_dc = term_DC = visible_bell = (char *)NULL;
391 term_ku = term_kd = term_kl = term_kr = (char *)NULL;
392 term_mm = term_mo = (char *)NULL;
393 #if defined (HACK_TERMCAP_MOTION)
394 term_forward_char = (char *)NULL;
396 terminal_can_insert = term_has_meta = 0;
398 /* Reasonable defaults for tgoto(). Readline currently only uses
399 tgoto if term_IC or term_DC is defined, but just in case we
400 change that later... */
402 BC = term_backspace = "\b";
408 get_term_capabilities (&buffer);
410 /* Set up the variables that the termcap library expects the application
412 PC = term_pc ? *term_pc : 0;
419 _rl_term_autowrap = tgetflag ("am") && tgetflag ("xn");
421 _rl_get_screen_size (tty, 0);
423 /* "An application program can assume that the terminal can do
424 character insertion if *any one of* the capabilities `IC',
425 `im', `ic' or `ip' is provided." But we can't do anything if
426 only `ip' is provided, so... */
427 terminal_can_insert = (term_IC || term_im || term_ic);
429 /* Check to see if this terminal has a meta key and clear the capability
430 variables if there is none. */
431 term_has_meta = (tgetflag ("km") || tgetflag ("MT"));
433 term_mm = term_mo = (char *)NULL;
435 #endif /* !__MSDOS__ */
437 /* Attempt to find and bind the arrow keys. Do not override already
438 bound keys in an overzealous attempt, however. */
439 xkeymap = _rl_keymap;
441 _rl_keymap = emacs_standard_keymap;
442 _rl_bind_if_unbound (term_ku, rl_get_previous_history);
443 _rl_bind_if_unbound (term_kd, rl_get_next_history);
444 _rl_bind_if_unbound (term_kr, rl_forward);
445 _rl_bind_if_unbound (term_kl, rl_backward);
447 _rl_bind_if_unbound (term_kh, rl_beg_of_line); /* Home */
448 _rl_bind_if_unbound (term_kH, rl_end_of_line); /* End */
450 #if defined (VI_MODE)
451 _rl_keymap = vi_movement_keymap;
452 _rl_bind_if_unbound (term_ku, rl_get_previous_history);
453 _rl_bind_if_unbound (term_kd, rl_get_next_history);
454 _rl_bind_if_unbound (term_kr, rl_forward);
455 _rl_bind_if_unbound (term_kl, rl_backward);
457 _rl_bind_if_unbound (term_kh, rl_beg_of_line); /* Home */
458 _rl_bind_if_unbound (term_kH, rl_end_of_line); /* End */
461 _rl_keymap = xkeymap;
472 if (tcap_initialized == 0)
473 return ((char *)NULL);
474 for (i = 0; i < NUM_TC_STRINGS; i++)
476 if (tc_strings[i].tc_var[0] == cap[0] && strcmp (tc_strings[i].tc_var, cap) == 0)
477 return *(tc_strings[i].tc_value);
479 return ((char *)NULL);
482 /* Re-initialize the terminal considering that the TERM/TERMCAP variable
485 rl_reset_terminal (terminal_name)
488 _rl_init_terminal_io (terminal_name);
492 /* A function for the use of tputs () */
495 _rl_output_character_function (c)
498 putc (c, _rl_out_stream);
502 _rl_output_character_function (c)
505 return putc (c, _rl_out_stream);
509 /* Write COUNT characters from STRING to the output stream. */
511 _rl_output_some_chars (string, count)
515 fwrite (string, 1, count, _rl_out_stream);
518 /* Move the cursor back. */
520 _rl_backspace (count)
527 for (i = 0; i < count; i++)
528 tputs (term_backspace, 1, _rl_output_character_function);
531 for (i = 0; i < count; i++)
532 putc ('\b', _rl_out_stream);
536 /* Move to the start of the next line. */
540 #if defined (NEW_TTY_DRIVER)
542 tputs (term_cr, 1, _rl_output_character_function);
543 #endif /* NEW_TTY_DRIVER */
544 putc ('\n', _rl_out_stream);
548 /* Ring the terminal bell. */
552 if (readline_echoing_p)
554 switch (_rl_bell_preference)
566 tputs (visible_bell, 1, _rl_output_character_function);
572 fprintf (stderr, "\007");
581 /* **************************************************************** */
583 /* Controlling the Meta Key and Keypad */
585 /* **************************************************************** */
588 _rl_enable_meta_key ()
590 #if !defined (__DJGPP__)
591 if (term_has_meta && term_mm)
592 tputs (term_mm, 1, _rl_output_character_function);
597 _rl_control_keypad (on)
600 #if !defined (__DJGPP__)
602 tputs (term_ks, 1, _rl_output_character_function);
603 else if (!on && term_ke)
604 tputs (term_ke, 1, _rl_output_character_function);