/************************************************************************
 *									*
 *			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 (modified by Tom Hageman)
 *
 */

#include <stdio.h>
#include "_termcap.h"

#define FALSE	0
#define TRUE	1

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[TBUFSIZE];

    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) {
	putcap(buffer);
    }
    exit(0);
}

/*
 *  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(2);
}


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(2);
    case NO_ENTRY:
	fprintf(stderr,"Can't find entry \"%s\"\n",name);
	exit(1);
    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(-1);
    }
}

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);
	}
    }
}

doprint(id,cp)
char *id;
char *cp;
{
    printf("%s = ",id);
    for ( ; *cp != NULL; cp++) {
	if ((unsigned) *cp < 040) {
	    printf("^%c ",*cp | 0100);
	} else {
	    printf("%c ",*cp);
	}
    }
    printf("\n");
}

putcap(buffer)
char *buffer;
{
#if !FASTCAP
    puts(buffer);
#else
    register char	*s;
    register int	c;
    register t_entry	*tp;

    printf("%s:", buffer);

    /* start at end since table is in reverse order. */

    for (tp = &_tcptable.t_body[_tcptable.t_size]; --tp >= _tcptable.t_body; ) {

	s = _TCP_VAL(tp);

	putchar((char)(tp->t_cap >> 8));	/* output cap. name */
	putchar((char)tp->t_cap);

	while (c = *s++ & 0377) {		/* re-escape... */

	    switch (c) {

	    default:
		if (c >= 0177) {
		    printf("\\%03o", c);
		    continue;
		}
		if (c < ' ') {
		    putchar('^');
		    c += '@';
		} 
		putchar(c);
		continue;

	    case '\33':	c = 'E';	break;
	    case '\r':	c = 'r';	break;
	    case '\n':	c = 'n';	break;
	    case '\t':	c = 't';	break;
	    case '\b':  c = 'b';	break;
	    case '\f':	c = 'f';	break;

	    case '\\':			break;
	    case ':':			break;
	    case '^':			break;
	    case ' ':			break;
	    }
	    putchar('\\');
	    putchar(c);
	}
	putchar(':');
    }
    putchar('\n');

#endif /* FASTCAP */
}
