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