1999-08-09 Jason Molenda (jsm@bugshack.cygnus.com)
[deliverable/binutils-gdb.git] / readline / terminal.c
CommitLineData
d60d9f65
SS
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
10 as published by the Free Software Foundation; either version 1, or
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,
21 675 Mass Ave, Cambridge, MA 02139, USA. */
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
49#include <signal.h>
50#include <stdio.h>
51#include <setjmp.h>
52
53/* System-specific feature definitions and include files. */
54#include "rldefs.h"
55
56#if defined (GWINSZ_IN_SYS_IOCTL) && !defined (TIOCGWINSZ)
57# include <sys/ioctl.h>
58#endif /* GWINSZ_IN_SYS_IOCTL && !TIOCGWINSZ */
59
60#include "rltty.h"
61#include "tcap.h"
62
63/* Some standard library routines. */
64#include "readline.h"
65#include "history.h"
66
67/* Variables and functions imported from readline.c */
68extern FILE *_rl_in_stream, *_rl_out_stream;
69extern int readline_echoing_p;
70extern int _rl_bell_preference;
71extern Keymap _rl_keymap;
72
73/* Functions imported from bind.c */
74extern void _rl_bind_if_unbound ();
75
76/* Functions imported from shell.c */
77extern void set_lines_and_columns ();
78extern char *get_env_value ();
79
80/* **************************************************************** */
81/* */
82/* Terminal and Termcap */
83/* */
84/* **************************************************************** */
85
86static char *term_buffer = (char *)NULL;
87static char *term_string_buffer = (char *)NULL;
88
89static int tcap_initialized;
90
91/* Non-zero means this terminal can't really do anything. */
92static int dumb_term;
93
94#if !defined (__linux__)
95# if defined (__EMX__) || defined (NEED_EXTERN_PC)
96extern
97# endif /* __EMX__ || NEED_EXTERN_PC */
98char PC, *BC, *UP;
99#endif /* __linux__ */
100
101/* Some strings to control terminal actions. These are output by tputs (). */
102char *term_goto, *term_clreol, *term_cr, *term_clrpag, *term_backspace;
103char *term_pc;
104
105/* Non-zero if we determine that the terminal can do character insertion. */
106int terminal_can_insert = 0;
107
108/* How to insert characters. */
109char *term_im, *term_ei, *term_ic, *term_ip, *term_IC;
110
111/* How to delete characters. */
112char *term_dc, *term_DC;
113
114#if defined (HACK_TERMCAP_MOTION)
115char *term_forward_char;
116#endif /* HACK_TERMCAP_MOTION */
117
118/* How to go up a line. */
119char *term_up;
120
121/* A visible bell, if the terminal can be made to flash the screen. */
122static char *visible_bell;
123
124/* Non-zero means the terminal can auto-wrap lines. */
125int _rl_term_autowrap;
126
127/* Non-zero means that this terminal has a meta key. */
128static int term_has_meta;
129
130/* The sequences to write to turn on and off the meta key, if this
131 terminal has one. */
132static char *term_mm, *term_mo;
133
134/* The key sequences output by the arrow keys, if this terminal has any. */
135static char *term_ku, *term_kd, *term_kr, *term_kl;
136
137/* How to initialize and reset the arrow keys, if this terminal has any. */
138static char *term_ks, *term_ke;
139
140/* The key sequences sent by the Home and End keys, if any. */
141static char *term_kh, *term_kH;
142
143/* Variables that hold the screen dimensions, used by the display code. */
144int screenwidth, screenheight, screenchars;
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
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. */
156void
157_rl_get_screen_size (tty, ignore_env)
158 int tty, ignore_env;
159{
160 char *ss;
161#if defined (TIOCGWINSZ)
162 struct winsize window_size;
163#endif /* TIOCGWINSZ */
164#if defined (__EMX__)
165 int sz[2];
166#endif
167
168#if defined (TIOCGWINSZ)
169 if (ioctl (tty, TIOCGWINSZ, &window_size) == 0)
170 {
171 screenwidth = (int) window_size.ws_col;
172 screenheight = (int) window_size.ws_row;
173 }
174#endif /* TIOCGWINSZ */
175
176#if defined (__EMX__)
177 _scrsize (sz);
178 screenwidth = sz[0];
179 screenheight = sz[1];
180#endif
181
182 /* Environment variable COLUMNS overrides setting of "co" if IGNORE_ENV
183 is unset. */
184 if (screenwidth <= 0)
185 {
186 if (ignore_env == 0 && (ss = get_env_value ("COLUMNS")))
187 screenwidth = atoi (ss);
188
771578d1 189#if !defined(__DJGPP__)
d60d9f65
SS
190 if (screenwidth <= 0 && term_string_buffer)
191 screenwidth = tgetnum ("co");
771578d1 192#endif
d60d9f65
SS
193 }
194
195 /* Environment variable LINES overrides setting of "li" if IGNORE_ENV
196 is unset. */
197 if (screenheight <= 0)
198 {
199 if (ignore_env == 0 && (ss = get_env_value ("LINES")))
200 screenheight = atoi (ss);
201
771578d1 202#if !defined(__DJGPP__)
d60d9f65
SS
203 if (screenheight <= 0 && term_string_buffer)
204 screenheight = tgetnum ("li");
771578d1 205#endif
d60d9f65
SS
206 }
207
208 /* If all else fails, default to 80x24 terminal. */
209 if (screenwidth <= 1)
210 screenwidth = 80;
211
212 if (screenheight <= 0)
213 screenheight = 24;
214
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);
219
220 if (!_rl_term_autowrap)
221 screenwidth--;
222
223 screenchars = screenwidth * screenheight;
224}
225
226void
227_rl_set_screen_size (rows, cols)
228 int rows, cols;
229{
230 screenheight = rows;
231 screenwidth = cols;
232
233 if (_rl_term_autowrap == 0)
234 screenwidth--;
235
236 screenchars = screenwidth * screenheight;
237}
238
c862e87b
JM
239void
240rl_resize_terminal ()
241{
242 if (readline_echoing_p)
243 {
244 _rl_get_screen_size (fileno (rl_instream), 1);
245 _rl_redisplay_after_sigwinch ();
246 }
247}
248
d60d9f65
SS
249struct _tc_string {
250 char *tc_var;
251 char **tc_value;
252};
253
254/* This should be kept sorted, just in case we decide to change the
255 search algorithm to something smarter. */
256static struct _tc_string tc_strings[] =
257{
258 "DC", &term_DC,
259 "IC", &term_IC,
260 "ce", &term_clreol,
261 "cl", &term_clrpag,
262 "cr", &term_cr,
263 "dc", &term_dc,
264 "ei", &term_ei,
265 "ic", &term_ic,
266 "im", &term_im,
267 "kd", &term_kd,
268 "kh", &term_kh, /* home */
269 "kH", &term_kH, /* end */
270 "kl", &term_kl,
271 "kr", &term_kr,
272 "ku", &term_ku,
273 "ks", &term_ks,
274 "ke", &term_ke,
275 "le", &term_backspace,
276 "mm", &term_mm,
277 "mo", &term_mo,
278#if defined (HACK_TERMCAP_MOTION)
279 "nd", &term_forward_char,
280#endif
281 "pc", &term_pc,
282 "up", &term_up,
283 "vb", &visible_bell,
284};
285
286#define NUM_TC_STRINGS (sizeof (tc_strings) / sizeof (struct _tc_string))
287
288/* Read the desired terminal capability strings into BP. The capabilities
289 are described in the TC_STRINGS table. */
290static void
291get_term_capabilities (bp)
292 char **bp;
293{
771578d1 294#if !defined(__DJGPP__)
d60d9f65
SS
295 register int i;
296
297 for (i = 0; i < NUM_TC_STRINGS; i++)
298 *(tc_strings[i].tc_value) = tgetstr (tc_strings[i].tc_var, bp);
771578d1 299#endif
d60d9f65
SS
300 tcap_initialized = 1;
301}
302
303int
304_rl_init_terminal_io (terminal_name)
305 char *terminal_name;
306{
307#if defined (__GO32__)
308 screenwidth = ScreenCols ();
309 screenheight = ScreenRows ();
310 screenchars = screenwidth * screenheight;
311 term_cr = "\r";
312 term_im = term_ei = term_ic = term_IC = (char *)NULL;
313 term_up = term_dc = term_DC = visible_bell = (char *)NULL;
314
315 /* Does the __GO32__ have a meta key? I don't know. */
316 term_has_meta = 0;
317 term_mm = term_mo = (char *)NULL;
318
319 /* It probably has arrow keys, but I don't know what they are. */
320 term_ku = term_kd = term_kr = term_kl = (char *)NULL;
321
322#if defined (HACK_TERMCAP_MOTION)
323 term_forward_char = (char *)NULL;
324#endif /* HACK_TERMCAP_MOTION */
325 terminal_can_insert = _rl_term_autowrap = 0;
326 return;
327#else /* !__GO32__ */
328
329 char *term, *buffer;
330 int tty;
331 Keymap xkeymap;
332
333 term = terminal_name ? terminal_name : get_env_value ("TERM");
334
335 if (term_string_buffer == 0)
336 term_string_buffer = xmalloc (2032);
337
338 if (term_buffer == 0)
339 term_buffer = xmalloc (4080);
340
341 buffer = term_string_buffer;
342
343 term_clrpag = term_cr = term_clreol = (char *)NULL;
344
345 if (term == 0)
346 term = "dumb";
347
348 if (tgetent (term_buffer, term) <= 0)
349 {
350 dumb_term = 1;
351 screenwidth = 79;
352 screenheight = 24;
353 screenchars = 79 * 24;
354 term_cr = "\r";
355 term_im = term_ei = term_ic = term_IC = (char *)NULL;
356 term_up = term_dc = term_DC = visible_bell = (char *)NULL;
357 term_ku = term_kd = term_kl = term_kr = (char *)NULL;
358#if defined (HACK_TERMCAP_MOTION)
359 term_forward_char = (char *)NULL;
360#endif
361 terminal_can_insert = 0;
362 return 0;
363 }
364
365 get_term_capabilities (&buffer);
366
367 /* Set up the variables that the termcap library expects the application
368 to provide. */
369 PC = term_pc ? *term_pc : 0;
370 BC = term_backspace;
371 UP = term_up;
372
373 if (!term_cr)
374 term_cr = "\r";
375
376 tty = rl_instream ? fileno (rl_instream) : 0;
377
378 screenwidth = screenheight = 0;
379
380 _rl_term_autowrap = tgetflag ("am") && tgetflag ("xn");
381
382 _rl_get_screen_size (tty, 0);
383
384 /* "An application program can assume that the terminal can do
385 character insertion if *any one of* the capabilities `IC',
386 `im', `ic' or `ip' is provided." But we can't do anything if
387 only `ip' is provided, so... */
388 terminal_can_insert = (term_IC || term_im || term_ic);
389
390 /* Check to see if this terminal has a meta key and clear the capability
391 variables if there is none. */
392 term_has_meta = (tgetflag ("km") || tgetflag ("MT"));
393 if (!term_has_meta)
394 term_mm = term_mo = (char *)NULL;
395
396 /* Attempt to find and bind the arrow keys. Do not override already
397 bound keys in an overzealous attempt, however. */
398 xkeymap = _rl_keymap;
399
400 _rl_keymap = emacs_standard_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);
405
406 _rl_bind_if_unbound (term_kh, rl_beg_of_line); /* Home */
407 _rl_bind_if_unbound (term_kH, rl_end_of_line); /* End */
408
409#if defined (VI_MODE)
410 _rl_keymap = vi_movement_keymap;
411 _rl_bind_if_unbound (term_ku, rl_get_previous_history);
412 _rl_bind_if_unbound (term_kd, rl_get_next_history);
413 _rl_bind_if_unbound (term_kr, rl_forward);
414 _rl_bind_if_unbound (term_kl, rl_backward);
415
416 _rl_bind_if_unbound (term_kh, rl_beg_of_line); /* Home */
417 _rl_bind_if_unbound (term_kH, rl_end_of_line); /* End */
418#endif /* VI_MODE */
419
420 _rl_keymap = xkeymap;
421
422#endif /* !__GO32__ */
423 return 0;
424}
425
426char *
427rl_get_termcap (cap)
428 char *cap;
429{
430 register int i;
431
432 if (tcap_initialized == 0)
433 return ((char *)NULL);
434 for (i = 0; i < NUM_TC_STRINGS; i++)
435 {
436 if (tc_strings[i].tc_var[0] == cap[0] && strcmp (tc_strings[i].tc_var, cap) == 0)
437 return *(tc_strings[i].tc_value);
438 }
439 return ((char *)NULL);
440}
441
442/* Re-initialize the terminal considering that the TERM/TERMCAP variable
443 has changed. */
444int
445rl_reset_terminal (terminal_name)
446 char *terminal_name;
447{
448 _rl_init_terminal_io (terminal_name);
449 return 0;
450}
451
452/* A function for the use of tputs () */
453#ifdef _MINIX
454void
455_rl_output_character_function (c)
456 int c;
457{
458 putc (c, _rl_out_stream);
459}
460#else /* !_MINIX */
461int
462_rl_output_character_function (c)
463 int c;
464{
465 return putc (c, _rl_out_stream);
466}
467#endif /* !_MINIX */
468/* Write COUNT characters from STRING to the output stream. */
469void
470_rl_output_some_chars (string, count)
471 char *string;
472 int count;
473{
474 fwrite (string, 1, count, _rl_out_stream);
475}
476
477/* Move the cursor back. */
478int
479_rl_backspace (count)
480 int count;
481{
482 register int i;
483
484#if !defined (__GO32__)
485 if (term_backspace)
486 for (i = 0; i < count; i++)
487 tputs (term_backspace, 1, _rl_output_character_function);
488 else
489#endif /* !__GO32__ */
490 for (i = 0; i < count; i++)
491 putc ('\b', _rl_out_stream);
492 return 0;
493}
494
495/* Move to the start of the next line. */
496int
497crlf ()
498{
499#if defined (NEW_TTY_DRIVER)
500 if (term_cr)
501 tputs (term_cr, 1, _rl_output_character_function);
502#endif /* NEW_TTY_DRIVER */
503 putc ('\n', _rl_out_stream);
504 return 0;
505}
506
507/* Ring the terminal bell. */
508int
509ding ()
510{
511 if (readline_echoing_p)
512 {
513#if !defined (__GO32__)
514 switch (_rl_bell_preference)
515 {
516 case NO_BELL:
517 default:
518 break;
519 case VISIBLE_BELL:
520 if (visible_bell)
521 {
522 tputs (visible_bell, 1, _rl_output_character_function);
523 break;
524 }
525 /* FALLTHROUGH */
526 case AUDIBLE_BELL:
527 fprintf (stderr, "\007");
528 fflush (stderr);
529 break;
530 }
531#else /* __GO32__ */
532 fprintf (stderr, "\007");
533 fflush (stderr);
534#endif /* __GO32__ */
535 return (0);
536 }
537 return (-1);
538}
539
540/* **************************************************************** */
541/* */
542/* Controlling the Meta Key and Keypad */
543/* */
544/* **************************************************************** */
545
546void
547_rl_enable_meta_key ()
548{
771578d1 549#if !defined(__DJGPP__)
d60d9f65
SS
550 if (term_has_meta && term_mm)
551 tputs (term_mm, 1, _rl_output_character_function);
771578d1 552#endif
d60d9f65
SS
553}
554
555void
556_rl_control_keypad (on)
557 int on;
558{
771578d1 559#if !defined(__DJGPP__)
d60d9f65
SS
560 if (on && term_ks)
561 tputs (term_ks, 1, _rl_output_character_function);
562 else if (!on && term_ke)
563 tputs (term_ke, 1, _rl_output_character_function);
771578d1 564#endif
d60d9f65 565}
This page took 0.050461 seconds and 4 git commands to generate.