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