]> git.ipfire.org Git - thirdparty/bash.git/blame - lib/readline/terminal.c
Imported from ../bash-2.05.tar.gz.
[thirdparty/bash.git] / lib / readline / terminal.c
CommitLineData
ccc6cda3
JA
1/* terminal.c -- controlling the terminal with termcap. */
2
3/* Copyright (C) 1996 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
bb70624e 10 as published by the Free Software Foundation; either version 2, or
ccc6cda3
JA
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,
bb70624e 21 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
ccc6cda3
JA
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
ccc6cda3 49#include <stdio.h>
ccc6cda3
JA
50
51/* System-specific feature definitions and include files. */
52#include "rldefs.h"
53
d166f048 54#if defined (GWINSZ_IN_SYS_IOCTL) && !defined (TIOCGWINSZ)
ccc6cda3 55# include <sys/ioctl.h>
d166f048
JA
56#endif /* GWINSZ_IN_SYS_IOCTL && !TIOCGWINSZ */
57
58#include "rltty.h"
59#include "tcap.h"
ccc6cda3
JA
60
61/* Some standard library routines. */
62#include "readline.h"
63#include "history.h"
64
bb70624e
JA
65#include "rlprivate.h"
66#include "rlshell.h"
d166f048 67
ccc6cda3
JA
68/* **************************************************************** */
69/* */
70/* Terminal and Termcap */
71/* */
72/* **************************************************************** */
73
74static char *term_buffer = (char *)NULL;
75static char *term_string_buffer = (char *)NULL;
76
77static int tcap_initialized;
78
ccc6cda3 79#if !defined (__linux__)
d166f048
JA
80# if defined (__EMX__) || defined (NEED_EXTERN_PC)
81extern
82# endif /* __EMX__ || NEED_EXTERN_PC */
83char PC, *BC, *UP;
ccc6cda3
JA
84#endif /* __linux__ */
85
86/* Some strings to control terminal actions. These are output by tputs (). */
28ef6c31
JA
87char *_rl_term_clreol;
88char *_rl_term_clrpag;
89char *_rl_term_cr;
90char *_rl_term_backspace;
91char *_rl_term_goto;
92char *_rl_term_pc;
ccc6cda3
JA
93
94/* Non-zero if we determine that the terminal can do character insertion. */
28ef6c31 95int _rl_terminal_can_insert = 0;
ccc6cda3
JA
96
97/* How to insert characters. */
28ef6c31
JA
98char *_rl_term_im;
99char *_rl_term_ei;
100char *_rl_term_ic;
101char *_rl_term_ip;
102char *_rl_term_IC;
ccc6cda3
JA
103
104/* How to delete characters. */
28ef6c31
JA
105char *_rl_term_dc;
106char *_rl_term_DC;
ccc6cda3
JA
107
108#if defined (HACK_TERMCAP_MOTION)
28ef6c31 109char *_rl_term_forward_char;
ccc6cda3
JA
110#endif /* HACK_TERMCAP_MOTION */
111
112/* How to go up a line. */
28ef6c31 113char *_rl_term_up;
ccc6cda3 114
28ef6c31
JA
115/* A visible bell; char if the terminal can be made to flash the screen. */
116static char *_rl_visible_bell;
ccc6cda3
JA
117
118/* Non-zero means the terminal can auto-wrap lines. */
119int _rl_term_autowrap;
120
121/* Non-zero means that this terminal has a meta key. */
122static int term_has_meta;
123
124/* The sequences to write to turn on and off the meta key, if this
28ef6c31
JA
125 terminal has one. */
126static char *_rl_term_mm;
127static char *_rl_term_mo;
ccc6cda3
JA
128
129/* The key sequences output by the arrow keys, if this terminal has any. */
28ef6c31
JA
130static char *_rl_term_ku;
131static char *_rl_term_kd;
132static char *_rl_term_kr;
133static char *_rl_term_kl;
ccc6cda3
JA
134
135/* How to initialize and reset the arrow keys, if this terminal has any. */
28ef6c31
JA
136static char *_rl_term_ks;
137static char *_rl_term_ke;
ccc6cda3
JA
138
139/* The key sequences sent by the Home and End keys, if any. */
28ef6c31
JA
140static char *_rl_term_kh;
141static char *_rl_term_kH;
ccc6cda3
JA
142
143/* Variables that hold the screen dimensions, used by the display code. */
28ef6c31 144int _rl_screenwidth, _rl_screenheight, _rl_screenchars;
ccc6cda3
JA
145
146/* Non-zero means the user wants to enable the keypad. */
147int _rl_enable_keypad;
148
149/* Non-zero means the user wants to enable a meta key. */
150int _rl_enable_meta = 1;
151
bb70624e
JA
152#if defined (__EMX__)
153static void
154_emx_get_screensize (swp, shp)
155 int *swp, *shp;
156{
157 int sz[2];
158
159 _scrsize (sz);
160
161 if (swp)
162 *swp = sz[0];
163 if (shp)
164 *shp = sz[1];
165}
166#endif
167
ccc6cda3
JA
168/* Get readline's idea of the screen size. TTY is a file descriptor open
169 to the terminal. If IGNORE_ENV is true, we do not pay attention to the
170 values of $LINES and $COLUMNS. The tests for TERM_STRING_BUFFER being
171 non-null serve to check whether or not we have initialized termcap. */
172void
173_rl_get_screen_size (tty, ignore_env)
174 int tty, ignore_env;
175{
176 char *ss;
177#if defined (TIOCGWINSZ)
178 struct winsize window_size;
179#endif /* TIOCGWINSZ */
180
181#if defined (TIOCGWINSZ)
182 if (ioctl (tty, TIOCGWINSZ, &window_size) == 0)
183 {
28ef6c31
JA
184 _rl_screenwidth = (int) window_size.ws_col;
185 _rl_screenheight = (int) window_size.ws_row;
ccc6cda3
JA
186 }
187#endif /* TIOCGWINSZ */
188
d166f048 189#if defined (__EMX__)
28ef6c31 190 _emx_get_screensize (&_rl_screenwidth, &_rl_screenheight);
d166f048
JA
191#endif
192
ccc6cda3
JA
193 /* Environment variable COLUMNS overrides setting of "co" if IGNORE_ENV
194 is unset. */
28ef6c31 195 if (_rl_screenwidth <= 0)
ccc6cda3 196 {
28ef6c31
JA
197 if (ignore_env == 0 && (ss = sh_get_env_value ("COLUMNS")))
198 _rl_screenwidth = atoi (ss);
ccc6cda3 199
bb70624e 200#if !defined (__DJGPP__)
28ef6c31
JA
201 if (_rl_screenwidth <= 0 && term_string_buffer)
202 _rl_screenwidth = tgetnum ("co");
bb70624e 203#endif
ccc6cda3
JA
204 }
205
206 /* Environment variable LINES overrides setting of "li" if IGNORE_ENV
207 is unset. */
28ef6c31 208 if (_rl_screenheight <= 0)
ccc6cda3 209 {
28ef6c31
JA
210 if (ignore_env == 0 && (ss = sh_get_env_value ("LINES")))
211 _rl_screenheight = atoi (ss);
ccc6cda3 212
bb70624e 213#if !defined (__DJGPP__)
28ef6c31
JA
214 if (_rl_screenheight <= 0 && term_string_buffer)
215 _rl_screenheight = tgetnum ("li");
bb70624e 216#endif
ccc6cda3
JA
217 }
218
219 /* If all else fails, default to 80x24 terminal. */
28ef6c31
JA
220 if (_rl_screenwidth <= 1)
221 _rl_screenwidth = 80;
ccc6cda3 222
28ef6c31
JA
223 if (_rl_screenheight <= 0)
224 _rl_screenheight = 24;
ccc6cda3
JA
225
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. */
28ef6c31 229 sh_set_lines_and_columns (_rl_screenheight, _rl_screenwidth);
ccc6cda3 230
bb70624e 231 if (_rl_term_autowrap == 0)
28ef6c31 232 _rl_screenwidth--;
ccc6cda3 233
28ef6c31 234 _rl_screenchars = _rl_screenwidth * _rl_screenheight;
ccc6cda3
JA
235}
236
237void
238_rl_set_screen_size (rows, cols)
239 int rows, cols;
240{
28ef6c31
JA
241 if (rows == 0 || cols == 0)
242 return;
243
244 _rl_screenheight = rows;
245 _rl_screenwidth = cols;
ccc6cda3
JA
246
247 if (_rl_term_autowrap == 0)
28ef6c31 248 _rl_screenwidth--;
ccc6cda3 249
28ef6c31
JA
250 _rl_screenchars = _rl_screenwidth * _rl_screenheight;
251}
252
253void
254rl_set_screen_size (rows, cols)
255 int rows, cols;
256{
257 _rl_set_screen_size (rows, cols);
ccc6cda3
JA
258}
259
28ef6c31
JA
260void
261rl_get_screen_size (rows, cols)
262 int *rows, *cols;
263{
264 if (rows)
265 *rows = _rl_screenheight;
266 if (cols)
267 *cols = _rl_screenwidth;
268}
269
b72432fd
JA
270void
271rl_resize_terminal ()
272{
273 if (readline_echoing_p)
274 {
275 _rl_get_screen_size (fileno (rl_instream), 1);
276 _rl_redisplay_after_sigwinch ();
277 }
278}
279
ccc6cda3 280struct _tc_string {
28ef6c31 281 const char *tc_var;
ccc6cda3
JA
282 char **tc_value;
283};
284
285/* This should be kept sorted, just in case we decide to change the
286 search algorithm to something smarter. */
287static struct _tc_string tc_strings[] =
288{
28ef6c31
JA
289 { "DC", &_rl_term_DC },
290 { "IC", &_rl_term_IC },
291 { "ce", &_rl_term_clreol },
292 { "cl", &_rl_term_clrpag },
293 { "cr", &_rl_term_cr },
294 { "dc", &_rl_term_dc },
295 { "ei", &_rl_term_ei },
296 { "ic", &_rl_term_ic },
297 { "im", &_rl_term_im },
298 { "kd", &_rl_term_kd },
299 { "kh", &_rl_term_kh }, /* home */
300 { "kH", &_rl_term_kH }, /* end */
301 { "kl", &_rl_term_kl },
302 { "kr", &_rl_term_kr },
303 { "ku", &_rl_term_ku },
304 { "ks", &_rl_term_ks },
305 { "ke", &_rl_term_ke },
306 { "le", &_rl_term_backspace },
307 { "mm", &_rl_term_mm },
308 { "mo", &_rl_term_mo },
ccc6cda3 309#if defined (HACK_TERMCAP_MOTION)
28ef6c31 310 { "nd", &_rl_term_forward_char },
ccc6cda3 311#endif
28ef6c31
JA
312 { "pc", &_rl_term_pc },
313 { "up", &_rl_term_up },
314 { "vb", &_rl_visible_bell },
ccc6cda3
JA
315};
316
317#define NUM_TC_STRINGS (sizeof (tc_strings) / sizeof (struct _tc_string))
318
319/* Read the desired terminal capability strings into BP. The capabilities
320 are described in the TC_STRINGS table. */
321static void
322get_term_capabilities (bp)
323 char **bp;
324{
bb70624e 325#if !defined (__DJGPP__) /* XXX - doesn't DJGPP have a termcap library? */
ccc6cda3
JA
326 register int i;
327
328 for (i = 0; i < NUM_TC_STRINGS; i++)
329 *(tc_strings[i].tc_value) = tgetstr (tc_strings[i].tc_var, bp);
bb70624e 330#endif
ccc6cda3
JA
331 tcap_initialized = 1;
332}
333
bb70624e
JA
334#define CUSTOM_REDISPLAY_FUNC() (rl_redisplay_function != rl_redisplay)
335#define CUSTOM_INPUT_FUNC() (rl_getc_function != rl_getc)
336
ccc6cda3
JA
337int
338_rl_init_terminal_io (terminal_name)
28ef6c31 339 const char *terminal_name;
ccc6cda3 340{
28ef6c31
JA
341 const char *term;
342 char *buffer;
bb70624e 343 int tty, tgetent_ret;
ccc6cda3
JA
344 Keymap xkeymap;
345
28ef6c31
JA
346 term = terminal_name ? terminal_name : sh_get_env_value ("TERM");
347 _rl_term_clrpag = _rl_term_cr = _rl_term_clreol = (char *)NULL;
bb70624e 348 tty = rl_instream ? fileno (rl_instream) : 0;
28ef6c31 349 _rl_screenwidth = _rl_screenheight = 0;
ccc6cda3 350
bb70624e
JA
351 if (term == 0)
352 term = "dumb";
ccc6cda3 353
bb70624e
JA
354 /* I've separated this out for later work on not calling tgetent at all
355 if the calling application has supplied a custom redisplay function,
356 (and possibly if the application has supplied a custom input function). */
357 if (CUSTOM_REDISPLAY_FUNC())
358 {
359 tgetent_ret = -1;
360 }
361 else
362 {
363 if (term_string_buffer == 0)
364 term_string_buffer = xmalloc(2032);
ccc6cda3 365
bb70624e
JA
366 if (term_buffer == 0)
367 term_buffer = xmalloc(4080);
ccc6cda3 368
bb70624e 369 buffer = term_string_buffer;
ccc6cda3 370
bb70624e
JA
371 tgetent_ret = tgetent (term_buffer, term);
372 }
ccc6cda3 373
bb70624e 374 if (tgetent_ret <= 0)
ccc6cda3 375 {
bb70624e
JA
376 FREE (term_string_buffer);
377 FREE (term_buffer);
378 buffer = term_buffer = term_string_buffer = (char *)NULL;
379
bb70624e
JA
380 _rl_term_autowrap = 0; /* used by _rl_get_screen_size */
381
382#if defined (__EMX__)
28ef6c31
JA
383 _emx_get_screensize (&_rl_screenwidth, &_rl_screenheight);
384 _rl_screenwidth--;
bb70624e
JA
385#else /* !__EMX__ */
386 _rl_get_screen_size (tty, 0);
387#endif /* !__EMX__ */
388
389 /* Defaults. */
28ef6c31 390 if (_rl_screenwidth <= 0 || _rl_screenheight <= 0)
bb70624e 391 {
28ef6c31
JA
392 _rl_screenwidth = 79;
393 _rl_screenheight = 24;
bb70624e
JA
394 }
395
396 /* Everything below here is used by the redisplay code (tputs). */
28ef6c31
JA
397 _rl_screenchars = _rl_screenwidth * _rl_screenheight;
398 _rl_term_cr = "\r";
399 _rl_term_im = _rl_term_ei = _rl_term_ic = _rl_term_IC = (char *)NULL;
400 _rl_term_up = _rl_term_dc = _rl_term_DC = _rl_visible_bell = (char *)NULL;
401 _rl_term_ku = _rl_term_kd = _rl_term_kl = _rl_term_kr = (char *)NULL;
402 _rl_term_mm = _rl_term_mo = (char *)NULL;
ccc6cda3
JA
403#if defined (HACK_TERMCAP_MOTION)
404 term_forward_char = (char *)NULL;
405#endif
28ef6c31 406 _rl_terminal_can_insert = term_has_meta = 0;
bb70624e
JA
407
408 /* Reasonable defaults for tgoto(). Readline currently only uses
28ef6c31 409 tgoto if _rl_term_IC or _rl_term_DC is defined, but just in case we
bb70624e
JA
410 change that later... */
411 PC = '\0';
28ef6c31
JA
412 BC = _rl_term_backspace = "\b";
413 UP = _rl_term_up;
bb70624e 414
ccc6cda3
JA
415 return 0;
416 }
417
418 get_term_capabilities (&buffer);
419
420 /* Set up the variables that the termcap library expects the application
421 to provide. */
28ef6c31
JA
422 PC = _rl_term_pc ? *_rl_term_pc : 0;
423 BC = _rl_term_backspace;
424 UP = _rl_term_up;
ccc6cda3 425
28ef6c31
JA
426 if (!_rl_term_cr)
427 _rl_term_cr = "\r";
ccc6cda3 428
ccc6cda3
JA
429 _rl_term_autowrap = tgetflag ("am") && tgetflag ("xn");
430
431 _rl_get_screen_size (tty, 0);
432
433 /* "An application program can assume that the terminal can do
434 character insertion if *any one of* the capabilities `IC',
435 `im', `ic' or `ip' is provided." But we can't do anything if
436 only `ip' is provided, so... */
28ef6c31 437 _rl_terminal_can_insert = (_rl_term_IC || _rl_term_im || _rl_term_ic);
ccc6cda3
JA
438
439 /* Check to see if this terminal has a meta key and clear the capability
440 variables if there is none. */
441 term_has_meta = (tgetflag ("km") || tgetflag ("MT"));
442 if (!term_has_meta)
28ef6c31 443 _rl_term_mm = _rl_term_mo = (char *)NULL;
ccc6cda3
JA
444
445 /* Attempt to find and bind the arrow keys. Do not override already
446 bound keys in an overzealous attempt, however. */
447 xkeymap = _rl_keymap;
448
449 _rl_keymap = emacs_standard_keymap;
28ef6c31
JA
450 _rl_bind_if_unbound (_rl_term_ku, rl_get_previous_history);
451 _rl_bind_if_unbound (_rl_term_kd, rl_get_next_history);
452 _rl_bind_if_unbound (_rl_term_kr, rl_forward);
453 _rl_bind_if_unbound (_rl_term_kl, rl_backward);
ccc6cda3 454
28ef6c31
JA
455 _rl_bind_if_unbound (_rl_term_kh, rl_beg_of_line); /* Home */
456 _rl_bind_if_unbound (_rl_term_kH, rl_end_of_line); /* End */
ccc6cda3
JA
457
458#if defined (VI_MODE)
459 _rl_keymap = vi_movement_keymap;
28ef6c31
JA
460 _rl_bind_if_unbound (_rl_term_ku, rl_get_previous_history);
461 _rl_bind_if_unbound (_rl_term_kd, rl_get_next_history);
462 _rl_bind_if_unbound (_rl_term_kr, rl_forward);
463 _rl_bind_if_unbound (_rl_term_kl, rl_backward);
ccc6cda3 464
28ef6c31
JA
465 _rl_bind_if_unbound (_rl_term_kh, rl_beg_of_line); /* Home */
466 _rl_bind_if_unbound (_rl_term_kH, rl_end_of_line); /* End */
ccc6cda3
JA
467#endif /* VI_MODE */
468
469 _rl_keymap = xkeymap;
470
ccc6cda3
JA
471 return 0;
472}
473
474char *
475rl_get_termcap (cap)
28ef6c31 476 const char *cap;
ccc6cda3
JA
477{
478 register int i;
479
480 if (tcap_initialized == 0)
481 return ((char *)NULL);
482 for (i = 0; i < NUM_TC_STRINGS; i++)
483 {
484 if (tc_strings[i].tc_var[0] == cap[0] && strcmp (tc_strings[i].tc_var, cap) == 0)
485 return *(tc_strings[i].tc_value);
486 }
487 return ((char *)NULL);
488}
489
d166f048
JA
490/* Re-initialize the terminal considering that the TERM/TERMCAP variable
491 has changed. */
492int
493rl_reset_terminal (terminal_name)
28ef6c31 494 const char *terminal_name;
d166f048
JA
495{
496 _rl_init_terminal_io (terminal_name);
497 return 0;
498}
499
ccc6cda3 500/* A function for the use of tputs () */
cce855bc
JA
501#ifdef _MINIX
502void
503_rl_output_character_function (c)
504 int c;
505{
506 putc (c, _rl_out_stream);
507}
508#else /* !_MINIX */
ccc6cda3
JA
509int
510_rl_output_character_function (c)
511 int c;
512{
513 return putc (c, _rl_out_stream);
514}
cce855bc 515#endif /* !_MINIX */
bb70624e 516
ccc6cda3
JA
517/* Write COUNT characters from STRING to the output stream. */
518void
519_rl_output_some_chars (string, count)
28ef6c31 520 const char *string;
ccc6cda3
JA
521 int count;
522{
523 fwrite (string, 1, count, _rl_out_stream);
524}
525
526/* Move the cursor back. */
527int
528_rl_backspace (count)
529 int count;
530{
531 register int i;
532
28ef6c31 533 if (_rl_term_backspace)
ccc6cda3 534 for (i = 0; i < count; i++)
28ef6c31 535 tputs (_rl_term_backspace, 1, _rl_output_character_function);
ccc6cda3 536 else
ccc6cda3
JA
537 for (i = 0; i < count; i++)
538 putc ('\b', _rl_out_stream);
539 return 0;
540}
541
542/* Move to the start of the next line. */
543int
28ef6c31 544rl_crlf ()
ccc6cda3
JA
545{
546#if defined (NEW_TTY_DRIVER)
28ef6c31
JA
547 if (_rl_term_cr)
548 tputs (_rl_term_cr, 1, _rl_output_character_function);
ccc6cda3
JA
549#endif /* NEW_TTY_DRIVER */
550 putc ('\n', _rl_out_stream);
551 return 0;
552}
553
554/* Ring the terminal bell. */
555int
28ef6c31 556rl_ding ()
ccc6cda3
JA
557{
558 if (readline_echoing_p)
559 {
ccc6cda3
JA
560 switch (_rl_bell_preference)
561 {
562 case NO_BELL:
563 default:
564 break;
565 case VISIBLE_BELL:
28ef6c31 566 if (_rl_visible_bell)
ccc6cda3 567 {
28ef6c31 568 tputs (_rl_visible_bell, 1, _rl_output_character_function);
ccc6cda3
JA
569 break;
570 }
571 /* FALLTHROUGH */
572 case AUDIBLE_BELL:
573 fprintf (stderr, "\007");
574 fflush (stderr);
575 break;
576 }
ccc6cda3
JA
577 return (0);
578 }
579 return (-1);
580}
581
582/* **************************************************************** */
583/* */
584/* Controlling the Meta Key and Keypad */
585/* */
586/* **************************************************************** */
587
d166f048 588void
ccc6cda3
JA
589_rl_enable_meta_key ()
590{
bb70624e 591#if !defined (__DJGPP__)
28ef6c31
JA
592 if (term_has_meta && _rl_term_mm)
593 tputs (_rl_term_mm, 1, _rl_output_character_function);
bb70624e 594#endif
ccc6cda3
JA
595}
596
597void
598_rl_control_keypad (on)
599 int on;
600{
bb70624e 601#if !defined (__DJGPP__)
28ef6c31
JA
602 if (on && _rl_term_ks)
603 tputs (_rl_term_ks, 1, _rl_output_character_function);
604 else if (!on && _rl_term_ke)
605 tputs (_rl_term_ke, 1, _rl_output_character_function);
bb70624e 606#endif
ccc6cda3 607}