home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 8
/
FreshFishVol8-CD1.bin
/
useful
/
util
/
edit
/
vim
/
src
/
termlib.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-09
|
16KB
|
648 lines
/* vi:sw=4:ts=4:
The following software is (C) 1984 Peter da Silva,
the Mad Australian, in the public domain. It may
be re-distributed for any purpose with the inclusion
of this notice. */
/* modified by Bram Moolenaar for use with VIM - Vi Improved */
/* TERMLIB: Terminal independant database. */
#include "vim.h"
#include "proto.h"
#include "proto/termlib.pro"
#ifndef AMIGA
# include <sgtty.h>
#endif
static int getent __PARMS((char *, char *, FILE *, int));
static int nextent __PARMS((char *, FILE *, int));
static int _match __PARMS((char *, char *));
static char *_addfmt __PARMS((char *, char *, int));
static char *_find __PARMS((char *, char *));
/*
* Global variables for termlib
*/
char *tent; /* Pointer to terminal entry, set by tgetent */
char PC = 0; /* Pad character, default NULL */
char *UP = 0, *BC = 0; /* Pointers to UP and BC strings from database */
short ospeed; /* Baud rate (1-16, 1=300, 16=19200), as in stty */
/*
* Module: tgetent
*
* Purpose: Get termcap entry for <term> into buffer at <tbuf>.
*
* Calling conventions: char tbuf[TBUFSZ+], term=canonical name for
* terminal.
*
* Returned values: 1 = success, -1 = can't open file,
* 0 = can't find terminal.
*
* Notes
* Should probably supply static buffer.
*
* Uses environment variables "TERM" and
* "TERMCAP". If TERM = term (that is, if the argument
* matches the environment) then it looks at TERMCAP.
* If TERMCAP begins with a slash, then it assumes
* this is the file to search rather than /etc/termcap.
* If TERMCAP does not begin with a slash, and it
* matches TERM, then this is used as the entry.
*
* This could be simplified considerably for non-UNIX
* systems.
*/
#ifdef AMIGA
# define TERMCAPFILE "s:termcap"
#else
# define TERMCAPFILE "/etc/termcap"
#endif
tgetent(tbuf, term)
char *tbuf; /* Buffer to hold termcap entry, TBUFSZ bytes max */
char *term; /* Name of terminal */
{
char tcbuf[32]; /* Temp buffer to handle */
char *tcptr = tcbuf; /* extended entries */
char *tcap = TERMCAPFILE; /* Default termcap file */
char *tmp;
FILE *termcap;
int retval = 0;
int len;
if ((tmp = (char *)vimgetenv("TERMCAP")) != NULL)
{
if (*tmp == '/') /* TERMCAP = name of termcap file */
tcap = tmp ;
else /* TERMCAP = termcap entry itself */
{
int tlen = strlen(term);
while (*tmp && *tmp != ':') /* Check if TERM matches */
{
while (*tmp == '|')
tmp++;
if (_match(tmp, term) == tlen)
{
strcpy(tbuf, tmp);
tent = tbuf;
return 1;
}
else
tmp = _find(tmp, ":|");
}
}
}
if (!(termcap = fopen(tcap, "r")))
{
strcpy(tbuf, tcap);
return -1;
}
len = 0;
while (getent(tbuf + len, term, termcap, TBUFSZ - len))
{
if ((term = tgetstr("tc", &tcptr))) /* extended entry */
{
rewind(termcap);
len = strlen(tbuf);
}
else
{
retval = 1;
tent = tbuf;
break;
}
}
fclose(termcap);
return retval;
}
static int
getent(tbuf, term, termcap, buflen)
char *tbuf, *term;
FILE *termcap;
int buflen;
{
char *tptr;
int tlen = strlen(term);
while (nextent(tbuf, termcap, buflen)) /* For each possible entry */
{
tptr = tbuf;
while (*tptr && *tptr != ':') /* : terminates name field */
{
while (*tptr == '|') /* | seperates names */
tptr++;
if (_match(tptr, term) == tlen) /* FOUND! */
{
tent = tbuf;
return 1;
}
else /* Look for next name */
tptr = _find(tptr, ":|");
}
}
return 0;
}
static int
nextent(tbuf, termcap, buflen) /* Read 1 entry from TERMCAP file */
char *tbuf;
FILE *termcap;
int buflen;
{
char *lbuf = tbuf; /* lbuf=line buffer */
/* read lines straight into buffer */
while (lbuf < tbuf+buflen && /* There's room and */
fgets(lbuf, (int)(tbuf+buflen-lbuf), termcap)) /* another line */
{
int llen = strlen(lbuf);
if (*lbuf == '#') /* eat comments */
continue;
if (lbuf[-1] == ':' && /* and whitespace */
lbuf[0] == '\t' &&
lbuf[1] == ':')
{
strcpy(lbuf, lbuf+2);
llen -= 2;
}
if (lbuf[llen-2] == '\\') /* and continuations */
lbuf += llen-2;
else
{
lbuf[llen-1]=0; /* no continuation, return */
return 1;
}
}
return 0; /* ran into end of file */
}
/*
* Module: tgetflag
*
* Purpose: returns flag true or false as to the existence of a given
* entry. used with 'bs', 'am', etc...
*
* Calling conventions: id is the 2 character capability id.
*
* Returned values: 1 for success, 0 for failure.
*/
tgetflag(id)
char *id;
{
char buf[256], *ptr = buf;
return tgetstr(id, &ptr) ? 1 : 0;
}
/*
* Module: tgetnum
*
* Purpose: get numeric value such as 'li' or 'co' from termcap.
*
* Calling conventions: id = 2 character id.
*
* Returned values: -1 for failure, else numerical value.
*/
tgetnum(id)
char *id;
{
char *ptr, buf[256];
ptr = buf;
if (tgetstr(id, &ptr))
return atoi(buf);
else
return 0;
}
/*
* Module: tgetstr
*
* Purpose: get terminal capability string from database.
*
* Calling conventions: id is the two character capability id.
* (*buf) points into a hold buffer for the
* id. the capability is copied into the buffer
* and (*buf) is advanced to point to the next
* free byte in the buffer.
*
* Returned values: 0 = no such entry, otherwise returns original
* (*buf) (now a pointer to the string).
*
* Notes
* It also decodes certain escape sequences in the buffer.
* they should be obvious from the code:
* \E = escape.
* \n, \r, \t, \f, \b match the 'c' escapes.
* ^x matches control-x (^@...^_).
* \nnn matches nnn octal.
* \x, where x is anything else, matches x. I differ
* from the standard library here, in that I allow ^: to match
* :.
*
*/
char *
tgetstr(id, buf)
char *id, **buf;
{
int len = strlen(id);
char *tmp=tent;
char *hold;
int i;
do {
tmp = _find(tmp, ":"); /* For each field */
while (*tmp == ':') /* skip empty fields */
tmp++;
if (!*tmp)
break;
if (_match(id, tmp) == len) {
tmp += len; /* find '=' '@' or '#' */
if (*tmp == '@') /* :xx@: entry for tc */
return 0; /* deleted entry */
hold= *buf;
while (*++tmp && *tmp != ':') {/* not at end of field */
switch(*tmp) {
case '\\': /* Expand escapes here */
switch(*++tmp) {
case 0: /* ignore backslashes */
tmp--; /* at end of entry */
break; /* shouldn't happen */
case 'e':
case 'E': /* ESC */
*(*buf)++ = '\033';
break;
case 'n': /* \n */
*(*buf)++ = '\n';
break;
case 'r': /* \r */
*(*buf)++ = '\r';
break;
case 't': /* \t */
*(*buf)++ = '\t';
break;
case 'b': /* \b */
*(*buf)++ = '\b';
break;
case 'f': /* \f */
*(*buf)++ = '\f';
break;
case '0': /* \nnn */
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
**buf = 0;
/* get up to three digits */
for (i = 0; i < 3 && isdigit(*tmp); ++i)
**buf = **buf * 8 + *tmp++ - '0';
(*buf)++;
tmp--;
break;
default: /* \x, for all other x */
*(*buf)++= *tmp;
}
break;
case '^': /* control characters */
*(*buf)++ = *++tmp - '@';
break;
default:
*(*buf)++ = *tmp;
}
}
*(*buf)++ = 0;
return hold;
}
} while (*tmp);
return 0;
}
/*
* Module: tgoto
*
* Purpose: decode cm cursor motion string.
*
* Calling conventions: cm is cursor m