/* EMACS_MODES: !fill */
#include <stdio.h>
#include <time.h>
#include <ctype.h>

#define NAME "input"
#define VERSION "2.0"

#define MAXLINE 256
#define DEFWAIT 30

void prompt();
void inline();
int charin();

main(argc,argv)
int argc;
char *argv[];
{
	FILE *fo;
	char option[3];
	char outfile[128];
	char format[MAXLINE+1];
	char outstr[MAXLINE+1];
	char s[MAXLINE+1];
	long maxwait;
	int i,j;
	int c,inlen,outlen;


	if (argc<4){
		usage();
		exit(1);
	}
	if ( strcpy(format,argv[1]) == NULL) {
		usage();
		exit(1);
	}
	maxwait=atol(argv[2]);
	if (maxwait>60 || maxwait<1){
		usage();
		exit(1);
	}
	if ( strcpy(outfile,argv[3]) == NULL) {
		usage();
		exit(1);
	}

	outlen=0;
	inlen=strlen(format);


/* fprintf(stderr,"format=[%s]\nlen=%d\nmaxwait=%d\n",format,strlen(format),maxwait); */

	inline(inlen);
	i=0;j=0;
	while(j < inlen ){

		c=charin(maxwait);
/*		fprintf(stderr,"\nformat[%d]:%c\tc:%c\t",i,format[i],c); */
		if (c=='\r'){
			c='\0';
			break;
		}

		if (c=='\b'){
			if(j>0){
				fprintf(stdout,"\b_\b");
				i--;
				j--;
				outlen--;
			}
			continue;
		}

		/* Control character */
		if (format[i]=='^') {
			if (!iscntrl(c)){
				prompt("< type a control character >",inlen,outlen);
				continue;
			}
		}

		/* Decimal Digit */
		if (format[i]=='#') {
			if (!isdigit(c)){
				prompt("< type a digit >",inlen,outlen);
				continue;
			}
		}


		/* Graph  */
		if (format[i]=='g') {
			if (!isgraph(c)){
				prompt("< type a graphic char >",inlen,outlen);
				continue;
			}
		}

		/* Lower case */
		if (format[i]=='l') {
			if(isupper(c)){
				c=tolower(c);
			}
			if (!islower(c)){
				prompt("< use lower case >",inlen,outlen);
				continue;
			}
		}

		/* Upper case */
		if (format[i]=='u') {
			if(islower(c)){
				c=toupper(c);
			}
			if (!isupper(c)){
				prompt("< use upper case >",inlen,outlen);
				continue;
			}
		}

		/* Printable */
		if (format[i]=='p') {
			if (!isprint(c)){
				prompt("< type a printable char. >",inlen,outlen);
				continue;
			}
		}

		/* Punctuation */
		if (format[i]=='.') {
			if (!ispunct(c)){
				prompt("< use punctuation >",inlen,outlen);
				continue;
			}
		}

		/* White Space */
		if (format[i]==' ') {
			if (!isspace(c)){
				prompt("< type space/tab or enter >",inlen,outlen);
				continue;
			}
		}

		/* Anything ASCII */
		if (format[i]=='?') {
			if (!isascii(c)){
				prompt("< use ascii >",inlen,outlen);
				continue;
			}
		}

		i++;

		outstr[j]=c;
		fprintf(stdout,"%c",outstr[j]);
		j++;
		outstr[j]='\0';
		outlen=strlen(outstr);
	}

	if ( (fo=fopen(outfile,"a")) == NULL) {
		fprintf(stderr,"can't write to %s\n",argv[3]);
		exit(2);
	}
	fprintf(fo,"%s",outstr);
	fclose(fo);
	exit(0);
}

int charin(maxwait)
long maxwait;
{
	long t0,t1;
	time(&t0);
	while (!kbhit()) {
		time(&t1);
		if(t1>t0+maxwait){
/* 			printf("<< Keyboard timeout >>\n"); */
			exit(-1);
		}
	}
	return(getch());
}



void prompt(s,i,o)
char *s[];
int i,o;
{
	int j;
	fprintf(stdout,"%s",s);
	while (!kbhit()){
	}
	for(j=0;j<strlen(s);j++){
		fprintf(stdout,"\b \b");
	}
	for(j=0;j<(i-o);j++){
		fprintf(stdout,"_");
	}
	for(j=0;j<(i-o);j++){
		fprintf(stdout,"\b");
	}

}

void inline(l)
int l;
{
	int i;
	for(i=0;i<l;i++){
		fprintf(stdout,"_");
	}
	for(i=0;i<l;i++){
		fprintf(stdout,"\b");
	}
}

usage()
{
	printf("By Andrew Gaunt, AKA Quantum, #1@6300 - May be freely shared.\n\n");
	printf("usage: input format timeout outfile\n\n");
	printf("Format is a string of characters used to describe the type ");
	printf("of input to\nbe expected.\n\n");
	printf("FORMAT:\n");
	printf(" ^ Control character\n");
	printf(" # Digit\n");
	printf(" g Graphic\n");
	printf(" l Lower case\n");
	printf(" u Upper case\n");
	printf(" p Printable\n");
	printf(" . Punctuation\n");
	printf(" ? Anything ASCII\n");
	printf("<space> White Space\n\n");
	printf("Timeout is the number of seconds input will wait if no keys ");
	printf("are pressed.\n\n");
	printf("Outfile is the name of the file that the user input will be appended to.\n");
	printf("\n[%s v%s]\n",NAME,VERSION);
}
