import gdb-19990422 snapshot
[deliverable/binutils-gdb.git] / readline / terminal.c
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 */
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;
72
73 /* Functions imported from bind.c */
74 extern void _rl_bind_if_unbound ();
75
76 /* Functions imported from shell.c */
77 extern void set_lines_and_columns ();
78 extern char *get_env_value ();
79
80 /* **************************************************************** */
81 /* */
82 /* Terminal and Termcap */
83 /* */
84 /* **************************************************************** */
85
86 static char *term_buffer = (char *)NULL;
87 static char *term_string_buffer = (char *)NULL;
88
89 static int tcap_initialized;
90
91 /* Non-zero means this terminal can't really do anything. */
92 static int dumb_term;
93
94 #if !defined (__linux__)
95 # if defined (__EMX__) || defined (NEED_EXTERN_PC)
96 extern
97 # endif /* __EMX__ || NEED_EXTERN_PC */
98 char PC, *BC, *UP;
99 #endif /* __linux__ */
100
101 /* Some strings to control terminal actions. These are output by tputs (). */
102 char *term_goto, *term_clreol, *term_cr, *term_clrpag, *term_backspace;
103 char *term_pc;
104
105 /* Non-zero if we determine that the terminal can do character insertion. */
106 int terminal_can_insert = 0;
107
108 /* How to insert characters. */
109 char *term_im, *term_ei, *term_ic, *term_ip, *term_IC;
110
111 /* How to delete characters. */
112 char *term_dc, *term_DC;
113
114 #if defined (HACK_TERMCAP_MOTION)
115 char *term_forward_char;
116 #endif /* HACK_TERMCAP_MOTION */
117
118 /* How to go up a line. */
119 char *term_up;
120
121 /* A visible bell, if the terminal can be made to flash the screen. */
122 static char *visible_bell;
123
124 /* Non-zero means the terminal can auto-wrap lines. */
125 int _rl_term_autowrap;
126
127 /* Non-zero means that this terminal has a meta key. */
128 static int term_has_meta;
129
130 /* The sequences to write to turn on and off the meta key, if this
131 terminal has one. */
132 static char *term_mm, *term_mo;
133
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;
136
137 /* How to initialize and reset the arrow keys, if this terminal has any. */
138 static char *term_ks, *term_ke;
139
140 /* The key sequences sent by the Home and End keys, if any. */
141 static char *term_kh, *term_kH;
142
143 /* Variables that hold the screen dimensions, used by the display code. */
144 int screenwidth, screenheight, screenchars;
145
146 /* Non-zero means the user wants to enable the keypad. */
147 int _rl_enable_keypad;
148
149 /* Non-zero means the user wants to enable a meta key. */
150 int _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. */
156 void
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
189 #if !defined(__DJGPP__)
190 if (screenwidth <= 0 && term_string_buffer)
191 screenwidth = tgetnum ("co");
192 #endif
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
202 #if !defined(__DJGPP__)
203 if (screenheight <= 0 && term_string_buffer)
204 screenheight = tgetnum ("li");
205 #endif
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
226 void
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
239 struct _tc_string {
240 char *tc_var;
241 char **tc_value;
242 };
243
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[] =
247 {
248 "DC", &term_DC,
249 "IC", &term_IC,
250 "ce", &term_clreol,
251 "cl", &term_clrpag,
252 "cr", &term_cr,
253 "dc", &term_dc,
254 "ei", &term_ei,
255 "ic", &term_ic,
256 "im", &term_im,
257 "kd", &term_kd,
258 "kh", &term_kh, /* home */
259 "kH", &term_kH, /* end */
260 "kl", &term_kl,
261 "kr", &term_kr,
262 "ku", &term_ku,
263 "ks", &term_ks,
264 "ke", &term_ke,
265 "le", &term_backspace,
266 "mm", &term_mm,
267 "mo", &term_mo,
268 #if defined (HACK_TERMCAP_MOTION)
269 "nd", &term_forward_char,
270 #endif
271 "pc", &term_pc,
272 "up", &term_up,
273 "vb", &visible_bell,
274 };
275
276 #define NUM_TC_STRINGS (sizeof (tc_strings) / sizeof (struct _tc_string))
277
278 /* Read the desired terminal capability strings into BP. The capabilities
279 are described in the TC_STRINGS table. */
280 static void
281 get_term_capabilities (bp)
282 char **bp;
283 {
284 #if !defined(__DJGPP__)
285 register int i;
286
287 for (i = 0; i < NUM_TC_STRINGS; i++)
288 *(tc_strings[i].tc_value) = tgetstr (tc_strings[i].tc_var, bp);
289 #endif
290 tcap_initialized = 1;
291 }
292
293 int
294 _rl_init_terminal_io (terminal_name)
295 char *terminal_name;
296 {
297 #if defined (__GO32__)
298 screenwidth = ScreenCols ();
299 screenheight = ScreenRows ();
300 screenchars = screenwidth * screenheight;
301 term_cr = "\r";
302 term_im = term_ei = term_ic = term_IC = (char *)NULL;
303 term_up = term_dc = term_DC = visible_bell = (char *)NULL;
304
305 /* Does the __GO32__ have a meta key? I don't know. */
306 term_has_meta = 0;
307 term_mm = term_mo = (char *)NULL;
308
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;
311
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;
316 return;
317 #else /* !__GO32__ */
318
319 char *term, *buffer;
320 int tty;
321 Keymap xkeymap;
322
323 term = terminal_name ? terminal_name : get_env_value ("TERM");
324
325 if (term_string_buffer == 0)
326 term_string_buffer = xmalloc (2032);
327
328 if (term_buffer == 0)
329 term_buffer = xmalloc (4080);
330
331 buffer = term_string_buffer;
332
333 term_clrpag = term_cr = term_clreol = (char *)NULL;
334
335 if (term == 0)
336 term = "dumb";
337
338 if (tgetent (term_buffer, term) <= 0)
339 {
340 dumb_term = 1;
341 screenwidth = 79;
342 screenheight = 24;
343 screenchars = 79 * 24;
344 term_cr = "\r";
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;
350 #endif
351 terminal_can_insert = 0;
352 return 0;
353 }
354
355 get_term_capabilities (&buffer);
356
357 /* Set up the variables that the termcap library expects the application
358 to provide. */
359 PC = term_pc ? *term_pc : 0;
360 BC = term_backspace;
361 UP = term_up;
362
363 if (!term_cr)
364 term_cr = "\r";
365
366 tty = rl_instream ? fileno (rl_instream) : 0;
367
368 screenwidth = screenheight = 0;
369
370 _rl_term_autowrap = tgetflag ("am") && tgetflag ("xn");
371
372 _rl_get_screen_size (tty, 0);
373
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);
379
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"));
383 if (!term_has_meta)
384 term_mm = term_mo = (char *)NULL;
385
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;
389
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);
395
396 _rl_bind_if_unbound (term_kh, rl_beg_of_line); /* Home */
397 _rl_bind_if_unbound (term_kH, rl_end_of_line); /* End */
398
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);
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 #endif /* VI_MODE */
409
410 _rl_keymap = xkeymap;
411
412 #endif /* !__GO32__ */
413 return 0;
414 }
415
416 char *
417 rl_get_termcap (cap)
418 char *cap;
419 {
420 register int i;
421
422 if (tcap_initialized == 0)
423 return ((char *)NULL);
424 for (i = 0; i < NUM_TC_STRINGS; i++)
425 {
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);
428 }
429 return ((char *)NULL);
430 }
431
432 /* Re-initialize the terminal considering that the TERM/TERMCAP variable
433 has changed. */
434 int
435 rl_reset_terminal (terminal_name)
436 char *terminal_name;
437 {
438 _rl_init_terminal_io (terminal_name);
439 return 0;
440 }
441
442 /* A function for the use of tputs () */
443 #ifdef _MINIX
444 void
445 _rl_output_character_function (c)
446 int c;
447 {
448 putc (c, _rl_out_stream);
449 }
450 #else /* !_MINIX */
451 int
452 _rl_output_character_function (c)
453 int c;
454 {
455 return putc (c, _rl_out_stream);
456 }
457 #endif /* !_MINIX */
458 /* Write COUNT characters from STRING to the output stream. */
459 void
460 _rl_output_some_chars (string, count)
461 char *string;
462 int count;
463 {
464 fwrite (string, 1, count, _rl_out_stream);
465 }
466
467 /* Move the cursor back. */
468 int
469 _rl_backspace (count)
470 int count;
471 {
472 register int i;
473
474 #if !defined (__GO32__)
475 if (term_backspace)
476 for (i = 0; i < count; i++)
477 tputs (term_backspace, 1, _rl_output_character_function);
478 else
479 #endif /* !__GO32__ */
480 for (i = 0; i < count; i++)
481 putc ('\b', _rl_out_stream);
482 return 0;
483 }
484
485 /* Move to the start of the next line. */
486 int
487 crlf ()
488 {
489 #if defined (NEW_TTY_DRIVER)
490 if (term_cr)
491 tputs (term_cr, 1, _rl_output_character_function);
492 #endif /* NEW_TTY_DRIVER */
493 putc ('\n', _rl_out_stream);
494 return 0;
495 }
496
497 /* Ring the terminal bell. */
498 int
499 ding ()
500 {
501 if (readline_echoing_p)
502 {
503 #if !defined (__GO32__)
504 switch (_rl_bell_preference)
505 {
506 case NO_BELL:
507 default:
508 break;
509 case VISIBLE_BELL:
510 if (visible_bell)
511 {
512 tputs (visible_bell, 1, _rl_output_character_function);
513 break;
514 }
515 /* FALLTHROUGH */
516 case AUDIBLE_BELL:
517 fprintf (stderr, "\007");
518 fflush (stderr);
519 break;
520 }
521 #else /* __GO32__ */
522 fprintf (stderr, "\007");
523 fflush (stderr);
524 #endif /* __GO32__ */
525 return (0);
526 }
527 return (-1);
528 }
529
530 /* **************************************************************** */
531 /* */
532 /* Controlling the Meta Key and Keypad */
533 /* */
534 /* **************************************************************** */
535
536 void
537 _rl_enable_meta_key ()
538 {
539 #if !defined(__DJGPP__)
540 if (term_has_meta && term_mm)
541 tputs (term_mm, 1, _rl_output_character_function);
542 #endif
543 }
544
545 void
546 _rl_control_keypad (on)
547 int on;
548 {
549 #if !defined(__DJGPP__)
550 if (on && term_ks)
551 tputs (term_ks, 1, _rl_output_character_function);
552 else if (!on && term_ke)
553 tputs (term_ke, 1, _rl_output_character_function);
554 #endif
555 }
This page took 0.042757 seconds and 5 git commands to generate.