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