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