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