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 1, 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 675 Mass Ave, Cambridge, MA 02139, 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)
53 /* System-specific feature definitions and include files. */
56 #if defined (GWINSZ_IN_SYS_IOCTL) && !defined (TIOCGWINSZ)
57 # include <sys/ioctl.h>
58 #endif /* GWINSZ_IN_SYS_IOCTL && !TIOCGWINSZ */
60 #if defined (__GO32__)
67 /* Some standard library routines. */
71 /* Variables and functions imported from readline.c */
72 extern FILE *_rl_in_stream, *_rl_out_stream;
73 extern int readline_echoing_p;
74 extern int _rl_bell_preference;
75 extern Keymap _rl_keymap;
77 /* Functions imported from bind.c */
78 extern void _rl_bind_if_unbound ();
80 /* Functions imported from shell.c */
81 extern void set_lines_and_columns ();
82 extern char *get_env_value ();
84 /* Functions imported from display.c */
85 extern void _rl_redisplay_after_sigwinch ();
87 /* **************************************************************** */
89 /* Terminal and Termcap */
91 /* **************************************************************** */
94 static char *term_buffer = (char *)NULL;
95 static char *term_string_buffer = (char *)NULL;
97 /* Non-zero means this terminal can't really do anything. */
101 static int tcap_initialized;
103 #if !defined (__linux__)
104 # if defined (__EMX__) || defined (NEED_EXTERN_PC)
106 # endif /* __EMX__ || NEED_EXTERN_PC */
108 #endif /* __linux__ */
110 /* Some strings to control terminal actions. These are output by tputs (). */
111 char *term_goto, *term_clreol, *term_cr, *term_clrpag, *term_backspace;
114 /* Non-zero if we determine that the terminal can do character insertion. */
115 int terminal_can_insert = 0;
117 /* How to insert characters. */
118 char *term_im, *term_ei, *term_ic, *term_ip, *term_IC;
120 /* How to delete characters. */
121 char *term_dc, *term_DC;
123 #if defined (HACK_TERMCAP_MOTION)
124 char *term_forward_char;
125 #endif /* HACK_TERMCAP_MOTION */
127 /* How to go up a line. */
130 /* A visible bell, if the terminal can be made to flash the screen. */
131 static char *visible_bell;
133 /* Non-zero means the terminal can auto-wrap lines. */
134 int _rl_term_autowrap;
136 /* Non-zero means that this terminal has a meta key. */
137 static int term_has_meta;
139 /* The sequences to write to turn on and off the meta key, if this
141 static char *term_mm, *term_mo;
143 /* The key sequences output by the arrow keys, if this terminal has any. */
144 static char *term_ku, *term_kd, *term_kr, *term_kl;
146 /* How to initialize and reset the arrow keys, if this terminal has any. */
147 static char *term_ks, *term_ke;
149 /* The key sequences sent by the Home and End keys, if any. */
150 static char *term_kh, *term_kH;
152 /* Variables that hold the screen dimensions, used by the display code. */
153 int screenwidth, screenheight, screenchars;
155 /* Non-zero means the user wants to enable the keypad. */
156 int _rl_enable_keypad;
158 /* Non-zero means the user wants to enable a meta key. */
159 int _rl_enable_meta = 1;
161 /* Get readline's idea of the screen size. TTY is a file descriptor open
162 to the terminal. If IGNORE_ENV is true, we do not pay attention to the
163 values of $LINES and $COLUMNS. The tests for TERM_STRING_BUFFER being
164 non-null serve to check whether or not we have initialized termcap. */
166 _rl_get_screen_size (tty, ignore_env)
170 #if defined (TIOCGWINSZ)
171 struct winsize window_size;
172 #endif /* TIOCGWINSZ */
173 #if defined (__EMX__)
177 #if defined (TIOCGWINSZ)
178 if (ioctl (tty, TIOCGWINSZ, &window_size) == 0)
180 screenwidth = (int) window_size.ws_col;
181 screenheight = (int) window_size.ws_row;
183 #endif /* TIOCGWINSZ */
185 #if defined (__EMX__)
188 screenheight = sz[1];
191 /* Environment variable COLUMNS overrides setting of "co" if IGNORE_ENV
193 if (screenwidth <= 0)
195 if (ignore_env == 0 && (ss = get_env_value ("COLUMNS")))
196 screenwidth = atoi (ss);
198 #if defined(__DJGPP__)
200 if (screenwidth <= 0)
201 screenwidth = ScreenCols ();
203 if (screenwidth <= 0 && term_string_buffer)
204 screenwidth = tgetnum ("co");
208 /* Environment variable LINES overrides setting of "li" if IGNORE_ENV
210 if (screenheight <= 0)
212 if (ignore_env == 0 && (ss = get_env_value ("LINES")))
213 screenheight = atoi (ss);
215 #if defined(__DJGPP__)
216 if (screenheight <= 0)
217 screenheight = ScreenRows ();
219 if (screenheight <= 0 && term_string_buffer)
220 screenheight = tgetnum ("li");
224 /* If all else fails, default to 80x24 terminal. */
225 if (screenwidth <= 1)
228 if (screenheight <= 0)
231 /* If we're being compiled as part of bash, set the environment
232 variables $LINES and $COLUMNS to new values. Otherwise, just
233 do a pair of putenv () or setenv () calls. */
234 set_lines_and_columns (screenheight, screenwidth);
236 if (!_rl_term_autowrap)
239 screenchars = screenwidth * screenheight;
243 _rl_set_screen_size (rows, cols)
249 if (_rl_term_autowrap == 0)
252 screenchars = screenwidth * screenheight;
256 rl_resize_terminal ()
258 if (readline_echoing_p)
260 _rl_get_screen_size (fileno (rl_instream), 1);
261 _rl_redisplay_after_sigwinch ();
270 /* This should be kept sorted, just in case we decide to change the
271 search algorithm to something smarter. */
272 static struct _tc_string tc_strings[] =
284 "kh", &term_kh, /* home */
285 "kH", &term_kH, /* end */
291 "le", &term_backspace,
294 #if defined (HACK_TERMCAP_MOTION)
295 "nd", &term_forward_char,
302 #define NUM_TC_STRINGS (sizeof (tc_strings) / sizeof (struct _tc_string))
304 /* Read the desired terminal capability strings into BP. The capabilities
305 are described in the TC_STRINGS table. */
307 get_term_capabilities (bp)
310 #if defined(__DJGPP__)
315 for (i = 0; i < NUM_TC_STRINGS; i++)
316 *(tc_strings[i].tc_value) = tgetstr (tc_strings[i].tc_var, bp);
318 tcap_initialized = 1;
322 _rl_init_terminal_io (terminal_name)
325 #if defined (__GO32__)
326 terminal_name = terminal_name;
327 screenwidth = screenheight = 0;
328 _rl_get_screen_size (rl_instream ? fileno (rl_instream) : 0, 0);
331 term_im = term_ei = term_ic = term_IC = (char *)NULL;
332 term_up = term_dc = term_DC = visible_bell = (char *)NULL;
334 /* Does the __GO32__ have a meta key? I don't know. */
336 term_mm = term_mo = (char *)NULL;
338 /* It probably has arrow keys, but I don't know what they are. */
339 term_ku = term_kd = term_kr = term_kl = (char *)NULL;
341 #if defined (HACK_TERMCAP_MOTION)
342 term_forward_char = (char *)NULL;
343 #endif /* HACK_TERMCAP_MOTION */
344 terminal_can_insert = _rl_term_autowrap = 0;
346 #else /* !__GO32__ */
352 term = terminal_name ? terminal_name : get_env_value ("TERM");
354 if (term_string_buffer == 0)
355 term_string_buffer = xmalloc (2032);
357 if (term_buffer == 0)
358 term_buffer = xmalloc (4080);
360 buffer = term_string_buffer;
362 term_clrpag = term_cr = term_clreol = (char *)NULL;
367 if (tgetent (term_buffer, term) <= 0)
372 screenchars = 79 * 24;
374 term_im = term_ei = term_ic = term_IC = (char *)NULL;
375 term_up = term_dc = term_DC = visible_bell = (char *)NULL;
376 term_ku = term_kd = term_kl = term_kr = (char *)NULL;
377 #if defined (HACK_TERMCAP_MOTION)
378 term_forward_char = (char *)NULL;
380 terminal_can_insert = 0;
384 get_term_capabilities (&buffer);
386 /* Set up the variables that the termcap library expects the application
388 PC = term_pc ? *term_pc : 0;
395 tty = rl_instream ? fileno (rl_instream) : 0;
397 screenwidth = screenheight = 0;
399 _rl_term_autowrap = tgetflag ("am") && tgetflag ("xn");
401 _rl_get_screen_size (tty, 0);
403 /* "An application program can assume that the terminal can do
404 character insertion if *any one of* the capabilities `IC',
405 `im', `ic' or `ip' is provided." But we can't do anything if
406 only `ip' is provided, so... */
407 terminal_can_insert = (term_IC || term_im || term_ic);
409 /* Check to see if this terminal has a meta key and clear the capability
410 variables if there is none. */
411 term_has_meta = (tgetflag ("km") || tgetflag ("MT"));
413 term_mm = term_mo = (char *)NULL;
415 /* Attempt to find and bind the arrow keys. Do not override already
416 bound keys in an overzealous attempt, however. */
417 xkeymap = _rl_keymap;
419 _rl_keymap = emacs_standard_keymap;
420 _rl_bind_if_unbound (term_ku, rl_get_previous_history);
421 _rl_bind_if_unbound (term_kd, rl_get_next_history);
422 _rl_bind_if_unbound (term_kr, rl_forward);
423 _rl_bind_if_unbound (term_kl, rl_backward);
425 _rl_bind_if_unbound (term_kh, rl_beg_of_line); /* Home */
426 _rl_bind_if_unbound (term_kH, rl_end_of_line); /* End */
428 #if defined (VI_MODE)
429 _rl_keymap = vi_movement_keymap;
430 _rl_bind_if_unbound (term_ku, rl_get_previous_history);
431 _rl_bind_if_unbound (term_kd, rl_get_next_history);
432 _rl_bind_if_unbound (term_kr, rl_forward);
433 _rl_bind_if_unbound (term_kl, rl_backward);
435 _rl_bind_if_unbound (term_kh, rl_beg_of_line); /* Home */
436 _rl_bind_if_unbound (term_kH, rl_end_of_line); /* End */
439 _rl_keymap = xkeymap;
441 #endif /* !__GO32__ */
451 if (tcap_initialized == 0)
452 return ((char *)NULL);
453 for (i = 0; i < NUM_TC_STRINGS; i++)
455 if (tc_strings[i].tc_var[0] == cap[0] && strcmp (tc_strings[i].tc_var, cap) == 0)
456 return *(tc_strings[i].tc_value);
458 return ((char *)NULL);
461 /* Re-initialize the terminal considering that the TERM/TERMCAP variable
464 rl_reset_terminal (terminal_name)
467 _rl_init_terminal_io (terminal_name);
471 /* A function for the use of tputs () */
474 _rl_output_character_function (c)
477 putc (c, _rl_out_stream);
481 _rl_output_character_function (c)
484 return putc (c, _rl_out_stream);
487 /* Write COUNT characters from STRING to the output stream. */
489 _rl_output_some_chars (string, count)
493 fwrite (string, 1, count, _rl_out_stream);
496 /* Move the cursor back. */
498 _rl_backspace (count)
503 #if !defined (__GO32__)
505 for (i = 0; i < count; i++)
506 tputs (term_backspace, 1, _rl_output_character_function);
508 #endif /* !__GO32__ */
509 for (i = 0; i < count; i++)
510 putc ('\b', _rl_out_stream);
514 /* Move to the start of the next line. */
518 #if defined (NEW_TTY_DRIVER)
520 tputs (term_cr, 1, _rl_output_character_function);
521 #endif /* NEW_TTY_DRIVER */
522 putc ('\n', _rl_out_stream);
526 /* Ring the terminal bell. */
530 if (readline_echoing_p)
532 switch (_rl_bell_preference)
538 #if defined (__GO32__)
544 tputs (visible_bell, 1, _rl_output_character_function);
550 fprintf (stderr, "\007");
559 /* **************************************************************** */
561 /* Controlling the Meta Key and Keypad */
563 /* **************************************************************** */
566 _rl_enable_meta_key ()
568 #if !defined(__DJGPP__)
569 if (term_has_meta && term_mm)
570 tputs (term_mm, 1, _rl_output_character_function);
575 _rl_control_keypad (on)
578 #if defined(__DJGPP__)
582 tputs (term_ks, 1, _rl_output_character_function);
583 else if (!on && term_ke)
584 tputs (term_ke, 1, _rl_output_character_function);