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
14static 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
38static char	*ke;				/* Keypad on. */
39static char	*ks;				/* Keypad off. */
40static 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 */
58int
59waddnstr(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 */
80void
81beep()
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 */
96void
97flash()
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 */
116void
117idlok(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 */
134int
135keypad(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 */
158void *
159newterm(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 */
176void
177setupterm(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. */
203typedef struct _tl {
204	const char *terminfo;		/* Terminfo name. */
205	const char *termcap;		/* Termcap name. */
206} TL;
207static 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 */
244static 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 */
262static 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 */
276static int
277lcmp(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 */
297char *
298tigetstr(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 */
341int
342tigetnum(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