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 */
63 /* Some standard library routines. */
67 /* Variables and functions imported from readline.c */
68 extern FILE *_rl_in_stream
, *_rl_out_stream
;
69 extern int readline_echoing_p
;
70 extern int _rl_bell_preference
;
71 extern Keymap _rl_keymap
;
73 /* Functions imported from bind.c */
74 extern void _rl_bind_if_unbound ();
76 /* Functions imported from shell.c */
77 extern void set_lines_and_columns ();
78 extern char *get_env_value ();
80 /* **************************************************************** */
82 /* Terminal and Termcap */
84 /* **************************************************************** */
86 static char *term_buffer
= (char *)NULL
;
87 static char *term_string_buffer
= (char *)NULL
;
89 static int tcap_initialized
;
91 /* Non-zero means this terminal can't really do anything. */
94 #if !defined (__linux__)
95 # if defined (__EMX__) || defined (NEED_EXTERN_PC)
97 # endif /* __EMX__ || NEED_EXTERN_PC */
99 #endif /* __linux__ */
101 /* Some strings to control terminal actions. These are output by tputs (). */
102 char *term_goto
, *term_clreol
, *term_cr
, *term_clrpag
, *term_backspace
;
105 /* Non-zero if we determine that the terminal can do character insertion. */
106 int terminal_can_insert
= 0;
108 /* How to insert characters. */
109 char *term_im
, *term_ei
, *term_ic
, *term_ip
, *term_IC
;
111 /* How to delete characters. */
112 char *term_dc
, *term_DC
;
114 #if defined (HACK_TERMCAP_MOTION)
115 char *term_forward_char
;
116 #endif /* HACK_TERMCAP_MOTION */
118 /* How to go up a line. */
121 /* A visible bell, if the terminal can be made to flash the screen. */
122 static char *visible_bell
;
124 /* Non-zero means the terminal can auto-wrap lines. */
125 int _rl_term_autowrap
;
127 /* Non-zero means that this terminal has a meta key. */
128 static int term_has_meta
;
130 /* The sequences to write to turn on and off the meta key, if this
132 static char *term_mm
, *term_mo
;
134 /* The key sequences output by the arrow keys, if this terminal has any. */
135 static char *term_ku
, *term_kd
, *term_kr
, *term_kl
;
137 /* How to initialize and reset the arrow keys, if this terminal has any. */
138 static char *term_ks
, *term_ke
;
140 /* The key sequences sent by the Home and End keys, if any. */
141 static char *term_kh
, *term_kH
;
143 /* Variables that hold the screen dimensions, used by the display code. */
144 int screenwidth
, screenheight
, screenchars
;
146 /* Non-zero means the user wants to enable the keypad. */
147 int _rl_enable_keypad
;
149 /* Non-zero means the user wants to enable a meta key. */
150 int _rl_enable_meta
= 1;
152 /* Get readline's idea of the screen size. TTY is a file descriptor open
153 to the terminal. If IGNORE_ENV is true, we do not pay attention to the
154 values of $LINES and $COLUMNS. The tests for TERM_STRING_BUFFER being
155 non-null serve to check whether or not we have initialized termcap. */
157 _rl_get_screen_size (tty
, ignore_env
)
161 #if defined (TIOCGWINSZ)
162 struct winsize window_size
;
163 #endif /* TIOCGWINSZ */
164 #if defined (__EMX__)
168 #if defined (TIOCGWINSZ)
169 if (ioctl (tty
, TIOCGWINSZ
, &window_size
) == 0)
171 screenwidth
= (int) window_size
.ws_col
;
172 screenheight
= (int) window_size
.ws_row
;
174 #endif /* TIOCGWINSZ */
176 #if defined (__EMX__)
179 screenheight
= sz
[1];
182 /* Environment variable COLUMNS overrides setting of "co" if IGNORE_ENV
184 if (screenwidth
<= 0)
186 if (ignore_env
== 0 && (ss
= get_env_value ("COLUMNS")))
187 screenwidth
= atoi (ss
);
189 #if !defined(__DJGPP__)
190 if (screenwidth
<= 0 && term_string_buffer
)
191 screenwidth
= tgetnum ("co");
195 /* Environment variable LINES overrides setting of "li" if IGNORE_ENV
197 if (screenheight
<= 0)
199 if (ignore_env
== 0 && (ss
= get_env_value ("LINES")))
200 screenheight
= atoi (ss
);
202 #if !defined(__DJGPP__)
203 if (screenheight
<= 0 && term_string_buffer
)
204 screenheight
= tgetnum ("li");
208 /* If all else fails, default to 80x24 terminal. */
209 if (screenwidth
<= 1)
212 if (screenheight
<= 0)
215 /* If we're being compiled as part of bash, set the environment
216 variables $LINES and $COLUMNS to new values. Otherwise, just
217 do a pair of putenv () or setenv () calls. */
218 set_lines_and_columns (screenheight
, screenwidth
);
220 if (!_rl_term_autowrap
)
223 screenchars
= screenwidth
* screenheight
;
227 _rl_set_screen_size (rows
, cols
)
233 if (_rl_term_autowrap
== 0)
236 screenchars
= screenwidth
* screenheight
;
244 /* This should be kept sorted, just in case we decide to change the
245 search algorithm to something smarter. */
246 static struct _tc_string tc_strings
[] =
258 "kh", &term_kh
, /* home */
259 "kH", &term_kH
, /* end */
265 "le", &term_backspace
,
268 #if defined (HACK_TERMCAP_MOTION)
269 "nd", &term_forward_char
,
276 #define NUM_TC_STRINGS (sizeof (tc_strings) / sizeof (struct _tc_string))
278 /* Read the desired terminal capability strings into BP. The capabilities
279 are described in the TC_STRINGS table. */
281 get_term_capabilities (bp
)
284 #if !defined(__DJGPP__)
287 for (i
= 0; i
< NUM_TC_STRINGS
; i
++)
288 *(tc_strings
[i
].tc_value
) = tgetstr (tc_strings
[i
].tc_var
, bp
);
290 tcap_initialized
= 1;
294 _rl_init_terminal_io (terminal_name
)
297 #if defined (__GO32__)
298 screenwidth
= ScreenCols ();
299 screenheight
= ScreenRows ();
300 screenchars
= screenwidth
* screenheight
;
302 term_im
= term_ei
= term_ic
= term_IC
= (char *)NULL
;
303 term_up
= term_dc
= term_DC
= visible_bell
= (char *)NULL
;
305 /* Does the __GO32__ have a meta key? I don't know. */
307 term_mm
= term_mo
= (char *)NULL
;
309 /* It probably has arrow keys, but I don't know what they are. */
310 term_ku
= term_kd
= term_kr
= term_kl
= (char *)NULL
;
312 #if defined (HACK_TERMCAP_MOTION)
313 term_forward_char
= (char *)NULL
;
314 #endif /* HACK_TERMCAP_MOTION */
315 terminal_can_insert
= _rl_term_autowrap
= 0;
317 #else /* !__GO32__ */
323 term
= terminal_name
? terminal_name
: get_env_value ("TERM");
325 if (term_string_buffer
== 0)
326 term_string_buffer
= xmalloc (2032);
328 if (term_buffer
== 0)
329 term_buffer
= xmalloc (4080);
331 buffer
= term_string_buffer
;
333 term_clrpag
= term_cr
= term_clreol
= (char *)NULL
;
338 if (tgetent (term_buffer
, term
) <= 0)
343 screenchars
= 79 * 24;
345 term_im
= term_ei
= term_ic
= term_IC
= (char *)NULL
;
346 term_up
= term_dc
= term_DC
= visible_bell
= (char *)NULL
;
347 term_ku
= term_kd
= term_kl
= term_kr
= (char *)NULL
;
348 #if defined (HACK_TERMCAP_MOTION)
349 term_forward_char
= (char *)NULL
;
351 terminal_can_insert
= 0;
355 get_term_capabilities (&buffer
);
357 /* Set up the variables that the termcap library expects the application
359 PC
= term_pc
? *term_pc
: 0;
366 tty
= rl_instream
? fileno (rl_instream
) : 0;
368 screenwidth
= screenheight
= 0;
370 _rl_term_autowrap
= tgetflag ("am") && tgetflag ("xn");
372 _rl_get_screen_size (tty
, 0);
374 /* "An application program can assume that the terminal can do
375 character insertion if *any one of* the capabilities `IC',
376 `im', `ic' or `ip' is provided." But we can't do anything if
377 only `ip' is provided, so... */
378 terminal_can_insert
= (term_IC
|| term_im
|| term_ic
);
380 /* Check to see if this terminal has a meta key and clear the capability
381 variables if there is none. */
382 term_has_meta
= (tgetflag ("km") || tgetflag ("MT"));
384 term_mm
= term_mo
= (char *)NULL
;
386 /* Attempt to find and bind the arrow keys. Do not override already
387 bound keys in an overzealous attempt, however. */
388 xkeymap
= _rl_keymap
;
390 _rl_keymap
= emacs_standard_keymap
;
391 _rl_bind_if_unbound (term_ku
, rl_get_previous_history
);
392 _rl_bind_if_unbound (term_kd
, rl_get_next_history
);
393 _rl_bind_if_unbound (term_kr
, rl_forward
);
394 _rl_bind_if_unbound (term_kl
, rl_backward
);
396 _rl_bind_if_unbound (term_kh
, rl_beg_of_line
); /* Home */
397 _rl_bind_if_unbound (term_kH
, rl_end_of_line
); /* End */
399 #if defined (VI_MODE)
400 _rl_keymap
= vi_movement_keymap
;
401 _rl_bind_if_unbound (term_ku
, rl_get_previous_history
);
402 _rl_bind_if_unbound (term_kd
, rl_get_next_history
);
403 _rl_bind_if_unbound (term_kr
, rl_forward
);
404 _rl_bind_if_unbound (term_kl
, rl_backward
);
406 _rl_bind_if_unbound (term_kh
, rl_beg_of_line
); /* Home */
407 _rl_bind_if_unbound (term_kH
, rl_end_of_line
); /* End */
410 _rl_keymap
= xkeymap
;
412 #endif /* !__GO32__ */
422 if (tcap_initialized
== 0)
423 return ((char *)NULL
);
424 for (i
= 0; i
< NUM_TC_STRINGS
; i
++)
426 if (tc_strings
[i
].tc_var
[0] == cap
[0] && strcmp (tc_strings
[i
].tc_var
, cap
) == 0)
427 return *(tc_strings
[i
].tc_value
);
429 return ((char *)NULL
);
432 /* Re-initialize the terminal considering that the TERM/TERMCAP variable
435 rl_reset_terminal (terminal_name
)
438 _rl_init_terminal_io (terminal_name
);
442 /* A function for the use of tputs () */
445 _rl_output_character_function (c
)
448 putc (c
, _rl_out_stream
);
452 _rl_output_character_function (c
)
455 return putc (c
, _rl_out_stream
);
458 /* Write COUNT characters from STRING to the output stream. */
460 _rl_output_some_chars (string
, count
)
464 fwrite (string
, 1, count
, _rl_out_stream
);
467 /* Move the cursor back. */
469 _rl_backspace (count
)
474 #if !defined (__GO32__)
476 for (i
= 0; i
< count
; i
++)
477 tputs (term_backspace
, 1, _rl_output_character_function
);
479 #endif /* !__GO32__ */
480 for (i
= 0; i
< count
; i
++)
481 putc ('\b', _rl_out_stream
);
485 /* Move to the start of the next line. */
489 #if defined (NEW_TTY_DRIVER)
491 tputs (term_cr
, 1, _rl_output_character_function
);
492 #endif /* NEW_TTY_DRIVER */
493 putc ('\n', _rl_out_stream
);
497 /* Ring the terminal bell. */
501 if (readline_echoing_p
)
503 #if !defined (__GO32__)
504 switch (_rl_bell_preference
)
512 tputs (visible_bell
, 1, _rl_output_character_function
);
517 fprintf (stderr
, "\007");
522 fprintf (stderr
, "\007");
524 #endif /* __GO32__ */
530 /* **************************************************************** */
532 /* Controlling the Meta Key and Keypad */
534 /* **************************************************************** */
537 _rl_enable_meta_key ()
539 #if !defined(__DJGPP__)
540 if (term_has_meta
&& term_mm
)
541 tputs (term_mm
, 1, _rl_output_character_function
);
546 _rl_control_keypad (on
)
549 #if !defined(__DJGPP__)
551 tputs (term_ks
, 1, _rl_output_character_function
);
552 else if (!on
&& term_ke
)
553 tputs (term_ke
, 1, _rl_output_character_function
);