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