[comp.sources.misc] v03i035: mg 2a part 11 of 15

BLARSON@ECLA.USC.EDU (Bob Larson) (05/26/88)

comp.sources.misc: Volume 3, Issue 35
Submitted-By: "Bob Larson" <BLARSON@ECLA.USC.EDU>
Archive-Name: mg2a/Part11

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:    Shell Archiver
#	Run the following text with /bin/sh to create:
#	termlib/fgetlr.c
#	termlib/isdigit.c
#	termlib/testtcp.c
#	termlib/tgetent.c
#	termlib/tgetflag.c
#	termlib/tgetnum.c
#	termlib/tgetstr.c
#	termlib/tgoto.c
#	termlib/tputs.c
#	termlib/ttest.c
# This archive created: Tue May 17 21:42:47 1988
# By:	blarson
if test -d termlib
then true
else mkdir termlib
fi
cat << \SHAR_EOF > termlib/fgetlr.c
/************************************************************************
 *								      *
 *		      Copyright (c) 1982, Fred Fish		      *
 *			  All Rights Reserved			      *
 *								      *
 *    This software and/or documentation is released for public	      *
 *    distribution for personal, non-commercial use only.	      *
 *    Limited rights to use, modify, and redistribute are hereby      *
 *    granted for non-commercial purposes, provided that all	      *
 *    copyright notices remain intact and all changes are clearly     *
 *    documented.  The author makes no warranty of any kind with      *
 *    respect to this product and explicitly disclaims any implied    *
 *    warranties of merchantability or fitness for any particular     *
 *    purpose.							      *
 *								      *
 ************************************************************************
 */




/*
 *  LIBRARY FUNCTION
 *
 *    fgetlr	get logical record from a file
 *
 *  KEY WORDS
 *
 *    fgetlr
 *    string functions
 *
 *  SYNOPSIS
 *
 *    char *fgetlr(bp,bpsize,fp)
 *    char *bp;
 *    int bpsize;
 *    FILE *fp;
 *
 *  DESCRIPTION
 *
 *    Reads the next logical record from stream "fp" into buffer "bp"
 *    until next unescaped newline, "bpsize" minus one characters
 *    have been read, end of file, or read error.
 *    The last character read is followed by a NULL.
 *
 *    A logical record may span several physical records by having
 *    each newline escaped with the standard C escape character
 *    (backslash).
 *
 *    This is particularly useful for things like the termcap
 *    file, where a single entry is too long for one physical
 *    line, yet needs to be treated as a single record.
 *
 *    Returns its first argument unless an end of file or read
 *    error occurs prior to any characters being read.
 *
 *  BUGS
 *
 *    The only way to know if read was terminated due to buffer size
 *    limitation is to test for a newline before the terminating
 *    null.
 *
 */

#include <stdio.h>



/*
 *  PSEUDO CODE
 *
 *    Begin fgetlr
 *	  If read fails then
 *	      Return NULL.
 *	  Else
 *	      Find out how many characters were read.
 *	      Initialize pointer to terminating null.
 *	      If last char read was newline then
 *		  If newline was escaped then
 *		      Replace backslash with the newline.
 *		      Replace newline with null.
 *		      Read and append more.
 *		  End if
 *	      End if
 *	      Return buffer pointer.
 *	  End if
 *    End fgetlr
 *
 */

char *fgetlr(bp,bpsize,fp)
char *bp;
int bpsize;
FILE *fp;
{
    int numch;
    char *cp;

    if (fgets(bp,bpsize,fp) == NULL) {
      return(NULL);
    } else {
      numch = strlen(bp);
      cp = &bp[numch];
      if (*--cp == '\n') {
	  if (numch > 1 && *--cp == '\\') {
	      *cp++ = '\n';
	      *cp = NULL;
	      fgetlr(cp,bpsize-numch+1,fp);
	  }
      }
      return(bp);
    }
}
SHAR_EOF
cat << \SHAR_EOF > termlib/isdigit.c
/************************************************************************
 *								      *
 *		      Copyright (c) 1982, Fred Fish		      *
 *			  All Rights Reserved			      *
 *								      *
 *    This software and/or documentation is released for public	      *
 *    distribution for personal, non-commercial use only.	      *
 *    Limited rights to use, modify, and redistribute are hereby      *
 *    granted for non-commercial purposes, provided that all	      *
 *    copyright notices remain intact and all changes are clearly     *
 *    documented.  The author makes no warranty of any kind with      *
 *    respect to this product and explicitly disclaims any implied    *
 *    warranties of merchantability or fitness for any particular     *
 *    purpose.							      *
 *								      *
 ************************************************************************
 */




/*
 *  LIBRARY FUNCTION
 *
 *    isdigit	 test character for numeric property
 *
 *  SYNOPSIS
 *
 *    int isdigit(ch)
 *    char ch;
 *
 *  DESCRIPTION
 *
 *    Returns TRUE or FALSE depending upon whether the specified
 *    character is a numeric character or not.
 *
 *  BUGS
 *
 *    May fail on machines in which native character set is not ASCII.
 *
 */

#include <stdio.h>

#define TRUE 1
#define FALSE 0

int isdigit(ch)
char ch;
{
    if (ch > '9' || ch < '0') {
      return(FALSE);
    } else {
      return(TRUE);
    }
}
SHAR_EOF
cat << \SHAR_EOF > termlib/testtcp.c
/************************************************************************
 *								      *
 *		      Copyright (c) 1982, Fred Fish		      *
 *			  All Rights Reserved			      *
 *								      *
 *    This software and/or documentation is released for public	      *
 *    distribution for personal, non-commercial use only.	      *
 *    Limited rights to use, modify, and redistribute are hereby      *
 *    granted for non-commercial purposes, provided that all	      *
 *    copyright notices remain intact and all changes are clearly     *
 *    documented.  The author makes no warranty of any kind with      *
 *    respect to this product and explicitly disclaims any implied    *
 *    warranties of merchantability or fitness for any particular     *
 *    purpose.							      *
 *								      *
 ************************************************************************
 */




/*
 *  TEST PROGRAM
 *
 *    testtcp	test termcap functions
 *
 *  KEY WORDS
 *
 *    test routines
 *    termcap test
 *
 *  SYNOPSIS
 *
 *    termcap [-efns] terminal [capability [capability ...]]
 *
 *	      -e  =>   expand string capability given by -s
 *	      -f  =>   determine boolean capabilities for terminal
 *	      -n  =>   determine numeric capabilities for terminal
 *	      -s  =>   determine string capabilities for terminal
 *
 *	      terminal =>  terminal name as given in termcap file
 *	      capability => a boolean, numeric, or string capability
 *
 *	      NOTE:  All capabilities must be of same type, as
 *		     given by [-fns].
 *
 *	      If terminal is only argument then entire entry is
 *	      printed.
 *
 *  DESCRIPTION
 *
 *    Provides way to test termcap functions.  Can find
 *    and print an entire termcap terminal entry, or various
 *    capabilities from the entry.
 *
 *  AUTHOR
 *
 *    Fred Fish
 *
 */

#include <stdio.h>

#define TRUE 1
#define FALSE 0
#define NO_FILE	       -1		      /* Returned if can't open file */
#define NO_ENTRY  0		      /* Returned if can't find entry */
#define SUCCESS	  1		      /* Returned if entry found ok */
#define TRUNCATED 2		      /* Returned if entry found but trunc */
#define BUFFER_SIZE 1024

int eflag = FALSE;
int fflag = FALSE;
int nflag = FALSE;
int sflag = FALSE;

int got_terminal = FALSE;
int got_capability = FALSE;




/*
 *  FUNCTION
 *
 *    main   termcap test entry point
 *
 *  KEY WORDS
 *
 *    main
 *
 *  SYNOPSIS
 *
 *    main(argc,argv)
 *    int argc;
 *    char *argv[];
 *
 *  DESCRIPTION
 *
 *    This is where the termcap test starts executing.	All argument list
 *    switches are processed first, then all the specified
 *    capability identification strings are processed.
 *
 */



