[__GO32__]: Include <pc.h>.
[external/binutils.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 }