xref: /original-bsd/lib/libedit/term.c (revision dde3e7d7)
1263c78bbSbostic /*-
2f5b291e3Sbostic  * Copyright (c) 1992, 1993
3f5b291e3Sbostic  *	The Regents of the University of California.  All rights reserved.
4263c78bbSbostic  *
5263c78bbSbostic  * This code is derived from software contributed to Berkeley by
6263c78bbSbostic  * Christos Zoulas of Cornell University.
7263c78bbSbostic  *
8263c78bbSbostic  * %sccs.include.redist.c%
9263c78bbSbostic  */
10263c78bbSbostic 
118cbf4338Schristos #if !defined(lint) && !defined(SCCSID)
12*dde3e7d7Schristos static char sccsid[] = "@(#)term.c	8.2 (Berkeley) 04/30/95";
138cbf4338Schristos #endif /* not lint && not SCCSID */
14263c78bbSbostic 
15263c78bbSbostic /*
168cbf4338Schristos  * term.c: Editor/termcap-curses interface
17263c78bbSbostic  *	   We have to declare a static variable here, since the
18263c78bbSbostic  *	   termcap putchar routine does not take an argument!
19263c78bbSbostic  */
20263c78bbSbostic #include "sys.h"
21263c78bbSbostic #include <stdio.h>
22263c78bbSbostic #include <signal.h>
23263c78bbSbostic #include <string.h>
24263c78bbSbostic #include <stdlib.h>
25263c78bbSbostic #include <unistd.h>
26263c78bbSbostic #include "termcap.h"	/* XXX: should be <termcap.h> */
27263c78bbSbostic #include <sys/types.h>
28263c78bbSbostic 
29263c78bbSbostic #include "el.h"
30263c78bbSbostic 
31263c78bbSbostic /*
32263c78bbSbostic  * IMPORTANT NOTE: these routines are allowed to look at the current screen
33263c78bbSbostic  * and the current possition assuming that it is correct.  If this is not
34263c78bbSbostic  * true, then the update will be WRONG!  This is (should be) a valid
35263c78bbSbostic  * assumption...
36263c78bbSbostic  */
37263c78bbSbostic 
38263c78bbSbostic #define TC_BUFSIZE 2048
39263c78bbSbostic 
40263c78bbSbostic #define GoodStr(a) (el->el_term.t_str[a] != NULL && \
41263c78bbSbostic 		    el->el_term.t_str[a][0] != '\0')
42263c78bbSbostic #define Str(a) el->el_term.t_str[a]
43263c78bbSbostic #define Val(a) el->el_term.t_val[a]
44263c78bbSbostic 
45263c78bbSbostic private struct {
46263c78bbSbostic     char   *b_name;
47263c78bbSbostic     int     b_rate;
48263c78bbSbostic } baud_rate[] = {
49263c78bbSbostic #ifdef B0
50263c78bbSbostic     { "0", B0 },
51263c78bbSbostic #endif
52263c78bbSbostic #ifdef B50
53263c78bbSbostic     { "50", B50 },
54263c78bbSbostic #endif
55263c78bbSbostic #ifdef B75
56263c78bbSbostic     { "75", B75 },
57263c78bbSbostic #endif
58263c78bbSbostic #ifdef B110
59263c78bbSbostic     { "110", B110 },
60263c78bbSbostic #endif
61263c78bbSbostic #ifdef B134
62263c78bbSbostic     { "134", B134 },
63263c78bbSbostic #endif
64263c78bbSbostic #ifdef B150
65263c78bbSbostic     { "150", B150 },
66263c78bbSbostic #endif
67263c78bbSbostic #ifdef B200
68263c78bbSbostic     { "200", B200 },
69263c78bbSbostic #endif
70263c78bbSbostic #ifdef B300
71263c78bbSbostic     { "300", B300 },
72263c78bbSbostic #endif
73263c78bbSbostic #ifdef B600
74263c78bbSbostic     { "600", B600 },
75263c78bbSbostic #endif
76263c78bbSbostic #ifdef B900
77263c78bbSbostic     { "900", B900 },
78263c78bbSbostic #endif
79263c78bbSbostic #ifdef B1200
80263c78bbSbostic     { "1200", B1200 },
81263c78bbSbostic #endif
82263c78bbSbostic #ifdef B1800
83263c78bbSbostic     { "1800", B1800 },
84263c78bbSbostic #endif
85263c78bbSbostic #ifdef B2400
86263c78bbSbostic     { "2400", B2400 },
87263c78bbSbostic #endif
88263c78bbSbostic #ifdef B3600
89263c78bbSbostic     { "3600", B3600 },
90263c78bbSbostic #endif
91263c78bbSbostic #ifdef B4800
92263c78bbSbostic     { "4800", B4800 },
93263c78bbSbostic #endif
94263c78bbSbostic #ifdef B7200
95263c78bbSbostic     { "7200", B7200 },
96263c78bbSbostic #endif
97263c78bbSbostic #ifdef B9600
98263c78bbSbostic     { "9600", B9600 },
99263c78bbSbostic #endif
100263c78bbSbostic #ifdef EXTA
101263c78bbSbostic     { "19200", EXTA },
102263c78bbSbostic #endif
103263c78bbSbostic #ifdef B19200
104263c78bbSbostic     { "19200", B19200 },
105263c78bbSbostic #endif
106263c78bbSbostic #ifdef EXTB
107263c78bbSbostic     { "38400", EXTB },
108263c78bbSbostic #endif
109263c78bbSbostic #ifdef B38400
110263c78bbSbostic     { "38400", B38400 },
111263c78bbSbostic #endif
112263c78bbSbostic     { NULL, 0 }
113263c78bbSbostic };
114263c78bbSbostic 
115263c78bbSbostic private struct termcapstr {
116263c78bbSbostic     char   *name;
117263c78bbSbostic     char   *long_name;
118263c78bbSbostic } tstr[] = {
119263c78bbSbostic 
120263c78bbSbostic #define T_al	0
121263c78bbSbostic     {	"al",	"add new blank line"		},
122263c78bbSbostic #define T_bl	1
123263c78bbSbostic     {	"bl",	"audible bell"			},
124263c78bbSbostic #define T_cd	2
125263c78bbSbostic     {	"cd",	"clear to bottom"		},
126263c78bbSbostic #define T_ce	3
127263c78bbSbostic     {	"ce",	"clear to end of line"		},
128263c78bbSbostic #define T_ch	4
129263c78bbSbostic     {	"ch",	"cursor to horiz pos"		},
130263c78bbSbostic #define T_cl	5
131263c78bbSbostic     {	"cl",	"clear screen"			},
132263c78bbSbostic #define	T_dc	6
133263c78bbSbostic     {	"dc",	"delete a character"		},
134263c78bbSbostic #define	T_dl	7
135263c78bbSbostic     {	"dl",	"delete a line"		 	},
136263c78bbSbostic #define	T_dm	8
137263c78bbSbostic     {	"dm",	"start delete mode"		},
138263c78bbSbostic #define	T_ed	9
139263c78bbSbostic     {	"ed",	"end delete mode"		},
140263c78bbSbostic #define	T_ei	10
141263c78bbSbostic     {	"ei",	"end insert mode"		},
142263c78bbSbostic #define	T_fs	11
143263c78bbSbostic     {	"fs",	"cursor from status line"	},
144263c78bbSbostic #define	T_ho	12
145263c78bbSbostic     {	"ho",	"home cursor"			},
146263c78bbSbostic #define	T_ic	13
147263c78bbSbostic     {	"ic",	"insert character"		},
148263c78bbSbostic #define	T_im	14
149263c78bbSbostic     {	"im",	"start insert mode"		},
150263c78bbSbostic #define	T_ip	15
151263c78bbSbostic     {	"ip",	"insert padding"		},
152263c78bbSbostic #define	T_kd	16
153263c78bbSbostic     {	"kd",	"sends cursor down"		},
154263c78bbSbostic #define	T_kl	17
155263c78bbSbostic     {	"kl",	"sends cursor left"		},
156263c78bbSbostic #define T_kr	18
157263c78bbSbostic     {	"kr",	"sends cursor right"		},
158263c78bbSbostic #define T_ku	19
159263c78bbSbostic     {	"ku",	"sends cursor up"		},
160263c78bbSbostic #define T_md	20
161263c78bbSbostic     {	"md",	"begin bold"			},
162263c78bbSbostic #define T_me	21
163263c78bbSbostic     {	"me",	"end attributes"		},
164263c78bbSbostic #define T_nd	22
165263c78bbSbostic     {	"nd",	"non destructive space"	 	},
166263c78bbSbostic #define T_se	23
167263c78bbSbostic     {	"se",	"end standout"			},
168263c78bbSbostic #define T_so	24
169263c78bbSbostic     {	"so",	"begin standout"		},
170263c78bbSbostic #define T_ts	25
171263c78bbSbostic     {	"ts",	"cursor to status line"	 	},
172263c78bbSbostic #define T_up	26
173263c78bbSbostic     {	"up",	"cursor up one"		 	},
174263c78bbSbostic #define T_us	27
175263c78bbSbostic     {	"us",	"begin underline"		},
176263c78bbSbostic #define T_ue	28
177263c78bbSbostic     {	"ue",	"end underline"		 	},
178263c78bbSbostic #define T_vb	29
179263c78bbSbostic     {	"vb",	"visible bell"			},
180263c78bbSbostic #define T_DC	30
181263c78bbSbostic     {	"DC",	"delete multiple chars"	 	},
182263c78bbSbostic #define T_DO	31
183263c78bbSbostic     {	"DO",	"cursor down multiple"		},
184263c78bbSbostic #define T_IC	32
185263c78bbSbostic     {	"IC",	"insert multiple chars"	 	},
186263c78bbSbostic #define T_LE	33
187263c78bbSbostic     {	"LE",	"cursor left multiple"		},
188263c78bbSbostic #define T_RI	34
189263c78bbSbostic     {	"RI",	"cursor right multiple"	 	},
190263c78bbSbostic #define T_UP	35
191263c78bbSbostic     {	"UP",	"cursor up multiple"		},
192263c78bbSbostic #define T_str	36
193263c78bbSbostic     {	NULL,   NULL			 	}
194263c78bbSbostic };
195263c78bbSbostic 
196263c78bbSbostic private struct termcapval {
197263c78bbSbostic     char   *name;
198263c78bbSbostic     char   *long_name;
199263c78bbSbostic } tval[] = {
200263c78bbSbostic #define T_pt	0
201263c78bbSbostic     {	"pt",	"has physical tabs"	},
202263c78bbSbostic #define T_li	1
203263c78bbSbostic     {	"li",	"Number of lines"	},
204263c78bbSbostic #define T_co	2
205263c78bbSbostic     {	"co",	"Number of columns"	},
206263c78bbSbostic #define T_km	3
207263c78bbSbostic     {	"km",	"Has meta key"		},
208263c78bbSbostic #define T_xt	4
209263c78bbSbostic     {	"xt",	"Tab chars destructive" },
210263c78bbSbostic #define T_MT	5
211263c78bbSbostic     {	"MT",	"Has meta key"		},	/* XXX? */
212263c78bbSbostic #define T_val	6
213263c78bbSbostic     {	NULL, 	NULL,			}
214263c78bbSbostic };
215263c78bbSbostic 
216263c78bbSbostic /* do two or more of the attributes use me */
217263c78bbSbostic 
218263c78bbSbostic private	void	term_rebuffer_display	__P((EditLine *));
219263c78bbSbostic private	void	term_free_display	__P((EditLine *));
220263c78bbSbostic private	void	term_alloc_display	__P((EditLine *));
221263c78bbSbostic private	void	term_alloc		__P((EditLine *,
222263c78bbSbostic 					     struct termcapstr *, char *));
2238cbf4338Schristos private void	term_init_arrow		__P((EditLine *));
2248cbf4338Schristos private void	term_reset_arrow	__P((EditLine *));
225263c78bbSbostic 
226263c78bbSbostic 
227263c78bbSbostic private FILE *term_outfile = NULL;	/* XXX: How do we fix that? */
228263c78bbSbostic 
229263c78bbSbostic 
230263c78bbSbostic /* term_setflags():
231263c78bbSbostic  *	Set the terminal capability flags
232263c78bbSbostic  */
233263c78bbSbostic private void
term_setflags(el)234263c78bbSbostic term_setflags(el)
235263c78bbSbostic     EditLine *el;
236263c78bbSbostic {
237263c78bbSbostic     EL_FLAGS = 0;
238263c78bbSbostic     if (el->el_tty.t_tabs)
239263c78bbSbostic 	EL_FLAGS |= (Val(T_pt) && !Val(T_xt)) ? TERM_CAN_TAB : 0;
240263c78bbSbostic 
241263c78bbSbostic     EL_FLAGS |= (Val(T_km) || Val(T_MT)) ? TERM_HAS_META : 0;
242263c78bbSbostic     EL_FLAGS |= GoodStr(T_ce) ? TERM_CAN_CEOL : 0;
243263c78bbSbostic     EL_FLAGS |= (GoodStr(T_dc) || GoodStr(T_DC)) ? TERM_CAN_DELETE : 0;
244263c78bbSbostic     EL_FLAGS |= (GoodStr(T_im) || GoodStr(T_ic) || GoodStr(T_IC)) ?
245263c78bbSbostic 		 TERM_CAN_INSERT : 0;
246263c78bbSbostic     EL_FLAGS |= (GoodStr(T_up) || GoodStr(T_UP))  ? TERM_CAN_UP : 0;
247263c78bbSbostic 
248263c78bbSbostic     if (GoodStr(T_me) && GoodStr(T_ue))
249263c78bbSbostic 	EL_FLAGS |= (strcmp(Str(T_me), Str(T_ue)) == 0) ? TERM_CAN_ME : 0;
250263c78bbSbostic     else
251263c78bbSbostic 	EL_FLAGS &= ~TERM_CAN_ME;
252263c78bbSbostic     if (GoodStr(T_me) && GoodStr(T_se))
253263c78bbSbostic 	EL_FLAGS |= (strcmp(Str(T_me), Str(T_se)) == 0) ? TERM_CAN_ME : 0;
254263c78bbSbostic 
255263c78bbSbostic 
256263c78bbSbostic #ifdef DEBUG_SCREEN
257263c78bbSbostic     if (!EL_CAN_UP) {
258263c78bbSbostic 	(void) fprintf(el->el_errfile, "WARNING: Your terminal cannot move up.\n");
259263c78bbSbostic 	(void) fprintf(el->el_errfile, "Editing may be odd for long lines.\n");
260263c78bbSbostic     }
261263c78bbSbostic     if (!EL_CAN_CEOL)
262263c78bbSbostic 	(void) fprintf(el->el_errfile, "no clear EOL capability.\n");
263263c78bbSbostic     if (!EL_CAN_DELETE)
264263c78bbSbostic 	(void) fprintf(el->el_errfile, "no delete char capability.\n");
265263c78bbSbostic     if (!EL_CAN_INSERT)
266263c78bbSbostic 	(void) fprintf(el->el_errfile, "no insert char capability.\n");
267263c78bbSbostic #endif /* DEBUG_SCREEN */
268263c78bbSbostic }
269263c78bbSbostic 
270263c78bbSbostic 
271263c78bbSbostic /* term_init():
272263c78bbSbostic  *	Initialize the terminal stuff
273263c78bbSbostic  */
274263c78bbSbostic protected int
term_init(el)275263c78bbSbostic term_init(el)
276263c78bbSbostic     EditLine *el;
277263c78bbSbostic {
278263c78bbSbostic     el->el_term.t_buf = (char *)  el_malloc(TC_BUFSIZE);
279263c78bbSbostic     el->el_term.t_cap = (char *)  el_malloc(TC_BUFSIZE);
2808cbf4338Schristos     el->el_term.t_fkey = (fkey_t *) el_malloc(4 * sizeof(fkey_t));
281263c78bbSbostic     el->el_term.t_loc = 0;
282263c78bbSbostic     el->el_term.t_str = (char **) el_malloc(T_str * sizeof(char*));
283263c78bbSbostic     (void) memset(el->el_term.t_str, 0, T_str * sizeof(char*));
284263c78bbSbostic     el->el_term.t_val = (int *)   el_malloc(T_val * sizeof(int));
285263c78bbSbostic     (void) memset(el->el_term.t_val, 0, T_val * sizeof(char*));
286263c78bbSbostic     term_outfile = el->el_outfile;
2878cbf4338Schristos     (void) term_set(el, NULL);
2888cbf4338Schristos     term_init_arrow(el);
289263c78bbSbostic     return 0;
290263c78bbSbostic }
291263c78bbSbostic 
292263c78bbSbostic /* term_end():
293263c78bbSbostic  *	Clean up the terminal stuff
294263c78bbSbostic  */
295263c78bbSbostic protected void
term_end(el)296263c78bbSbostic term_end(el)
297263c78bbSbostic     EditLine *el;
298263c78bbSbostic {
299263c78bbSbostic     el_free((ptr_t) el->el_term.t_buf);
300263c78bbSbostic     el->el_term.t_buf = NULL;
301263c78bbSbostic     el_free((ptr_t) el->el_term.t_cap);
302263c78bbSbostic     el->el_term.t_cap = NULL;
303263c78bbSbostic     el->el_term.t_loc = 0;
304263c78bbSbostic     el_free((ptr_t) el->el_term.t_str);
305263c78bbSbostic     el->el_term.t_str = NULL;
306263c78bbSbostic     el_free((ptr_t) el->el_term.t_val);
307263c78bbSbostic     el->el_term.t_val = NULL;
308263c78bbSbostic     term_free_display(el);
309263c78bbSbostic }
310263c78bbSbostic 
311263c78bbSbostic 
312263c78bbSbostic /* term_alloc():
313263c78bbSbostic  *	Maintain a string pool for termcap strings
314263c78bbSbostic  */
315263c78bbSbostic private void
term_alloc(el,t,cap)316263c78bbSbostic term_alloc(el, t, cap)
317263c78bbSbostic     EditLine *el;
318263c78bbSbostic     struct termcapstr *t;
319263c78bbSbostic     char   *cap;
320263c78bbSbostic {
321263c78bbSbostic     char    termbuf[TC_BUFSIZE];
322263c78bbSbostic     int     tlen, clen;
323263c78bbSbostic     char    **tlist = el->el_term.t_str;
324263c78bbSbostic     char    **tmp, **str = &tlist[t - tstr];
325263c78bbSbostic 
326263c78bbSbostic     if (cap == NULL || *cap == '\0') {
327263c78bbSbostic 	*str = NULL;
328263c78bbSbostic 	return;
329263c78bbSbostic     }
330263c78bbSbostic     else
331263c78bbSbostic 	clen = strlen(cap);
332263c78bbSbostic 
333263c78bbSbostic     tlen  = *str == NULL ? 0 : strlen(*str);
334263c78bbSbostic 
335263c78bbSbostic     /*
336263c78bbSbostic      * New string is shorter; no need to allocate space
337263c78bbSbostic      */
338263c78bbSbostic     if (clen <= tlen) {
339263c78bbSbostic 	(void) strcpy(*str, cap);
340263c78bbSbostic 	return;
341263c78bbSbostic     }
342263c78bbSbostic 
343263c78bbSbostic     /*
344263c78bbSbostic      * New string is longer; see if we have enough space to append
345263c78bbSbostic      */
346263c78bbSbostic     if (el->el_term.t_loc + 3 < TC_BUFSIZE) {
347263c78bbSbostic 	(void) strcpy(*str = &el->el_term.t_buf[el->el_term.t_loc], cap);
348263c78bbSbostic 	el->el_term.t_loc += clen + 1;	/* one for \0 */
349263c78bbSbostic 	return;
350263c78bbSbostic     }
351263c78bbSbostic 
352263c78bbSbostic     /*
353263c78bbSbostic      * Compact our buffer; no need to check compaction, cause we know it
354263c78bbSbostic      * fits...
355263c78bbSbostic      */
356263c78bbSbostic     tlen = 0;
357263c78bbSbostic     for (tmp = tlist; tmp < &tlist[T_str]; tmp++)
358263c78bbSbostic 	if (*tmp != NULL && *tmp != '\0' && *tmp != *str) {
359263c78bbSbostic 	    char   *ptr;
360263c78bbSbostic 
361263c78bbSbostic 	    for (ptr = *tmp; *ptr != '\0'; termbuf[tlen++] = *ptr++)
362263c78bbSbostic 		continue;
363263c78bbSbostic 	    termbuf[tlen++] = '\0';
364263c78bbSbostic 	}
365263c78bbSbostic     memcpy(el->el_term.t_buf, termbuf, TC_BUFSIZE);
366263c78bbSbostic     el->el_term.t_loc = tlen;
367263c78bbSbostic     if (el->el_term.t_loc + 3 >= TC_BUFSIZE) {
368263c78bbSbostic 	(void) fprintf(el->el_errfile, "Out of termcap string space.\n");
369263c78bbSbostic 	return;
370263c78bbSbostic     }
371263c78bbSbostic     (void) strcpy(*str = &el->el_term.t_buf[el->el_term.t_loc], cap);
372263c78bbSbostic     el->el_term.t_loc += clen + 1;		/* one for \0 */
373263c78bbSbostic     return;
374263c78bbSbostic } /* end term_alloc */
375263c78bbSbostic 
376263c78bbSbostic 
377263c78bbSbostic /* term_rebuffer_display():
378263c78bbSbostic  *	Rebuffer the display after the screen changed size
379263c78bbSbostic  */
380263c78bbSbostic private void
term_rebuffer_display(el)381263c78bbSbostic term_rebuffer_display(el)
382263c78bbSbostic     EditLine *el;
383263c78bbSbostic {
384263c78bbSbostic     coord_t *c = &el->el_term.t_size;
385263c78bbSbostic 
386263c78bbSbostic     term_free_display(el);
387263c78bbSbostic 
388263c78bbSbostic     /* make this public, -1 to avoid wraps */
389263c78bbSbostic     c->h = Val(T_co) - 1;
390263c78bbSbostic     c->v = (EL_BUFSIZ * 4) / c->h + 1;
391263c78bbSbostic 
392263c78bbSbostic     term_alloc_display(el);
393263c78bbSbostic } /* end term_rebuffer_display */
394263c78bbSbostic 
395263c78bbSbostic 
396263c78bbSbostic /* term_alloc_display():
397263c78bbSbostic  *	Allocate a new display.
398263c78bbSbostic  */
399263c78bbSbostic private void
term_alloc_display(el)400263c78bbSbostic term_alloc_display(el)
401263c78bbSbostic     EditLine *el;
402263c78bbSbostic {
403263c78bbSbostic     int i;
404263c78bbSbostic     char  **b;
405263c78bbSbostic     coord_t *c = &el->el_term.t_size;
406263c78bbSbostic 
407263c78bbSbostic     b = (char **) el_malloc((size_t) (sizeof(char *) * (c->v + 1)));
408263c78bbSbostic     for (i = 0; i < c->v; i++)
409263c78bbSbostic 	b[i] = (char *) el_malloc((size_t) (sizeof(char) * (c->h + 1)));
410263c78bbSbostic     b[c->v] = NULL;
411263c78bbSbostic     el->el_display = b;
412263c78bbSbostic 
413263c78bbSbostic     b = (char **) el_malloc((size_t) (sizeof(char *) * (c->v + 1)));
414263c78bbSbostic     for (i = 0; i < c->v; i++)
415263c78bbSbostic 	b[i] = (char *) el_malloc((size_t) (sizeof(char) * (c->h + 1)));
416263c78bbSbostic     b[c->v] = NULL;
417263c78bbSbostic     el->el_vdisplay = b;
418263c78bbSbostic 
419263c78bbSbostic } /* end term_alloc_display */
420263c78bbSbostic 
421263c78bbSbostic 
422263c78bbSbostic /* term_free_display():
423263c78bbSbostic  *	Free the display buffers
424263c78bbSbostic  */
425263c78bbSbostic private void
term_free_display(el)426263c78bbSbostic term_free_display(el)
427263c78bbSbostic     EditLine *el;
428263c78bbSbostic {
429263c78bbSbostic     char  **b;
430263c78bbSbostic     char  **bufp;
431263c78bbSbostic 
432263c78bbSbostic     b = el->el_display;
433263c78bbSbostic     el->el_display = NULL;
434263c78bbSbostic     if (b != NULL) {
435263c78bbSbostic 	for (bufp = b; *bufp != NULL; bufp++)
436263c78bbSbostic 	    el_free((ptr_t) *bufp);
437263c78bbSbostic 	el_free((ptr_t) b);
438263c78bbSbostic     }
439263c78bbSbostic     b = el->el_vdisplay;
440263c78bbSbostic     el->el_vdisplay = NULL;
441263c78bbSbostic     if (b != NULL) {
442263c78bbSbostic 	for (bufp = b; *bufp != NULL; bufp++)
443263c78bbSbostic 	    el_free((ptr_t) * bufp);
444263c78bbSbostic 	el_free((ptr_t) b);
445263c78bbSbostic     }
446263c78bbSbostic } /* end term_free_display */
447263c78bbSbostic 
448263c78bbSbostic 
449263c78bbSbostic /* term_move_to_line():
450263c78bbSbostic  *	move to line <where> (first line == 0)
451263c78bbSbostic  * 	as efficiently as possible
452263c78bbSbostic  */
453263c78bbSbostic protected void
term_move_to_line(el,where)454263c78bbSbostic term_move_to_line(el, where)
455263c78bbSbostic     EditLine *el;
456263c78bbSbostic     int     where;
457263c78bbSbostic {
458263c78bbSbostic     int     del, i;
459263c78bbSbostic 
460263c78bbSbostic     if (where == el->el_cursor.v)
461263c78bbSbostic 	return;
462263c78bbSbostic 
463263c78bbSbostic     if (where > el->el_term.t_size.v) {
464263c78bbSbostic #ifdef DEBUG_SCREEN
465263c78bbSbostic 	(void) fprintf(el->el_errfile,
466263c78bbSbostic 		"term_move_to_line: where is ridiculous: %d\r\n", where);
467263c78bbSbostic #endif /* DEBUG_SCREEN */
468263c78bbSbostic 	return;
469263c78bbSbostic     }
470263c78bbSbostic 
471263c78bbSbostic     if ((del = where - el->el_cursor.v) > 0) {
472263c78bbSbostic 	if ((del > 1) && GoodStr(T_DO))
473263c78bbSbostic 	    (void) tputs(tgoto(Str(T_DO), del, del), del, term__putc);
474263c78bbSbostic 	else {
475263c78bbSbostic 	    for (i = 0; i < del; i++)
476263c78bbSbostic 		term__putc('\n');
477263c78bbSbostic 	    el->el_cursor.h = 0;	/* because the \n will become \r\n */
478263c78bbSbostic 	}
479263c78bbSbostic     }
480263c78bbSbostic     else {			/* del < 0 */
481263c78bbSbostic 	if (GoodStr(T_UP) && (-del > 1 || !GoodStr(T_up)))
482263c78bbSbostic 	    (void) tputs(tgoto(Str(T_UP), -del, -del), -del, term__putc);
483263c78bbSbostic 	else {
484263c78bbSbostic 	    if (GoodStr(T_up))
485263c78bbSbostic 		for (i = 0; i < -del; i++)
486263c78bbSbostic 		    (void) tputs(Str(T_up), 1, term__putc);
487263c78bbSbostic 	}
488263c78bbSbostic     }
489263c78bbSbostic     el->el_cursor.v = where;		/* now where is here */
490263c78bbSbostic } /* end term_move_to_line */
491263c78bbSbostic 
492263c78bbSbostic 
493263c78bbSbostic /* term_move_to_char():
494263c78bbSbostic  *	Move to the character position specified
495263c78bbSbostic  */
496263c78bbSbostic protected void
term_move_to_char(el,where)497263c78bbSbostic term_move_to_char(el, where)
498263c78bbSbostic     EditLine *el;
499263c78bbSbostic     int     where;
500263c78bbSbostic {
501263c78bbSbostic     int     del, i;
502263c78bbSbostic 
503263c78bbSbostic mc_again:
504263c78bbSbostic     if (where == el->el_cursor.h)
505263c78bbSbostic 	return;
506263c78bbSbostic 
507263c78bbSbostic     if (where > (el->el_term.t_size.h + 1)) {
508263c78bbSbostic #ifdef DEBUG_SCREEN
509263c78bbSbostic 	(void) fprintf(el->el_errfile,
510263c78bbSbostic 		"term_move_to_char: where is riduculous: %d\r\n", where);
511263c78bbSbostic #endif /* DEBUG_SCREEN */
512263c78bbSbostic 	return;
513263c78bbSbostic     }
514263c78bbSbostic 
515263c78bbSbostic     if (!where) {		/* if where is first column */
516263c78bbSbostic 	term__putc('\r');	/* do a CR */
517263c78bbSbostic 	el->el_cursor.h = 0;
518263c78bbSbostic 	return;
519263c78bbSbostic     }
520263c78bbSbostic 
521263c78bbSbostic     del = where - el->el_cursor.h;
522263c78bbSbostic 
523263c78bbSbostic     if ((del < -4 || del > 4) && GoodStr(T_ch))
524263c78bbSbostic 	/* go there directly */
525263c78bbSbostic 	(void) tputs(tgoto(Str(T_ch), where, where), where, term__putc);
526263c78bbSbostic     else {
527263c78bbSbostic 	if (del > 0) {		/* moving forward */
528263c78bbSbostic 	    if ((del > 4) && GoodStr(T_RI))
529263c78bbSbostic 		(void) tputs(tgoto(Str(T_RI), del, del), del, term__putc);
530263c78bbSbostic 	    else {
531263c78bbSbostic 		if (EL_CAN_TAB) {	/* if I can do tabs, use them */
532263c78bbSbostic 		    if ((el->el_cursor.h & 0370) != (where & 0370)) {
533263c78bbSbostic 			/* if not within tab stop */
534263c78bbSbostic 			for (i = (el->el_cursor.h & 0370);
535263c78bbSbostic 			     i < (where & 0370); i += 8)
536263c78bbSbostic 			    term__putc('\t');	/* then tab over */
537263c78bbSbostic 			el->el_cursor.h = where & 0370;
538263c78bbSbostic 		    }
539263c78bbSbostic 		}
540263c78bbSbostic 		/* it's usually cheaper to just write the chars, so we do. */
541263c78bbSbostic 
542263c78bbSbostic 		/* NOTE THAT term_overwrite() WILL CHANGE el->el_cursor.h!!! */
543263c78bbSbostic 		term_overwrite(el,
544263c78bbSbostic 			&el->el_display[el->el_cursor.v][el->el_cursor.h],
545263c78bbSbostic 		        where - el->el_cursor.h);
546263c78bbSbostic 
547263c78bbSbostic 	    }
548263c78bbSbostic 	}
549263c78bbSbostic 	else {			/* del < 0 := moving backward */
550263c78bbSbostic 	    if ((-del > 4) && GoodStr(T_LE))
551263c78bbSbostic 		(void) tputs(tgoto(Str(T_LE), -del, -del), -del, term__putc);
552263c78bbSbostic 	    else {		/* can't go directly there */
553263c78bbSbostic 		/* if the "cost" is greater than the "cost" from col 0 */
554263c78bbSbostic 		if (EL_CAN_TAB ? (-del > ((where >> 3) + (where & 07)))
555263c78bbSbostic 		    : (-del > where)) {
556263c78bbSbostic 		    term__putc('\r');	/* do a CR */
557263c78bbSbostic 		    el->el_cursor.h = 0;
558263c78bbSbostic 		    goto mc_again;	/* and try again */
559263c78bbSbostic 		}
560263c78bbSbostic 		for (i = 0; i < -del; i++)
561263c78bbSbostic 		    term__putc('\b');
562263c78bbSbostic 	    }
563263c78bbSbostic 	}
564263c78bbSbostic     }
565263c78bbSbostic     el->el_cursor.h = where;		/* now where is here */
566263c78bbSbostic } /* end term_move_to_char */
567263c78bbSbostic 
568263c78bbSbostic 
569263c78bbSbostic /* term_overwrite():
570263c78bbSbostic  *	Overstrike num characters
571263c78bbSbostic  */
572263c78bbSbostic protected void
term_overwrite(el,cp,n)573263c78bbSbostic term_overwrite(el, cp, n)
574263c78bbSbostic     EditLine *el;
575263c78bbSbostic     char *cp;
576263c78bbSbostic     int n;
577263c78bbSbostic {
578263c78bbSbostic     if (n <= 0)
579263c78bbSbostic 	return;			/* catch bugs */
580263c78bbSbostic 
581263c78bbSbostic     if (n > (el->el_term.t_size.h + 1)) {
582263c78bbSbostic #ifdef DEBUG_SCREEN
583263c78bbSbostic 	(void) fprintf(el->el_errfile, "term_overwrite: n is riduculous: %d\r\n", n);
584263c78bbSbostic #endif /* DEBUG_SCREEN */
585263c78bbSbostic 	return;
586263c78bbSbostic     }
587263c78bbSbostic 
588263c78bbSbostic     do {
589263c78bbSbostic 	term__putc(*cp++);
590263c78bbSbostic 	el->el_cursor.h++;
591263c78bbSbostic     } while (--n);
592263c78bbSbostic } /* end term_overwrite */
593263c78bbSbostic 
594263c78bbSbostic 
595263c78bbSbostic /* term_deletechars():
596263c78bbSbostic  *	Delete num characters
597263c78bbSbostic  */
598263c78bbSbostic protected void
term_deletechars(el,num)599263c78bbSbostic term_deletechars(el, num)
600263c78bbSbostic     EditLine *el;
601263c78bbSbostic     int     num;
602263c78bbSbostic {
603263c78bbSbostic     if (num <= 0)
604263c78bbSbostic 	return;
605263c78bbSbostic 
606263c78bbSbostic     if (!EL_CAN_DELETE) {
607263c78bbSbostic #ifdef DEBUG_EDIT
608263c78bbSbostic 	(void) fprintf(el->el_errfile, "   ERROR: cannot delete   \n");
609263c78bbSbostic #endif /* DEBUG_EDIT */
610263c78bbSbostic 	return;
611263c78bbSbostic     }
612263c78bbSbostic 
613263c78bbSbostic     if (num > el->el_term.t_size.h) {
614263c78bbSbostic #ifdef DEBUG_SCREEN
615263c78bbSbostic 	(void) fprintf(el->el_errfile,
616263c78bbSbostic 		"term_deletechars: num is riduculous: %d\r\n", num);
617263c78bbSbostic #endif /* DEBUG_SCREEN */
618263c78bbSbostic 	return;
619263c78bbSbostic     }
620263c78bbSbostic 
621263c78bbSbostic     if (GoodStr(T_DC))		/* if I have multiple delete */
622263c78bbSbostic 	if ((num > 1) || !GoodStr(T_dc)) {	/* if dc would be more expen. */
623263c78bbSbostic 	    (void) tputs(tgoto(Str(T_DC), num, num), num, term__putc);
624263c78bbSbostic 	    return;
625263c78bbSbostic 	}
626263c78bbSbostic 
627263c78bbSbostic     if (GoodStr(T_dm))		/* if I have delete mode */
628263c78bbSbostic 	(void) tputs(Str(T_dm), 1, term__putc);
629263c78bbSbostic 
630263c78bbSbostic     if (GoodStr(T_dc))		/* else do one at a time */
631263c78bbSbostic 	while (num--)
632263c78bbSbostic 	    (void) tputs(Str(T_dc), 1, term__putc);
633263c78bbSbostic 
634263c78bbSbostic     if (GoodStr(T_ed))		/* if I have delete mode */
635263c78bbSbostic 	(void) tputs(Str(T_ed), 1, term__putc);
636263c78bbSbostic } /* end term_deletechars */
637263c78bbSbostic 
638263c78bbSbostic 
639263c78bbSbostic /* term_insertwrite():
640263c78bbSbostic  *	Puts terminal in insert character mode or inserts num
641263c78bbSbostic  *	characters in the line
642263c78bbSbostic  */
643263c78bbSbostic protected void
term_insertwrite(el,cp,num)644263c78bbSbostic term_insertwrite(el, cp, num)
645263c78bbSbostic     EditLine *el;
646263c78bbSbostic     char *cp;
647263c78bbSbostic     int num;
648263c78bbSbostic {
649263c78bbSbostic     if (num <= 0)
650263c78bbSbostic 	return;
651263c78bbSbostic     if (!EL_CAN_INSERT) {
652263c78bbSbostic #ifdef DEBUG_EDIT
653263c78bbSbostic 	(void) fprintf(el->el_errfile, "   ERROR: cannot insert   \n");
654263c78bbSbostic #endif /* DEBUG_EDIT */
655263c78bbSbostic 	return;
656263c78bbSbostic     }
657263c78bbSbostic 
658263c78bbSbostic     if (num > el->el_term.t_size.h) {
659263c78bbSbostic #ifdef DEBUG_SCREEN
660263c78bbSbostic 	(void) fprintf(el->el_errfile, "StartInsert: num is riduculous: %d\r\n", num);
661263c78bbSbostic #endif /* DEBUG_SCREEN */
662263c78bbSbostic 	return;
663263c78bbSbostic     }
664263c78bbSbostic 
665263c78bbSbostic     if (GoodStr(T_IC))		/* if I have multiple insert */
666263c78bbSbostic 	if ((num > 1) || !GoodStr(T_ic)) {	/* if ic would be more expen. */
667263c78bbSbostic 	    (void) tputs(tgoto(Str(T_IC), num, num), num, term__putc);
668263c78bbSbostic 	    term_overwrite(el, cp, num);	/* this updates el_cursor.h */
669263c78bbSbostic 	    return;
670263c78bbSbostic 	}
671263c78bbSbostic 
672263c78bbSbostic     if (GoodStr(T_im) && GoodStr(T_ei)) { /* if I have insert mode */
673263c78bbSbostic 	(void) tputs(Str(T_im), 1, term__putc);
674263c78bbSbostic 
675263c78bbSbostic 	el->el_cursor.h += num;
676263c78bbSbostic 	do
677263c78bbSbostic 	    term__putc(*cp++);
678263c78bbSbostic 	while (--num);
679263c78bbSbostic 
680263c78bbSbostic 	if (GoodStr(T_ip))	/* have to make num chars insert */
681263c78bbSbostic 	    (void) tputs(Str(T_ip), 1, term__putc);
682263c78bbSbostic 
683263c78bbSbostic 	(void) tputs(Str(T_ei), 1, term__putc);
684263c78bbSbostic 	return;
685263c78bbSbostic     }
686263c78bbSbostic 
687263c78bbSbostic     do {
688263c78bbSbostic 	if (GoodStr(T_ic))	/* have to make num chars insert */
689263c78bbSbostic 	    (void) tputs(Str(T_ic), 1, term__putc);	/* insert a char */
690263c78bbSbostic 
691263c78bbSbostic 	term__putc(*cp++);
692263c78bbSbostic 
693263c78bbSbostic 	el->el_cursor.h++;
694263c78bbSbostic 
695263c78bbSbostic 	if (GoodStr(T_ip))	/* have to make num chars insert */
696263c78bbSbostic 	    (void) tputs(Str(T_ip), 1, term__putc);/* pad the inserted char */
697263c78bbSbostic 
698263c78bbSbostic     } while (--num);
699263c78bbSbostic } /* end term_insertwrite */
700263c78bbSbostic 
701263c78bbSbostic 
702263c78bbSbostic /* term_clear_EOL():
703263c78bbSbostic  *	clear to end of line.  There are num characters to clear
704263c78bbSbostic  */
705263c78bbSbostic protected void
term_clear_EOL(el,num)706263c78bbSbostic term_clear_EOL(el, num)
707263c78bbSbostic     EditLine *el;
708263c78bbSbostic     int     num;
709263c78bbSbostic {
710263c78bbSbostic     int i;
711263c78bbSbostic 
712263c78bbSbostic     if (EL_CAN_CEOL && GoodStr(T_ce))
713263c78bbSbostic 	(void) tputs(Str(T_ce), 1, term__putc);
714263c78bbSbostic     else {
715263c78bbSbostic 	for (i = 0; i < num; i++)
716263c78bbSbostic 	    term__putc(' ');
717263c78bbSbostic 	el->el_cursor.h += num;		/* have written num spaces */
718263c78bbSbostic     }
719263c78bbSbostic } /* end term_clear_EOL */
720263c78bbSbostic 
721263c78bbSbostic 
722263c78bbSbostic /* term_clear_screen():
723263c78bbSbostic  *	Clear the screen
724263c78bbSbostic  */
725263c78bbSbostic protected void
term_clear_screen(el)726263c78bbSbostic term_clear_screen(el)
727263c78bbSbostic     EditLine *el;
728263c78bbSbostic {				/* clear the whole screen and home */
729263c78bbSbostic     if (GoodStr(T_cl))
730263c78bbSbostic 	/* send the clear screen code */
731263c78bbSbostic 	(void) tputs(Str(T_cl), Val(T_li), term__putc);
732263c78bbSbostic     else if (GoodStr(T_ho) && GoodStr(T_cd)) {
733263c78bbSbostic 	(void) tputs(Str(T_ho), Val(T_li), term__putc);	/* home */
734263c78bbSbostic 	/* clear to bottom of screen */
735263c78bbSbostic 	(void) tputs(Str(T_cd), Val(T_li), term__putc);
736263c78bbSbostic     }
737263c78bbSbostic     else {
738263c78bbSbostic 	term__putc('\r');
739263c78bbSbostic 	term__putc('\n');
740263c78bbSbostic     }
741263c78bbSbostic } /* end term_clear_screen */
742263c78bbSbostic 
743263c78bbSbostic 
744263c78bbSbostic /* term_beep():
745263c78bbSbostic  *	Beep the way the terminal wants us
746263c78bbSbostic  */
747263c78bbSbostic protected void
term_beep(el)748263c78bbSbostic term_beep(el)
749263c78bbSbostic     EditLine *el;
750263c78bbSbostic {
751263c78bbSbostic     if (GoodStr(T_vb))
752263c78bbSbostic 	(void) tputs(Str(T_vb), 1, term__putc);	/* visible bell */
753263c78bbSbostic     else if (GoodStr(T_bl))
754263c78bbSbostic 	/* what termcap says we should use */
755263c78bbSbostic 	(void) tputs(Str(T_bl), 1, term__putc);
756263c78bbSbostic     else
757263c78bbSbostic 	term__putc('\007');	/* an ASCII bell; ^G */
758263c78bbSbostic } /* end term_beep */
759263c78bbSbostic 
760263c78bbSbostic 
761263c78bbSbostic #ifdef notdef
762263c78bbSbostic /* term_clear_to_bottom():
763263c78bbSbostic  *	Clear to the bottom of the screen
764263c78bbSbostic  */
765263c78bbSbostic protected void
term_clear_to_bottom(el)766263c78bbSbostic term_clear_to_bottom(el)
767263c78bbSbostic     EditLine *el;
768263c78bbSbostic {
769263c78bbSbostic     if (GoodStr(T_cd))
770263c78bbSbostic 	(void) tputs(Str(T_cd), Val(T_li), term__putc);
771263c78bbSbostic     else if (GoodStr(T_ce))
772263c78bbSbostic 	(void) tputs(Str(T_ce), Val(T_li), term__putc);
773263c78bbSbostic } /* end term_clear_to_bottom */
774263c78bbSbostic #endif
775263c78bbSbostic 
776263c78bbSbostic 
7778cbf4338Schristos /* term_set():
7788cbf4338Schristos  *	Read in the terminal capabilities from the requested terminal
779263c78bbSbostic  */
7808cbf4338Schristos protected int
term_set(el,term)7818cbf4338Schristos term_set(el, term)
782263c78bbSbostic     EditLine *el;
783263c78bbSbostic     char *term;
784263c78bbSbostic {
785263c78bbSbostic     int i;
786263c78bbSbostic     char    buf[TC_BUFSIZE];
787263c78bbSbostic     char   *area;
788263c78bbSbostic     struct termcapstr *t;
789263c78bbSbostic     sigset_t oset, nset;
790263c78bbSbostic     int     lins, cols;
791263c78bbSbostic 
792263c78bbSbostic     (void) sigemptyset(&nset);
793263c78bbSbostic     (void) sigaddset(&nset, SIGWINCH);
794263c78bbSbostic     (void) sigprocmask(SIG_BLOCK, &nset, &oset);
795263c78bbSbostic 
796263c78bbSbostic     area = buf;
797263c78bbSbostic 
798263c78bbSbostic 
799263c78bbSbostic     if (term == NULL)
800263c78bbSbostic 	term = getenv("TERM");
801263c78bbSbostic 
802263c78bbSbostic     if (!term || !term[0])
803263c78bbSbostic 	term = "dumb";
804263c78bbSbostic 
805263c78bbSbostic     memset(el->el_term.t_cap, 0, TC_BUFSIZE);
806263c78bbSbostic 
807263c78bbSbostic     i = tgetent(el->el_term.t_cap, term);
808263c78bbSbostic 
809263c78bbSbostic     if (i <= 0) {
810263c78bbSbostic 	if (i == -1)
811263c78bbSbostic 	    (void) fprintf(el->el_errfile, "Cannot open /etc/termcap.\n");
812263c78bbSbostic 	else if (i == 0)
813263c78bbSbostic 	    (void) fprintf(el->el_errfile,
814263c78bbSbostic 			   "No entry for terminal type \"%s\"\n", term);
815263c78bbSbostic 	(void) fprintf(el->el_errfile, "using dumb terminal settings.\n");
816263c78bbSbostic 	Val(T_co) = 80;		/* do a dumb terminal */
817263c78bbSbostic 	Val(T_pt) = Val(T_km) = Val(T_li) = 0;
818263c78bbSbostic 	Val(T_xt) = Val(T_MT);
819263c78bbSbostic 	for (t = tstr; t->name != NULL; t++)
820263c78bbSbostic 	    term_alloc(el, t, NULL);
821263c78bbSbostic     }
822263c78bbSbostic     else {
823263c78bbSbostic 	/* Can we tab */
824263c78bbSbostic 	Val(T_pt) = tgetflag("pt");
825263c78bbSbostic 	Val(T_xt) = tgetflag("xt");
826263c78bbSbostic 	/* do we have a meta? */
827263c78bbSbostic 	Val(T_km) = tgetflag("km");
828263c78bbSbostic 	Val(T_MT) = tgetflag("MT");
829263c78bbSbostic 	/* Get the size */
830263c78bbSbostic 	Val(T_co) = tgetnum("co");
831263c78bbSbostic 	Val(T_li) = tgetnum("li");
832263c78bbSbostic 	for (t = tstr; t->name != NULL; t++)
833263c78bbSbostic 	    term_alloc(el, t, tgetstr(t->name, &area));
834263c78bbSbostic     }
835263c78bbSbostic 
836263c78bbSbostic     if (Val(T_co) < 2)
837263c78bbSbostic 	Val(T_co) = 80;		/* just in case */
838263c78bbSbostic     if (Val(T_li) < 1)
839263c78bbSbostic 	Val(T_li) = 24;
840263c78bbSbostic 
841263c78bbSbostic     el->el_term.t_size.v = Val(T_co);
842263c78bbSbostic     el->el_term.t_size.h = Val(T_li);
843263c78bbSbostic 
844263c78bbSbostic     term_setflags(el);
845263c78bbSbostic 
846263c78bbSbostic     (void) term_get_size(el, &lins, &cols);/* get the correct window size */
847263c78bbSbostic     term_change_size(el, lins, cols);
848263c78bbSbostic     (void) sigprocmask(SIG_SETMASK, &oset, NULL);
8498cbf4338Schristos     term_bind_arrow(el);
8508cbf4338Schristos     return 0;
8518cbf4338Schristos } /* end term_set */
852263c78bbSbostic 
853263c78bbSbostic 
854263c78bbSbostic /* term_get_size():
855263c78bbSbostic  *	Return the new window size in lines and cols, and
856263c78bbSbostic  *	true if the size was changed.
857263c78bbSbostic  */
858263c78bbSbostic protected int
term_get_size(el,lins,cols)859263c78bbSbostic term_get_size(el, lins, cols)
860263c78bbSbostic     EditLine *el;
861263c78bbSbostic     int    *lins, *cols;
862263c78bbSbostic {
863263c78bbSbostic 
864263c78bbSbostic     *cols = Val(T_co);
865263c78bbSbostic     *lins = Val(T_li);
866263c78bbSbostic 
867263c78bbSbostic #ifdef TIOCGWINSZ
868263c78bbSbostic     {
869263c78bbSbostic 	struct winsize ws;
870263c78bbSbostic 	if (ioctl(el->el_infd, TIOCGWINSZ, (ioctl_t) &ws) != -1) {
871263c78bbSbostic 	    if (ws.ws_col)
872263c78bbSbostic 		*cols = ws.ws_col;
873263c78bbSbostic 	    if (ws.ws_row)
874263c78bbSbostic 		*lins = ws.ws_row;
875263c78bbSbostic 	}
876263c78bbSbostic     }
877263c78bbSbostic #endif
878263c78bbSbostic #ifdef TIOCGSIZE
879263c78bbSbostic     {
880263c78bbSbostic 	struct ttysize ts;
881263c78bbSbostic 	if (ioctl(el->el_infd, TIOCGSIZE, (ioctl_t) &ts) != -1) {
882263c78bbSbostic 	    if (ts.ts_cols)
883263c78bbSbostic 		*cols = ts.ts_cols;
884263c78bbSbostic 	    if (ts.ts_lines)
885263c78bbSbostic 		*lins = ts.ts_lines;
886263c78bbSbostic 	}
887263c78bbSbostic     }
888263c78bbSbostic #endif
889263c78bbSbostic     return (Val(T_co) != *cols || Val(T_li) != *lins);
890263c78bbSbostic } /* end term_get_size */
891263c78bbSbostic 
892263c78bbSbostic 
893263c78bbSbostic /* term_change_size():
894263c78bbSbostic  *	Change the size of the terminal
895263c78bbSbostic  */
896263c78bbSbostic protected void
term_change_size(el,lins,cols)897263c78bbSbostic term_change_size(el, lins, cols)
898263c78bbSbostic     EditLine *el;
899263c78bbSbostic     int     lins, cols;
900263c78bbSbostic {
901263c78bbSbostic     /*
902263c78bbSbostic      * Just in case
903263c78bbSbostic      */
904263c78bbSbostic     Val(T_co) = (cols < 2) ? 80 : cols;
905263c78bbSbostic     Val(T_li) = (lins < 1) ? 24 : lins;
906263c78bbSbostic 
907263c78bbSbostic     term_rebuffer_display(el);		/* re-make display buffers */
908263c78bbSbostic     re_clear_display(el);
909263c78bbSbostic } /* end term_change_size */
910263c78bbSbostic 
911263c78bbSbostic 
9128cbf4338Schristos /* term_init_arrow():
9138cbf4338Schristos  *	Initialize the arrow key bindings from termcap
9148cbf4338Schristos  */
9158cbf4338Schristos private void
term_init_arrow(el)9168cbf4338Schristos term_init_arrow(el)
9178cbf4338Schristos     EditLine *el;
9188cbf4338Schristos {
9198cbf4338Schristos     fkey_t *arrow = el->el_term.t_fkey;
9208cbf4338Schristos 
9218cbf4338Schristos     arrow[A_K_DN].name    = "down";
922*dde3e7d7Schristos     arrow[A_K_DN].key	  = T_kd;
9238cbf4338Schristos     arrow[A_K_DN].fun.cmd = ED_NEXT_HISTORY;
9248cbf4338Schristos     arrow[A_K_DN].type    = XK_CMD;
9258cbf4338Schristos 
9268cbf4338Schristos     arrow[A_K_UP].name    = "up";
927*dde3e7d7Schristos     arrow[A_K_UP].key	  = T_ku;
9288cbf4338Schristos     arrow[A_K_UP].fun.cmd = ED_PREV_HISTORY;
9298cbf4338Schristos     arrow[A_K_UP].type    = XK_CMD;
9308cbf4338Schristos 
9318cbf4338Schristos     arrow[A_K_LT].name    = "left";
932*dde3e7d7Schristos     arrow[A_K_LT].key	  = T_kl;
9338cbf4338Schristos     arrow[A_K_LT].fun.cmd = ED_PREV_CHAR;
9348cbf4338Schristos     arrow[A_K_LT].type    = XK_CMD;
9358cbf4338Schristos 
9368cbf4338Schristos     arrow[A_K_RT].name    = "right";
937*dde3e7d7Schristos     arrow[A_K_RT].key	  = T_kr;
9388cbf4338Schristos     arrow[A_K_RT].fun.cmd = ED_NEXT_CHAR;
9398cbf4338Schristos     arrow[A_K_RT].type    = XK_CMD;
9408cbf4338Schristos 
9418cbf4338Schristos }
9428cbf4338Schristos 
9438cbf4338Schristos 
9448cbf4338Schristos /* term_reset_arrow():
9458cbf4338Schristos  *	Reset arrow key bindings
9468cbf4338Schristos  */
9478cbf4338Schristos private void
term_reset_arrow(el)9488cbf4338Schristos term_reset_arrow(el)
9498cbf4338Schristos     EditLine *el;
9508cbf4338Schristos {
9518cbf4338Schristos     fkey_t *arrow = el->el_term.t_fkey;
9528cbf4338Schristos     static char strA[] = {033, '[', 'A', '\0'};
9538cbf4338Schristos     static char strB[] = {033, '[', 'B', '\0'};
9548cbf4338Schristos     static char strC[] = {033, '[', 'C', '\0'};
9558cbf4338Schristos     static char strD[] = {033, '[', 'D', '\0'};
9568cbf4338Schristos     static char stOA[] = {033, 'O', 'A', '\0'};
9578cbf4338Schristos     static char stOB[] = {033, 'O', 'B', '\0'};
9588cbf4338Schristos     static char stOC[] = {033, 'O', 'C', '\0'};
9598cbf4338Schristos     static char stOD[] = {033, 'O', 'D', '\0'};
9608cbf4338Schristos 
9618cbf4338Schristos     key_add(el, strA, &arrow[A_K_UP].fun, arrow[A_K_UP].type);
9628cbf4338Schristos     key_add(el, strB, &arrow[A_K_DN].fun, arrow[A_K_DN].type);
9638cbf4338Schristos     key_add(el, strC, &arrow[A_K_RT].fun, arrow[A_K_RT].type);
9648cbf4338Schristos     key_add(el, strD, &arrow[A_K_LT].fun, arrow[A_K_LT].type);
9658cbf4338Schristos     key_add(el, stOA, &arrow[A_K_UP].fun, arrow[A_K_UP].type);
9668cbf4338Schristos     key_add(el, stOB, &arrow[A_K_DN].fun, arrow[A_K_DN].type);
9678cbf4338Schristos     key_add(el, stOC, &arrow[A_K_RT].fun, arrow[A_K_RT].type);
9688cbf4338Schristos     key_add(el, stOD, &arrow[A_K_LT].fun, arrow[A_K_LT].type);
9698cbf4338Schristos 
9708cbf4338Schristos     if (el->el_map.type == MAP_VI) {
9718cbf4338Schristos 	key_add(el, &strA[1], &arrow[A_K_UP].fun, arrow[A_K_UP].type);
9728cbf4338Schristos 	key_add(el, &strB[1], &arrow[A_K_DN].fun, arrow[A_K_DN].type);
9738cbf4338Schristos 	key_add(el, &strC[1], &arrow[A_K_RT].fun, arrow[A_K_RT].type);
9748cbf4338Schristos 	key_add(el, &strD[1], &arrow[A_K_LT].fun, arrow[A_K_LT].type);
9758cbf4338Schristos 	key_add(el, &stOA[1], &arrow[A_K_UP].fun, arrow[A_K_UP].type);
9768cbf4338Schristos 	key_add(el, &stOB[1], &arrow[A_K_DN].fun, arrow[A_K_DN].type);
9778cbf4338Schristos 	key_add(el, &stOC[1], &arrow[A_K_RT].fun, arrow[A_K_RT].type);
9788cbf4338Schristos 	key_add(el, &stOD[1], &arrow[A_K_LT].fun, arrow[A_K_LT].type);
9798cbf4338Schristos     }
9808cbf4338Schristos }
9818cbf4338Schristos 
9828cbf4338Schristos 
9838cbf4338Schristos /* term_set_arrow():
9848cbf4338Schristos  *	Set an arrow key binding
9858cbf4338Schristos  */
9868cbf4338Schristos protected int
term_set_arrow(el,name,fun,type)9878cbf4338Schristos term_set_arrow(el, name, fun, type)
9888cbf4338Schristos     EditLine *el;
9898cbf4338Schristos     char *name;
9908cbf4338Schristos     key_value_t *fun;
9918cbf4338Schristos     int type;
9928cbf4338Schristos {
9938cbf4338Schristos     fkey_t *arrow = el->el_term.t_fkey;
9948cbf4338Schristos     int i;
9958cbf4338Schristos 
9968cbf4338Schristos     for (i = 0; i < A_K_NKEYS; i++)
9978cbf4338Schristos 	if (strcmp(name, arrow[i].name) == 0) {
9988cbf4338Schristos 	    arrow[i].fun  = *fun;
9998cbf4338Schristos 	    arrow[i].type = type;
10008cbf4338Schristos 	    return 0;
10018cbf4338Schristos 	}
10028cbf4338Schristos     return -1;
10038cbf4338Schristos }
10048cbf4338Schristos 
10058cbf4338Schristos 
10068cbf4338Schristos /* term_clear_arrow():
10078cbf4338Schristos  *	Clear an arrow key binding
10088cbf4338Schristos  */
10098cbf4338Schristos protected int
term_clear_arrow(el,name)10108cbf4338Schristos term_clear_arrow(el, name)
10118cbf4338Schristos     EditLine *el;
10128cbf4338Schristos     char *name;
10138cbf4338Schristos {
10148cbf4338Schristos     fkey_t *arrow = el->el_term.t_fkey;
10158cbf4338Schristos     int i;
10168cbf4338Schristos 
10178cbf4338Schristos     for (i = 0; i < A_K_NKEYS; i++)
10188cbf4338Schristos 	if (strcmp(name, arrow[i].name) == 0) {
10198cbf4338Schristos 	    arrow[i].type = XK_NOD;
10208cbf4338Schristos 	    return 0;
10218cbf4338Schristos 	}
10228cbf4338Schristos     return -1;
10238cbf4338Schristos }
10248cbf4338Schristos 
10258cbf4338Schristos 
10268cbf4338Schristos /* term_print_arrow():
10278cbf4338Schristos  *	Print the arrow key bindings
10288cbf4338Schristos  */
10298cbf4338Schristos protected void
term_print_arrow(el,name)10308cbf4338Schristos term_print_arrow(el, name)
10318cbf4338Schristos     EditLine *el;
10328cbf4338Schristos     char *name;
10338cbf4338Schristos {
10348cbf4338Schristos     int i;
10358cbf4338Schristos     fkey_t *arrow = el->el_term.t_fkey;
10368cbf4338Schristos 
10378cbf4338Schristos     for (i = 0; i < A_K_NKEYS; i++)
10388cbf4338Schristos 	if (*name == '\0' || strcmp(name, arrow[i].name) == 0)
10398cbf4338Schristos 	    if (arrow[i].type != XK_NOD)
10408cbf4338Schristos 		key_kprint(el, arrow[i].name, &arrow[i].fun, arrow[i].type);
10418cbf4338Schristos }
10428cbf4338Schristos 
10438cbf4338Schristos 
10448cbf4338Schristos /* term_bind_arrow():
1045263c78bbSbostic  *	Bind the arrow keys
1046263c78bbSbostic  */
1047263c78bbSbostic protected void
term_bind_arrow(el)10488cbf4338Schristos term_bind_arrow(el)
1049263c78bbSbostic     EditLine *el;
1050263c78bbSbostic {
1051263c78bbSbostic     el_action_t *map, *dmap;
1052263c78bbSbostic     int     i, j;
1053263c78bbSbostic     char   *p;
10548cbf4338Schristos     fkey_t *arrow = el->el_term.t_fkey;
1055263c78bbSbostic 
1056263c78bbSbostic     /* Check if the components needed are initialized */
1057263c78bbSbostic     if (el->el_term.t_buf == NULL || el->el_map.key == NULL)
1058263c78bbSbostic 	return;
1059263c78bbSbostic 
1060263c78bbSbostic     map  = el->el_map.type == MAP_VI ? el->el_map.alt : el->el_map.key;
1061263c78bbSbostic     dmap = el->el_map.type == MAP_VI ? el->el_map.vic : el->el_map.emacs;
1062263c78bbSbostic 
10638cbf4338Schristos     term_reset_arrow(el);
10648cbf4338Schristos 
1065263c78bbSbostic     for (i = 0; i < 4; i++) {
10668cbf4338Schristos 	p = el->el_term.t_str[arrow[i].key];
1067263c78bbSbostic 	if (p && *p) {
1068263c78bbSbostic 	    j = (unsigned char) *p;
1069263c78bbSbostic 	    /*
1070263c78bbSbostic 	     * Assign the arrow keys only if:
1071263c78bbSbostic 	     *
1072263c78bbSbostic 	     * 1. They are multi-character arrow keys and the user
1073263c78bbSbostic 	     *    has not re-assigned the leading character, or
1074263c78bbSbostic 	     *    has re-assigned the leading character to be
1075263c78bbSbostic 	     *	  ED_SEQUENCE_LEAD_IN
1076263c78bbSbostic 	     * 2. They are single arrow keys pointing to an unassigned key.
1077263c78bbSbostic 	     */
10788cbf4338Schristos 	    if (arrow[i].type == XK_NOD)
10798cbf4338Schristos 		key_clear(el, map, p);
10808cbf4338Schristos 	    else {
10818cbf4338Schristos 		if (p[1] && (dmap[j] == map[j] ||
10828cbf4338Schristos 			     map[j] == ED_SEQUENCE_LEAD_IN)) {
10838cbf4338Schristos 		    key_add(el, p, &arrow[i].fun, arrow[i].type);
1084263c78bbSbostic 		    map[j] = ED_SEQUENCE_LEAD_IN;
1085263c78bbSbostic 		}
1086263c78bbSbostic 		else if (map[j] == ED_UNASSIGNED) {
1087263c78bbSbostic 		    key_clear(el, map, p);
10888cbf4338Schristos 		    if (arrow[i].type == XK_CMD)
10898cbf4338Schristos 			map[j] = arrow[i].fun.cmd;
10908cbf4338Schristos 		    else
10918cbf4338Schristos 			key_add(el, p, &arrow[i].fun, arrow[i].type);
10928cbf4338Schristos 		}
1093263c78bbSbostic 	    }
1094263c78bbSbostic 	}
1095263c78bbSbostic     }
1096263c78bbSbostic }
1097263c78bbSbostic 
1098263c78bbSbostic 
1099263c78bbSbostic /* term__putc():
1100263c78bbSbostic  *	Add a character
1101263c78bbSbostic  */
1102263c78bbSbostic protected void
term__putc(c)1103263c78bbSbostic term__putc(c)
1104263c78bbSbostic     int c;
1105263c78bbSbostic {
1106263c78bbSbostic     (void) fputc(c, term_outfile);
1107263c78bbSbostic } /* end term__putc */
1108263c78bbSbostic 
1109263c78bbSbostic 
1110263c78bbSbostic /* term__flush():
1111263c78bbSbostic  *	Flush output
1112263c78bbSbostic  */
1113263c78bbSbostic protected void
term__flush()1114263c78bbSbostic term__flush()
1115263c78bbSbostic {
1116263c78bbSbostic     (void) fflush(term_outfile);
1117263c78bbSbostic } /* end term__flush */
1118263c78bbSbostic 
1119263c78bbSbostic 
1120263c78bbSbostic /* term_telltc():
1121263c78bbSbostic  *	Print the current termcap characteristics
1122263c78bbSbostic  */
1123263c78bbSbostic protected int
1124263c78bbSbostic /*ARGSUSED*/
term_telltc(el,argc,argv)1125263c78bbSbostic term_telltc(el, argc, argv)
1126263c78bbSbostic     EditLine *el;
1127263c78bbSbostic     int argc;
1128263c78bbSbostic     char **argv;
1129263c78bbSbostic {
1130263c78bbSbostic     struct termcapstr *t;
1131263c78bbSbostic     char **ts;
1132263c78bbSbostic     char upbuf[EL_BUFSIZ];
1133263c78bbSbostic 
1134263c78bbSbostic     (void) fprintf(el->el_outfile, "\n\tYour terminal has the\n");
1135263c78bbSbostic     (void) fprintf(el->el_outfile, "\tfollowing characteristics:\n\n");
1136263c78bbSbostic     (void) fprintf(el->el_outfile, "\tIt has %d columns and %d lines\n",
1137263c78bbSbostic 	    Val(T_co), Val(T_li));
1138263c78bbSbostic     (void) fprintf(el->el_outfile,
1139263c78bbSbostic 		   "\tIt has %s meta key\n", EL_HAS_META ? "a" : "no");
1140263c78bbSbostic     (void) fprintf(el->el_outfile,
1141263c78bbSbostic 		   "\tIt can%suse tabs\n", EL_CAN_TAB ? " " : "not ");
1142263c78bbSbostic #ifdef notyet
1143263c78bbSbostic     (void) fprintf(el->el_outfile, "\tIt %s automatic margins\n",
1144263c78bbSbostic 		   (T_Margin&MARGIN_AUTO)? "has": "does not have");
1145263c78bbSbostic     if (T_Margin & MARGIN_AUTO)
1146263c78bbSbostic 	(void) fprintf(el->el_outfile, "\tIt %s magic margins\n",
1147263c78bbSbostic 			(T_Margin&MARGIN_MAGIC)?"has":"does not have");
1148263c78bbSbostic #endif
1149263c78bbSbostic 
1150263c78bbSbostic     for (t = tstr, ts = el->el_term.t_str; t->name != NULL; t++, ts++)
1151263c78bbSbostic 	(void) fprintf(el->el_outfile, "\t%25s (%s) == %s\n", t->long_name,
1152263c78bbSbostic 		       t->name, *ts && **ts ?
1153263c78bbSbostic 			key__decode_str(*ts, upbuf, "") : "(empty)");
1154263c78bbSbostic     (void) fputc('\n', el->el_outfile);
1155263c78bbSbostic     return 0;
1156263c78bbSbostic }
1157263c78bbSbostic 
1158263c78bbSbostic 
1159263c78bbSbostic /* term_settc():
1160263c78bbSbostic  *	Change the current terminal characteristics
1161263c78bbSbostic  */
1162263c78bbSbostic protected int
1163263c78bbSbostic /*ARGSUSED*/
term_settc(el,argc,argv)1164263c78bbSbostic term_settc(el, argc, argv)
1165263c78bbSbostic     EditLine *el;
1166263c78bbSbostic     int argc;
1167263c78bbSbostic     char **argv;
1168263c78bbSbostic {
1169263c78bbSbostic     struct termcapstr *ts;
1170263c78bbSbostic     struct termcapval *tv;
1171263c78bbSbostic     char   *what, *how;
1172263c78bbSbostic 
1173263c78bbSbostic     if (argv == NULL || argv[1] == NULL || argv[2] == NULL)
1174263c78bbSbostic 	return -1;
1175263c78bbSbostic 
1176263c78bbSbostic     what = argv[1];
1177263c78bbSbostic     how = argv[2];
1178263c78bbSbostic 
1179263c78bbSbostic     /*
1180263c78bbSbostic      * Do the strings first
1181263c78bbSbostic      */
1182263c78bbSbostic     for (ts = tstr; ts->name != NULL; ts++)
1183263c78bbSbostic 	if (strcmp(ts->name, what) == 0)
1184263c78bbSbostic 	    break;
1185263c78bbSbostic 
1186263c78bbSbostic     if (ts->name != NULL) {
1187263c78bbSbostic 	term_alloc(el, ts, how);
1188263c78bbSbostic 	term_setflags(el);
1189263c78bbSbostic 	return 0;
1190263c78bbSbostic     }
1191263c78bbSbostic 
1192263c78bbSbostic     /*
1193263c78bbSbostic      * Do the numeric ones second
1194263c78bbSbostic      */
1195263c78bbSbostic     for (tv = tval; tv->name != NULL; tv++)
1196263c78bbSbostic 	if (strcmp(tv->name, what) == 0)
1197263c78bbSbostic 	    break;
1198263c78bbSbostic 
1199263c78bbSbostic     if (tv->name != NULL) {
1200263c78bbSbostic 	if (tv == &tval[T_pt] || tv == &tval[T_km]
1201263c78bbSbostic #ifdef notyet
1202263c78bbSbostic 	    || tv == &tval[T_am] || tv == &tval[T_xn]
1203263c78bbSbostic #endif
1204263c78bbSbostic 	    ) {
1205263c78bbSbostic 	    if (strcmp(how, "yes") == 0)
1206263c78bbSbostic 		el->el_term.t_val[tv - tval] = 1;
1207263c78bbSbostic 	    else if (strcmp(how, "no") == 0)
1208263c78bbSbostic 		el->el_term.t_val[tv - tval] = 0;
1209263c78bbSbostic 	    else {
1210263c78bbSbostic 		(void) fprintf(el->el_errfile, "settc: Bad value `%s'.\n", how);
1211263c78bbSbostic 		return -1;
1212263c78bbSbostic 	    }
1213263c78bbSbostic 	    term_setflags(el);
1214263c78bbSbostic 	    term_change_size(el, Val(T_li), Val(T_co));
1215263c78bbSbostic 	    return 0;
1216263c78bbSbostic 	}
1217263c78bbSbostic 	else {
1218263c78bbSbostic 	    el->el_term.t_val[tv - tval] = atoi(how);
1219263c78bbSbostic 	    el->el_term.t_size.v = Val(T_co);
1220263c78bbSbostic 	    el->el_term.t_size.h = Val(T_li);
1221263c78bbSbostic 	    if (tv == &tval[T_co] || tv == &tval[T_li])
1222263c78bbSbostic 		term_change_size(el, Val(T_li), Val(T_co));
1223263c78bbSbostic 	    return 0;
1224263c78bbSbostic 	}
1225263c78bbSbostic     }
1226263c78bbSbostic     return -1;
1227263c78bbSbostic }
1228263c78bbSbostic 
1229263c78bbSbostic 
1230263c78bbSbostic /* term_echotc():
1231263c78bbSbostic  *	Print the termcap string out with variable substitution
1232263c78bbSbostic  */
1233263c78bbSbostic protected int
1234263c78bbSbostic /*ARGSUSED*/
term_echotc(el,argc,argv)1235263c78bbSbostic term_echotc(el, argc, argv)
1236263c78bbSbostic     EditLine *el;
1237263c78bbSbostic     int argc;
1238263c78bbSbostic     char **argv;
1239263c78bbSbostic {
1240263c78bbSbostic     char   *cap, *scap;
1241263c78bbSbostic     int     arg_need, arg_cols, arg_rows;
1242263c78bbSbostic     int     verbose = 0, silent = 0;
1243263c78bbSbostic     char   *area;
1244263c78bbSbostic     static char *fmts = "%s\n", *fmtd = "%d\n";
1245263c78bbSbostic     struct termcapstr *t;
1246263c78bbSbostic     char    buf[TC_BUFSIZE];
1247263c78bbSbostic 
1248263c78bbSbostic     area = buf;
1249263c78bbSbostic 
1250263c78bbSbostic     if (argv == NULL || argv[1] == NULL)
1251263c78bbSbostic 	return -1;
1252263c78bbSbostic     argv++;
1253263c78bbSbostic 
1254263c78bbSbostic     if (argv[0][0] == '-') {
1255263c78bbSbostic 	switch (argv[0][1]) {
1256263c78bbSbostic 	case 'v':
1257263c78bbSbostic 	    verbose = 1;
1258263c78bbSbostic 	    break;
1259263c78bbSbostic 	case 's':
1260263c78bbSbostic 	    silent = 1;
1261263c78bbSbostic 	    break;
1262263c78bbSbostic 	default:
1263263c78bbSbostic 	    /* stderror(ERR_NAME | ERR_TCUSAGE); */
1264263c78bbSbostic 	    break;
1265263c78bbSbostic 	}
1266263c78bbSbostic 	argv++;
1267263c78bbSbostic     }
1268263c78bbSbostic     if (!*argv || *argv[0] == '\0')
1269263c78bbSbostic 	return 0;
1270263c78bbSbostic     if (strcmp(*argv, "tabs") == 0) {
1271263c78bbSbostic 	(void) fprintf(el->el_outfile, fmts, EL_CAN_TAB ? "yes" : "no");
1272263c78bbSbostic 	return 0;
1273263c78bbSbostic     }
1274263c78bbSbostic     else if (strcmp(*argv, "meta") == 0) {
1275263c78bbSbostic 	(void) fprintf(el->el_outfile, fmts, Val(T_km) ? "yes" : "no");
1276263c78bbSbostic 	return 0;
1277263c78bbSbostic     }
1278263c78bbSbostic #ifdef notyet
1279263c78bbSbostic     else if (strcmp(*argv, "xn") == 0) {
1280263c78bbSbostic 	(void) fprintf(el->el_outfile, fmts, T_Margin & MARGIN_MAGIC ?
1281263c78bbSbostic 			"yes" : "no");
1282263c78bbSbostic 	return 0;
1283263c78bbSbostic     }
1284263c78bbSbostic     else if (strcmp(*argv, "am") == 0) {
1285263c78bbSbostic 	(void) fprintf(el->el_outfile, fmts, T_Margin & MARGIN_AUTO ?
1286263c78bbSbostic 			"yes" : "no");
1287263c78bbSbostic 	return 0;
1288263c78bbSbostic     }
1289263c78bbSbostic #endif
1290263c78bbSbostic     else if (strcmp(*argv, "baud") == 0) {
1291263c78bbSbostic 	int     i;
1292263c78bbSbostic 
1293263c78bbSbostic 	for (i = 0; baud_rate[i].b_name != NULL; i++)
1294263c78bbSbostic 	    if (el->el_tty.t_speed == baud_rate[i].b_rate) {
1295263c78bbSbostic 		(void) fprintf(el->el_outfile, fmts, baud_rate[i].b_name);
1296263c78bbSbostic 		return 0;
1297263c78bbSbostic 	    }
1298263c78bbSbostic 	(void) fprintf(el->el_outfile, fmtd, 0);
1299263c78bbSbostic 	return 0;
1300263c78bbSbostic     }
1301263c78bbSbostic     else if (strcmp(*argv, "rows") == 0 || strcmp(*argv, "lines") == 0) {
1302263c78bbSbostic 	(void) fprintf(el->el_outfile, fmtd, Val(T_li));
1303263c78bbSbostic 	return 0;
1304263c78bbSbostic     }
1305263c78bbSbostic     else if (strcmp(*argv, "cols") == 0) {
1306263c78bbSbostic 	(void) fprintf(el->el_outfile, fmtd, Val(T_co));
1307263c78bbSbostic 	return 0;
1308263c78bbSbostic     }
1309263c78bbSbostic 
1310263c78bbSbostic     /*
1311263c78bbSbostic      * Try to use our local definition first
1312263c78bbSbostic      */
1313263c78bbSbostic     scap = NULL;
1314263c78bbSbostic     for (t = tstr; t->name != NULL; t++)
1315263c78bbSbostic 	if (strcmp(t->name, *argv) == 0) {
1316263c78bbSbostic 	    scap = el->el_term.t_str[t - tstr];
1317263c78bbSbostic 	    break;
1318263c78bbSbostic 	}
1319263c78bbSbostic     if (t->name == NULL)
1320263c78bbSbostic 	scap = tgetstr(*argv, &area);
1321263c78bbSbostic     if (!scap || scap[0] == '\0') {
1322263c78bbSbostic 	if (!silent)
1323263c78bbSbostic 	    (void) fprintf(el->el_errfile,
1324263c78bbSbostic 		"echotc: Termcap parameter `%s' not found.\n", *argv);
1325263c78bbSbostic 	return -1;
1326263c78bbSbostic     }
1327263c78bbSbostic 
1328263c78bbSbostic     /*
1329263c78bbSbostic      * Count home many values we need for this capability.
1330263c78bbSbostic      */
1331263c78bbSbostic     for (cap = scap, arg_need = 0; *cap; cap++)
1332263c78bbSbostic 	if (*cap == '%')
1333263c78bbSbostic 	    switch (*++cap) {
1334263c78bbSbostic 	    case 'd':
1335263c78bbSbostic 	    case '2':
1336263c78bbSbostic 	    case '3':
1337263c78bbSbostic 	    case '.':
1338263c78bbSbostic 	    case '+':
1339263c78bbSbostic 		arg_need++;
1340263c78bbSbostic 		break;
1341263c78bbSbostic 	    case '%':
1342263c78bbSbostic 	    case '>':
1343263c78bbSbostic 	    case 'i':
1344263c78bbSbostic 	    case 'r':
1345263c78bbSbostic 	    case 'n':
1346263c78bbSbostic 	    case 'B':
1347263c78bbSbostic 	    case 'D':
1348263c78bbSbostic 		break;
1349263c78bbSbostic 	    default:
1350263c78bbSbostic 		/*
1351263c78bbSbostic 		 * hpux has lot's of them...
1352263c78bbSbostic 		 */
1353263c78bbSbostic 		if (verbose)
1354263c78bbSbostic 		    (void) fprintf(el->el_errfile,
1355263c78bbSbostic 			"echotc: Warning: unknown termcap %% `%c'.\n", *cap);
1356263c78bbSbostic 		/* This is bad, but I won't complain */
1357263c78bbSbostic 		break;
1358263c78bbSbostic 	    }
1359263c78bbSbostic 
1360263c78bbSbostic     switch (arg_need) {
1361263c78bbSbostic     case 0:
1362263c78bbSbostic 	argv++;
1363263c78bbSbostic 	if (*argv && *argv[0]) {
1364263c78bbSbostic 	    if (!silent)
1365263c78bbSbostic 		(void) fprintf(el->el_errfile,
1366263c78bbSbostic 		    "echotc: Warning: Extra argument `%s'.\n", *argv);
1367263c78bbSbostic 	    return -1;
1368263c78bbSbostic 	}
1369263c78bbSbostic 	(void) tputs(scap, 1, term__putc);
1370263c78bbSbostic 	break;
1371263c78bbSbostic     case 1:
1372263c78bbSbostic 	argv++;
1373263c78bbSbostic 	if (!*argv || *argv[0] == '\0') {
1374263c78bbSbostic 	    if (!silent)
1375263c78bbSbostic 		(void) fprintf(el->el_errfile,
1376263c78bbSbostic 		    "echotc: Warning: Missing argument.\n");
1377263c78bbSbostic 	    return -1;
1378263c78bbSbostic 	}
1379263c78bbSbostic 	arg_cols = 0;
1380263c78bbSbostic 	arg_rows = atoi(*argv);
1381263c78bbSbostic 	argv++;
1382263c78bbSbostic 	if (*argv && *argv[0]) {
1383263c78bbSbostic 	    if (!silent)
1384263c78bbSbostic 		(void) fprintf(el->el_errfile,
1385263c78bbSbostic 		    "echotc: Warning: Extra argument `%s'.\n", *argv);
1386263c78bbSbostic 	    return -1;
1387263c78bbSbostic 	}
1388263c78bbSbostic 	(void) tputs(tgoto(scap, arg_cols, arg_rows), 1, term__putc);
1389263c78bbSbostic 	break;
1390263c78bbSbostic     default:
1391263c78bbSbostic 	/* This is wrong, but I will ignore it... */
1392263c78bbSbostic 	if (verbose)
1393263c78bbSbostic 	    (void) fprintf(el->el_errfile,
1394263c78bbSbostic 		"echotc: Warning: Too many required arguments (%d).\n",
1395263c78bbSbostic 		arg_need);
1396263c78bbSbostic 	/*FALLTHROUGH*/
1397263c78bbSbostic     case 2:
1398263c78bbSbostic 	argv++;
1399263c78bbSbostic 	if (!*argv || *argv[0] == '\0') {
1400263c78bbSbostic 	    if (!silent)
1401263c78bbSbostic 		(void) fprintf(el->el_errfile,
1402263c78bbSbostic 		    "echotc: Warning: Missing argument.\n");
1403263c78bbSbostic 	    return -1;
1404263c78bbSbostic 	}
1405263c78bbSbostic 	arg_cols = atoi(*argv);
1406263c78bbSbostic 	argv++;
1407263c78bbSbostic 	if (!*argv || *argv[0] == '\0') {
1408263c78bbSbostic 	    if (!silent)
1409263c78bbSbostic 		(void) fprintf(el->el_errfile,
1410263c78bbSbostic 		    "echotc: Warning: Missing argument.\n");
1411263c78bbSbostic 	    return -1;
1412263c78bbSbostic 	}
1413263c78bbSbostic 	arg_rows = atoi(*argv);
1414263c78bbSbostic 	argv++;
1415263c78bbSbostic 	if (*argv && *argv[0]) {
1416263c78bbSbostic 	    if (!silent)
1417263c78bbSbostic 		(void) fprintf(el->el_errfile,
1418263c78bbSbostic 		    "echotc: Warning: Extra argument `%s'.\n", *argv);
1419263c78bbSbostic 	    return -1;
1420263c78bbSbostic 	}
1421263c78bbSbostic 	(void) tputs(tgoto(scap, arg_cols, arg_rows), arg_rows, term__putc);
1422263c78bbSbostic 	break;
1423263c78bbSbostic     }
1424263c78bbSbostic     return 0;
1425263c78bbSbostic }
1426