2013-12-06 12:04:52 +01:00
|
|
|
/* $NetBSD: cl_bsd.c,v 1.2 2013/11/22 15:52:05 christos Exp $ */
|
2013-01-22 12:03:53 +01:00
|
|
|
/*-
|
|
|
|
* Copyright (c) 1995, 1996
|
|
|
|
* Keith Bostic. All rights reserved.
|
|
|
|
*
|
|
|
|
* See the LICENSE file for redistribution information.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#ifndef lint
|
2013-12-06 12:04:52 +01:00
|
|
|
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 ";
|
2013-01-22 12:03:53 +01:00
|
|
|
#endif /* not lint */
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/queue.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
|
|
|
|
#include <bitstring.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <termios.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include "../common/common.h"
|
|
|
|
#include "../vi/vi.h"
|
|
|
|
#include "cl.h"
|
|
|
|
|
|
|
|
#ifndef HAVE_CURSES_SETUPTERM
|
|
|
|
static char *ke; /* Keypad on. */
|
|
|
|
static char *ks; /* Keypad off. */
|
|
|
|
static char *vb; /* Visible bell string. */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* HP's support the entire System V curses package except for the tigetstr
|
|
|
|
* and tigetnum functions. Ultrix supports the BSD curses package except
|
|
|
|
* for the idlok function. Cthulu only knows why. Break things up into a
|
|
|
|
* minimal set of functions.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef HAVE_CURSES_WADDNSTR
|
|
|
|
/*
|
|
|
|
* waddnstr --
|
|
|
|
*
|
|
|
|
* PUBLIC: #ifndef HAVE_CURSES_WADDNSTR
|
|
|
|
* PUBLIC: int waddnstr __P((WINDOW*, char *, int));
|
|
|
|
* PUBLIC: #endif
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
waddnstr(w, s, n)
|
|
|
|
WINDOW *w;
|
|
|
|
char *s;
|
|
|
|
int n;
|
|
|
|
{
|
|
|
|
int ch;
|
|
|
|
|
|
|
|
while (n-- && (ch = *s++))
|
|
|
|
waddch(w, ch);
|
|
|
|
return (OK);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef HAVE_CURSES_BEEP
|
|
|
|
/*
|
|
|
|
* beep --
|
|
|
|
*
|
|
|
|
* PUBLIC: #ifndef HAVE_CURSES_BEEP
|
|
|
|
* PUBLIC: void beep __P((void));
|
|
|
|
* PUBLIC: #endif
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
beep()
|
|
|
|
{
|
|
|
|
(void)write(1, "\007", 1); /* '\a' */
|
|
|
|
}
|
|
|
|
#endif /* !HAVE_CURSES_BEEP */
|
|
|
|
|
|
|
|
#ifndef HAVE_CURSES_FLASH
|
|
|
|
/*
|
|
|
|
* flash --
|
|
|
|
* Flash the screen.
|
|
|
|
*
|
|
|
|
* PUBLIC: #ifndef HAVE_CURSES_FLASH
|
|
|
|
* PUBLIC: void flash __P((void));
|
|
|
|
* PUBLIC: #endif
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
flash()
|
|
|
|
{
|
|
|
|
if (vb != NULL) {
|
|
|
|
(void)tputs(vb, 1, cl_putchar);
|
|
|
|
(void)fflush(stdout);
|
|
|
|
} else
|
|
|
|
beep();
|
|
|
|
}
|
|
|
|
#endif /* !HAVE_CURSES_FLASH */
|
|
|
|
|
|
|
|
#ifndef HAVE_CURSES_IDLOK
|
|
|
|
/*
|
|
|
|
* idlok --
|
|
|
|
* Turn on/off hardware line insert/delete.
|
|
|
|
*
|
|
|
|
* PUBLIC: #ifndef HAVE_CURSES_IDLOK
|
|
|
|
* PUBLIC: void idlok __P((WINDOW *, int));
|
|
|
|
* PUBLIC: #endif
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
idlok(win, bf)
|
|
|
|
WINDOW *win;
|
|
|
|
int bf;
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif /* !HAVE_CURSES_IDLOK */
|
|
|
|
|
|
|
|
#ifndef HAVE_CURSES_KEYPAD
|
|
|
|
/*
|
|
|
|
* keypad --
|
|
|
|
* Put the keypad/cursor arrows into or out of application mode.
|
|
|
|
*
|
|
|
|
* PUBLIC: #ifndef HAVE_CURSES_KEYPAD
|
|
|
|
* PUBLIC: int keypad __P((void *, int));
|
|
|
|
* PUBLIC: #endif
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
keypad(a, on)
|
|
|
|
void *a;
|
|
|
|
int on;
|
|
|
|
{
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
if ((p = tigetstr(on ? "smkx" : "rmkx")) != (char *)-1) {
|
|
|
|
(void)tputs(p, 0, cl_putchar);
|
|
|
|
(void)fflush(stdout);
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
#endif /* !HAVE_CURSES_KEYPAD */
|
|
|
|
|
|
|
|
#ifndef HAVE_CURSES_NEWTERM
|
|
|
|
/*
|
|
|
|
* newterm --
|
|
|
|
* Create a new curses screen.
|
|
|
|
*
|
|
|
|
* PUBLIC: #ifndef HAVE_CURSES_NEWTERM
|
|
|
|
* PUBLIC: void *newterm __P((const char *, FILE *, FILE *));
|
|
|
|
* PUBLIC: #endif
|
|
|
|
*/
|
|
|
|
void *
|
|
|
|
newterm(a, b, c)
|
|
|
|
const char *a;
|
|
|
|
FILE *b, *c;
|
|
|
|
{
|
|
|
|
return (initscr());
|
|
|
|
}
|
|
|
|
#endif /* !HAVE_CURSES_NEWTERM */
|
|
|
|
|
|
|
|
#ifndef HAVE_CURSES_SETUPTERM
|
|
|
|
/*
|
|
|
|
* setupterm --
|
|
|
|
* Set up terminal.
|
|
|
|
*
|
|
|
|
* PUBLIC: #ifndef HAVE_CURSES_SETUPTERM
|
|
|
|
* PUBLIC: void setupterm __P((char *, int, int *));
|
|
|
|
* PUBLIC: #endif
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
setupterm(ttype, fno, errp)
|
|
|
|
char *ttype;
|
|
|
|
int fno, *errp;
|
|
|
|
{
|
|
|
|
static char buf[2048];
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
if ((*errp = tgetent(buf, ttype)) > 0) {
|
|
|
|
if (ke != NULL)
|
|
|
|
free(ke);
|
|
|
|
ke = ((p = tigetstr("rmkx")) == (char *)-1) ?
|
|
|
|
NULL : strdup(p);
|
|
|
|
if (ks != NULL)
|
|
|
|
free(ks);
|
|
|
|
ks = ((p = tigetstr("smkx")) == (char *)-1) ?
|
|
|
|
NULL : strdup(p);
|
|
|
|
if (vb != NULL)
|
|
|
|
free(vb);
|
|
|
|
vb = ((p = tigetstr("flash")) == (char *)-1) ?
|
|
|
|
NULL : strdup(p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* !HAVE_CURSES_SETUPTERM */
|
|
|
|
|
|
|
|
#ifndef HAVE_CURSES_TIGETSTR
|
|
|
|
/* Terminfo-to-termcap translation table. */
|
|
|
|
typedef struct _tl {
|
|
|
|
const char *terminfo; /* Terminfo name. */
|
|
|
|
const char *termcap; /* Termcap name. */
|
|
|
|
} TL;
|
|
|
|
static const TL list[] = {
|
|
|
|
{ "cols", "co", }, /* Terminal columns. */
|
|
|
|
{ "cup", "cm", }, /* Cursor up. */
|
|
|
|
{ "cuu1", "up", }, /* Cursor up. */
|
|
|
|
{ "el", "ce", }, /* Clear to end-of-line. */
|
|
|
|
{ "flash", "vb", }, /* Visible bell. */
|
|
|
|
{ "kcub1", "kl", }, /* Cursor left. */
|
|
|
|
{ "kcud1", "kd", }, /* Cursor down. */
|
|
|
|
{ "kcuf1", "kr", }, /* Cursor right. */
|
|
|
|
{ "kcuu1", "ku", }, /* Cursor up. */
|
|
|
|
{ "kdch1", "kD", }, /* Delete character. */
|
|
|
|
{ "kdl1", "kL", }, /* Delete line. */
|
|
|
|
{ "ked", "kS", }, /* Delete to end of screen. */
|
|
|
|
{ "kel", "kE", }, /* Delete to eol. */
|
|
|
|
{ "kend", "@7", }, /* Go to eol. */
|
|
|
|
{ "khome", "kh", }, /* Go to sol. */
|
|
|
|
{ "kich1", "kI", }, /* Insert at cursor. */
|
|
|
|
{ "kil1", "kA", }, /* Insert line. */
|
|
|
|
{ "kind", "kF", }, /* Scroll down. */
|
|
|
|
{ "kll", "kH", }, /* Go to eol. */
|
|
|
|
{ "knp", "kN", }, /* Page down. */
|
|
|
|
{ "kpp", "kP", }, /* Page up. */
|
|
|
|
{ "kri", "kR", }, /* Scroll up. */
|
|
|
|
{ "lines", "li", }, /* Terminal lines. */
|
|
|
|
{ "rmcup", "te", }, /* Terminal end string. */
|
|
|
|
{ "rmkx", "ke", }, /* Exit "keypad-transmit" mode. */
|
|
|
|
{ "rmso", "se", }, /* Standout end. */
|
|
|
|
{ "smcup", "ti", }, /* Terminal initialization string. */
|
|
|
|
{ "smkx", "ks", }, /* Enter "keypad-transmit" mode. */
|
|
|
|
{ "smso", "so", }, /* Standout begin. */
|
|
|
|
};
|
|
|
|
|
|
|
|
#ifdef _AIX
|
|
|
|
/*
|
|
|
|
* AIX's implementation for function keys greater than 10 is different and
|
|
|
|
* only goes as far as 36.
|
|
|
|
*/
|
|
|
|
static const char codes[] = {
|
|
|
|
/* 0-10 */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ';',
|
|
|
|
/* 11-20 */ '<', '>', '!', '@', '#', '$', '%', '^', '&', '*',
|
|
|
|
/* 21-30 */ '(', ')', '-', '_', '+', ',', ':', '?', '[', ']',
|
|
|
|
/* 31-36 */ '{', '}', '|', '~', '/', '='
|
|
|
|
};
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
/*
|
|
|
|
* !!!
|
|
|
|
* Historically, the 4BSD termcap code didn't support functions keys greater
|
|
|
|
* than 9. This was silently enforced -- asking for key k12 would return the
|
|
|
|
* value for k1. We try and get around this by using the tables specified in
|
|
|
|
* the terminfo(TI_ENV) man page from the 3rd Edition SVID. This assumes the
|
|
|
|
* implementors of any System V compatibility code or an extended termcap used
|
|
|
|
* those codes.
|
|
|
|
*/
|
|
|
|
static const char codes[] = {
|
|
|
|
/* 0-10 */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ';',
|
|
|
|
/* 11-19 */ '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
|
|
|
/* 20-63 */ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
|
|
|
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
|
|
|
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
|
|
|
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
|
|
|
};
|
|
|
|
#endif /* _AIX */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* lcmp --
|
|
|
|
* list comparison routine for bsearch.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
lcmp(const void *a, const void *b)
|
|
|
|
{
|
|
|
|
return (strcmp(a, ((const TL *)b)->terminfo));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* tigetstr --
|
|
|
|
*
|
|
|
|
* Vendors put the prototype for tigetstr into random include files, including
|
|
|
|
* <term.h>, which we can't include because it makes other systems unhappy.
|
|
|
|
* Try and work around the problem, since we only care about the return value.
|
|
|
|
*
|
|
|
|
* PUBLIC: #ifdef HAVE_CURSES_TIGETSTR
|
2013-12-06 12:04:52 +01:00
|
|
|
* PUBLIC: char *tigetstr __P((const char *));
|
2013-01-22 12:03:53 +01:00
|
|
|
* PUBLIC: #else
|
|
|
|
* PUBLIC: char *tigetstr __P((char *));
|
|
|
|
* PUBLIC: #endif
|
|
|
|
*/
|
|
|
|
char *
|
|
|
|
tigetstr(name)
|
|
|
|
const char *name;
|
|
|
|
{
|
|
|
|
static char sbuf[256];
|
|
|
|
TL *tlp;
|
|
|
|
int n;
|
|
|
|
char *p, mykeyname[3];
|
|
|
|
|
|
|
|
if ((tlp = bsearch(name,
|
|
|
|
list, sizeof(list) / sizeof(TL), sizeof(TL), lcmp)) == NULL) {
|
|
|
|
#ifdef _AIX
|
|
|
|
if (name[0] == 'k' &&
|
|
|
|
name[1] == 'f' && (n = atoi(name + 2)) <= 36) {
|
|
|
|
mykeyname[0] = 'k';
|
|
|
|
mykeyname[1] = codes[n];
|
|
|
|
mykeyname[2] = '\0';
|
|
|
|
#else
|
|
|
|
if (name[0] == 'k' &&
|
|
|
|
name[1] == 'f' && (n = atoi(name + 2)) <= 63) {
|
|
|
|
mykeyname[0] = n <= 10 ? 'k' : 'F';
|
|
|
|
mykeyname[1] = codes[n];
|
|
|
|
mykeyname[2] = '\0';
|
|
|
|
#endif
|
|
|
|
name = mykeyname;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
name = tlp->termcap;
|
|
|
|
|
|
|
|
p = sbuf;
|
|
|
|
#ifdef _AIX
|
|
|
|
return ((p = tgetstr(name, &p)) == NULL ? (char *)-1 : strcpy(sbuf, p));
|
|
|
|
#else
|
|
|
|
return (tgetstr(name, &p) == NULL ? (char *)-1 : sbuf);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* tigetnum --
|
|
|
|
*
|
|
|
|
* PUBLIC: #ifndef HAVE_CURSES_TIGETSTR
|
|
|
|
* PUBLIC: int tigetnum __P((char *));
|
|
|
|
* PUBLIC: #endif
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
tigetnum(name)
|
|
|
|
const char *name;
|
|
|
|
{
|
|
|
|
TL *tlp;
|
|
|
|
int val;
|
|
|
|
|
|
|
|
if ((tlp = bsearch(name,
|
|
|
|
list, sizeof(list) / sizeof(TL), sizeof(TL), lcmp)) != NULL) {
|
|
|
|
name = tlp->termcap;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ((val = tgetnum(name)) == -1 ? -2 : val);
|
|
|
|
}
|
|
|
|
#endif /* !HAVE_CURSES_TIGETSTR */
|
|
|
|
|