/*
** pmod23.c, Copyright (C) 1992 by John Edward Mosley
** 
**                        - Amiga Version 2.3a -
**	This program sends codes to the printer like condensed/elite type,
**	line feeds, form feeds, and line spacing. It will also print out
**	given text files listed in the argument list. Code arguments must be
**	preceeded by "-" signs and many may immediately follow.  This is a
**	beta version of this program, which makes use of a nice and friendly
**	requestor to allow the user to make corrections to the command-line
**	arguments.  The support file for this is Request.c.  Written in SAS/C
**	version 5.10 or so.
**	
**	Compile with: lc -L pmod23.c Request.c
*/
 
#include <stdio.h>
#include <ctype.h>
#include "pmod23.h"

void main(int argc, char *argv[]) {
	if(badargs(argc, argv)) print_usage();
	printcodes(argc, argv);
} /* main() */

 
/*
** Checks the command line for valid data and returns 1 if
** the data was bad, else a 0.
*/
int badargs(int argc, char *argv[]) {
	int i, num;
	char *ptr, exnptr[11];

	if(argc < 2 ) {
		printf("%s: Not enough arguments\n", NAME);
		return(1);
	} /* if */
	for(i = 1; i < argc; i++) {
		ptr = argv[i];
		if(*ptr == '-')
			while(*ptr) {
				*ptr = tolower(*ptr);
				if(*ptr == 'l') {
					/* check the number's validity */
					exnum(ptr, exnptr);
					if(strlen(exnptr) == 0) {
						printf("%s: Must supply a number for -l option\n", NAME);
						return(1);
					} /* if */
					num = atoi(exnptr);
					if(num < 1 || num > 999) {
						printf("%s: Number for -l option must be from 1 to 999\n", NAME);
						return(1);
					} /* if */
					ptr += strlen(exnptr);
				} /* if */
				ptr++;
			} /* while */
	} /* for */
	return(0);
} /* badargs() */


/* global vars for keeping up with file stuff */
char *source_file_buffer = NULL, *dest_file_buffer = NULL;

