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