/*
 *  PSEUDO CODE
 *
 *    Begin main
 *	  Process command line options.
 *	  For each argument list field
 *	      If field was not erased during option processing
 *		  If terminal name field not yet processed then
 *		      Process an assumed terminal name field.
 *		      Set terminal name processed flag.
 *		  Else
 *		      Process a capability field.
 *		      Set capability field processed flag.
 *		  End if
 *	      End if
 *	  End for
 *	  If no capabilities processed then
 *	      Simply dump buffer.
 *	  End if
 *    End main
 *
 */

main(argc, argv)
int argc;
char *argv[];
{
    char *argp;
    int argnum;
    char buffer[BUFFER_SIZE];

    options(argc,argv);
    for (argnum = 1; argnum < argc; argnum++) {
	if ((argp = argv[argnum]) != NULL) {
	  if (!got_terminal) {
	      terminal(buffer,argp);
	      got_terminal = TRUE;
	  } else {
	      capability(argp);
	      got_capability = TRUE;
	  }
	}
    }
    if (got_terminal && !got_capability) {
      printf("%s",buffer);
    }
}



/*
 *  FUNCTION
 *
 *    options	process command line options
 *
 *  SYNOPSIS
 *
 *    options(argc,argv)
 *    int argc;
 *    char *argv[];
 *
 *  DESCRIPTION
 *
 *    Scans argument list, processing each switch as it is
 *    found.  The pointer to each switch string is then
 *    replaced with a NULL to effectively erase the switch
 *    argument.
 *
 */



/*
 *  PSEUDO CODE
 *
 *    Begin options
 *	  For each argument in the argument list
 *	      Get pointer to first char of argument.
 *	      If the argument is a switch then
 *		  Replace argument pointer with NULL.
 *		  Look at next argument character.
 *		  While there is another argument character
 *		      Switch on the argument character
 *		      Case "EXPAND":
 *			  Set expand (e) flag.
 *			  Break out of switch.
 *		      Case "BOOLEAN":
 *			  Set boolean (f) flag.
 *			  Break out of switch.
 *		      Case "NUMERIC":
 *			  Set numeric flag.
 *			  Break out of switch.
 *		      Case "STRING":
 *			  Set string flag.
 *			  Break out of switch.
 *		      Default:
 *			  Abort with usage message.
 *		      End switch
 *		  End while
 *	      End if
 *	  End for
 *    End options
 *
 */



options(argc, argv)
int argc;
char *argv[];
{
    int i;
    char c;	      /* 1st char of current command-line argument */
    char *cp;	      /* current argument pointer */

    for (i=1; i<argc; i++) {
	cp = argv[i];
	if (*cp == '-') {
	    argv[i] = NULL;
	  cp++;
	  while (c = *cp++) {
	      switch (c) {
	      case 'e':
		  eflag = TRUE;
		  break;
	      case 'f':
		  fflag = TRUE;
		  break;
	      case 'n':
		  nflag = TRUE;
		  break;
	      case 's':
		  sflag = TRUE;
		  break;
	      default:
		  usage();
	      }
	    }
	}
    }
}



/*
 *  FUNCTION
 *
 *    usage   give usage message and abort
 *
 *  KEY WORDS
 *
 *    usage
 *    help processing
 *    abort locations
 *
 *  SYNOPSIS
 *
 *    usage()
 *
 *  DESCRIPTION
 *
 *    Usage is typically called when a problem has been
 *    detected in the argument list.
 *    It prints a usage message and exits.
 *
 */



/*
 *  PSEUDO CODE
 *
 *    Begin usage
 *	  Print usage message.
 *	  Exit.
 *    End usage
 *
 */

usage()
{
    printf("Usage: termcap [-fns] terminal [capability [capability ... ]]\n");
    exit();
}




terminal(buffer,name)
char *buffer;
char *name;
{
    int status;

    status = tgetent(buffer,name);
    switch (status) {
    case NO_FILE:
      fprintf(stderr,"Can't find a termcap data base file.\n");
      exit();
    case NO_ENTRY:
      fprintf(stderr,"Can't find entry \"%s\"\n",name);
      exit();
    case TRUNCATED:
      fprintf(stderr,"Warning --- entry \"%s\" too long\n",name);
      break;
    case SUCCESS:
	break;
    default:
	fprintf(stderr,"? tgetent returned illegal status %d\n",status);
      exit();
    }
}



capability(id)
char *id;
{
    int value;
    char buffer[256];
    char *area;
    char *ep, *tgoto();

    if (fflag) {
      value = tgetflag(id);
      if (value) {
	  printf("%s TRUE\n",id);
      } else {
	  printf("%s FALSE\n",id);
      }
    } else if (nflag) {
      value = tgetnum(id);
      printf("%s = %o octal %d decimal\n",id,value,value);
    } else if (sflag) {
      area = buffer;
      tgetstr(id,&area);
      if (eflag) {
	  ep = tgoto(buffer,75,23);
      }
      doprint(id,buffer);
      if (eflag) {
	  doprint(id,ep);
	  ep = tgoto(buffer,1,2);
	  doprint(id,ep);
      }
    }
}



doprint(id,cp)
char *id;
char *cp;
{
    printf("%s = \"",id);
    for ( ; *cp != NULL; cp++) {
      if (*cp < 040) {
	  printf("^%c",*cp |= 0100);
      } else {
	  printf("%c",*cp);
      }
    }
    printf("\"\n");
}
SHAR_EOF
cat << \SHAR_EOF > termlib/tgetent.c
/************************************************************************
 *								      *
 *		      Copyright (c) 1982, Fred Fish		      *
 *			  All Rights Reserved			      *
 *								      *
 *    This software and/or documentation is released for public	      *
 *    distribution for personal, non-commercial use only.	      *
 *    Limited rights to use, modify, and redistribute are hereby      *
 *    granted for non-commercial purposes, provided that all	      *
 *    copyright notices remain intact and all changes are clearly     *
 *    documented.  The author makes no warranty of any kind with      *
 *    respect to this product and explicitly disclaims any implied    *
 *    warranties of merchantability or fitness for any particular     *
 *    purpose.							      *
 *								      *
 ************************************************************************
 */
/*
 * Modified:
 *    30-Apr-86 Mic Kaczmarczik ...!ihnp4!seismo!ut-sally!ut-ngp!mic
 *		Instead of using VAX C getenv("TERM"), which does not
 *		return the value of logical name "TERM", translate the
 *		logical name by hand.
 *    11-Oct-86 Mic Kaczmarczik ...!ihnp4!seismo!ut-sally!ut-ngp!mic
 *		Support tc capability to allow the library to use standard
 *		termcaps.  Rewrote tgetent to look for tc capability
 *		and add new terminal definition to the caller's buffer.
 *		This makes it rather possible to overflow the caller's
 *		buffer, but the library doesn't make any claim that it
 *		won't overwrite the buffer anyway...
 *    27-Jan-88 Bob Larson  blarson@ecla.usc.edu
 *		Add primos (__50SERIES) support.
 *	1-Feb-88  Sandra Loosemore  (sandra@cs.utah.edu)
 *		  Change default termcap file for VMS to be the same place
 *		  that GNU puts it.
 *	23-Apr-88 Bob Larson
 *		  merge primos and vms changes
 */



