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