1 /* terminal.c -- controlling the terminal with termcap. */
3 /* Copyright (C) 1996 Free Software Foundation, Inc.
5 This file is part of the GNU Readline Library, a library for
6 reading lines of text with interactive input and history editing.
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.
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.
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
24 #if defined (HAVE_CONFIG_H)
28 #include <sys/types.h>
29 #include "posixstat.h"
31 #if defined (HAVE_SYS_FILE_H)
32 # include <sys/file.h>
33 #endif /* HAVE_SYS_FILE_H */
35 #if defined (HAVE_UNISTD_H)
37 #endif /* HAVE_UNISTD_H */
39 #if defined (HAVE_STDLIB_H)
42 # include "ansi_stdlib.h"
43 #endif /* HAVE_STDLIB_H */
45 #if defined (HAVE_LOCALE_H)
51 /* System-specific feature definitions and include files. */
54 #if defined (GWINSZ_IN_SYS_IOCTL) && !defined (TIOCGWINSZ)
55 # include <sys/ioctl.h>
56 #endif /* GWINSZ_IN_SYS_IOCTL && !TIOCGWINSZ */
65 /* Some standard library routines. */
69 #include "rlprivate.h"
73 #if defined (__MINGW32__)
78 #define CUSTOM_REDISPLAY_FUNC() (rl_redisplay_function != rl_redisplay)
79 #define CUSTOM_INPUT_FUNC() (rl_getc_function != rl_getc)
81 /* **************************************************************** */
83 /* Terminal and Termcap */
85 /* **************************************************************** */
88 static char *term_buffer
= (char *)NULL
;
89 static char *term_string_buffer
= (char *)NULL
;
91 /* Non-zero means this terminal can't really do anything. */
93 #endif /* !__MSDOS__ */
95 static int tcap_initialized
;
97 #if !defined (__linux__)
98 # if defined (__EMX__) || defined (NEED_EXTERN_PC)
100 # endif /* __EMX__ || NEED_EXTERN_PC */
102 #endif /* __linux__ */
104 /* Some strings to control terminal actions. These are output by tputs (). */
105 char *_rl_term_clreol
;
106 char *_rl_term_clrpag
;
108 char *_rl_term_backspace
;
112 /* Non-zero if we determine that the terminal can do character insertion. */
113 int _rl_terminal_can_insert
= 0;
115 /* How to insert characters. */
122 /* How to delete characters. */
126 #if defined (HACK_TERMCAP_MOTION)
127 char *_rl_term_forward_char
;
128 #endif /* HACK_TERMCAP_MOTION */
130 /* How to go up a line. */
133 /* A visible bell; char if the terminal can be made to flash the screen. */
134 static char *_rl_visible_bell
;
136 /* Non-zero means the terminal can auto-wrap lines. */
137 int _rl_term_autowrap
;
139 /* Non-zero means that this terminal has a meta key. */
140 static int term_has_meta
;
142 /* The sequences to write to turn on and off the meta key, if this
144 static char *_rl_term_mm
;
145 static char *_rl_term_mo
;
147 /* The key sequences output by the arrow keys, if this terminal has any. */
148 static char *_rl_term_ku
;
149 static char *_rl_term_kd
;
150 static char *_rl_term_kr
;
151 static char *_rl_term_kl
;
153 /* How to initialize and reset the arrow keys, if this terminal has any. */
154 static char *_rl_term_ks
;
155 static char *_rl_term_ke
;
157 /* The key sequences sent by the Home and End keys, if any. */
158 static char *_rl_term_kh
;
159 static char *_rl_term_kH
;
160 static char *_rl_term_at7
; /* @7 */
163 static char *_rl_term_kI
;
166 static char *_rl_term_vs
; /* very visible */
167 static char *_rl_term_ve
; /* normal */
169 static void bind_termcap_arrow_keys
PARAMS((Keymap
));
171 /* Variables that hold the screen dimensions, used by the display code. */
172 int _rl_screenwidth
, _rl_screenheight
, _rl_screenchars
;
174 /* Non-zero means the user wants to enable the keypad. */
175 int _rl_enable_keypad
;
177 /* Non-zero means the user wants to enable a meta key. */
178 int _rl_enable_meta
= 1;
180 #if defined (__EMX__)
182 _emx_get_screensize (swp
, shp
)
196 /* Get readline's idea of the screen size. TTY is a file descriptor open
197 to the terminal. If IGNORE_ENV is true, we do not pay attention to the
198 values of $LINES and $COLUMNS. The tests for TERM_STRING_BUFFER being
199 non-null serve to check whether or not we have initialized termcap. */
201 _rl_get_screen_size (tty
, ignore_env
)
205 #if defined (TIOCGWINSZ)
206 struct winsize window_size
;
207 #endif /* TIOCGWINSZ */
209 #if defined (TIOCGWINSZ)
210 if (ioctl (tty
, TIOCGWINSZ
, &window_size
) == 0)
212 _rl_screenwidth
= (int) window_size
.ws_col
;
213 _rl_screenheight
= (int) window_size
.ws_row
;
215 #endif /* TIOCGWINSZ */
217 /* For MinGW, we get the console size from the Windows API. */
218 #if defined (__MINGW32__)
219 HANDLE hConOut
= GetStdHandle (STD_OUTPUT_HANDLE
);
220 if (hConOut
!= INVALID_HANDLE_VALUE
)
222 CONSOLE_SCREEN_BUFFER_INFO scr
;
223 if (GetConsoleScreenBufferInfo (hConOut
, &scr
))
225 _rl_screenwidth
= scr
.dwSize
.X
;
226 _rl_screenheight
= scr
.srWindow
.Bottom
- scr
.srWindow
.Top
+ 1;
231 #if defined (__EMX__)
232 _emx_get_screensize (&_rl_screenwidth
, &_rl_screenheight
);
235 /* Environment variable COLUMNS overrides setting of "co" if IGNORE_ENV
237 if (_rl_screenwidth
<= 0)
239 if (ignore_env
== 0 && (ss
= sh_get_env_value ("COLUMNS")))
240 _rl_screenwidth
= atoi (ss
);
242 #if defined (__DJGPP__)
243 if (_rl_screenwidth
<= 0)
244 _rl_screenwidth
= ScreenCols ();
246 if (_rl_screenwidth
<= 0 && term_string_buffer
)
247 _rl_screenwidth
= tgetnum ("co");
251 /* Environment variable LINES overrides setting of "li" if IGNORE_ENV
253 if (_rl_screenheight
<= 0)
255 if (ignore_env
== 0 && (ss
= sh_get_env_value ("LINES")))
256 _rl_screenheight
= atoi (ss
);
258 #if defined (__DJGPP__)
259 if (_rl_screenheight
<= 0)
260 _rl_screenheight
= ScreenRows ();
262 if (_rl_screenheight
<= 0 && term_string_buffer
)
263 _rl_screenheight
= tgetnum ("li");
267 /* If all else fails, default to 80x24 terminal. */
268 if (_rl_screenwidth
<= 1)
269 _rl_screenwidth
= 80;
271 if (_rl_screenheight
<= 0)
272 _rl_screenheight
= 24;
274 /* If we're being compiled as part of bash, set the environment
275 variables $LINES and $COLUMNS to new values. Otherwise, just
276 do a pair of putenv () or setenv () calls. */
277 sh_set_lines_and_columns (_rl_screenheight
, _rl_screenwidth
);
279 if (_rl_term_autowrap
== 0)
282 _rl_screenchars
= _rl_screenwidth
* _rl_screenheight
;
286 _rl_set_screen_size (rows
, cols
)
289 if (rows
== 0 || cols
== 0)
292 _rl_screenheight
= rows
;
293 _rl_screenwidth
= cols
;
295 if (_rl_term_autowrap
== 0)
298 _rl_screenchars
= _rl_screenwidth
* _rl_screenheight
;
302 rl_set_screen_size (rows
, cols
)
305 _rl_set_screen_size (rows
, cols
);
309 rl_get_screen_size (rows
, cols
)
313 *rows
= _rl_screenheight
;
315 *cols
= _rl_screenwidth
;
319 rl_resize_terminal ()
321 if (readline_echoing_p
)
323 _rl_get_screen_size (fileno (rl_instream
), 1);
324 if (CUSTOM_REDISPLAY_FUNC ())
325 rl_forced_update_display ();
327 _rl_redisplay_after_sigwinch ();
336 /* This should be kept sorted, just in case we decide to change the
337 search algorithm to something smarter. */
338 static struct _tc_string tc_strings
[] =
340 { "@7", &_rl_term_at7
},
341 { "DC", &_rl_term_DC
},
342 { "IC", &_rl_term_IC
},
343 { "ce", &_rl_term_clreol
},
344 { "cl", &_rl_term_clrpag
},
345 { "cr", &_rl_term_cr
},
346 { "dc", &_rl_term_dc
},
347 { "ei", &_rl_term_ei
},
348 { "ic", &_rl_term_ic
},
349 { "im", &_rl_term_im
},
350 { "kH", &_rl_term_kH
}, /* home down ?? */
351 { "kI", &_rl_term_kI
}, /* insert */
352 { "kd", &_rl_term_kd
},
353 { "ke", &_rl_term_ke
}, /* end keypad mode */
354 { "kh", &_rl_term_kh
}, /* home */
355 { "kl", &_rl_term_kl
},
356 { "kr", &_rl_term_kr
},
357 { "ks", &_rl_term_ks
}, /* start keypad mode */
358 { "ku", &_rl_term_ku
},
359 { "le", &_rl_term_backspace
},
360 { "mm", &_rl_term_mm
},
361 { "mo", &_rl_term_mo
},
362 #if defined (HACK_TERMCAP_MOTION)
363 { "nd", &_rl_term_forward_char
},
365 { "pc", &_rl_term_pc
},
366 { "up", &_rl_term_up
},
367 { "vb", &_rl_visible_bell
},
368 { "vs", &_rl_term_vs
},
369 { "ve", &_rl_term_ve
},
372 #define NUM_TC_STRINGS (sizeof (tc_strings) / sizeof (struct _tc_string))
374 /* Read the desired terminal capability strings into BP. The capabilities
375 are described in the TC_STRINGS table. */
377 get_term_capabilities (bp
)
380 #if !defined (__DJGPP__) /* XXX - doesn't DJGPP have a termcap library? */
383 for (i
= 0; i
< NUM_TC_STRINGS
; i
++)
385 *(tc_strings
[i
].tc_value
) = tgetstr ((char *)tc_strings
[i
].tc_var
, bp
);
387 *(tc_strings
[i
].tc_value
) = tgetstr (tc_strings
[i
].tc_var
, bp
);
390 tcap_initialized
= 1;
394 _rl_init_terminal_io (terminal_name
)
395 const char *terminal_name
;
399 int tty
, tgetent_ret
;
401 term
= terminal_name
? terminal_name
: sh_get_env_value ("TERM");
402 _rl_term_clrpag
= _rl_term_cr
= _rl_term_clreol
= (char *)NULL
;
403 tty
= rl_instream
? fileno (rl_instream
) : 0;
404 _rl_screenwidth
= _rl_screenheight
= 0;
410 _rl_term_im
= _rl_term_ei
= _rl_term_ic
= _rl_term_IC
= (char *)NULL
;
411 _rl_term_up
= _rl_term_dc
= _rl_term_DC
= _rl_visible_bell
= (char *)NULL
;
412 _rl_term_ku
= _rl_term_kd
= _rl_term_kl
= _rl_term_kr
= (char *)NULL
;
413 _rl_term_mm
= _rl_term_mo
= (char *)NULL
;
414 _rl_terminal_can_insert
= term_has_meta
= _rl_term_autowrap
= 0;
416 _rl_term_clreol
= _rl_term_clrpag
= _rl_term_backspace
= (char *)NULL
;
417 _rl_term_goto
= _rl_term_pc
= _rl_term_ip
= (char *)NULL
;
418 _rl_term_ks
= _rl_term_ke
=_rl_term_vs
= _rl_term_ve
= (char *)NULL
;
419 _rl_term_kh
= _rl_term_kH
= _rl_term_at7
= _rl_term_kI
= (char *)NULL
;
420 #if defined(HACK_TERMCAP_MOTION)
421 _rl_term_forward_char
= (char *)NULL
;
424 _rl_get_screen_size (tty
, 0);
425 #else /* !__MSDOS__ */
426 /* I've separated this out for later work on not calling tgetent at all
427 if the calling application has supplied a custom redisplay function,
428 (and possibly if the application has supplied a custom input function). */
429 if (CUSTOM_REDISPLAY_FUNC())
435 if (term_string_buffer
== 0)
436 term_string_buffer
= (char *)xmalloc(2032);
438 if (term_buffer
== 0)
439 term_buffer
= (char *)xmalloc(4080);
441 buffer
= term_string_buffer
;
443 tgetent_ret
= tgetent (term_buffer
, term
);
446 if (tgetent_ret
<= 0)
448 FREE (term_string_buffer
);
450 buffer
= term_buffer
= term_string_buffer
= (char *)NULL
;
452 _rl_term_autowrap
= 0; /* used by _rl_get_screen_size */
454 #if defined (__EMX__)
455 _emx_get_screensize (&_rl_screenwidth
, &_rl_screenheight
);
458 _rl_get_screen_size (tty
, 0);
459 #endif /* !__EMX__ */
462 if (_rl_screenwidth
<= 0 || _rl_screenheight
<= 0)
464 _rl_screenwidth
= 79;
465 _rl_screenheight
= 24;
468 /* Everything below here is used by the redisplay code (tputs). */
469 _rl_screenchars
= _rl_screenwidth
* _rl_screenheight
;
471 _rl_term_im
= _rl_term_ei
= _rl_term_ic
= _rl_term_IC
= (char *)NULL
;
472 _rl_term_up
= _rl_term_dc
= _rl_term_DC
= _rl_visible_bell
= (char *)NULL
;
473 _rl_term_ku
= _rl_term_kd
= _rl_term_kl
= _rl_term_kr
= (char *)NULL
;
474 _rl_term_kh
= _rl_term_kH
= _rl_term_kI
= (char *)NULL
;
475 _rl_term_ks
= _rl_term_ke
= _rl_term_at7
= (char *)NULL
;
476 _rl_term_mm
= _rl_term_mo
= (char *)NULL
;
477 _rl_term_ve
= _rl_term_vs
= (char *)NULL
;
478 #if defined (HACK_TERMCAP_MOTION)
479 term_forward_char
= (char *)NULL
;
481 _rl_terminal_can_insert
= term_has_meta
= 0;
483 /* Reasonable defaults for tgoto(). Readline currently only uses
484 tgoto if _rl_term_IC or _rl_term_DC is defined, but just in case we
485 change that later... */
487 BC
= _rl_term_backspace
= "\b";
493 get_term_capabilities (&buffer
);
495 /* Set up the variables that the termcap library expects the application
497 PC
= _rl_term_pc
? *_rl_term_pc
: 0;
498 BC
= _rl_term_backspace
;
504 _rl_term_autowrap
= tgetflag ("am") && tgetflag ("xn");
506 _rl_get_screen_size (tty
, 0);
508 /* "An application program can assume that the terminal can do
509 character insertion if *any one of* the capabilities `IC',
510 `im', `ic' or `ip' is provided." But we can't do anything if
511 only `ip' is provided, so... */
512 _rl_terminal_can_insert
= (_rl_term_IC
|| _rl_term_im
|| _rl_term_ic
);
514 /* Check to see if this terminal has a meta key and clear the capability
515 variables if there is none. */
516 term_has_meta
= (tgetflag ("km") || tgetflag ("MT"));
518 _rl_term_mm
= _rl_term_mo
= (char *)NULL
;
520 #endif /* !__MSDOS__ */
522 /* Attempt to find and bind the arrow keys. Do not override already
523 bound keys in an overzealous attempt, however. */
525 bind_termcap_arrow_keys (emacs_standard_keymap
);
527 #if defined (VI_MODE)
528 bind_termcap_arrow_keys (vi_movement_keymap
);
529 bind_termcap_arrow_keys (vi_insertion_keymap
);
535 /* Bind the arrow key sequences from the termcap description in MAP. */
537 bind_termcap_arrow_keys (map
)
542 xkeymap
= _rl_keymap
;
545 _rl_bind_if_unbound (_rl_term_ku
, rl_get_previous_history
);
546 _rl_bind_if_unbound (_rl_term_kd
, rl_get_next_history
);
547 _rl_bind_if_unbound (_rl_term_kr
, rl_forward
);
548 _rl_bind_if_unbound (_rl_term_kl
, rl_backward
);
550 _rl_bind_if_unbound (_rl_term_kh
, rl_beg_of_line
); /* Home */
551 _rl_bind_if_unbound (_rl_term_at7
, rl_end_of_line
); /* End */
553 _rl_keymap
= xkeymap
;
562 if (tcap_initialized
== 0)
563 return ((char *)NULL
);
564 for (i
= 0; i
< NUM_TC_STRINGS
; i
++)
566 if (tc_strings
[i
].tc_var
[0] == cap
[0] && strcmp (tc_strings
[i
].tc_var
, cap
) == 0)
567 return *(tc_strings
[i
].tc_value
);
569 return ((char *)NULL
);
572 /* Re-initialize the terminal considering that the TERM/TERMCAP variable
575 rl_reset_terminal (terminal_name
)
576 const char *terminal_name
;
578 _rl_init_terminal_io (terminal_name
);
582 /* A function for the use of tputs () */
585 _rl_output_character_function (c
)
588 putc (c
, _rl_out_stream
);
592 _rl_output_character_function (c
)
595 return putc (c
, _rl_out_stream
);
599 /* Write COUNT characters from STRING to the output stream. */
601 _rl_output_some_chars (string
, count
)
605 fwrite (string
, 1, count
, _rl_out_stream
);
608 /* Move the cursor back. */
610 _rl_backspace (count
)
616 if (_rl_term_backspace
)
617 for (i
= 0; i
< count
; i
++)
618 tputs (_rl_term_backspace
, 1, _rl_output_character_function
);
621 for (i
= 0; i
< count
; i
++)
622 putc ('\b', _rl_out_stream
);
626 /* Move to the start of the next line. */
630 #if defined (NEW_TTY_DRIVER)
632 tputs (_rl_term_cr
, 1, _rl_output_character_function
);
633 #endif /* NEW_TTY_DRIVER */
634 putc ('\n', _rl_out_stream
);
638 /* Ring the terminal bell. */
642 if (readline_echoing_p
)
644 switch (_rl_bell_preference
)
654 if (_rl_visible_bell
)
656 tputs (_rl_visible_bell
, 1, _rl_output_character_function
);
662 fprintf (stderr
, "\007");
671 /* **************************************************************** */
673 /* Controlling the Meta Key and Keypad */
675 /* **************************************************************** */
678 _rl_enable_meta_key ()
680 #if !defined (__DJGPP__)
681 if (term_has_meta
&& _rl_term_mm
)
682 tputs (_rl_term_mm
, 1, _rl_output_character_function
);
687 _rl_control_keypad (on
)
690 #if !defined (__DJGPP__)
691 if (on
&& _rl_term_ks
)
692 tputs (_rl_term_ks
, 1, _rl_output_character_function
);
693 else if (!on
&& _rl_term_ke
)
694 tputs (_rl_term_ke
, 1, _rl_output_character_function
);
698 /* **************************************************************** */
700 /* Controlling the Cursor */
702 /* **************************************************************** */
704 /* Set the cursor appropriately depending on IM, which is one of the
705 insert modes (insert or overwrite). Insert mode gets the normal
706 cursor. Overwrite mode gets a very visible cursor. Only does
707 anything if we have both capabilities. */
709 _rl_set_cursor (im
, force
)
713 if (_rl_term_ve
&& _rl_term_vs
)
715 if (force
|| im
!= rl_insert_mode
)
717 if (im
== RL_IM_OVERWRITE
)
718 tputs (_rl_term_vs
, 1, _rl_output_character_function
);
720 tputs (_rl_term_ve
, 1, _rl_output_character_function
);