/*
** Prints out the corresponding codes in the
** command string pointed to by pmode.
*/
void printcodes(int argc, char *argv[]) {
	FILE *dfptr, *sfptr;
	int i, j, lines;
	char ch, *pmode, exnptr[11], answer[11];
	GRES result;

	result.ID = NOTHING;
	if((dfptr = fopen("par:","w")) == NULL) {
		printf("%s: Printer not accessible\n", NAME);
		exit(10);
	} /* if */
	if((dest_file_buffer = (char *)malloc(DFB_SIZE)) == NULL
	  || setvbuf(dfptr, dest_file_buffer, _IOFBF, DFB_SIZE) != NULL)
		printf("%s: Cannot set up printer buffer\n", NAME);
	/* loop through each argument */
	for(i = 1; i < argc; i++) {
		pmode = argv[i];
		if(*pmode == '-') {	/* argument contains options */
			/* check each option and print the corresponding printer codes */
			while(*pmode) {
				switch(*pmode) {
					case '-':
						break;
					case '6':
						fprintf(dfptr, "\x1b");
						fprintf(dfptr, "2");
						break;
					case '8':
						fprintf(dfptr, "\x1b");
						fprintf(dfptr, "0");
						break;
					case 'q':
						fprintf(dfptr, "\x1bx\x01");
						break;
					case 'd':
						fprintf(dfptr, "\x1bx");
						fputc(0, dfptr);
						break;
					case 'c':
						fprintf(dfptr, "\x1b\x0f");
						break;
					case 'n':
						fprintf(dfptr, "\x12");
						break;
					case 'e':
						fprintf(dfptr, "\x1bM");
						break;
					case 'p':
						fprintf(dfptr, "\x1bP");
						break;
					case 'f':
						fprintf(dfptr, "\x0c");
						break;
					case 'l':
						exnum(pmode, exnptr);
						lines = atoi(exnptr);
						pmode += strlen(exnptr);
						for(j = 0; j < lines; j++)
							fprintf(dfptr, "\x0a");
						break;
					default:
						/* unknown option - signal to break out of while loop */
						result.ID = OPTION_REQ;
				} /* switch */
				if(result.ID == OPTION_REQ)
					break;	/* break out of while */
				else
					pmode++;
			} /* while */
			if(result.ID == OPTION_REQ) {	/* have found an unknown option */
				/* this brings up the nifty requestor - check results */
				Do_Request(pmode, &result, OPTION_REQ);
				if(result.ID == NOTHING) {	/* ICK!  Intuition failed, use default exit */
					printf("%s: **FATAL ERROR** Unknown option \"%c\"\n", NAME, *pmode);
					fclose(dfptr);
					clean_up();
					print_usage();
				} /* if */
				else if(result.ID == RETRY_UP) {	/* user may have altered remaining argument */
					argv[i--] = result.string;
					continue;
				} /* else if */
				else if(result.ID == SKIP_UP) continue;	/* skip that argument */
				else if(result.ID == ABORT_UP) break;	/* abort entire printing session */
				else printf("%s: Bad gadget return result\n", NAME);
			} /* if */
		} /* if */
		/* if it doesn't start with "-", assume it's a file to print */
		else if((sfptr = fopen(pmode, "r")) == NULL) {	/* give user a chance to act on the file error */
			/* spiffy requester */
			Do_Request(pmode, &result, FILE_REQ);
			if(result.ID == NOTHING) {	/* ICK! Intuition failed!  Use default user input */
				printf("%s: File \"%s\" not accessible.", NAME, pmode);
				if(i < argc - 1) {
					printf("  Continue (Y/N)? ");
					fgets(answer, 11, stdin);
					if(tolower(*answer) == 'n') break;
				} /* if */
				else puts("");
			} /* if */
			else if(result.ID == RETRY_UP) {	/* user may have retyped the filename */
				argv[i--] = result.string;
				continue;
			} /* else if */
			else if(result.ID == SKIP_UP) continue;	/* skip this file - go onto next argument */
			else if(result.ID == ABORT_UP) break;	/* abort entire printing session */
			else printf("%s: Bad gadget return result\n", NAME);
		} /* else */
		else {	/* OK. the file acces succeeded; print th' sukka */
			if((source_file_buffer = (char *)malloc(SFB_SIZE)) == NULL
			  || setvbuf(sfptr, source_file_buffer, _IOFBF, SFB_SIZE) != NULL)
				printf("%s: Cannot set up source file buffer for \"%s\"\n", NAME, pmode);
			while((ch = getc(sfptr)) != EOF) fprintf(dfptr, "%c", ch);
			fclose(sfptr);
		} /* else */
	} /* for */
	fclose(dfptr);
	clean_up();
} /* printcodes() */


/*
** Searches down a string to find a valid number and
** returns the pointer of the string containing that number.
*/
void exnum(char *p, char *digits) {
	char *dptr;

	dptr = digits;
	p++;
	while(*p>='0' && *p<='9') *(dptr++) = *(p++);
	*dptr = NULL;
} /* exnum() */


/* Frees the file buffers from memory. */
void clean_up(void) {
	if(source_file_buffer) free(source_file_buffer);
	if(dest_file_buffer) free(dest_file_buffer);
} /* clean_up() */
 

/* Prints out error message and gives usage. */
void print_usage(void) {
	puts(VERSION_INFO);
	puts("USAGE: pmod [-{68qdcnepfl###}] [file] [-{68qdcnepfl###}] [file]...");
	puts("\t6 = Use 1/6\" line spacing");
	puts("\t8 = Use 1/8\" line spacing");
	puts("\tq = Near letter quality mode ON");
	puts("\td = Draft printing mode (NLQ OFF)");
	puts("\tc = Condensed printing mode");
	puts("\tn = Cancel condensed printing mode");
	puts("\te = Elite character style");
	puts("\tp = Pica character style");
	puts("\tf = Send Form Feed");
	puts("\tl = Send ### Line Feeds");
	puts("\tfile = Text file to print on printer");
	exit(10);
} /* print_usage() */
