Deleted Added
full compact
terminal.c (119614) terminal.c (136758)
1/* $FreeBSD: head/contrib/libreadline/terminal.c 136758 2004-10-21 20:02:02Z peter $ */
2
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. */
3/* terminal.c -- controlling the terminal with termcap. */
4
5/* Copyright (C) 1996 Free Software Foundation, Inc.
6
7 This file is part of the GNU Readline Library, a library for
8 reading lines of text with interactive input and history editing.
9
10 The GNU Readline Library is free software; you can redistribute it
11 and/or modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2, or
13 (at your option) any later version.
14
15 The GNU Readline Library is distributed in the hope that it will be
16 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
17 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 The GNU General Public License is often shipped with GNU software, and
21 is generally kept in a file called COPYING or LICENSE. If you do not
22 have a copy of the license, write to the Free Software Foundation,
23 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
22/* $FreeBSD: head/contrib/libreadline/terminal.c 119614 2003-08-31 18:29:38Z ache $ */
23#define READLINE_LIBRARY
24
25#if defined (HAVE_CONFIG_H)
26# include <config.h>
27#endif
28
29#include <sys/types.h>
30#include "posixstat.h"
31#include <fcntl.h>
32#if defined (HAVE_SYS_FILE_H)
33# include <sys/file.h>
34#endif /* HAVE_SYS_FILE_H */
35
36#if defined (HAVE_UNISTD_H)
37# include <unistd.h>
38#endif /* HAVE_UNISTD_H */
39
40#if defined (HAVE_STDLIB_H)
41# include <stdlib.h>
42#else
43# include "ansi_stdlib.h"
44#endif /* HAVE_STDLIB_H */
45
46#if defined (HAVE_LOCALE_H)
47# include <locale.h>
48#endif
49
50#include <stdio.h>
51
52/* System-specific feature definitions and include files. */
53#include "rldefs.h"
54
55#if defined (GWINSZ_IN_SYS_IOCTL) && !defined (TIOCGWINSZ)
56# include <sys/ioctl.h>
57#endif /* GWINSZ_IN_SYS_IOCTL && !TIOCGWINSZ */
58
59#include "rltty.h"
60#include "tcap.h"
61
62/* Some standard library routines. */
63#include "readline.h"
64#include "history.h"
65
66#include "rlprivate.h"
67#include "rlshell.h"
68#include "xmalloc.h"
69
70#define CUSTOM_REDISPLAY_FUNC() (rl_redisplay_function != rl_redisplay)
71#define CUSTOM_INPUT_FUNC() (rl_getc_function != rl_getc)
72
73/* **************************************************************** */
74/* */
75/* Terminal and Termcap */
76/* */
77/* **************************************************************** */
78
79static char *term_buffer = (char *)NULL;
80static char *term_string_buffer = (char *)NULL;
81
82static int tcap_initialized;
83
84#if !defined (__linux__)
85# if defined (__EMX__) || defined (NEED_EXTERN_PC)
86extern
87# endif /* __EMX__ || NEED_EXTERN_PC */
88char PC, *BC, *UP;
89#endif /* __linux__ */
90
91/* Some strings to control terminal actions. These are output by tputs (). */
92char *_rl_term_clreol;
93char *_rl_term_clrpag;
94char *_rl_term_cr;
95char *_rl_term_backspace;
96char *_rl_term_goto;
97char *_rl_term_pc;
98
99/* Non-zero if we determine that the terminal can do character insertion. */
100int _rl_terminal_can_insert = 0;
101
102/* How to insert characters. */
103char *_rl_term_im;
104char *_rl_term_ei;
105char *_rl_term_ic;
106char *_rl_term_ip;
107char *_rl_term_IC;
108
109/* How to delete characters. */
110char *_rl_term_dc;
111char *_rl_term_DC;
112
113#if defined (HACK_TERMCAP_MOTION)
114char *_rl_term_forward_char;
115#endif /* HACK_TERMCAP_MOTION */
116
117/* How to go up a line. */
118char *_rl_term_up;
119
120/* A visible bell; char if the terminal can be made to flash the screen. */
121static char *_rl_visible_bell;
122
123/* Non-zero means the terminal can auto-wrap lines. */
124int _rl_term_autowrap;
125
126/* Non-zero means that this terminal has a meta key. */
127static int term_has_meta;
128
129/* The sequences to write to turn on and off the meta key, if this
130 terminal has one. */
131static char *_rl_term_mm;
132static char *_rl_term_mo;
133
134/* The key sequences output by the arrow keys, if this terminal has any. */
135static char *_rl_term_ku;
136static char *_rl_term_kd;
137static char *_rl_term_kr;
138static char *_rl_term_kl;
139
140/* How to initialize and reset the arrow keys, if this terminal has any. */
141static char *_rl_term_ks;
142static char *_rl_term_ke;
143
144/* The key sequences sent by the Home and End keys, if any. */
145static char *_rl_term_kh;
146static char *_rl_term_kH;
147static char *_rl_term_at7; /* @7 */
148
149/* Insert key */
150static char *_rl_term_kI;
151
152/* Cursor control */
153static char *_rl_term_vs; /* very visible */
154static char *_rl_term_ve; /* normal */
155
156static void bind_termcap_arrow_keys PARAMS((Keymap));
157
158/* Variables that hold the screen dimensions, used by the display code. */
159int _rl_screenwidth, _rl_screenheight, _rl_screenchars;
160
161/* Non-zero means the user wants to enable the keypad. */
162int _rl_enable_keypad;
163
164/* Non-zero means the user wants to enable a meta key. */
165int _rl_enable_meta = 1;
166
167#if defined (__EMX__)
168static void
169_emx_get_screensize (swp, shp)
170 int *swp, *shp;
171{
172 int sz[2];
173
174 _scrsize (sz);
175
176 if (swp)
177 *swp = sz[0];
178 if (shp)
179 *shp = sz[1];
180}
181#endif
182
183/* Get readline's idea of the screen size. TTY is a file descriptor open
184 to the terminal. If IGNORE_ENV is true, we do not pay attention to the
185 values of $LINES and $COLUMNS. The tests for TERM_STRING_BUFFER being
186 non-null serve to check whether or not we have initialized termcap. */
187void
188_rl_get_screen_size (tty, ignore_env)
189 int tty, ignore_env;
190{
191 char *ss;
192#if defined (TIOCGWINSZ)
193 struct winsize window_size;
194#endif /* TIOCGWINSZ */
195
196#if defined (TIOCGWINSZ)
197 if (ioctl (tty, TIOCGWINSZ, &window_size) == 0)
198 {
199 _rl_screenwidth = (int) window_size.ws_col;
200 _rl_screenheight = (int) window_size.ws_row;
201 }
202#endif /* TIOCGWINSZ */
203
204#if defined (__EMX__)
205 _emx_get_screensize (&_rl_screenwidth, &_rl_screenheight);
206#endif
207
208 /* Environment variable COLUMNS overrides setting of "co" if IGNORE_ENV
209 is unset. */
210 if (_rl_screenwidth <= 0)
211 {
212 if (ignore_env == 0 && (ss = sh_get_env_value ("COLUMNS")))
213 _rl_screenwidth = atoi (ss);
214
215#if !defined (__DJGPP__)
216 if (_rl_screenwidth <= 0 && term_string_buffer)
217 _rl_screenwidth = tgetnum ("co");
218#endif
219 }
220
221 /* Environment variable LINES overrides setting of "li" if IGNORE_ENV
222 is unset. */
223 if (_rl_screenheight <= 0)
224 {
225 if (ignore_env == 0 && (ss = sh_get_env_value ("LINES")))
226 _rl_screenheight = atoi (ss);
227
228#if !defined (__DJGPP__)
229 if (_rl_screenheight <= 0 && term_string_buffer)
230 _rl_screenheight = tgetnum ("li");
231#endif
232 }
233
234 /* If all else fails, default to 80x24 terminal. */
235 if (_rl_screenwidth <= 1)
236 _rl_screenwidth = 80;
237
238 if (_rl_screenheight <= 0)
239 _rl_screenheight = 24;
240
241 /* If we're being compiled as part of bash, set the environment
242 variables $LINES and $COLUMNS to new values. Otherwise, just
243 do a pair of putenv () or setenv () calls. */
244 sh_set_lines_and_columns (_rl_screenheight, _rl_screenwidth);
245
246 if (_rl_term_autowrap == 0)
247 _rl_screenwidth--;
248
249 _rl_screenchars = _rl_screenwidth * _rl_screenheight;
250}
251
252void
253_rl_set_screen_size (rows, cols)
254 int rows, cols;
255{
256 if (rows == 0 || cols == 0)
257 return;
258
259 _rl_screenheight = rows;
260 _rl_screenwidth = cols;
261
262 if (_rl_term_autowrap == 0)
263 _rl_screenwidth--;
264
265 _rl_screenchars = _rl_screenwidth * _rl_screenheight;
266}
267
268void
269rl_set_screen_size (rows, cols)
270 int rows, cols;
271{
272 _rl_set_screen_size (rows, cols);
273}
274
275void
276rl_get_screen_size (rows, cols)
277 int *rows, *cols;
278{
279 if (rows)
280 *rows = _rl_screenheight;
281 if (cols)
282 *cols = _rl_screenwidth;
283}
284
285void
286rl_resize_terminal ()
287{
288 if (readline_echoing_p)
289 {
290 _rl_get_screen_size (fileno (rl_instream), 1);
291 if (CUSTOM_REDISPLAY_FUNC ())
292 rl_forced_update_display ();
293 else
294 _rl_redisplay_after_sigwinch ();
295 }
296}
297
298struct _tc_string {
299 const char *tc_var;
300 char **tc_value;
301};
302
303/* This should be kept sorted, just in case we decide to change the
304 search algorithm to something smarter. */
305static struct _tc_string tc_strings[] =
306{
307 { "@7", &_rl_term_at7 },
308 { "DC", &_rl_term_DC },
309 { "IC", &_rl_term_IC },
310 { "ce", &_rl_term_clreol },
311 { "cl", &_rl_term_clrpag },
312 { "cr", &_rl_term_cr },
313 { "dc", &_rl_term_dc },
314 { "ei", &_rl_term_ei },
315 { "ic", &_rl_term_ic },
316 { "im", &_rl_term_im },
317 { "kH", &_rl_term_kH }, /* home down ?? */
318 { "kI", &_rl_term_kI }, /* insert */
319 { "kd", &_rl_term_kd },
320 { "ke", &_rl_term_ke }, /* end keypad mode */
321 { "kh", &_rl_term_kh }, /* home */
322 { "kl", &_rl_term_kl },
323 { "kr", &_rl_term_kr },
324 { "ks", &_rl_term_ks }, /* start keypad mode */
325 { "ku", &_rl_term_ku },
326 { "le", &_rl_term_backspace },
327 { "mm", &_rl_term_mm },
328 { "mo", &_rl_term_mo },
329#if defined (HACK_TERMCAP_MOTION)
330 { "nd", &_rl_term_forward_char },
331#endif
332 { "pc", &_rl_term_pc },
333 { "up", &_rl_term_up },
334 { "vb", &_rl_visible_bell },
335 { "vs", &_rl_term_vs },
336 { "ve", &_rl_term_ve },
337};
338
339#define NUM_TC_STRINGS (sizeof (tc_strings) / sizeof (struct _tc_string))
340
341/* Read the desired terminal capability strings into BP. The capabilities
342 are described in the TC_STRINGS table. */
343static void
344get_term_capabilities (bp)
345 char **bp;
346{
347#if !defined (__DJGPP__) /* XXX - doesn't DJGPP have a termcap library? */
348 register int i;
349
350 for (i = 0; i < NUM_TC_STRINGS; i++)
24#define READLINE_LIBRARY
25
26#if defined (HAVE_CONFIG_H)
27# include <config.h>
28#endif
29
30#include <sys/types.h>
31#include "posixstat.h"
32#include <fcntl.h>
33#if defined (HAVE_SYS_FILE_H)
34# include <sys/file.h>
35#endif /* HAVE_SYS_FILE_H */
36
37#if defined (HAVE_UNISTD_H)
38# include <unistd.h>
39#endif /* HAVE_UNISTD_H */
40
41#if defined (HAVE_STDLIB_H)
42# include <stdlib.h>
43#else
44# include "ansi_stdlib.h"
45#endif /* HAVE_STDLIB_H */
46
47#if defined (HAVE_LOCALE_H)
48# include <locale.h>
49#endif
50
51#include <stdio.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#include "rlprivate.h"
68#include "rlshell.h"
69#include "xmalloc.h"
70
71#define CUSTOM_REDISPLAY_FUNC() (rl_redisplay_function != rl_redisplay)
72#define CUSTOM_INPUT_FUNC() (rl_getc_function != rl_getc)
73
74/* **************************************************************** */
75/* */
76/* Terminal and Termcap */
77/* */
78/* **************************************************************** */
79
80static char *term_buffer = (char *)NULL;
81static char *term_string_buffer = (char *)NULL;
82
83static int tcap_initialized;
84
85#if !defined (__linux__)
86# if defined (__EMX__) || defined (NEED_EXTERN_PC)
87extern
88# endif /* __EMX__ || NEED_EXTERN_PC */
89char PC, *BC, *UP;
90#endif /* __linux__ */
91
92/* Some strings to control terminal actions. These are output by tputs (). */
93char *_rl_term_clreol;
94char *_rl_term_clrpag;
95char *_rl_term_cr;
96char *_rl_term_backspace;
97char *_rl_term_goto;
98char *_rl_term_pc;
99
100/* Non-zero if we determine that the terminal can do character insertion. */
101int _rl_terminal_can_insert = 0;
102
103/* How to insert characters. */
104char *_rl_term_im;
105char *_rl_term_ei;
106char *_rl_term_ic;
107char *_rl_term_ip;
108char *_rl_term_IC;
109
110/* How to delete characters. */
111char *_rl_term_dc;
112char *_rl_term_DC;
113
114#if defined (HACK_TERMCAP_MOTION)
115char *_rl_term_forward_char;
116#endif /* HACK_TERMCAP_MOTION */
117
118/* How to go up a line. */
119char *_rl_term_up;
120
121/* A visible bell; char if the terminal can be made to flash the screen. */
122static char *_rl_visible_bell;
123
124/* Non-zero means the terminal can auto-wrap lines. */
125int _rl_term_autowrap;
126
127/* Non-zero means that this terminal has a meta key. */
128static int term_has_meta;
129
130/* The sequences to write to turn on and off the meta key, if this
131 terminal has one. */
132static char *_rl_term_mm;
133static char *_rl_term_mo;
134
135/* The key sequences output by the arrow keys, if this terminal has any. */
136static char *_rl_term_ku;
137static char *_rl_term_kd;
138static char *_rl_term_kr;
139static char *_rl_term_kl;
140
141/* How to initialize and reset the arrow keys, if this terminal has any. */
142static char *_rl_term_ks;
143static char *_rl_term_ke;
144
145/* The key sequences sent by the Home and End keys, if any. */
146static char *_rl_term_kh;
147static char *_rl_term_kH;
148static char *_rl_term_at7; /* @7 */
149
150/* Insert key */
151static char *_rl_term_kI;
152
153/* Cursor control */
154static char *_rl_term_vs; /* very visible */
155static char *_rl_term_ve; /* normal */
156
157static void bind_termcap_arrow_keys PARAMS((Keymap));
158
159/* Variables that hold the screen dimensions, used by the display code. */
160int _rl_screenwidth, _rl_screenheight, _rl_screenchars;
161
162/* Non-zero means the user wants to enable the keypad. */
163int _rl_enable_keypad;
164
165/* Non-zero means the user wants to enable a meta key. */
166int _rl_enable_meta = 1;
167
168#if defined (__EMX__)
169static void
170_emx_get_screensize (swp, shp)
171 int *swp, *shp;
172{
173 int sz[2];
174
175 _scrsize (sz);
176
177 if (swp)
178 *swp = sz[0];
179 if (shp)
180 *shp = sz[1];
181}
182#endif
183
184/* Get readline's idea of the screen size. TTY is a file descriptor open
185 to the terminal. If IGNORE_ENV is true, we do not pay attention to the
186 values of $LINES and $COLUMNS. The tests for TERM_STRING_BUFFER being
187 non-null serve to check whether or not we have initialized termcap. */
188void
189_rl_get_screen_size (tty, ignore_env)
190 int tty, ignore_env;
191{
192 char *ss;
193#if defined (TIOCGWINSZ)
194 struct winsize window_size;
195#endif /* TIOCGWINSZ */
196
197#if defined (TIOCGWINSZ)
198 if (ioctl (tty, TIOCGWINSZ, &window_size) == 0)
199 {
200 _rl_screenwidth = (int) window_size.ws_col;
201 _rl_screenheight = (int) window_size.ws_row;
202 }
203#endif /* TIOCGWINSZ */
204
205#if defined (__EMX__)
206 _emx_get_screensize (&_rl_screenwidth, &_rl_screenheight);
207#endif
208
209 /* Environment variable COLUMNS overrides setting of "co" if IGNORE_ENV
210 is unset. */
211 if (_rl_screenwidth <= 0)
212 {
213 if (ignore_env == 0 && (ss = sh_get_env_value ("COLUMNS")))
214 _rl_screenwidth = atoi (ss);
215
216#if !defined (__DJGPP__)
217 if (_rl_screenwidth <= 0 && term_string_buffer)
218 _rl_screenwidth = tgetnum ("co");
219#endif
220 }
221
222 /* Environment variable LINES overrides setting of "li" if IGNORE_ENV
223 is unset. */
224 if (_rl_screenheight <= 0)
225 {
226 if (ignore_env == 0 && (ss = sh_get_env_value ("LINES")))
227 _rl_screenheight = atoi (ss);
228
229#if !defined (__DJGPP__)
230 if (_rl_screenheight <= 0 && term_string_buffer)
231 _rl_screenheight = tgetnum ("li");
232#endif
233 }
234
235 /* If all else fails, default to 80x24 terminal. */
236 if (_rl_screenwidth <= 1)
237 _rl_screenwidth = 80;
238
239 if (_rl_screenheight <= 0)
240 _rl_screenheight = 24;
241
242 /* If we're being compiled as part of bash, set the environment
243 variables $LINES and $COLUMNS to new values. Otherwise, just
244 do a pair of putenv () or setenv () calls. */
245 sh_set_lines_and_columns (_rl_screenheight, _rl_screenwidth);
246
247 if (_rl_term_autowrap == 0)
248 _rl_screenwidth--;
249
250 _rl_screenchars = _rl_screenwidth * _rl_screenheight;
251}
252
253void
254_rl_set_screen_size (rows, cols)
255 int rows, cols;
256{
257 if (rows == 0 || cols == 0)
258 return;
259
260 _rl_screenheight = rows;
261 _rl_screenwidth = cols;
262
263 if (_rl_term_autowrap == 0)
264 _rl_screenwidth--;
265
266 _rl_screenchars = _rl_screenwidth * _rl_screenheight;
267}
268
269void
270rl_set_screen_size (rows, cols)
271 int rows, cols;
272{
273 _rl_set_screen_size (rows, cols);
274}
275
276void
277rl_get_screen_size (rows, cols)
278 int *rows, *cols;
279{
280 if (rows)
281 *rows = _rl_screenheight;
282 if (cols)
283 *cols = _rl_screenwidth;
284}
285
286void
287rl_resize_terminal ()
288{
289 if (readline_echoing_p)
290 {
291 _rl_get_screen_size (fileno (rl_instream), 1);
292 if (CUSTOM_REDISPLAY_FUNC ())
293 rl_forced_update_display ();
294 else
295 _rl_redisplay_after_sigwinch ();
296 }
297}
298
299struct _tc_string {
300 const char *tc_var;
301 char **tc_value;
302};
303
304/* This should be kept sorted, just in case we decide to change the
305 search algorithm to something smarter. */
306static struct _tc_string tc_strings[] =
307{
308 { "@7", &_rl_term_at7 },
309 { "DC", &_rl_term_DC },
310 { "IC", &_rl_term_IC },
311 { "ce", &_rl_term_clreol },
312 { "cl", &_rl_term_clrpag },
313 { "cr", &_rl_term_cr },
314 { "dc", &_rl_term_dc },
315 { "ei", &_rl_term_ei },
316 { "ic", &_rl_term_ic },
317 { "im", &_rl_term_im },
318 { "kH", &_rl_term_kH }, /* home down ?? */
319 { "kI", &_rl_term_kI }, /* insert */
320 { "kd", &_rl_term_kd },
321 { "ke", &_rl_term_ke }, /* end keypad mode */
322 { "kh", &_rl_term_kh }, /* home */
323 { "kl", &_rl_term_kl },
324 { "kr", &_rl_term_kr },
325 { "ks", &_rl_term_ks }, /* start keypad mode */
326 { "ku", &_rl_term_ku },
327 { "le", &_rl_term_backspace },
328 { "mm", &_rl_term_mm },
329 { "mo", &_rl_term_mo },
330#if defined (HACK_TERMCAP_MOTION)
331 { "nd", &_rl_term_forward_char },
332#endif
333 { "pc", &_rl_term_pc },
334 { "up", &_rl_term_up },
335 { "vb", &_rl_visible_bell },
336 { "vs", &_rl_term_vs },
337 { "ve", &_rl_term_ve },
338};
339
340#define NUM_TC_STRINGS (sizeof (tc_strings) / sizeof (struct _tc_string))
341
342/* Read the desired terminal capability strings into BP. The capabilities
343 are described in the TC_STRINGS table. */
344static void
345get_term_capabilities (bp)
346 char **bp;
347{
348#if !defined (__DJGPP__) /* XXX - doesn't DJGPP have a termcap library? */
349 register int i;
350
351 for (i = 0; i < NUM_TC_STRINGS; i++)
351# ifdef __LCC__
352 *(tc_strings[i].tc_value) = tgetstr ((char *)tc_strings[i].tc_var, bp);
352 *(tc_strings[i].tc_value) = tgetstr ((char *)tc_strings[i].tc_var, bp);
353# else
354 *(tc_strings[i].tc_value) = tgetstr (tc_strings[i].tc_var, bp);
355# endif
356#endif
357 tcap_initialized = 1;
358}
359
360int
361_rl_init_terminal_io (terminal_name)
362 const char *terminal_name;
363{
364 const char *term;
365 char *buffer;
366 int tty, tgetent_ret;
367
368 term = terminal_name ? terminal_name : sh_get_env_value ("TERM");
369 _rl_term_clrpag = _rl_term_cr = _rl_term_clreol = (char *)NULL;
370 tty = rl_instream ? fileno (rl_instream) : 0;
371 _rl_screenwidth = _rl_screenheight = 0;
372
373 if (term == 0)
374 term = "dumb";
375
376 /* I've separated this out for later work on not calling tgetent at all
377 if the calling application has supplied a custom redisplay function,
378 (and possibly if the application has supplied a custom input function). */
379 if (CUSTOM_REDISPLAY_FUNC())
380 {
381 tgetent_ret = -1;
382 }
383 else
384 {
385 if (term_string_buffer == 0)
386 term_string_buffer = (char *)xmalloc(2032);
387
388 if (term_buffer == 0)
389 term_buffer = (char *)xmalloc(4080);
390
391 buffer = term_string_buffer;
392
393 tgetent_ret = tgetent (term_buffer, term);
394 }
395
396 if (tgetent_ret <= 0)
397 {
398 FREE (term_string_buffer);
399 FREE (term_buffer);
400 buffer = term_buffer = term_string_buffer = (char *)NULL;
401
402 _rl_term_autowrap = 0; /* used by _rl_get_screen_size */
403
404#if defined (__EMX__)
405 _emx_get_screensize (&_rl_screenwidth, &_rl_screenheight);
406 _rl_screenwidth--;
407#else /* !__EMX__ */
408 _rl_get_screen_size (tty, 0);
409#endif /* !__EMX__ */
410
411 /* Defaults. */
412 if (_rl_screenwidth <= 0 || _rl_screenheight <= 0)
413 {
414 _rl_screenwidth = 79;
415 _rl_screenheight = 24;
416 }
417
418 /* Everything below here is used by the redisplay code (tputs). */
419 _rl_screenchars = _rl_screenwidth * _rl_screenheight;
420 _rl_term_cr = "\r";
421 _rl_term_im = _rl_term_ei = _rl_term_ic = _rl_term_IC = (char *)NULL;
422 _rl_term_up = _rl_term_dc = _rl_term_DC = _rl_visible_bell = (char *)NULL;
423 _rl_term_ku = _rl_term_kd = _rl_term_kl = _rl_term_kr = (char *)NULL;
424 _rl_term_kh = _rl_term_kH = _rl_term_kI = (char *)NULL;
425 _rl_term_ks = _rl_term_ke = _rl_term_at7 = (char *)NULL;
426 _rl_term_mm = _rl_term_mo = (char *)NULL;
427 _rl_term_ve = _rl_term_vs = (char *)NULL;
428#if defined (HACK_TERMCAP_MOTION)
429 term_forward_char = (char *)NULL;
430#endif
431 _rl_terminal_can_insert = term_has_meta = 0;
432
433 /* Reasonable defaults for tgoto(). Readline currently only uses
434 tgoto if _rl_term_IC or _rl_term_DC is defined, but just in case we
435 change that later... */
436 PC = '\0';
437 BC = _rl_term_backspace = "\b";
438 UP = _rl_term_up;
439
440 return 0;
441 }
442
443 get_term_capabilities (&buffer);
444
445 /* Set up the variables that the termcap library expects the application
446 to provide. */
447 PC = _rl_term_pc ? *_rl_term_pc : 0;
448 BC = _rl_term_backspace;
449 UP = _rl_term_up;
450
451 if (!_rl_term_cr)
452 _rl_term_cr = "\r";
453
454 _rl_term_autowrap = tgetflag ("am") && tgetflag ("xn");
455
456 _rl_get_screen_size (tty, 0);
457
458 /* "An application program can assume that the terminal can do
459 character insertion if *any one of* the capabilities `IC',
460 `im', `ic' or `ip' is provided." But we can't do anything if
461 only `ip' is provided, so... */
462 _rl_terminal_can_insert = (_rl_term_IC || _rl_term_im || _rl_term_ic);
463
464 /* Check to see if this terminal has a meta key and clear the capability
465 variables if there is none. */
466 term_has_meta = (tgetflag ("km") || tgetflag ("MT"));
467 if (!term_has_meta)
468 _rl_term_mm = _rl_term_mo = (char *)NULL;
469
470 /* Attempt to find and bind the arrow keys. Do not override already
471 bound keys in an overzealous attempt, however. */
472
473 bind_termcap_arrow_keys (emacs_standard_keymap);
474
475#if defined (VI_MODE)
476 bind_termcap_arrow_keys (vi_movement_keymap);
477 bind_termcap_arrow_keys (vi_insertion_keymap);
478#endif /* VI_MODE */
479
480 return 0;
481}
482
483/* Bind the arrow key sequences from the termcap description in MAP. */
484static void
485bind_termcap_arrow_keys (map)
486 Keymap map;
487{
488 Keymap xkeymap;
489
490 xkeymap = _rl_keymap;
491 _rl_keymap = map;
492
353#endif
354 tcap_initialized = 1;
355}
356
357int
358_rl_init_terminal_io (terminal_name)
359 const char *terminal_name;
360{
361 const char *term;
362 char *buffer;
363 int tty, tgetent_ret;
364
365 term = terminal_name ? terminal_name : sh_get_env_value ("TERM");
366 _rl_term_clrpag = _rl_term_cr = _rl_term_clreol = (char *)NULL;
367 tty = rl_instream ? fileno (rl_instream) : 0;
368 _rl_screenwidth = _rl_screenheight = 0;
369
370 if (term == 0)
371 term = "dumb";
372
373 /* I've separated this out for later work on not calling tgetent at all
374 if the calling application has supplied a custom redisplay function,
375 (and possibly if the application has supplied a custom input function). */
376 if (CUSTOM_REDISPLAY_FUNC())
377 {
378 tgetent_ret = -1;
379 }
380 else
381 {
382 if (term_string_buffer == 0)
383 term_string_buffer = (char *)xmalloc(2032);
384
385 if (term_buffer == 0)
386 term_buffer = (char *)xmalloc(4080);
387
388 buffer = term_string_buffer;
389
390 tgetent_ret = tgetent (term_buffer, term);
391 }
392
393 if (tgetent_ret <= 0)
394 {
395 FREE (term_string_buffer);
396 FREE (term_buffer);
397 buffer = term_buffer = term_string_buffer = (char *)NULL;
398
399 _rl_term_autowrap = 0; /* used by _rl_get_screen_size */
400
401#if defined (__EMX__)
402 _emx_get_screensize (&_rl_screenwidth, &_rl_screenheight);
403 _rl_screenwidth--;
404#else /* !__EMX__ */
405 _rl_get_screen_size (tty, 0);
406#endif /* !__EMX__ */
407
408 /* Defaults. */
409 if (_rl_screenwidth <= 0 || _rl_screenheight <= 0)
410 {
411 _rl_screenwidth = 79;
412 _rl_screenheight = 24;
413 }
414
415 /* Everything below here is used by the redisplay code (tputs). */
416 _rl_screenchars = _rl_screenwidth * _rl_screenheight;
417 _rl_term_cr = "\r";
418 _rl_term_im = _rl_term_ei = _rl_term_ic = _rl_term_IC = (char *)NULL;
419 _rl_term_up = _rl_term_dc = _rl_term_DC = _rl_visible_bell = (char *)NULL;
420 _rl_term_ku = _rl_term_kd = _rl_term_kl = _rl_term_kr = (char *)NULL;
421 _rl_term_kh = _rl_term_kH = _rl_term_kI = (char *)NULL;
422 _rl_term_ks = _rl_term_ke = _rl_term_at7 = (char *)NULL;
423 _rl_term_mm = _rl_term_mo = (char *)NULL;
424 _rl_term_ve = _rl_term_vs = (char *)NULL;
425#if defined (HACK_TERMCAP_MOTION)
426 term_forward_char = (char *)NULL;
427#endif
428 _rl_terminal_can_insert = term_has_meta = 0;
429
430 /* Reasonable defaults for tgoto(). Readline currently only uses
431 tgoto if _rl_term_IC or _rl_term_DC is defined, but just in case we
432 change that later... */
433 PC = '\0';
434 BC = _rl_term_backspace = "\b";
435 UP = _rl_term_up;
436
437 return 0;
438 }
439
440 get_term_capabilities (&buffer);
441
442 /* Set up the variables that the termcap library expects the application
443 to provide. */
444 PC = _rl_term_pc ? *_rl_term_pc : 0;
445 BC = _rl_term_backspace;
446 UP = _rl_term_up;
447
448 if (!_rl_term_cr)
449 _rl_term_cr = "\r";
450
451 _rl_term_autowrap = tgetflag ("am") && tgetflag ("xn");
452
453 _rl_get_screen_size (tty, 0);
454
455 /* "An application program can assume that the terminal can do
456 character insertion if *any one of* the capabilities `IC',
457 `im', `ic' or `ip' is provided." But we can't do anything if
458 only `ip' is provided, so... */
459 _rl_terminal_can_insert = (_rl_term_IC || _rl_term_im || _rl_term_ic);
460
461 /* Check to see if this terminal has a meta key and clear the capability
462 variables if there is none. */
463 term_has_meta = (tgetflag ("km") || tgetflag ("MT"));
464 if (!term_has_meta)
465 _rl_term_mm = _rl_term_mo = (char *)NULL;
466
467 /* Attempt to find and bind the arrow keys. Do not override already
468 bound keys in an overzealous attempt, however. */
469
470 bind_termcap_arrow_keys (emacs_standard_keymap);
471
472#if defined (VI_MODE)
473 bind_termcap_arrow_keys (vi_movement_keymap);
474 bind_termcap_arrow_keys (vi_insertion_keymap);
475#endif /* VI_MODE */
476
477 return 0;
478}
479
480/* Bind the arrow key sequences from the termcap description in MAP. */
481static void
482bind_termcap_arrow_keys (map)
483 Keymap map;
484{
485 Keymap xkeymap;
486
487 xkeymap = _rl_keymap;
488 _rl_keymap = map;
489
493 _rl_bind_if_unbound (_rl_term_ku, rl_get_previous_history);
494 _rl_bind_if_unbound (_rl_term_kd, rl_get_next_history);
495 _rl_bind_if_unbound (_rl_term_kr, rl_forward);
496 _rl_bind_if_unbound (_rl_term_kl, rl_backward);
490 rl_bind_keyseq_if_unbound (_rl_term_ku, rl_get_previous_history);
491 rl_bind_keyseq_if_unbound (_rl_term_kd, rl_get_next_history);
492 rl_bind_keyseq_if_unbound (_rl_term_kr, rl_forward_char);
493 rl_bind_keyseq_if_unbound (_rl_term_kl, rl_backward_char);
497
494
498 _rl_bind_if_unbound (_rl_term_kh, rl_beg_of_line); /* Home */
499 _rl_bind_if_unbound (_rl_term_at7, rl_end_of_line); /* End */
495 rl_bind_keyseq_if_unbound (_rl_term_kh, rl_beg_of_line); /* Home */
496 rl_bind_keyseq_if_unbound (_rl_term_at7, rl_end_of_line); /* End */
500
501 _rl_keymap = xkeymap;
502}
503
504char *
505rl_get_termcap (cap)
506 const char *cap;
507{
508 register int i;
509
510 if (tcap_initialized == 0)
511 return ((char *)NULL);
512 for (i = 0; i < NUM_TC_STRINGS; i++)
513 {
514 if (tc_strings[i].tc_var[0] == cap[0] && strcmp (tc_strings[i].tc_var, cap) == 0)
515 return *(tc_strings[i].tc_value);
516 }
517 return ((char *)NULL);
518}
519
520/* Re-initialize the terminal considering that the TERM/TERMCAP variable
521 has changed. */
522int
523rl_reset_terminal (terminal_name)
524 const char *terminal_name;
525{
526 _rl_init_terminal_io (terminal_name);
527 return 0;
528}
529
530/* A function for the use of tputs () */
531#ifdef _MINIX
532void
533_rl_output_character_function (c)
534 int c;
535{
536 putc (c, _rl_out_stream);
537}
538#else /* !_MINIX */
539int
540_rl_output_character_function (c)
541 int c;
542{
543 return putc (c, _rl_out_stream);
544}
545#endif /* !_MINIX */
546
547/* Write COUNT characters from STRING to the output stream. */
548void
549_rl_output_some_chars (string, count)
550 const char *string;
551 int count;
552{
553 fwrite (string, 1, count, _rl_out_stream);
554}
555
556/* Move the cursor back. */
557int
558_rl_backspace (count)
559 int count;
560{
561 register int i;
562
563 if (_rl_term_backspace)
564 for (i = 0; i < count; i++)
565 tputs (_rl_term_backspace, 1, _rl_output_character_function);
566 else
567 for (i = 0; i < count; i++)
568 putc ('\b', _rl_out_stream);
569 return 0;
570}
571
572/* Move to the start of the next line. */
573int
574rl_crlf ()
575{
576#if defined (NEW_TTY_DRIVER)
577 if (_rl_term_cr)
578 tputs (_rl_term_cr, 1, _rl_output_character_function);
579#endif /* NEW_TTY_DRIVER */
580 putc ('\n', _rl_out_stream);
581 return 0;
582}
583
584/* Ring the terminal bell. */
585int
586rl_ding ()
587{
588 if (readline_echoing_p)
589 {
590 switch (_rl_bell_preference)
591 {
592 case NO_BELL:
593 default:
594 break;
595 case VISIBLE_BELL:
596 if (_rl_visible_bell)
597 {
598 tputs (_rl_visible_bell, 1, _rl_output_character_function);
599 break;
600 }
601 /* FALLTHROUGH */
602 case AUDIBLE_BELL:
603 fprintf (stderr, "\007");
604 fflush (stderr);
605 break;
606 }
607 return (0);
608 }
609 return (-1);
610}
611
612/* **************************************************************** */
613/* */
614/* Controlling the Meta Key and Keypad */
615/* */
616/* **************************************************************** */
617
618void
619_rl_enable_meta_key ()
620{
621#if !defined (__DJGPP__)
622 if (term_has_meta && _rl_term_mm)
623 tputs (_rl_term_mm, 1, _rl_output_character_function);
624#endif
625}
626
627void
628_rl_control_keypad (on)
629 int on;
630{
631#if !defined (__DJGPP__)
632 if (on && _rl_term_ks)
633 tputs (_rl_term_ks, 1, _rl_output_character_function);
634 else if (!on && _rl_term_ke)
635 tputs (_rl_term_ke, 1, _rl_output_character_function);
636#endif
637}
638
639/* **************************************************************** */
640/* */
641/* Controlling the Cursor */
642/* */
643/* **************************************************************** */
644
645/* Set the cursor appropriately depending on IM, which is one of the
646 insert modes (insert or overwrite). Insert mode gets the normal
647 cursor. Overwrite mode gets a very visible cursor. Only does
648 anything if we have both capabilities. */
649void
650_rl_set_cursor (im, force)
651 int im, force;
652{
653 if (_rl_term_ve && _rl_term_vs)
654 {
655 if (force || im != rl_insert_mode)
656 {
657 if (im == RL_IM_OVERWRITE)
658 tputs (_rl_term_vs, 1, _rl_output_character_function);
659 else
660 tputs (_rl_term_ve, 1, _rl_output_character_function);
661 }
662 }
663}
497
498 _rl_keymap = xkeymap;
499}
500
501char *
502rl_get_termcap (cap)
503 const char *cap;
504{
505 register int i;
506
507 if (tcap_initialized == 0)
508 return ((char *)NULL);
509 for (i = 0; i < NUM_TC_STRINGS; i++)
510 {
511 if (tc_strings[i].tc_var[0] == cap[0] && strcmp (tc_strings[i].tc_var, cap) == 0)
512 return *(tc_strings[i].tc_value);
513 }
514 return ((char *)NULL);
515}
516
517/* Re-initialize the terminal considering that the TERM/TERMCAP variable
518 has changed. */
519int
520rl_reset_terminal (terminal_name)
521 const char *terminal_name;
522{
523 _rl_init_terminal_io (terminal_name);
524 return 0;
525}
526
527/* A function for the use of tputs () */
528#ifdef _MINIX
529void
530_rl_output_character_function (c)
531 int c;
532{
533 putc (c, _rl_out_stream);
534}
535#else /* !_MINIX */
536int
537_rl_output_character_function (c)
538 int c;
539{
540 return putc (c, _rl_out_stream);
541}
542#endif /* !_MINIX */
543
544/* Write COUNT characters from STRING to the output stream. */
545void
546_rl_output_some_chars (string, count)
547 const char *string;
548 int count;
549{
550 fwrite (string, 1, count, _rl_out_stream);
551}
552
553/* Move the cursor back. */
554int
555_rl_backspace (count)
556 int count;
557{
558 register int i;
559
560 if (_rl_term_backspace)
561 for (i = 0; i < count; i++)
562 tputs (_rl_term_backspace, 1, _rl_output_character_function);
563 else
564 for (i = 0; i < count; i++)
565 putc ('\b', _rl_out_stream);
566 return 0;
567}
568
569/* Move to the start of the next line. */
570int
571rl_crlf ()
572{
573#if defined (NEW_TTY_DRIVER)
574 if (_rl_term_cr)
575 tputs (_rl_term_cr, 1, _rl_output_character_function);
576#endif /* NEW_TTY_DRIVER */
577 putc ('\n', _rl_out_stream);
578 return 0;
579}
580
581/* Ring the terminal bell. */
582int
583rl_ding ()
584{
585 if (readline_echoing_p)
586 {
587 switch (_rl_bell_preference)
588 {
589 case NO_BELL:
590 default:
591 break;
592 case VISIBLE_BELL:
593 if (_rl_visible_bell)
594 {
595 tputs (_rl_visible_bell, 1, _rl_output_character_function);
596 break;
597 }
598 /* FALLTHROUGH */
599 case AUDIBLE_BELL:
600 fprintf (stderr, "\007");
601 fflush (stderr);
602 break;
603 }
604 return (0);
605 }
606 return (-1);
607}
608
609/* **************************************************************** */
610/* */
611/* Controlling the Meta Key and Keypad */
612/* */
613/* **************************************************************** */
614
615void
616_rl_enable_meta_key ()
617{
618#if !defined (__DJGPP__)
619 if (term_has_meta && _rl_term_mm)
620 tputs (_rl_term_mm, 1, _rl_output_character_function);
621#endif
622}
623
624void
625_rl_control_keypad (on)
626 int on;
627{
628#if !defined (__DJGPP__)
629 if (on && _rl_term_ks)
630 tputs (_rl_term_ks, 1, _rl_output_character_function);
631 else if (!on && _rl_term_ke)
632 tputs (_rl_term_ke, 1, _rl_output_character_function);
633#endif
634}
635
636/* **************************************************************** */
637/* */
638/* Controlling the Cursor */
639/* */
640/* **************************************************************** */
641
642/* Set the cursor appropriately depending on IM, which is one of the
643 insert modes (insert or overwrite). Insert mode gets the normal
644 cursor. Overwrite mode gets a very visible cursor. Only does
645 anything if we have both capabilities. */
646void
647_rl_set_cursor (im, force)
648 int im, force;
649{
650 if (_rl_term_ve && _rl_term_vs)
651 {
652 if (force || im != rl_insert_mode)
653 {
654 if (im == RL_IM_OVERWRITE)
655 tputs (_rl_term_vs, 1, _rl_output_character_function);
656 else
657 tputs (_rl_term_ve, 1, _rl_output_character_function);
658 }
659 }
660}