OSDN Git Service

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