xref: /netbsd-src/external/bsd/nvi/dist/cl/cl_bsd.c (revision 75f37f2751b83883a29f2af00c25e9f682f1670c)
1 /*	$NetBSD: cl_bsd.c,v 1.4 2017/11/06 03:08:41 rin Exp $ */
2 /*-
3  * Copyright (c) 1995, 1996
4  *	Keith Bostic.  All rights reserved.
5  *
6  * See the LICENSE file for redistribution information.
7  */
8 
9 #include "config.h"
10 
11 #include <sys/cdefs.h>
12 #if 0
13 #ifndef lint
14 static const char sccsid[] = "Id: cl_bsd.c,v 8.32 2000/12/01 13:56:17 skimo Exp  (Berkeley) Date: 2000/12/01 13:56:17 ";
15 #endif /* not lint */
16 #else
17 __RCSID("$NetBSD: cl_bsd.c,v 1.4 2017/11/06 03:08:41 rin Exp $");
18 #endif
19 
20 #include <sys/types.h>
21 #include <sys/queue.h>
22 #include <sys/time.h>
23 
24 #include <bitstring.h>
25 #include <ctype.h>
26 #include <signal.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <termios.h>
31 #include <unistd.h>
32 
33 #include "../common/common.h"
34 #include "../vi/vi.h"
35 #include "cl.h"
36 
37 #ifndef HAVE_CURSES_SETUPTERM
38 static char	*ke;				/* Keypad on. */
39 static char	*ks;				/* Keypad off. */
40 static char	*vb;				/* Visible bell string. */
41 #endif
42 
43 /*
44  * HP's support the entire System V curses package except for the tigetstr
45  * and tigetnum functions.  Ultrix supports the BSD curses package except
46  * for the idlok function.  Cthulu only knows why.  Break things up into a
47  * minimal set of functions.
48  */
49 
50 #ifndef HAVE_CURSES_WADDNSTR
51 /*
52  * waddnstr --
53  *
54  * PUBLIC: #ifndef HAVE_CURSES_WADDNSTR
55  * PUBLIC: int waddnstr __P((WINDOW*, char *, int));
56  * PUBLIC: #endif
57  */
58 int
waddnstr(w,s,n)59 waddnstr(w, s, n)
60 	WINDOW *w;
61 	char *s;
62 	int n;
63 {
64 	int ch;
65 
66 	while (n-- && (ch = *s++))
67 		waddch(w, ch);
68 	return (OK);
69 }
70 #endif
71 
72 #ifndef	HAVE_CURSES_BEEP
73 /*
74  * beep --
75  *
76  * PUBLIC: #ifndef HAVE_CURSES_BEEP
77  * PUBLIC: void beep __P((void));
78  * PUBLIC: #endif
79  */
80 void
beep()81 beep()
82 {
83 	(void)write(1, "\007", 1);	/* '\a' */
84 }
85 #endif /* !HAVE_CURSES_BEEP */
86 
87 #ifndef	HAVE_CURSES_FLASH
88 /*
89  * flash --
90  *	Flash the screen.
91  *
92  * PUBLIC: #ifndef HAVE_CURSES_FLASH
93  * PUBLIC: void flash __P((void));
94  * PUBLIC: #endif
95  */
96 void
flash()97 flash()
98 {
99 	if (vb != NULL) {
100 		(void)tputs(vb, 1, cl_putchar);
101 		(void)fflush(stdout);
102 	} else
103 		beep();
104 }
105 #endif /* !HAVE_CURSES_FLASH */
106 
107 #ifndef	HAVE_CURSES_IDLOK
108 /*
109  * idlok --
110  *	Turn on/off hardware line insert/delete.
111  *
112  * PUBLIC: #ifndef HAVE_CURSES_IDLOK
113  * PUBLIC: void idlok __P((WINDOW *, int));
114  * PUBLIC: #endif
115  */
116 void
idlok(win,bf)117 idlok(win, bf)
118 	WINDOW *win;
119 	int bf;
120 {
121 	return;
122 }
123 #endif /* !HAVE_CURSES_IDLOK */
124 
125 #ifndef	HAVE_CURSES_KEYPAD
126 /*
127  * keypad --
128  *	Put the keypad/cursor arrows into or out of application mode.
129  *
130  * PUBLIC: #ifndef HAVE_CURSES_KEYPAD
131  * PUBLIC: int keypad __P((void *, int));
132  * PUBLIC: #endif
133  */
134 int
keypad(a,on)135 keypad(a, on)
136 	void *a;
137 	int on;
138 {
139 	char *p;
140 
141 	if ((p = tigetstr(on ? "smkx" : "rmkx")) != (char *)-1) {
142 		(void)tputs(p, 0, cl_putchar);
143 		(void)fflush(stdout);
144 	}
145 	return (0);
146 }
147 #endif /* !HAVE_CURSES_KEYPAD */
148 
149 #ifndef	HAVE_CURSES_NEWTERM
150 /*
151  * newterm --
152  *	Create a new curses screen.
153  *
154  * PUBLIC: #ifndef HAVE_CURSES_NEWTERM
155  * PUBLIC: void *newterm __P((const char *, FILE *, FILE *));
156  * PUBLIC: #endif
157  */
158 void *
newterm(a,b,c)159 newterm(a, b, c)
160 	const char *a;
161 	FILE *b, *c;
162 {
163 	return (initscr());
164 }
165 #endif /* !HAVE_CURSES_NEWTERM */
166 
167 #ifndef	HAVE_CURSES_SETUPTERM
168 /*
169  * setupterm --
170  *	Set up terminal.
171  *
172  * PUBLIC: #ifndef HAVE_CURSES_SETUPTERM
173  * PUBLIC: void setupterm __P((char *, int, int *));
174  * PUBLIC: #endif
175  */
176 void
setupterm(ttype,fno,errp)177 setupterm(ttype, fno, errp)
178 	char *ttype;
179 	int fno, *errp;
180 {
181 	static char buf[2048];
182 	char *p;
183 
184 	if ((*errp = tgetent(buf, ttype)) > 0) {
185 		if (ke != NULL)
186 			free(ke);
187 		ke = ((p = tigetstr("rmkx")) == (char *)-1) ?
188 		    NULL : strdup(p);
189 		if (ks != NULL)
190 			free(ks);
191 		ks = ((p = tigetstr("smkx")) == (char *)-1) ?
192 		    NULL : strdup(p);
193 		if (vb != NULL)
194 			free(vb);
195 		vb = ((p = tigetstr("flash")) == (char *)-1) ?
196 		    NULL : strdup(p);
197 	}
198 }
199 #endif /* !HAVE_CURSES_SETUPTERM */
200 
201 #ifndef	HAVE_CURSES_TIGETSTR
202 /* Terminfo-to-termcap translation table. */
203 typedef struct _tl {
204 	const char *terminfo;		/* Terminfo name. */
205 	const char *termcap;		/* Termcap name. */
206 } TL;
207 static const TL list[] = {
208 	{ "cols",	"co", },	/* Terminal columns. */
209 	{ "cup",	"cm", },	/* Cursor up. */
210 	{ "cuu1",	"up", },	/* Cursor up. */
211 	{ "el",		"ce", },	/* Clear to end-of-line. */
212 	{ "flash",	"vb", },	/* Visible bell. */
213 	{ "kcub1",  	"kl", },	/* Cursor left. */
214 	{ "kcud1",	"kd", },	/* Cursor down. */
215 	{ "kcuf1",	"kr", },	/* Cursor right. */
216 	{ "kcuu1",  	"ku", },	/* Cursor up. */
217 	{ "kdch1",	"kD", },	/* Delete character. */
218 	{ "kdl1",	"kL", },	/* Delete line. */
219 	{ "ked",	"kS", },	/* Delete to end of screen. */
220 	{ "kel",	"kE", },	/* Delete to eol. */
221 	{ "kend",	"@7", },	/* Go to eol. */
222 	{ "khome",	"kh", },	/* Go to sol. */
223 	{ "kich1",	"kI", },	/* Insert at cursor. */
224 	{ "kil1",	"kA", },	/* Insert line. */
225 	{ "kind",	"kF", },	/* Scroll down. */
226 	{ "kll",	"kH", },	/* Go to eol. */
227 	{ "knp",	"kN", },	/* Page down. */
228 	{ "kpp",	"kP", },	/* Page up. */
229 	{ "kri",	"kR", },	/* Scroll up. */
230 	{ "lines",	"li", },	/* Terminal lines. */
231 	{ "rmcup",	"te", },	/* Terminal end string. */
232 	{ "rmkx",	"ke", },	/* Exit "keypad-transmit" mode. */
233 	{ "rmso",	"se", },	/* Standout end. */
234 	{ "smcup",	"ti", },	/* Terminal initialization string. */
235 	{ "smkx",	"ks", },	/* Enter "keypad-transmit" mode. */
236 	{ "smso",	"so", },	/* Standout begin. */
237 };
238 
239 #ifdef _AIX
240 /*
241  * AIX's implementation for function keys greater than 10 is different and
242  * only goes as far as 36.
243  */
244 static const char codes[] = {
245 /*  0-10 */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ';',
246 /* 11-20 */ '<', '>', '!', '@', '#', '$', '%', '^', '&', '*',
247 /* 21-30 */ '(', ')', '-', '_', '+', ',', ':', '?', '[', ']',
248 /* 31-36 */ '{', '}', '|', '~', '/', '='
249 };
250 
251 #else
252 
253 /*
254  * !!!
255  * Historically, the 4BSD termcap code didn't support functions keys greater
256  * than 9.  This was silently enforced -- asking for key k12 would return the
257  * value for k1.  We try and get around this by using the tables specified in
258  * the terminfo(TI_ENV) man page from the 3rd Edition SVID.  This assumes the
259  * implementors of any System V compatibility code or an extended termcap used
260  * those codes.
261  */
262 static const char codes[] = {
263 /*  0-10 */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ';',
264 /* 11-19 */ '1', '2', '3', '4', '5', '6', '7', '8', '9',
265 /* 20-63 */ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
266 	    'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
267 	    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
268 	    'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
269 };
270 #endif /* _AIX */
271 
272 /*
273  * lcmp --
274  *	list comparison routine for bsearch.
275  */
276 static int
lcmp(const void * a,const void * b)277 lcmp(const void *a, const void *b)
278 {
279 	return (strcmp(a, ((const TL *)b)->terminfo));
280 }
281 
282 /*
283  * tigetstr --
284  *
285  * Vendors put the prototype for tigetstr into random include files, including
286  * <term.h>, which we can't include because it makes other systems unhappy.
287  * Try and work around the problem, since we only care about the return value.
288  *
289  * PUBLIC: #ifdef HAVE_CURSES_TIGETSTR
290  * PUBLIC: #if 0
291  * PUBLIC: char *tigetstr __P((const char *));
292  * PUBLIC: #endif
293  * PUBLIC: #else
294  * PUBLIC: char *tigetstr __P((char *));
295  * PUBLIC: #endif
296  */
297 char *
tigetstr(name)298 tigetstr(name)
299 	const char *name;
300 {
301 	static char sbuf[256];
302 	TL *tlp;
303 	int n;
304 	char *p, mykeyname[3];
305 
306 	if ((tlp = bsearch(name,
307 	    list, sizeof(list) / sizeof(TL), sizeof(TL), lcmp)) == NULL) {
308 #ifdef _AIX
309 		if (name[0] == 'k' &&
310 		    name[1] == 'f' && (n = atoi(name + 2)) <= 36) {
311 			mykeyname[0] = 'k';
312 			mykeyname[1] = codes[n];
313 			mykeyname[2] = '\0';
314 #else
315 		if (name[0] == 'k' &&
316 		    name[1] == 'f' && (n = atoi(name + 2)) <= 63) {
317 			mykeyname[0] = n <= 10 ? 'k' : 'F';
318 			mykeyname[1] = codes[n];
319 			mykeyname[2] = '\0';
320 #endif
321 			name = mykeyname;
322 		}
323 	} else
324 		name = tlp->termcap;
325 
326 	p = sbuf;
327 #ifdef _AIX
328 	return ((p = tgetstr(name, &p)) == NULL ? (char *)-1 : strcpy(sbuf, p));
329 #else
330 	return (tgetstr(name, &p) == NULL ? (char *)-1 : sbuf);
331 #endif
332 }
333 
334 /*
335  * tigetnum --
336  *
337  * PUBLIC: #ifndef HAVE_CURSES_TIGETSTR
338  * PUBLIC: int tigetnum __P((char *));
339  * PUBLIC: #endif
340  */
341 int
tigetnum(name)342 tigetnum(name)
343 	const char *name;
344 {
345 	TL *tlp;
346 	int val;
347 
348 	if ((tlp = bsearch(name,
349 	    list, sizeof(list) / sizeof(TL), sizeof(TL), lcmp)) != NULL) {
350 		name = tlp->termcap;
351 	}
352 
353 	return ((val = tgetnum(name)) == -1 ? -2 : val);
354 }
355 #endif /* !HAVE_CURSES_TIGETSTR */
356 
357