termlib
Peter da Silva
peter at sugar.hackercorp.com
Wed Mar 13 22:19:35 AEST 1991
I've had several requests for this, so here it is again.
: This archive contains the following files...
: 'termlib.h'
: 'tinit.c'
: 'tgetnum.c'
: 'tutil.c'
: 'tvars.c'
: 'tgoto.c'
: 'tgetent.c'
: 'tputs.c'
: 'cur.c'
: 'termcap.c'
: 'tgetflag.c'
: 'tgetstr.c'
: 'Makefile'
: To extract them, run the following through /bin/sh
echo x - termlib.h
sed 's/^X//' > termlib.h << '//END'
X/* TERMLIB: Terminal independant database.
X *
X * Module: termlib.h
X *
X * Purpose: declare global variables and functions.
X */
X
X/* termlib.h
X * Global variables for termlib
X *
X*/
X#ifndef AMIGA
X#define AMIGA 0
X#endif
X
Xextern char *tent; /* Pointer to terminal entry, set by tgetent */
Xextern char PC; /* Pad character, default NULL */
Xextern char *UP, *BC; /* Pointers to UP and BC strings from database */
Xextern short ospeed; /* Baud rate (1-16, 1=300, 16=19200), as in stty */
X
Xint tgetnum();
Xchar *tgoto();
Xint tgetent();
Xint tgetflag();
Xchar *tgetstr();
X
Xchar *_find();
Xchar *_addfmt();
//END
echo x - tinit.c
sed 's/^X//' > tinit.c << '//END'
X/* TERMLIB: Terminal independant database.
X *
X * Module: tinit
X *
X * Purpose: simplified terminal initialisation.
X *
X * Calling conventions: name is name of terminal.
X *
X * Returned values: none.
X *
X * Notes
X * tinit calls tgetent, then sets up the global
X * variables PC, UP, BC, ospeed appropriately.
X *
X */
X#include "termlib.h"
X#include <stdio.h>
X#if !AMIGA
X#include <sgtty.h>
X#endif
X
X/* tinit.c (libtermlib.a)
X *
X */
X
Xchar tbuf[1024]; /* Buffer for termcap entry */
Xchar junkbuf[1024]; /* Big buffer for junk */
Xchar *junkptr;
X
Xtinit(name)
Xchar *name;
X{
X#if !AMIGA
X struct sgttyb sgbuf;
X#endif
X char *ps;
X
X junkptr = junkbuf;
X
X tgetent(tbuf, name);
X
X ps = tgetstr("pc", &junkptr);
X if(ps) PC = *ps;
X UP = tgetstr("up", &junkptr);
X BC = tgetstr("bc", &junkptr);
X
X#if AMIGA
X ospeed=0;
X#else
X gtty(1, &sgbuf);
X ospeed=sgbuf.sg_ospeed;
X#endif
X}
//END
echo x - tgetnum.c
sed 's/^X//' > tgetnum.c << '//END'
X/* TERMLIB: Terminal independant database.
X *
X * Module: tgetnum
X *
X * Purpose: get numeric value such as 'li' or 'co' from termcap.
X *
X * Calling conventions: id = 2 character id.
X *
X * Returned values: -1 for failure, else numerical value.
X */
X#include <stdio.h>
X#include <ctype.h>
X#include "termlib.h"
X
X/* tgetnum.c (libtermlib.a)
X *
X */
X
Xtgetnum(id)
Xchar *id;
X{
X char *ptr, buf[256];
X ptr = buf;
X
X if(tgetstr(id, &ptr))
X return atoi(buf);
X else
X return 0;
X}
//END
echo x - tutil.c
sed 's/^X//' > tutil.c << '//END'
X/* TERMLIB: Terminal independant database.
X *
X * Module: tutil.c
X *
X * Purpose: Utility routines for TERMLIB functions.
X *
X */
X
X/* tutil.c (libtermlib.a)
X * Utility routines for termlib
X *
X */
X
X_match(s1, s2) /* returns length of text common to s1 and s2 */
Xchar *s1, *s2;
X{
X int i = 0;
X
X while(s1[i] && s1[i] == s2[i])
X i++;
X
X return i;
X}
X
Xchar *
X_find(s, set) /* finds next c in s that's a member of set, returns pointer */
Xchar *s, *set;
X{
X for(; *s; s++) {
X char *ptr = set;
X
X while(*ptr && *s != *ptr)
X ptr++;
X
X if(*ptr)
X return s;
X }
X
X return s;
X}
X
Xchar *
X_addfmt(buf, fmt, val) /* add val to buf according to format fmt */
Xchar *buf, *fmt;
Xint val;
X{
X sprintf(buf, fmt, val);
X while(*buf)
X buf++;
X return buf;
X}
//END
echo x - tvars.c
sed 's/^X//' > tvars.c << '//END'
X/* TERMLIB: Terminal independant database.
X *
X * Module: tvars
X *
X * Purpose: supply actual global variables.
X */
X
X/* tvars.c (libtermlib.a)
X * Global variables for termlib
X *
X*/
X
Xchar *tent; /* Pointer to terminal entry, set by tgetent */
Xchar PC = 0; /* Pad character, default NULL */
Xchar *UP = 0, *BC = 0; /* Pointers to UP and BC strings from database */
Xshort ospeed; /* Baud rate (1-16, 1=300, 16=19200), as in stty */
//END
echo x - tgoto.c
sed 's/^X//' > tgoto.c << '//END'
X/* TERMLIB: Terminal independant database.
X *
X * Module: tgoto
X *
X * Purpose: decode cm cursor motion string.
X *
X * Calling conventions: cm is cursor motion string.
X * line, col, are the desired destination.
X *
X * Returned values: a string pointing to the decoded string, or
X * "OOPS" if it cannot be decoded.
X *
X * Notes
X * The accepted escapes are:
X * %d as in printf, 0 origin.
X * %2, %3 like %02d, %03d in printf.
X * %. like %c
X * %+x adds <x> to value, then %.
X * %>xy if value>x, adds y. No output.
X * %i increments line& col, no output.
X * %r reverses order of line&col. No output.
X * %% prints as a single %.
X * %n exclusive or row & col with 0140.
X * %B BCD, no output.
X * %D reverse coding (x-2*(x%16)), no output.
X */
X#include <stdio.h>
X#include <ctype.h>
X#include "termlib.h"
X
X/* tgoto.c (libtermlib.a)
X *
X */
X
Xchar *
Xtgoto(cm, col, line)
Xchar *cm; /* cm string, from termcap */
Xint col, /* column, x position */
X line; /* line, y position */
X{
X char *_addfmt(),
X gx, gy, /* x, y */
X *ptr, /* pointer in 'cm' */
X reverse = 0, /* reverse flag */
X *bufp, /* pointer in returned string */
X addup = 0, /* add upline */
X addbak = 0, /* add backup */
X c;
X static char buffer[32];
X
X if(!cm)
X return "OOPS"; /* Kludge, but standard */
X
X bufp = buffer;
X ptr = cm;
X
X while(*ptr) {
X if((c = *ptr++) != '%') { /* normal char */
X *bufp++ = c;
X } else { /* % escape */
X switch(c = *ptr++) {
X case 'd': /* decimal */
X bufp = _addfmt(bufp, "%d", line);
X line = col;
X break;
X case '2': /* 2 digit decimal */
X bufp = _addfmt(bufp, "%02d", line);
X line = col;
X break;
X case '3': /* 3 digit decimal */
X bufp = _addfmt(bufp, "%03d", line);
X line = col;
X break;
X case '>': /* %>xy: if >x, add y */
X gx = *ptr++;
X gy = *ptr++;
X if(col>gx) col += gy;
X if(line>gx) line += gy;
X break;
X case '+': /* %+c: add c */
X line += *ptr++;
X case '.': /* print x/y */
X if(line=='\t' || /* these are */
X line == '\n' || /* chars that */
X line=='\004' || /* UNIX hates */
X line=='\0') {
X line++; /* so go to next pos */
X if(reverse==(line==col))
X addup=1; /* and mark UP */
X else
X addbak=1; /* or BC */
X }
X *bufp++=line;
X line = col;
X break;
X case 'r': /* r: reverse */
X gx = line;
X line = col;
X col = gx;
X reverse = 1;
X break;
X case 'i': /* increment (1-origin screen) */
X col++;
X line++;
X break;
X case '%': /* %%=% literally */
X *bufp++='%';
X break;
X case 'n': /* magic DM2500 code */
X line ^= 0140;
X col ^= 0140;
X break;
X case 'B': /* bcd encoding */
X line = line/10<<4+line%10;
X col = col/10<<4+col%10;
X break;
X case 'D': /* magic Delta Data code */
X line = line-2*(line&15);
X col = col-2*(col&15);
X break;
X default: /* Unknown escape */
X return "OOPS";
X }
X }
X }
X
X if(addup) /* add upline */
X if(UP) {
X ptr=UP;
X while(isdigit(*ptr) || *ptr=='.')
X ptr++;
X if(*ptr=='*')
X ptr++;
X while(*ptr)
X *bufp++ = *ptr++;
X }
X
X if(addbak) /* add backspace */
X if(BC) {
X ptr=BC;
X while(isdigit(*ptr) || *ptr=='.')
X ptr++;
X if(*ptr=='*')
X ptr++;
X while(*ptr)
X *bufp++ = *ptr++;
X }
X else
X *bufp++='\b';
X
X *bufp = 0;
X
X return(buffer);
X}
//END
echo x - tgetent.c
sed 's/^X//' > tgetent.c << '//END'
X/* TERMLIB: Terminal independant database.
X *
X * Module: tgetent
X *
X * Purpose: Get termcap entry for <term> into buffer at <tbuf>.
X *
X * Calling conventions: char tbuf[1024+], term=canonical name for
X * terminal.
X *
X * Returned values: 1 = success, -1 = can't open file,
X * 0 = can't find terminal.
X *
X * Notes
X * Should probably supply static buffer.
X *
X * Uses environment variables "TERM" and
X * "TERMCAP". If TERM = term (that is, if the argument
X * matches the environment) then it looks at TERMCAP.
X * If TERMCAP begins with a slash, then it assumes
X * this is the file to search rather than /etc/termcap.
X * If TERMCAP does not begin with a slash, and it
X * matches TERM, then this is used as the entry.
X *
X * This could be simplified considerably for non-UNIX
X * systems.
X */
X#include <stdio.h>
X#include <ctype.h>
X#include "termlib.h"
X
X/* tgetent.c (libtermlib.a)
X *
X */
X#if AMIGA
X#define TERMCAP "s:termcap"
X#else
X#define TERMCAP "/etc/termcap"
X#endif
X
Xtgetent(tbuf, term)
Xchar *tbuf, /* Buffer to hold termcap entry, 1024 bytes max */
X *term; /* Name of terminal */
X{
X char tcbuf[32], /* Temp buffer to handle */
X *tc, /* :tc=: entry for */
X *tcptr = tcbuf; /* extended entries */
X char *tcap = TERMCAP, /* Default termcap file */
X *getenv();
X char *tmp;
X FILE *termcap;
X
X if((tmp=getenv("TERMCAP")) != NULL) {
X if(*tmp == '/') /* TERMCAP = name of termcap file */
X tcap = tmp ;
X else { /* TERMCAP = termcap entry itself */
X int tlen = strlen(term);
X while(*tmp && *tmp != ':') {/* Check if TERM matches */
X while(*tmp == '|')
X tmp++;
X if(_match(tmp, term)==tlen) {
X strcpy(tbuf, tmp);
X tent=tbuf;
X return 1;
X }
X else
X tmp = _find(tmp, ":|");
X }
X }
X }
X if(!(termcap=fopen(tcap, "r"))) {
X strcpy(tbuf, tcap);
X return -1;
X }
X
X if(getent(tbuf, term, termcap)) {
X if(tc=tgetstr("tc", &tcptr)) { /* extended entry */
X rewind(termcap);
X if(getent(tbuf+strlen(tbuf), tc, termcap)) {
X fclose(termcap); /* Completed */
X return 1;
X }
X else {
X fclose(termcap); /* Incomplete */
X return 0;
X }
X } else {
X fclose(termcap); /* non-extended entry */
X return 1;
X }
X } else {
X fclose(termcap); /* No entry */
X return 0;
X }
X}
X
Xgetent(tbuf, term, termcap)
Xchar *tbuf, *term;
XFILE *termcap;
X{
X char *tptr;
X int tlen = strlen(term);
X
X while(nextent(tbuf, termcap)) { /* For each possible entry */
X tptr = tbuf;
X while(*tptr && *tptr != ':') { /* : terminates name field */
X while(*tptr == '|') /* | seperates names */
X tptr++;
X if(_match(tptr, term)==tlen) { /* FOUND! */
X fclose(termcap);
X tent=tbuf;
X return 1;
X }
X else /* Look for next name */
X tptr = _find(tptr, ":|");
X }
X }
X
X return 0;
X}
X
Xnextent(tbuf, termcap) /* Read 1 entry from TERMCAP file */
Xchar *tbuf;
XFILE *termcap;
X{
X char *lbuf = /* lbuf=line buffer */
X tbuf; /* read lines straight into buffer */
X
X while(lbuf < tbuf+1024 && /* There's room and */
X fgets(lbuf, tbuf+1024-lbuf, termcap)) { /* another line */
X int llen = strlen(lbuf);
X
X if(*lbuf=='#') /* eat comments */
X continue;
X if(lbuf[-1]==':' && /* and whitespace */
X lbuf[0]=='\t' &&
X lbuf[1]==':') {
X strcpy(lbuf, lbuf+2);
X llen -= 2;
X }
X if(lbuf[llen-2]=='\\') /* and continuations */
X lbuf += llen-2;
X else {
X lbuf[llen-1]=0; /* no continuation, return */
X return 1;
X }
X }
X
X return 0; /* ran into end of file */
X}
//END
echo x - tputs.c
sed 's/^X//' > tputs.c << '//END'
X/* TERMLIB: Terminal independant database.
X *
X * Module: tputs
X *
X * Purpose: decode padding information
X *
X * Calling conventions: cp = string to be padded, affcnt = # of items
X * affected (lines, characters, whatever),
X * outc = routine to output 1 character.
X *
X * Returned values: none
X *
X * Notes
X * cp has padding information ahead of it, in the form
X * nnnTEXT or nnn*TEXT. nnn is the number of milliseconds to delay,
X * and may be a decimal (nnn.mmm). If the asterisk is given, then
X * the delay is multiplied by afcnt. The delay is produced by outputting
X * a number of nulls (or other padding char) after printing the
X * TEXT.
X *
X */
X#include <stdio.h>
X#include <ctype.h>
X#include "termlib.h"
X
X/* tputs.c (libtermlib.a)
X *
X */
X
Xlong _bauds[16]={
X 0, 50, 75, 110,
X 134, 150, 200, 300,
X 600, 1200, 1800, 2400,
X 4800, 9600, 19200, 19200 };
X
Xtputs(cp, affcnt, outc)
Xchar *cp; /* string to print */
Xint affcnt; /* Number of lines affected */
Xint (*outc)(); /* routine to output 1 character */
X{
X long frac, /* 10^(#digits after decimal point) */
X counter, /* digits */
X atol();
X
X if(isdigit(*cp)) {
X counter = 0;
X frac = 1000;
X while(isdigit(*cp))
X counter = counter * 10L + (long)(*cp++ - '0');
X if(*cp=='.')
X while(isdigit(*++cp)) {
X counter = counter * 10L + (long)(*cp++ - '0');
X frac = frac * 10;
X }
X if(*cp!='*') { /* multiply by affected lines */
X if(affcnt>1) affcnt = 1;
X }
X else
X cp++;
X
X /* Calculate number of characters for padding counter/frac ms delay */
X if(ospeed)
X counter = (counter * _bauds[ospeed] * (long)affcnt) / frac;
X
X while(*cp) /* output string */
X (*outc)(*cp++);
X if(ospeed)
X while(counter--) /* followed by pad characters */
X (*outc)(PC);
X }
X else
X while(*cp)
X (*outc)(*cp++);
X}
//END
echo x - cur.c
sed 's/^X//' > cur.c << '//END'
X/* Cur: Provide cursor addressing for shell scripts.
X *
X * Cur performs the same functions as echo, with 2 differences:
X * 1.
X * a. Arguments of the form -xx result in the generation of the capability
X * string xx. The two special strings "cm" and "cs" are handled by
X * cur ... -cm x y ... and ... -cs lo hi ...
X * b. Arguments of the form #xx return the value of the numeric capability
X * xx.
X * c. Arguments of the form +terminal force cur to assume that as the
X * terminal type. Any number of these can be included, and will be
X * evaluated when encountered.
X * 2. No newline is appended to the echoed string.
X *
X * Syntax: cur [string|-xx|#xx|+term]...
X *
X * Other notes: The code is obvious.
X */
X#include <stdio.h>
X#include "termlib.h"
X
Xextern char *junkptr;
X
Xmain(ac, av)
Xint ac; char **av;
X{
X int line, col, outch();
X char *val;
X
X tinit(getenv("TERM"));
X
X while(--ac)
X if(**++av=='-') {
X if(val=tgetstr(*av+1, &junkptr)) {
X if(strcmp(*av+1, "cm") &&
X strcmp(*av+1, "cs"))
X tputs(val, 1, outch);
X else {
X col = atoi(*++av); --ac;
X line = atoi(*++av); --ac;
X tputs(tgoto(val, col, line), 0, outch);
X }
X }
X } else if(**av=='#') {
X if(val = tgetstr(*av+1, &junkptr))
X fputs(val, stdout);
X } else if(**av=='+') {
X tinit(*av+1);
X } else
X fputs(*av, stdout);
X}
X
Xoutch(c) char c; { putchar(c); }
//END
echo x - termcap.c
sed 's/^X//' > termcap.c << '//END'
X/* termcap... print current terminal capabilities.
X *
X * Termcap prints all the termcap capability strings for the terminal `term'.
X * The output is in machine readable form, suitable for use in the construct:
X *
X * TERMCAP="`termcap`"; export TERMCAP
X *
X * Syntax: termcap [term]
X */
X#include <stdio.h>
X
Xchar *tent;
Xmain(ac, av)
Xint ac;
Xchar **av;
X{
X char tbuf[1024];
X if(ac==1) if(tgetent(tbuf, getenv("TERM"))) {
X puts(tbuf);
X exit(0);
X } else exit(-1);
X if(tgetent(tbuf, av[1])) {
X puts(tbuf);
X exit(0);
X } else exit(-1);
X}
//END
echo x - tgetflag.c
sed 's/^X//' > tgetflag.c << '//END'
X/* The following software is (C) 1984 Peter da Silva,
X the Mad Australian, in the public domain. It may
X be re-distributed for any purpose with the inclusion
X of this notice. */
X/* TERMLIB: Terminal independant database.
X *
X * Module: tgetflag
X *
X * Purpose: returns flag true or false as to the existence of a given
X * entry. used with 'bs', 'am', etc...
X *
X * Calling conventions: id is the 2 character capability id.
X *
X * Returned values: 1 for success, 0 for failure.
X */
X#include <stdio.h>
X#include <ctype.h>
X#include "termlib.h"
X
X/* tgetflag.c (libtermlib.a)
X *
XBUILD
XOBJS=tinit.o tutil.o tvars.o \
X tgoto.o tputs.o tgetent.o tgetflag.o tgetnum.o tgetstr.o
XCFLAGS=-O
X
Xlibtermlib.a: $(OBJS) termlib.h
X ar cr libtermlib.a $(OBJS)
X ranlib libtermlib.a
X
X$(OBJS):: termlib.h
XEND
X*/
X
Xtgetflag(id)
Xchar *id;
X{
X char buf[256], *ptr = buf;
X
X return tgetstr(id, &ptr) ? 1 : 0;
X}
//END
echo x - tgetstr.c
sed 's/^X//' > tgetstr.c << '//END'
X/* The following software is (C) 1984 Peter da Silva,
X the Mad Australian, in the public domain. It may
X be re-distributed for any purpose with the inclusion
X of this notice. */
X/* TERMLIB: Terminal independant database.
X *
X * Module: tgetstr
X *
X * Purpose: get terminal capability string from database.
X *
X * Calling conventions: id is the two character capability id.
X * (*buf) points into a hold buffer for the
X * id. the capability is copied into the buffer
X * and (*buf) is advanced to point to the next
X * free byte in the buffer.
X *
X * Returned values: 0 = no such entry, otherwise returns original
X * (*buf) (now a pointer to the string).
X *
X * Notes
X * It also decodes certain escape sequences in the buffer.
X * they should be obvious from the code:
X * \E = escape.
X * \n, \r, \t, \f, \b match the 'c' escapes.
X * ^x matches control-x (^@...^_).
X * \nnn matches nnn octal.
X * \x, where x is anything else, matches x. I differ
X * from the standard library here, in that I allow ^: to match
X * :.
X *
X */
X#include <stdio.h>
X#include <ctype.h>
X#include "termlib.h"
X
X/* tgetstr.c (libtermlib.a)
X *
XBUILD
XOBJS=tinit.o tutil.o tvars.o \
X tgoto.o tputs.o tgetent.o tgetflag.o tgetnum.o tgetstr.o
XCFLAGS=-O
X
Xlibtermlib.a: $(OBJS) termlib.h
X ar cr libtermlib.a $(OBJS)
X ranlib libtermlib.a
X
X$(OBJS):: termlib.h
XEND
X*/
X
Xchar *
Xtgetstr(id, buf)
Xchar *id, **buf;
X{
X int len = strlen(id);
X char *tmp=tent;
X char *hold;
X
X do {
X tmp = _find(tmp, ":"); /* For each field */
X while(*tmp==':') /* skip empty fields */
X tmp++;
X if(!*tmp)
X break;
X
X if(_match(id, tmp)==len) {
X tmp += len; /* find '=' '@' or '#' */
X if(*tmp=='@') /* :xx@: entry for tc */
X return 0; /* deleted entry */
X hold= *buf;
X while(*++tmp && *tmp != ':') {/* not at end of field */
X switch(*tmp) {
X case '\\': /* Expand escapes here */
X switch(*++tmp) {
X case 0: /* ignore backslashes */
X tmp--; /* at end of entry */
X break; /* shouldn't happen */
X case 'e':
X case 'E': /* ESC */
X *(*buf)++ = '\033';
X break;
X case 'n': /* \n */
X *(*buf)++ = '\n';
X break;
X case 'r': /* \r */
X *(*buf)++ = '\r';
X break;
X case 't': /* \t */
X *(*buf)++ = '\t';
X break;
X case 'b': /* \b */
X *(*buf)++ = '\b';
X break;
X case 'f': /* \f */
X *(*buf)++ = '\f';
X break;
X case '0': /* \nnn */
X case '1':
X case '2':
X case '3':
X case '4':
X case '5':
X case '6':
X case '7':
X case '8':
X case '9':
X **buf = 0;
X while(isdigit(*tmp))
X **buf = **buf * 8 + *tmp++ - '0';
X (*buf)++;
X tmp--;
X break;
X default: /* \x, for all other x */
X *(*buf)++= *tmp;
X }
X break;
X case '^': /* control characters */
X *(*buf)++ = *++tmp - '@';
X break;
X default:
X *(*buf)++ = *tmp;
X }
X }
X *(*buf)++ = 0;
X return hold;
X }
X } while(*tmp);
X
X return 0;
X}
//END
echo x - Makefile
sed 's/^X//' > Makefile << '//END'
X#
X# The following module order is needed to create a properly sorted library
X# for Manx
X#
X
XOBJS=\
X tgetflag.o\
X tgetnum.o\
X tinit.o\
X tgoto.o\
X tputs.o\
X tvars.o\
X tgetent.o\
X tgetstr.o\
X tutil.o
XSRC=\
X termlib.h\
X tinit.c\
X tgetnum.c\
X tutil.c\
X tvars.c\
X tgoto.c\
X tgetent.c\
X tputs.c\
X cur.c\
X termcap.c\
X tgetflag.c\
X tgetstr.c\
X Makefile
X
XCFLAGS= +P -B -DAMIGA=1
XLIB=termlibl32.lib
X
XLIBDIR=manx:lib
XBINDIR=work:c
X
Xall: cur termcap
X
X$(LIB): $(OBJS)
X lb $(LIB) $(OBJS)
X
Xtermcap: $(LIB) termcap.o
X ln -o termcap termcap.o $(LIB) -lcl32
X
Xcur: $(LIB) cur.o
X ln -o cur cur.o $(LIB) -lcl32
X
Xclean:
X delete #?.o #?.lib termcap cur #?.bak
X
Xinstall: all
X copy $(LIB) $(LIBDIR)
X copy termcap $(BINDIR)
X copy cur $(BINDIR)
X
Xtermlib.shar: $(SRC)
X shar >termlib.shar $(SRC)
//END
: end of archive.
exit 0
--
Peter da Silva. `-_-'
<peter at sugar.hackercorp.com>.
More information about the Alt.sources
mailing list