/*
 *  LIBRARY FUNCTION
 *
 *    tgetent	load buffer with entry for specified terminal
 *
 *  KEY WORDS
 *
 *    termcap functions
 *    utility routines
 *
 *  SYNOPSIS
 *
 *    int tgetent(bp,name)
 *    char *bp;
 *    char *name;
 *
 *  DESCRIPTION
 *
 *    Extracts the entry for terminal <name> from the termcap file
 *    and places it in the character buffer <bp>.   It is currently
 *    assumed that bp is at least 1024 characters.  If the entry in
 *    the termcap file is larger than 1023 characters the excess
 *    characters will be discarded and appropriate status will
 *    be returned.
 *
 *    Also note that since bp is used by other termcap
 *    routines, the storage associated with the termcap entry
 *    cannot be freed until all termcap calls are completed.
 *
 *    Tgetent can be directed to look in a file other than
 *    the default (/etc/termcap) by defining an environment
 *    variable called TERMCAP to be the pathname of the desired
 *    termcap file.  This is useful for debugging new entries.
 *    NOTE: the pathname MUST begin with a '/' character.
 *
 *    Also, if the string assigned to TERMCAP does not begin with
 *    a '/' and if the environment variable TERM matches <name> then
 *    the string assigned to TERMCAP is copied to buffer <bp>
 *    instead of reading a termcap file.
 *
 *  RETURNS
 *
 *    -1  if the termcap file cannot be opened
 *     0  if no entry in termcap file matches <name>
 *     1  if extraction is successful with no errors
 *     2  if extraction is successful but entry truncated
 *
 *  SEE ALSO
 *
 *    tgetnum	extract numeric type capability
 *    tgetflag	test boolean type capability
 *    tgetstr	get string value of capability
 *
 *  AUTHOR
 *
 *    Fred Fish
 *
 */

#include <stdio.h>

#define TRUE 1
#define FALSE 0
#define BUFSIZE 1024		      /* Assumed size of external buffer */

#define NO_FILE	       -1		      /* Returned if can't open file */
#define NO_ENTRY  0		      /* Returned if can't find entry */
#define SUCCESS	  1		      /* Returned if entry found ok */
#define TRUNCATED 2		      /* Returned if entry found but trunc */

#ifdef __50SERIES
#define DEFAULT_FILE "mg*>termcap"
#else
#define DEFAULT_FILE "/etc/termcap"   /* default termcap filename */
#ifdef	      VAXC
#define	      index strchr
#endif
#endif

char *_tcpbuf;			      /* Place to remember buffer pointer */
FILE *fp;			      /* Termcap file		      */
static FILE *find_file();
extern char *index();

/*
 *  PSEUDO CODE
 *
 *    Begin tgetent
 *	  Erase any previous buffer contents.
 *	  Remember the buffer pointer.
 *	  If termcap file is not found then
 *	      If buffer was filled anyway then
 *		  Return SUCCESS.
 *	      Else
 *		  Return NO_FILE.
 *	      End if
 *	  Else
 *	      Find entry associated with name
 *	      While an entry was found and limit not reached
 *		  If no tc capability found Then
 *		      Exit while loop with status = SUCCESS
 *		  Else
 *		      Call getent to get entry indicated by tc=
 *		      If entry not found then
 *			      Exit loop with status != SUCCESS
 *		      End if
 *		      Concatenate entry into buffer
 *		  End If
 *	      End while
 *	  End if
 *	  Close termcap file
 *	  Return status code
 *    End tgetent
 *
 */

static int getent();

int tgetent(bp,name)
char *bp;
char *name;
{
      char    *tc, *tcbufp, tcbuf[80], termbuf[BUFSIZE], *tgetstr();
      char    *bufp, *cp;	      /* current start of buffer      */
      int     limit = 10;	      /* maximum nesting	      */
      int     status;		      /* return from getent()	      */

      *bp = '\0';		      /* clear buffer		      */
      _tcpbuf = bp;		      /* save base of buffer	      */

      /* Look for termcap file.	 If NULL, find_file may have found a  */
      /* a valid termcap string in the environment variable TERMCAP.  */
      /* If non-null, attempt to find the entry in the termcap file   */

      if ((fp = find_file(bp)) == NULL) {
	      if (*bp != NULL)
		      return(SUCCESS);
	      else
		      return(NO_FILE);
      }
      status = getent(bp, name);/* look for main entry	      */

      /* Start looking for tc capabilities in the termcap.  If
       * found, concatenate the entry for the new terminal to the
       * current buffer and try again.	To avoid infinite loops,
       * allow only 10 loops through this process.
       */
      while ((status == SUCCESS) && limit--) {
	      /* look for tc capability.  If none found, exit loop    */
	      tcbufp = tcbuf;
	      if (((tc = tgetstr("tc",&tcbufp)) == NULL)
		    || (*tc == '\0')) {
		      status = SUCCESS;/* no more tc= entries */
		      break;
	      }

	      /* Attempt to get next entry. Exit loop if unsuccessful */
	      if ((status = getent(termbuf, tcbuf)) != SUCCESS)
		      break;

	      /* Copy new entry into buffer, right at "tc="	      */
	      for (bufp = bp; *bufp; bufp++)	      /* find tc=     */
		      if ((*bufp=='t') && (bufp[1]=='c') && (bufp[2]=='='))
			      break;
	      if ((cp = index(termbuf,':')) == NULL)
		      cp = termbuf;
	      strcpy(bufp, cp + 1);
      }

      /* close termcap file and return the status     */
      fclose(fp);
      return status;
}




/*
 *  INTERNAL FUNCTION
 *
 *    getent	find termcap entry in termcap file
 *
 *  KEY WORDS
 *
 *    internal functions
 *    getent
 *
 *  SYNOPSIS
 *
 *    static int getent(bp,name)
 *    char *bp;
 *    char *name;
 *
 *  DESCRIPTION
 *
 *    Getent is called by tgetent each time tgetent attempts to
 *    read a capability from the termcap database file.	 Places
 *    the entry in the buffer pointed to by bp
 *
 *
 *  PSEUDOCODE
 *
 *    Begin Getent
 *	  Seek to beginning of termcap file
 *	  Clear buffer
 *	  While records left to process
 *	      If this is entry is what we want then
 *		  If entry was truncated then
 *		      Return TRUNCATED status
 *		  Else
 *		      Return SUCCESS status.
 *		  End if
 *	      End if
 *	  End while
 *	  Return NO_ENTRY status.
 *    End
 */

static int getent(bp,name)
char *bp;			      /* Pointer to buffer (1024 char min) */
char *name;			      /* Pointer to terminal entry to find */
{
      *bp = '\0';		      /* clear buffer		      */
      lseek(fileno(fp), 0L, 0l);      /* rewind termcap file	      */

      while (fgetlr(bp,BUFSIZE,fp)) {
	      if (gotcha(bp,name)) {
		      if (bp[strlen(bp)-1] != '\n') {
			      return(TRUNCATED);
		      } else {
			      return(SUCCESS);
		      }
	      }
      }
      return(NO_ENTRY);
}



/*
 *  INTERNAL FUNCTION
 *
 *    find_file	   find the termcap file and open it if possible
 *
 *  KEY WORDS
 *
 *    internal functions
 *    find_file
 *
 *  SYNOPSIS
 *
 *    static FILE *find_file(bp)
 *    char *bp;
 *
 *  DESCRIPTION
 *
 *    Attempts to locate and open the termcap file.  Also handles
 *    using the environment TERMCAP string as the actual buffer
 *    (that's why bp has to be an input parameter).
 *
 *    If TERMCAP is defined an begins with a '/' character then
 *    it is taken to be the pathname of the termcap file and
 *    an attempt is made to open it.  If this fails then
 *    the default termcap file is used instead.
 *
 *    If TERMCAP is defined but does not begin with a '/' then
 *    it is assumed to be the actual buffer contents provided
 *    that <name> matches the environment variable TERM.
 *
 *  BUGS
 *
 *    There is currently no way to be sure which termcap
 *    file was opened since the default will always be
 *    tried.
 *
 */



