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