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 (screenwidth <= 0 && term_string_buffer)
190
screenwidth = tgetnum ("co");
193
/* Environment variable LINES overrides setting of "li" if IGNORE_ENV
195
if (screenheight <= 0)
197
if (ignore_env == 0 && (ss = get_env_value ("LINES")))
198
screenheight = atoi (ss);
200
if (screenheight <= 0 && term_string_buffer)
201
screenheight = tgetnum ("li");
204
/* If all else fails, default to 80x24 terminal. */
205
if (screenwidth <= 1)
208
if (screenheight <= 0)
211
/* If we're being compiled as part of bash, set the environment
212
variables $LINES and $COLUMNS to new values. Otherwise, just
213
do a pair of putenv () or setenv () calls. */
214
set_lines_and_columns (screenheight, screenwidth);
216
if (!_rl_term_autowrap)
219
screenchars = screenwidth * screenheight;
223
_rl_set_screen_size (rows, cols)
229
if (_rl_term_autowrap == 0)
232
screenchars = screenwidth * screenheight;
236
rl_resize_terminal ()
238
if (readline_echoing_p)
240
_rl_get_screen_size (fileno (rl_instream), 1);
241
_rl_redisplay_after_sigwinch ();
250
/* This should be kept sorted, just in case we decide to change the
251
search algorithm to something smarter. */
252
static struct _tc_string tc_strings[] =
264
"kh", &term_kh, /* home */
265
"kH", &term_kH, /* end */
271
"le", &term_backspace,
274
#if defined (HACK_TERMCAP_MOTION)
275
"nd", &term_forward_char,
282
#define NUM_TC_STRINGS (sizeof (tc_strings) / sizeof (struct _tc_string))
284
/* Read the desired terminal capability strings into BP. The capabilities
285
are described in the TC_STRINGS table. */
287
get_term_capabilities (bp)
292
for (i = 0; i < NUM_TC_STRINGS; i++)
293
*(tc_strings[i].tc_value) = tgetstr (tc_strings[i].tc_var, bp);
294
tcap_initialized = 1;
298
_rl_init_terminal_io (terminal_name)
301
#if defined (__GO32__)
302
screenwidth = ScreenCols ();
303
screenheight = ScreenRows ();
304
screenchars = screenwidth * screenheight;
306
term_im = term_ei = term_ic = term_IC = (char *)NULL;
307
term_up = term_dc = term_DC = visible_bell = (char *)NULL;
309
/* Does the __GO32__ have a meta key? I don't know. */
311
term_mm = term_mo = (char *)NULL;
313
/* It probably has arrow keys, but I don't know what they are. */
314
term_ku = term_kd = term_kr = term_kl = (char *)NULL;
316
#if defined (HACK_TERMCAP_MOTION)
317
term_forward_char = (char *)NULL;
318
#endif /* HACK_TERMCAP_MOTION */
319
terminal_can_insert = _rl_term_autowrap = 0;
321
#else /* !__GO32__ */
327
term = terminal_name ? terminal_name : get_env_value ("TERM");
329
if (term_string_buffer == 0)
330
term_string_buffer = xmalloc (2032);
332
if (term_buffer == 0)
333
term_buffer = xmalloc (4080);
335
buffer = term_string_buffer;
337
term_clrpag = term_cr = term_clreol = (char *)NULL;
342
if (tgetent (term_buffer, term) <= 0)
347
screenchars = 79 * 24;
349
term_im = term_ei = term_ic = term_IC = (char *)NULL;
350
term_up = term_dc = term_DC = visible_bell = (char *)NULL;
351
term_ku = term_kd = term_kl = term_kr = (char *)NULL;
352
#if defined (HACK_TERMCAP_MOTION)
353
term_forward_char = (char *)NULL;
355
terminal_can_insert = 0;
359
get_term_capabilities (&buffer);
361
/* Set up the variables that the termcap library expects the application
363
PC = term_pc ? *term_pc : 0;
370
tty = rl_instream ? fileno (rl_instream) : 0;
372
screenwidth = screenheight = 0;
374
_rl_term_autowrap = tgetflag ("am") && tgetflag ("xn");
376
_rl_get_screen_size (tty, 0);
378
/* "An application program can assume that the terminal can do
379
character insertion if *any one of* the capabilities `IC',
380
`im', `ic' or `ip' is provided." But we can't do anything if
381
only `ip' is provided, so... */
382
terminal_can_insert = (term_IC || term_im || term_ic);
384
/* Check to see if this terminal has a meta key and clear the capability
385
variables if there is none. */
386
term_has_meta = (tgetflag ("km") || tgetflag ("MT"));
388
term_mm = term_mo = (char *)NULL;
390
/* Attempt to find and bind the arrow keys. Do not override already
391
bound keys in an overzealous attempt, however. */
392
xkeymap = _rl_keymap;
394
_rl_keymap = emacs_standard_keymap;
395
_rl_bind_if_unbound (term_ku, rl_get_previous_history);
396
_rl_bind_if_unbound (term_kd, rl_get_next_history);
397
_rl_bind_if_unbound (term_kr, rl_forward);
398
_rl_bind_if_unbound (term_kl, rl_backward);
400
_rl_bind_if_unbound (term_kh, rl_beg_of_line); /* Home */
401
_rl_bind_if_unbound (term_kH, rl_end_of_line); /* End */
403
#if defined (VI_MODE)
404
_rl_keymap = vi_movement_keymap;
405
_rl_bind_if_unbound (term_ku, rl_get_previous_history);
406
_rl_bind_if_unbound (term_kd, rl_get_next_history);
407
_rl_bind_if_unbound (term_kr, rl_forward);
408
_rl_bind_if_unbound (term_kl, rl_backward);
410
_rl_bind_if_unbound (term_kh, rl_beg_of_line); /* Home */
411
_rl_bind_if_unbound (term_kH, rl_end_of_line); /* End */
414
_rl_keymap = xkeymap;
416
#endif /* !__GO32__ */
426
if (tcap_initialized == 0)
427
return ((char *)NULL);
428
for (i = 0; i < NUM_TC_STRINGS; i++)
430
if (tc_strings[i].tc_var[0] == cap[0] && strcmp (tc_strings[i].tc_var, cap) == 0)
431
return *(tc_strings[i].tc_value);
433
return ((char *)NULL);
436
/* Re-initialize the terminal considering that the TERM/TERMCAP variable
439
rl_reset_terminal (terminal_name)
442
_rl_init_terminal_io (terminal_name);
446
/* A function for the use of tputs () */
449
_rl_output_character_function (c)
452
putc (c, _rl_out_stream);
456
_rl_output_character_function (c)
459
return putc (c, _rl_out_stream);
462
/* Write COUNT characters from STRING to the output stream. */
464
_rl_output_some_chars (string, count)
468
fwrite (string, 1, count, _rl_out_stream);
471
/* Move the cursor back. */
473
_rl_backspace (count)
478
#if !defined (__GO32__)
480
for (i = 0; i < count; i++)
481
tputs (term_backspace, 1, _rl_output_character_function);
483
#endif /* !__GO32__ */
484
for (i = 0; i < count; i++)
485
putc ('\b', _rl_out_stream);
489
/* Move to the start of the next line. */
493
#if defined (NEW_TTY_DRIVER)
495
tputs (term_cr, 1, _rl_output_character_function);
496
#endif /* NEW_TTY_DRIVER */
497
putc ('\n', _rl_out_stream);
501
/* Ring the terminal bell. */
505
if (readline_echoing_p)
507
#if !defined (__GO32__)
508
switch (_rl_bell_preference)
516
tputs (visible_bell, 1, _rl_output_character_function);
521
fprintf (stderr, "\007");
526
fprintf (stderr, "\007");
528
#endif /* __GO32__ */
534
/* **************************************************************** */
536
/* Controlling the Meta Key and Keypad */
538
/* **************************************************************** */
541
_rl_enable_meta_key ()
543
if (term_has_meta && term_mm)
544
tputs (term_mm, 1, _rl_output_character_function);
548
_rl_control_keypad (on)
552
tputs (term_ks, 1, _rl_output_character_function);
553
else if (!on && term_ke)
554
tputs (term_ke, 1, _rl_output_character_function);