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