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