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