V10/ncurses/screen/setupterm.c
/* @(#) setupterm.c: 1.2 10/31/83 (1.36 3/18/83) */
#include "curses.ext"
#include "../local/uparm.h"
extern struct term _first_term;
extern struct term *cur_term;
static char firststrtab[2048];
static int called_before = 0; /* To check for first time. */
char *getenv();
char *malloc();
char ttytype[128];
#ifndef termpath
#define termpath(file) "/usr/lib/terminfo/file"
#endif
#define MAGNUM 0432
#define getshi() getsh(ip) ; ip += 2
/*
* "function" to get a short from a pointer. The short is in a standard
* format: two bytes, the first is the low order byte, the second is
* the high order byte (base 256). The only negative number allowed is
* -1, which is represented as 255, 255. This format happens to be the
* same as the hardware on the pdp-11 and vax, making it fast and
* convenient and small to do this on a pdp-11.
*/
#ifdef vax
#define getsh(ip) (* (short *) ip)
#endif
#ifdef pdp11
#define getsh(ip) (* (short *) ip)
#endif
#ifndef getsh
/*
* Here is a more portable version, which does not assume byte ordering
* in shorts, sign extension, etc.
*/
getsh(p)
register char *p;
{
register int rv;
if (*p == 0377)
return -1;
rv = *p++;
rv += *p * 256;
return rv;
}
#endif
/*
* setupterm: low level routine to dig up terminfo from database
* and read it in. Parms are terminal type (0 means use getenv("TERM"),
* file descriptor all output will go to (for ioctls), and a pointer
* to an int into which the error return code goes (0 means to bomb
* out with an error message if there's an error). Thus, setupterm(0, 1, 0)
* is a reasonable way for a simple program to set up.
*/
setupterm(term, filenum, errret)
char *term;
int filenum; /* This is a UNIX file descriptor, not a stdio ptr. */
int *errret;
{
char tiebuf[4096];
char fname[128];
register char *ip;
register char *cp;
int n, tfd;
char *lcp, *ccp;
int snames, nbools, nints, nstrs, sstrtab;
char *strtab;
if (term == NULL)
term = getenv("TERM");
if (term == NULL || *term == '\0')
term = "unknown";
tfd = -1;
if (cp=getenv("TERMINFO")) {
strcpy(fname, cp);
cp = fname + strlen(fname);
*cp++ = '/';
*cp++ = *term;
*cp++ = '/';
strcpy(cp, term);
tfd = open(fname, 0);
}
if (tfd < 0) {
strcpy(fname, termpath(a/));
cp = fname + strlen(fname);
cp[-2] = *term;
strcpy(cp, term);
tfd = open(fname, 0);
}
if( tfd < 0 )
{
if( access( termpath( . ), 0 ) )
{
if( errret == 0 )
perror( termpath( . ) );
else
*errret = -1;
}
else
{
if( errret == 0 )
{
write(2, "No such terminal: ", 18);
write(2, term, strlen(term));
write(2, "\r\n", 2);
}
else
{
*errret = 0;
}
}
if( errret == 0 )
exit( -2 );
else
return -1;
}
if( called_before && cur_term ) /* 2nd or more times through */
{
cur_term = (struct term *) malloc(sizeof (struct term));
strtab = NULL;
}
else /* First time through */
{
cur_term = &_first_term;
called_before = TRUE;
strtab = firststrtab;
}
if( filenum == 1 && !isatty(filenum) ) /* Allow output redirect */
{
filenum = 2;
}
cur_term -> Filedes = filenum;
def_shell_mode();
if (errret)
*errret = 1;
n = read(tfd, tiebuf, sizeof tiebuf);
close(tfd);
if (n <= 0) {
corrupt:
write(2, "corrupted term entry\r\n", 22);
if (errret == 0)
exit(-3);
else
return -1;
}
if (n == sizeof tiebuf) {
write(2, "term entry too long\r\n", 21);
if (errret == 0)
exit(-4);
else
return -1;
}
cp = ttytype;
ip = tiebuf;
/* Pick up header */
snames = getshi();
if (snames != MAGNUM) {
goto corrupt;
}
snames = getshi();
nbools = getshi();
nints = getshi();
nstrs = getshi();
sstrtab = getshi();
if (strtab == NULL) {
strtab = (char *) malloc(sstrtab);
}
while (snames--)
*cp++ = *ip++; /* Skip names of terminals */
/*
* Inner blocks to share this register among two variables.
*/
{
register char *sp;
char *fp = (char *)&cur_term->Columns;
register char s;
for (cp= &cur_term->Auto_left_margin; nbools--; ) {
s = *ip++;
if (cp < fp)
*cp++ = s;
}
}
/* Force proper alignment */
if (((unsigned int) ip) & 1)
ip++;
{
register short *sp;
short *fp = (short *)&cur_term->strs;
register int s;
for (sp= &cur_term->Columns; nints--; ) {
s = getshi();
if (sp < fp)
*sp++ = s;
}
}
#ifdef JWINSIZE
/*
* ioctls for Blit - you may need to #include <jioctl.h>
* This ioctl defines the window size and overrides what
* it says in terminfo.
*/
{
struct winsize w;
if (ioctl(2, JWINSIZE, &w) != -1) {
lines = w.bytesy;
columns = w.bytesx;
}
}
#endif
lcp = getenv("LINES");
ccp = getenv("COLUMNS");
if (lcp)
lines = atoi(lcp);
if (ccp)
columns = atoi(ccp);
{
register char **pp;
char **fp = (char **)&cur_term->Filedes;
for (pp= &cur_term->strs.Back_tab; nstrs--; ) {
n = getshi();
if (pp < fp) {
if (n == -1)
*pp++ = NULL;
else
*pp++ = strtab+n;
}
}
}
for (cp=strtab; sstrtab--; ) {
*cp++ = *ip++;
}
/*
* If tabs are being expanded in software, turn this off
* so output won't get messed up. Also, don't use tab
* or backtab, even if the terminal has them, since the
* user might not have hardware tabs set right.
*/
#ifdef USG
if ((cur_term -> Nttyb.c_oflag & TABDLY) == TAB3) {
cur_term->Nttyb.c_oflag &= ~TABDLY;
tab = NULL;
back_tab = NULL;
reset_prog_mode();
return 0;
}
#else
if ((cur_term -> Nttyb.sg_flags & XTABS) == XTABS) {
cur_term->Nttyb.sg_flags &= ~XTABS;
tab = NULL;
back_tab = NULL;
reset_prog_mode();
return 0;
}
#endif
#ifdef DIOCSETT
reset_prog_mode();
#endif
#ifdef LTILDE
ioctl(cur_term -> Filedes, TIOCLGET, &n);
if (n & LTILDE);
reset_prog_mode();
#endif
return 0;
}