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