/*
 *  PSEUDO CODE
 *
 *    Begin find_file
 *	  If there is a TERMCAP environment string then
 *	      If the string is not null then
 *		  If the string is a pathname then
 *		      If that file is opened successfully then
 *			  Return its pointer.
 *		      End if
 *		  Else
 *		      If there is a TERM environment string then
 *			  If TERM matches <name> then
 *			      Copy TERMCAP string to buffer.
 *			      Return NULL for no file.
 *			  End if
 *		      End if
 *		  End if
 *	      End if
 *	  End if
 *	  Open default termcap file and return results.
 *    End find_file
 *
 */
#ifdef	      __50SERIES
static FILE *find_file(bp)
char *bp;
{
    char *cp;
    char *gvget();

    if((cp = gvget(".TERMCAP")) != NULL && *cp)
	return fopen(cp, "r");
    if((cp = gvget(".TERMCAP$")) != NULL && *cp)
	return fopen(cp, "r");
    return fopen(DEFAULT_FILE, "r");
}
#else
#ifdef	      VAXC
char *trnlnm();
#endif

static FILE *find_file(bp)
char *bp;
{
    FILE *fp, *fopen();
    char *cp, *ncp, *getenv(), vmsname[132];

    if ((cp = getenv("TERMCAP")) != NULL) {
      if (*cp != NULL) {
	  if (*cp == '/') {
	      if ((fp = fopen(cp,"r")) != NULL) {
		  return(fp);
	      }
	  } else {
#ifdef VAXC
	      if ((ncp = trnlnm("TERM")) != NULL) {
#else
	      if ((ncp = getenv("TERM")) != NULL) {
#endif
		  if (strcmp(cp,ncp) == 0) {
		      strcpy(bp,cp);
		      return((FILE *)NULL);
		  }
	      }
	  }
      }
    }
#ifdef VAXC
    if ((fp = fopen("emacs_library:[etc]termcap.dat","r")) != NULL)
	return(fp);
#endif
    return(fopen(DEFAULT_FILE,"r"));
}
#endif /* __50SERIES */



/*
 *  INTERNAL FUNCTION
 *
 *    gotcha   test to see if entry is for specified terminal
 *
 *  SYNOPSIS
 *
 *    gotcha(bp,name)
 *    char *bp;
 *    char *name;
 *
 *  DESCRIPTION
 *
 *    Tests to see if the entry in buffer bp matches the terminal
 *    specified by name.  Returns TRUE if match is detected, FALSE
 *    otherwise.
 *
 */



/*
 *  PSEUDO CODE
 *
 *    Begin gotcha
 *	  If buffer character is comment character then
 *	      Return FALSE since remainder is comment
 *	  Else
 *	      Initialize name scan pointer.
 *	      Compare name and buffer until end or mismatch.
 *	      If valid terminators for both name and buffer strings
 *		  Return TRUE since a match was found.
 *	      Else
 *		  Find next non-name character in buffer.
 *		  If not an alternate name separater character
 *		      Return FALSE since no more names to check.
 *		  Else
 *		      Test next name and return results.
 *		  End if
 *	      End if
 *	  End if
 *    End gotcha
 *
 */

gotcha(bp,name)
char *bp;
char *name;
{
    char *np;

    if (*bp == '#') {
      return(FALSE);
    } else {
      np = name;
      while (*np == *bp && *np != NULL) {np++; bp++;}
      if (*np == NULL && (*bp == NULL || *bp == '|' || *bp == ':')) {
	  return(TRUE);
      } else {
	  while (*bp != NULL && *bp != ':' && *bp != '|') {bp++;}
	  if (*bp != '|') {
	      return(FALSE);
	  } else {
	      return(gotcha(++bp,name));
	  }
      }
    }
}
SHAR_EOF
cat << \SHAR_EOF > termlib/tgetflag.c
/************************************************************************
 *								      *
 *		      Copyright (c) 1982, Fred Fish		      *
 *			  All Rights Reserved			      *
 *								      *
 *    This software and/or documentation is released for public	      *
 *    distribution for personal, non-commercial use only.	      *
 *    Limited rights to use, modify, and redistribute are hereby      *
 *    granted for non-commercial purposes, provided that all	      *
 *    copyright notices remain intact and all changes are clearly     *
 *    documented.  The author makes no warranty of any kind with      *
 *    respect to this product and explicitly disclaims any implied    *
 *    warranties of merchantability or fitness for any particular     *
 *    purpose.							      *
 *								      *
 ************************************************************************
 */
/*
 * Modified:
 *    30-Apr-86 Mic Kaczmarczik
 *    #define index to strchr if VAX C
 *
 */




/*
 *  LIBRARY FUNCTION
 *
 *    tgetflag	 extract boolean termcap capability
 *
 *  KEY WORDS
 *
 *    termcap
 *
 *  SYNOPSIS
 *
 *    tgetflag(id)
 *    char *id;
 *
 *  DESCRIPTION
 *
 *    Returns TRUE if specified id is present in terminal
 *    entry, FALSE otherwise.
 *
 */

#include <stdio.h>
#ifdef VAXC
#define index strchr
#endif

#define TRUE 1
#define FALSE 0

extern char *_tcpbuf;	      /* Termcap entry buffer pointer */



/*
 *  PSEUDO CODE
 *
 *    Begin tgetflag
 *	  Initialize pointer to the termcap entry buffer.
 *	  While there is a field to process
 *	      Skip over the field separator character.
 *	      If this is the entry we want then
 *		  If entry is identifier only then
 *		      Return TRUE
 *		  Else
 *		      Return FALSE
 *		  End if
 *	      End if
 *	  End while
 *	  Return FALSE as default.
 *    End tgetflag
 *
 */

tgetflag(id)
char *id;
{
    char *bp;
    extern char *index();

    bp = _tcpbuf;
    while ((bp = index(bp,':')) != NULL) {
      bp++;
      if (*bp++ == id[0] && *bp != NULL && *bp++ == id[1]) {
	  if (*bp == NULL || *bp++ == ':') {
	      return(TRUE);
	  } else {
	      return(FALSE);
	  }
      }
    }
    return(FALSE);
}
SHAR_EOF
cat << \SHAR_EOF > termlib/tgetnum.c
/************************************************************************
 *								      *
 *		      Copyright (c) 1982, Fred Fish		      *
 *			  All Rights Reserved			      *
 *								      *
 *    This software and/or documentation is released for public	      *
 *    distribution for personal, non-commercial use only.	      *
 *    Limited rights to use, modify, and redistribute are hereby      *
 *    granted for non-commercial purposes, provided that all	      *
 *    copyright notices remain intact and all changes are clearly     *
 *    documented.  The author makes no warranty of any kind with      *
 *    respect to this product and explicitly disclaims any implied    *
 *    warranties of merchantability or fitness for any particular     *
 *    purpose.							      *
 *								      *
 ************************************************************************
 */
/* Modified:
 * 30-Apr-86 Mic Kaczmarczik
 *	   Use ctype.h macros instead of the function isdigit().
 *	   #define index to strchr if VAXC
 */



/*
 *  LIBRARY FUNCTION
 *
 *    tgetnum	extract numeric option from termcap entry
 *
 *  KEY WORDS
 *
 *    termcap
 *    ce functions
 *
 *  SYNOPSIS
 *
 *    tgetnum(id)
 *    char *id;
 *
 *  DESCRIPTION
 *
 *    Returns numeric value of capability <id>, or -1 if <id>
 *    is not found.   Knows about octal numbers, which
 *    begin with 0.
 *
 */

#include <stdio.h>
#include <ctype.h>
#ifdef	      VAXC
#define index strchr
#endif

extern char *_tcpbuf;	      /* Termcap entry buffer pointer */



/*
 *  PSEUDO CODE
 *
 *    Begin tgetnum
 *	  Initialize pointer to the termcap entry buffer.
 *	  While there is a field to process
 *	      Skip over the field separator character.
 *	      If this is the entry we want then
 *		  If the entry is not a numeric then
 *		      Return failure value.
 *		  Else
 *		      Initialize value to zero.
 *		      If number begins with zero then
 *			  Set accumulation base to 8.
 *		      Else
 *			  Set accumulation base to 10.
 *		      End if
 *		      While there is a numeric character
 *			  Accumulate the value.
 *		      End while
 *		      Return value.
 *		  End if
 *	      End if
 *	  End while
 *	  Return failure value.
 *    End tgetnum
 *
 */

tgetnum(id)
char *id;
{
    int value, base;
    char *bp;
    extern char *index();

    bp = _tcpbuf;
    while ((bp = index(bp,':')) != NULL) {
      bp++;
      if (*bp++ == id[0] && *bp != NULL && *bp++ == id[1]) {
	  if (*bp != NULL && *bp++ != '#') {
	      return(-1);
	  } else {
	      value = 0;
	      if (*bp == '0') {
		  base = 8;
	      } else {
		  base = 10;
	      }
	      while (isdigit(*bp)) {
		  value *= base;
		  value += (*bp++ - '0');
	      }
	      return(value);
	  }
      }
    }
    return(-1);
}
SHAR_EOF
cat << \SHAR_EOF > termlib/tgetstr.c
/************************************************************************
 *								      *
 *		      Copyright (c) 1982, Fred Fish		      *
 *			  All Rights Reserved			      *
 *								      *
 *    This software and/or documentation is released for public	      *
 *    distribution for personal, non-commercial use only.	      *
 *    Limited rights to use, modify, and redistribute are hereby      *
 *    granted for non-commercial purposes, provided that all	      *
 *    copyright notices remain intact and all changes are clearly     *
 *    documented.  The author makes no warranty of any kind with      *
 *    respect to this product and explicitly disclaims any implied    *
 *    warranties of merchantability or fitness for any particular     *
 *    purpose.							      *
 *								      *
 ************************************************************************
 */
/* Modified:
 * 30-Apr-86 Mic Kaczmarczik
 *	   Use ctype.h macros instead of the function isdigit().
 *	   #define index() to be strchr() if VAX C
 */




/*
 *  LIBRARY FUNCTION
 *
 *    tgetstr	extract string capability from termcap entry
 *
 *  KEY WORDS
 *
 *    termcap
 *
 *  SYNOPSIS
 *
 *    char *tgetstr(id,area)
 *    char *id;
 *    char **area;
 *
 *  DESCRIPTION
 *
 *    Gets the string capability for <id>, placing it in
 *    the buffer at *area, and advancing *area to point
 *    to next available storage.
 *
 *    For example, if the following capabilities are
 *    in the termcap file:
 *
 *	      ZZ=zzzz
 *	      YY=yyyyyy
 *	      WW=www
 *
 *    then successive calls using YY, ZZ, and WW will
 *    build the following buffer:
 *
 *	      yyyyyy0zzzz0www0
 *
 *    The first call will return a pointer to yyyyyy, the
 *    second will return a pointer to zzzz and the third
 *    will return a pointer to www.  Note that each
 *    string is null terminated, as are all C strings.
 *
 *    Characters preceded by the carot character (\136)
 *    are mapped into the corresponding control character.
 *    For example, the two character sequence ^A becomes
 *    a single control-A (\001) character.
 *
 *    The escape character is the normal C backslash and
 *    the normal C escape sequences are recognized, along
 *    with a special sequence for the ASCII escape character
 *    (\033).  The recognized sequences are:
 *
 *	      \E   =>  '\033'  (ASCII escape character)
 *	      \b   =>  '\010'  (ASCII backspace character)
 *	      \f   =>  '\014'  (ASCII form feed character)
 *	      \n   =>  '\012'  (ASCII newline/linefeed char)
 *	      \r   =>  '\015'  (ASCII carriage return char)
 *	      \t   =>  '\011'  (ASCII tab character)
 *	      \ddd =>  '\ddd'  (arbitrary ASCII digit)
 *	      \x   =>  'x'     (ordinary ASCII character)
 *
 */

#include <stdio.h>
#include <ctype.h>
#ifdef VAXC
#define index strchr
#endif

extern char *_tcpbuf;	      /* Termcap entry buffer pointer */



/*
 *  PSEUDO CODE
 *
 *    Begin tgetstr
 *	  Initialize pointer to the termcap entry buffer.
 *	  While there is a field to process
 *	      Skip over the field separator character.
 *	      If this is the entry we want then
 *		  If the entry is not a string then
 *		      Return NULL.
 *		  Else
 *		      Transfer string and rtn pointer.
 *		  End if
 *	      End if
 *	  End while
 *	  Return NULL
 *    End tgetstr
 *
 */

char *tgetstr(id,area)
char *id;
char **area;
{
    char *bp;
    extern char *index();
    static char *decode();

    bp = _tcpbuf;
    while ((bp = index(bp,':')) != NULL) {
      if (*++bp == NULL)
	      break;
      if (*bp++ == id[0] && *bp != NULL && *bp++ == id[1]) {
	  if (*bp != NULL && *bp++ != '=') {
	      return(NULL);
	  } else {
	      return(decode(bp,area));
	  }
      }
    }
    **area = NULL;
    bp = (*area)++;
    return(bp);
}



/*
 *  INTERNAL FUNCTION
 *
 *    decode   transfer string capability, decoding escapes
 *
 *  SYNOPSIS
 *
 *    static char *decode(bp,area)
 *    char *bp;
 *    char **area;
 *
 *  DESCRIPTION
 *
 *    Transfers the string capability, up to the next ':'
 *    character, or null, to the buffer pointed to by
 *    the pointer in *area.  Note that the initial
 *    value of *area and *area is updated to point
 *    to the next available location after the null
 *    terminating the transfered string.
 *
 *  BUGS
 *
 *    There is no overflow checking done on the destination
 *    buffer, so it better be large enough to hold
 *    all expected strings.
 *
 */



/*
 *  PSEUDO CODE
 *
 *    Begin decode
 *	  Initialize the transfer pointer.
 *	  While there is an input character left to process
 *	      Switch on input character
 *	      Case ESCAPE:
 *		  Decode and xfer the escaped sequence.
 *		  Break
 *	      Case CONTROLIFY:
 *		  Controlify and xfer the next character.
 *		  Advance the buffer pointer.
 *		  Break
 *	      Default:
 *		  Xfer a normal character.
 *	      End switch
 *	  End while
 *	  Null terminate the output string.
 *	  Remember where the output string starts.
 *	  Update the output buffer pointer.
 *	  Return pointer to the output string.
 *    End decode
 *
 */

static char *decode(bp,area)
char *bp;
char **area;
{
    char *cp, *bgn;
    char *do_esc();

    cp = *area;
    while (*bp != NULL && *bp != ':') {
      switch(*bp) {
      case '\\':
	  bp = do_esc(cp++,++bp);
	  break;
      case '^':
	  *cp++ = *++bp & 037;
	  bp++;
	  break;
      default:
	  *cp++ = *bp++;
	  break;
      }
    }
    *cp++ = NULL;
    bgn = *area;
    *area = cp;
    return(bgn);
}



/*
 *  INTERNAL FUNCTION
 *
 *    do_esc	process an escaped sequence
 *
 *  SYNOPSIS
 *
 *    char *do_esc(out,in);
 *    char *out;
 *    char *in;
 *
 *  DESCRIPTION
 *
 *    Processes an escape sequence pointed to by
 *    in, transfering it to location pointed to
 *    by out, and updating the pointer to in.
 *
 */



/*
 *  PSEUDO CODE
 *
 *    Begin do_esc
 *	  If the first character is not a NULL then
 *	      If is a digit then
 *		  Set value to zero.
 *		  For up to 3 digits
 *		      Accumulate the sum.
 *		  End for
 *		  Transfer the sum.
 *	      Else if character is in remap list then
 *		  Transfer the remapped character.
 *		  Advance the input pointer once.
 *	      Else
 *		  Simply transfer the character.
 *	      End if
 *	  End if
 *	  Return updated input pointer.
 *    End do_esc
 *
 */

static char *maplist = {
    "E\033b\bf\fn\nr\rt\t"
};

char *do_esc(out,in)
char *out;
char *in;
{
    int count;
    char ch;
    extern char *index();
    char *cp;

    if (*in != NULL) {
      if (isdigit(*in)) {
	  ch = 0;
	  for (count = 0; count < 3 && isdigit(*in); in++) {
	       ch <<= 3;
	       ch |= (*in - '0');
	  }
	  *out++ = ch;
      } else if ((cp = index(maplist,*in)) != NULL) {
	  *out++ = *++cp;
	  in++;
      } else {
	  *out++ = *in++;
      }
    }
    return(in);
}
SHAR_EOF
cat << \SHAR_EOF > termlib/tgoto.c
/************************************************************************
 *								      *
 *		      Copyright (c) 1982, Fred Fish		      *
 *			  All Rights Reserved			      *
 *								      *
 *    This software and/or documentation is released for public	      *
 *    distribution for personal, non-commercial use only.	      *
 *    Limited rights to use, modify, and redistribute are hereby      *
 *    granted for non-commercial purposes, provided that all	      *
 *    copyright notices remain intact and all changes are clearly     *
 *    documented.  The author makes no warranty of any kind with      *
 *    respect to this product and explicitly disclaims any implied    *
 *    warranties of merchantability or fitness for any particular     *
 *    purpose.							      *
 *								      *
 ************************************************************************
 */
/*
 * Modified:
 *    1 May 86 ...!ihnp4!ut-sally!ut-ngp!mic
 *	      Now forces a '\0' at end of tgoto string.	 Tgoto wasn't,
 *	      and this screwed up VT100-style (i.e. variable) cursor
 *	      addressing.
 */



/*
 *  LIBRARY FUNCTION
 *
 *    tgoto   expand cursor addressing string from cm capability
 *
 *  KEY WORDS
 *
 *    termcap
 *
 *  SYNOPSIS
 *
 *    char *tgoto(cm,destcol,destline)
 *    char *cm;
 *    int destcol;
 *    int destline;
 *
 *  DESCRIPTION
 *
 *    Returns cursor addressing string, decoded from the cm
 *    capability string, to move cursor to column destcol on
 *    line destline.
 *
 *    The following sequences uses one input argument, either
 *    line or column, and place the appropriate substitution
 *    in the output string:
 *
 *	      %d      substitute decimal value (in ASCII)
 *	      %2      like %d but forces field width to 2
 *	      %3      like %d but forces field width to 3
 *	      %.      like %c
 *	      %+x     like %c but adds ASCII value of x
 *
 *    The following sequences cause processing modifications
 *    but do not "use up" one of the arguments.	If they
 *    act on an argument they act on the next one to
 *    be converted.
 *
 *	      %>xy    if next value to be converted is
 *		      greater than value of ASCII char x
 *		      then add value of ASCII char y.
 *	      %r      reverse substitution of line
 *		      and column (line is substituted
 *		      first by default).
 *	      %i      causes input values destcol and
 *		      destline to be incremented.
 *	      %%      gives single % character in output.
 *
 *  BUGS
 *
 *    Does not implement some of the more arcane sequences for
 *    radically weird terminals (specifically %n, %B, & %D).
 *    If you have one of these you deserve whatever happens.
 *
 */



/*
 *    Miscellaneous stuff
 */

#include <stdio.h>

#define MAXARGS 2

static char *in;	      /* Internal copy of input string pointer */
static char *out;	      /* Pointer to output array */
static int args[MAXARGS];     /* Maximum number of args to convert */
static int pcount;	      /* Count of args processed */
static char output[64];		      /* Converted string */




/*
 *  PSEUDO CODE
 *
 *    Begin tgoto
 *	  If no string to process then
 *	      Return pointer to error string.
 *	  Else
 *	      Initialize pointer to input string.
 *	      Initialize pointer to result string.
 *	      First arg is line number by default.
 *	      Second arg is col number by default.
 *	      No arguments processed yet.
 *	      While there is another character to process
 *		  If character is a not a % character then
 *		      Simply copy to output.
 *		  Else
 *		      Process the control sequence.
 *		  End if
 *	      End while
 *	      Return pointer to static output string.
 *	  End if
 *    End tgoto
 *
 */

char *tgoto(cm,destcol,destline)
char *cm;
int destcol;
int destline;
{
    static int process();

    if (cm == NULL) {
      return("OOPS");
    } else {
      in = cm;
      out = output;
      args[0] = destline;
      args[1] = destcol;
      pcount = 0;
      while (*in != NULL) {
	  if (*in != '%') {
	      *out++ = *in++;
	  } else {
	      process();
	  }
      }
      *out = NULL;    /* Just to make sure */
      return(output);
    }
}



/*
 *  INTERNAL FUNCTION
 *
 *    process	process the conversion/command sequence
 *
 *  SYNOPSIS
 *
 *    static process()
 *
 *  DESCRIPTION
 *
 *    Processes the sequence beginning with the % character.
 *    Directly manipulates the input string pointer, the
 *    output string pointer, and the arguments.	 Leaves
 *    the input string pointer pointing to the next character
 *    to be processed, and the output string pointer pointing
 *    to the next output location.  If conversion of
 *    one of the numeric arguments occurs, then the pcount
 *    is incremented.
 *
 */



/*
 *  PSEUDO CODE
 *
 *    Begin process
 *	  Skip over the % character.
 *	  Switch on next character after %
 *	  Case 'd':
 *	      Process %d type conversion (variable width).
 *	      Reinitialize output pointer.
 *	      Break;
 *	  Case '2':
 *	      Process %d type conversion (width 2).
 *	      Reinitialize output pointer.
 *	      Break;
 *	  Case '3':
 *	      Process %d type conversion (width 3).
 *	      Reinitialize output pointer.
 *	      Break;
 *	  Case '.'
 *	      Process %c type conversion.
 *	      Break;
 *	  Case '+':
 *	      Process %c type conversion with offset.
 *	      Break;
 *	  Case '>':
 *	      Process argument modification.
 *	      Break;
 *	  Case 'r':
 *	      Process argument reversal.
 *	      Break;
 *	  Case 'i':
 *	      Increment argument values.
 *	      Break;
 *	  Case '%':
 *	      Copy to output, incrementing pointers.
 *	      Break;
 *	  End switch
 *    End process
 *
 */




static process()
{
    int temp;

    in++;
    switch(*in++) {
    case 'd':
      sprintf(out,"%d",args[pcount++]);
      out = &output[strlen(output)];
      break;
    case '2':
      sprintf(out,"%02d",args[pcount++]);
      out = &output[strlen(output)];
      break;
    case '3':
      sprintf(out,"%03d",args[pcount++]);
      out = &output[strlen(output)];
      break;
    case '.':
      *out++ = args[pcount++];
      break;
    case '+':
      *out++ = args[pcount++] + *in++;
      break;
    case '>':
      if (args[pcount] > *in++) {
	  args[pcount] += *in++;
      } else {
	  in++;
      }
      break;
    case 'r':
      temp = args[pcount];
      args[pcount] = args[pcount+1];
      args[pcount+1] = temp;
      break;
    case 'i':
      args[pcount]++;
      args[pcount+1]++;
      break;
    case '%':
      *out++ = '%';
      break;
    }
}
SHAR_EOF
cat << \SHAR_EOF > termlib/tputs.c
/************************************************************************
 *								      *
 *		      Copyright (c) 1982, Fred Fish		      *
 *			  All Rights Reserved			      *
 *								      *
 *    This software and/or documentation is released for public	      *
 *    distribution for personal, non-commercial use only.	      *
 *    Limited rights to use, modify, and redistribute are hereby      *
 *    granted for non-commercial purposes, provided that all	      *
 *    copyright notices remain intact and all changes are clearly     *
 *    documented.  The author makes no warranty of any kind with      *
 *    respect to this product and explicitly disclaims any implied    *
 *    warranties of merchantability or fitness for any particular     *
 *    purpose.							      *
 *								      *
 ************************************************************************
 */
/* Modified:
 * 30-Apr-86 Mic Kaczmarczik
 *	   - Use ctype.h macros instead of the function isdigit().
 *	   - Use VMS speed value for ospeed -- in microEmacs
 *	     this is obtainted by ttinit().
 */




/*
 *  LIBRARY FUNCTION
 *
 *    tputs	output string with appropriate padding
 *
 *  KEY WORDS
 *
 *    termcap
 *
 *  SYNOPSIS
 *
 *    tputs(cp,affcnt,outc)
 *    char *cp;
 *    int affcnt;
 *    int (*outc)();
 *
 *  DESCRIPTION
 *
 *    Outputs string pointed to by cp, using function outc, and
 *    following it with the appropriate number of padding characters.
 *    Affcnt contains the number of lines affected, which is used
 *    as a multiplier for the specified per line pad time.  If
 *    per line pad count is not applicable, affcnt should be 1,
 *    NOT zero.
 *
 *    The format of the string pointed to by cp is:
 *
 *	      [pad time][*]<string to send>
 *
 *	      where:  pad time => time to delay in milliseconds
 *		      * => specifies that time is per line
 *
 *    The pad character is assumed to reside in the external
 *    variable "PC".  Also, the external variable "ospeed"
 *    should contain the output speed of the terminal as
 *    encoded in /usr/include/sgtty.h  (B0-B9600).
 *
 * SYSTEM DEPENDENCIES
 *
 *    On VMS, the external variable "ospeed" should contain the
 *    output speed of the terminal as obtained from byte 3 of
 *    the iosb status buffer, using the IO$_SENSEMODE QIO.
 *    The table times[] compiles into the correct values for VMS,
 *    and, happily, also handles 19200 baud.
 *
 *  BUGS
 *
 *    If ospeed is 0 for some reason, there is the chance of a
 *    divide by 0 operation.
 *
 */



/*
 *    Miscellaneous stuff
 */

#include <stdio.h>
#include <ctype.h>

extern char PC;			      /* Pad character to use */
extern short ospeed;	      /* Encoding of output speed */

#if   VMS
static int times[] = {
    10000,		      /* Tenths of ms per char	   0 baud (bogus) */
    2000,		      /* Tenths of ms per char	  50 baud */
    1333,		      /* Tenths of ms per char	  75 baud */
    909,		      /* Tenths of ms per char	 110 baud */
    743,		      /* Tenths of ms per char	 134 baud */
    666,		      /* Tenths of ms per char	 150 baud */
    333,		      /* Tenths of ms per char	 300 baud */
    166,		      /* Tenths of ms per char	 600 baud */
    83,				      /* Tenths of ms per char	1200 baud */
    55,				      /* Tenths of ms per char	1800 baud */
    50,				      /* Tenths of ms per char	2000 baud */
    41,				      /* Tenths of ms per char	2400 baud */
    28,				      /* Tenths of ms per char	3600 baud */
    20,				      /* Tenths of ms per char	4800 baud */
    14,				      /* Tenths of ms per char	7200 baud */
    10,				      /* Tenths of ms per char	9600 baud */
    5			      /* Tenths of ms per char 19200 baud */
};
#else
/* Times for Unix */
static int times[] = {
    0,				      /* Tenths of ms per char 0 baud */
    2000,		      /* Tenths of ms per char 50 baud */
    1333,		      /* Tenths of ms per char 75 baud */
    909,		      /* Tenths of ms per char 110 baud */
    743,		      /* Tenths of ms per char 134 baud */
    666,		      /* Tenths of ms per char 150 baud */
    500,		      /* Tenths of ms per char 200 baud */
    333,		      /* Tenths of ms per char 300 baud */
    166,		      /* Tenths of ms per char 600 baud */
    83,				      /* Tenths of ms per char 1200 baud */
    55,				      /* Tenths of ms per char 1800 baud */
    41,				      /* Tenths of ms per char 2400 baud */
    20,				      /* Tenths of ms per char 4800 baud */
    10				      /* Tenths of ms per char 9600 baud */
};
#endif




/*
 *  PSEUDO CODE
 *
 *    Begin tgoto
 *	  If string pointer is invalid then
 *	      Return without doing anything.
 *	  Else
 *	      For each pad digit (if any)
 *		  Do decimal left shift.
 *		  Accumulate the lower digit.
 *	      End for
 *	      Adjust scale to tenths of milliseconds
 *	      If there is a fractional field
 *		  Skip the decimal point.
 *		  If there is a valid tenths digit
 *		      Accumulate the tenths.
 *		  End if
 *		  Discard remaining digits.
 *	      End if
 *	      If per line is specified then
 *		  Adjust the pad time.
 *		  Discard the per line flag char.
 *	      End if
 *	      While there are any characters left
 *		  Send them out via output function.
 *	      End while
 *	      Transmit any padding required.
 *	  End if
 *    End tgoto
 *
 */

tputs(cp,affcnt,outc)
char *cp;
int affcnt;
int (*outc)();
{
    int ptime;			      /* Pad time in tenths of milliseconds */
    static do_padding();

    if (cp == NULL || *cp == NULL) {
      return;
    } else {
      for (ptime = 0; isdigit(*cp); cp++) {
	  ptime *= 10;
	  ptime += (*cp - '0');
      }
      ptime *= 10;
      if (*cp == '.') {
	  cp++;
	  if (isdigit(*cp)) {
	      ptime += (*cp++ - '0');
	  }
	  while (isdigit(*cp)) {cp++;}
      }
      if (*cp == '*') {
	  ptime *= affcnt;
	  cp++;
      }
      while (*cp != NULL) {
	  (*outc)(*cp++);
      }
      do_padding(ptime,outc);
    }
}



/*
 *  FUNCTION
 *
 *    do_padding    transmit any pad characters required
 *
 *  SYNOPSIS
 *
 *    static do_padding(ptime,outc)
 *    int ptime;
 *    int (*outc)();
 *
 *  DESCRIPTION
 *
 *    Does any padding required as specified by ptime (in tenths
 *    of milliseconds), the output speed given in the external
 *    variable ospeed, and the pad character given in the
 *    external variable PC.
 *
 */



/*
 *  PSEUDO CODE
 *
 *    Begin do_padding
 *	  If there is a non-zero pad time then
 *	      If the external speed is in range then
 *		  Look up the delay per pad character.
 *		  Round pad time up by half a character.
 *		  Compute number of characters to send.
 *		  For each pad character to send
 *		      Transmit the pad character.
 *		  End for
 *	      End if
 *	  End if
 *    End do_padding
 *
 */

static do_padding(ptime,outc)
int ptime;
int (*outc)();
{
    register int nchars;
    register int tpc;

    if (ptime >= 0) {
      if (ospeed >= 0 && ospeed <= (sizeof(times)/ sizeof(int))) {
	  tpc = times[ospeed];
	  ptime += (tpc / 2);
	  nchars = ptime / tpc;
	  for ( ; nchars > 0; --nchars) {
	      (*outc)(PC);
	  }
      }
    }
}
SHAR_EOF
cat << \SHAR_EOF > termlib/ttest.c
/************************************************************************
 *								      *
 *		      Copyright (c) 1982, Fred Fish		      *
 *			  All Rights Reserved			      *
 *								      *
 *    This software and/or documentation is released for public	      *
 *    distribution for personal, non-commercial use only.	      *
 *    Limited rights to use, modify, and redistribute are hereby      *
 *    granted for non-commercial purposes, provided that all	      *
 *    copyright notices remain intact and all changes are clearly     *
 *    documented.  The author makes no warranty of any kind with      *
 *    respect to this product and explicitly disclaims any implied    *
 *    warranties of merchantability or fitness for any particular     *
 *    purpose.							      *
 *								      *
 ************************************************************************
 */



/*
 *  TEST PROGRAM
 *
 *    testtcp	test termcap functions
 *
 *  KEY WORDS
 *
 *    test routines
 *    termcap test
 *
 *  SYNOPSIS
 *
 *    termcap [-efns] terminal [capability [capability ...]]
 *
 *	      -e  =>   expand string capability given by -s
 *	      -f  =>   determine boolean capabilities for terminal
 *	      -n  =>   determine numeric capabilities for terminal
 *	      -s  =>   determine string capabilities for terminal
 *
 *	      terminal =>  terminal name as given in termcap file
 *	      capability => a boolean, numeric, or string capability
 *
 *	      NOTE:  All capabilities must be of same type, as
 *		     given by [-fns].
 *
 *	      If terminal is only argument then entire entry is
 *	      printed.
 *
 *  DESCRIPTION
 *
 *    Provides way to test termcap functions.  Can find
 *    and print an entire termcap terminal entry, or various
 *    capabilities from the entry.
 *
 *  AUTHOR
 *
 *    Fred Fish
 *
 */

#include <stdio.h>

#define TRUE 1
#define FALSE 0
#define NO_FILE	       -1		      /* Returned if can't open file */
#define NO_ENTRY  0		      /* Returned if can't find entry */
#define SUCCESS	  1		      /* Returned if entry found ok */
#define TRUNCATED 2		      /* Returned if entry found but trunc */
#define BUFFER_SIZE 1024

int eflag = FALSE;
int fflag = FALSE;
int nflag = FALSE;
int sflag = FALSE;

int got_terminal = FALSE;
int got_capability = FALSE;

int ospeed = 15;      /* fake lots of padding */


/*
 *  FUNCTION
 *
 *    main   termcap test entry point
 *
 *  KEY WORDS
 *
 *    main
 *
 *  SYNOPSIS
 *
 *    main(argc,argv)
 *    int argc;
 *    char *argv[];
 *
 *  DESCRIPTION
 *
 *    This is where the termcap test starts executing.	All argument list
 *    switches are processed first, then all the specified
 *    capability identification strings are processed.
 *
 */


/*
 *  PSEUDO CODE
 *
 *    Begin main
 *	  Process command line options.
 *	  For each argument list field
 *	      If field was not erased during option processing
 *		  If terminal name field not yet processed then
 *		      Process an assumed terminal name field.
 *		      Set terminal name processed flag.
 *		  Else
 *		      Process a capability field.
 *		      Set capability field processed flag.
 *		  End if
 *	      End if
 *	  End for
 *	  If no capabilities processed then
 *	      Simply dump buffer.
 *	  End if
 *    End main
 *
 */

main(argc, argv)
int argc;
char *argv[];
{
    char *argp;
    int argnum;
    char buffer[BUFFER_SIZE];

    options(argc,argv);
    for (argnum = 1; argnum < argc; argnum++) {
	if ((argp = argv[argnum]) != NULL) {
	  if (!got_terminal) {
	      terminal(buffer,argp);
	      got_terminal = TRUE;
	  } else {
	      capability(argp);
	      got_capability = TRUE;
	  }
	}
    }
    if (got_terminal && !got_capability) {
      printf("size = %d\n%s",strlen(buffer),buffer);
    }
}


/*
 *  FUNCTION
 *
 *    options	process command line options
 *
 *  SYNOPSIS
 *
 *    options(argc,argv)
 *    int argc;
 *    char *argv[];
 *
 *  DESCRIPTION
 *
 *    Scans argument list, processing each switch as it is
 *    found.  The pointer to each switch string is then
 *    replaced with a NULL to effectively erase the switch
 *    argument.
 *
 */


/*
 *  PSEUDO CODE
 *
 *    Begin options
 *	  For each argument in the argument list
 *	      Get pointer to first char of argument.
 *	      If the argument is a switch then
 *		  Replace argument pointer with NULL.
 *		  Look at next argument character.
 *		  While there is another argument character
 *		      Switch on the argument character
 *		      Case "EXPAND":
 *			  Set expand (e) flag.
 *			  Break out of switch.
 *		      Case "BOOLEAN":
 *			  Set boolean (f) flag.
 *			  Break out of switch.
 *		      Case "NUMERIC":
 *			  Set numeric flag.
 *			  Break out of switch.
 *		      Case "STRING":
 *			  Set string flag.
 *			  Break out of switch.
 *		      Default:
 *			  Abort with usage message.
 *		      End switch
 *		  End while
 *	      End if
 *	  End for
 *    End options
 *
 */


options(argc, argv)
int argc;
char *argv[];
{
    int i;
    char c;	      /* 1st char of current command-line argument */
    char *cp;	      /* current argument pointer */

    for (i=1; i<argc; i++) {
	cp = argv[i];
	if (*cp == '-') {
	    argv[i] = NULL;
	  cp++;
	  while (c = *cp++) {
	      switch (c) {
	      case 'e':
		  eflag = TRUE;
		  break;
	      case 'f':
		  fflag = TRUE;
		  break;
	      case 'n':
		  nflag = TRUE;
		  break;
	      case 's':
		  sflag = TRUE;
		  break;
	      default:
		  usage();
	      }
	    }
	}
    }
}


/*
 *  FUNCTION
 *
 *    usage   give usage message and abort
 *
 *  KEY WORDS
 *
 *    usage
 *    help processing
 *    abort locations
 *
 *  SYNOPSIS
 *
 *    usage()
 *
 *  DESCRIPTION
 *
 *    Usage is typically called when a problem has been
 *    detected in the argument list.
 *    It prints a usage message and exits.
 *
 */


/*
 *  PSEUDO CODE
 *
 *    Begin usage
 *	  Print usage message.
 *	  Exit.
 *    End usage
 *
 */

usage()
{
    printf("Usage: termcap [-fns] terminal [capability [capability ... ]]\n");
    exit();
}



terminal(buffer,name)
char *buffer;
char *name;
{
    int status;

    status = tgetent(buffer,name);
    switch (status) {
    case NO_FILE:
      fprintf(stderr,"Can't find a termcap data base file.\n");
      exit();
    case NO_ENTRY:
      fprintf(stderr,"Can't find entry \"%s\"\n",name);
      exit();
    case TRUNCATED:
      fprintf(stderr,"Warning --- entry \"%s\" too long\n",name);
      break;
    case SUCCESS:
	break;
    default:
	fprintf(stderr,"? tgetent returned illegal status %d\n",status);
      exit();
    }
}


capability(id)
char *id;
{
    int value;
    char buffer[256];
    char *area;
    char *ep, *tgoto();

    if (fflag) {
      value = tgetflag(id);
      if (value) {
	  printf("%s TRUE\n",id);
      } else {
	  printf("%s FALSE\n",id);
      }
    } else if (nflag) {
      value = tgetnum(id);
      printf("%s = %o octal %d decimal\n",id,value,value);
    } else if (sflag) {
      area = buffer;
      tgetstr(id,&area);
      if (eflag) {
	  ep = tgoto(buffer,75,23);
      }
      doprint(id,buffer);
      if (eflag) {
	  doprint(id,ep);
	  ep = tgoto(buffer,1,2);
	  doprint(id,ep);
      }
    }
}


/*
 *  Use tputs to get a clearer picture of exactly what
 *  goes out to the terminal....
 */

princ(c)
int c;
{
      if (c < 040)
	  printf("^%c",c |= 0100);
      else
	  printf("%c",c);
}

doprint(id,cp)
char *id;
char *cp;
{
    printf("%s = \"",id);
    tputs(cp, 1, princ);
    printf("\"\n");
}
SHAR_EOF
#	End of shell archive
exit 0
-------