Home | History | Annotate | Line # | Download | only in cl
cl_bsd.c revision 1.1
      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
     11 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 #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 <signal.h>
     21 #include <stdio.h>
     22 #include <stdlib.h>
     23 #include <string.h>
     24 #include <termios.h>
     25 #include <unistd.h>
     26 
     27 #include "../common/common.h"
     28 #include "../vi/vi.h"
     29 #include "cl.h"
     30 
     31 static char	*ke;				/* Keypad on. */
     32 static char	*ks;				/* Keypad off. */
     33 static char	*vb;				/* Visible bell string. */
     34 
     35 /*
     36  * HP's support the entire System V curses package except for the tigetstr
     37  * and tigetnum functions.  Ultrix supports the BSD curses package except
     38  * for the idlok function.  Cthulu only knows why.  Break things up into a
     39  * minimal set of functions.
     40  */
     41 
     42 #ifndef HAVE_CURSES_WADDNSTR
     43 /*
     44  * waddnstr --
     45  *
     46  * PUBLIC: #ifndef HAVE_CURSES_WADDNSTR
     47  * PUBLIC: int waddnstr __P((WINDOW*, char *, int));
     48  * PUBLIC: #endif
     49  */
     50 int
     51 waddnstr(w, s, n)
     52 	WINDOW *w;
     53 	char *s;
     54 	int n;
     55 {
     56 	int ch;
     57 
     58 	while (n-- && (ch = *s++))
     59 		waddch(w, 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  */
     72 void
     73 beep()
     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  */
     88 void
     89 flash()
     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  */
    108 void
    109 idlok(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  */
    126 int
    127 keypad(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  */
    150 void *
    151 newterm(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  */
    168 void
    169 setupterm(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. */
    195 typedef struct _tl {
    196 	char *terminfo;			/* Terminfo name. */
    197 	char *termcap;			/* Termcap name. */
    198 } TL;
    199 static 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  */
    236 static 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  */
    254 static 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  */
    268 static int
    269 lcmp(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  */
    288 char *
    289 tigetstr(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  */
    332 int
    333 tigetnum(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