#include	<signal.h>
#include	"defs.h"
#include	"global.h"

#define	ChangeFlag(bool)	((bool) = (bool)?FALSE:TRUE)

static BOOLEAN stdindvi = FALSE;

void
sigabort(sig)
int sig;
{
    AbortRun(2);
}

/*
 * decode args and read fontdesc
 */
void
init_settings(argc, argv, fontdescfile)
int argc;
char *argv[];
char *fontdescfile;
{
    int argind;			/* argument index for flags	*/
    int argdvi;
    int nff = 0;		/* number of fontdesc files	*/
    char curname[STRSIZE];	/* current file name		*/
    char *outfile = NULL;
    char *tcp, *tcp1;		/* temporary character pointers	*/
    char *tmp;
    int ch;

    for (argind = 1; argind < argc; argind++) {
	tcp = argv[argind];
	if (*tcp == '-') {
	    switch (*++tcp) {

		case 'D':	/* D defines a variable */
		    if (++argind >= argc)
			Fatal("No argument following -D\n");
		    arg_define(argv[argind]);
		    break;

		case 'F':	/* F selects different fontdesc */
		    if (++argind >= argc)
			Fatal("No argument following -F\n");
		    nff++;
		    break;

		case 'K':	/* remove comments from included PS files */
		    ChangeFlag(G_removecomments);
		    break;
#ifdef MSDOS
		case 'L':	/*  L truncate file name to 8 characters */
		    ChangeFlag(G_longfontname);
		    break;
#endif
		case 'R':	/* R selects different resolution */
		    if (++argind >= argc)
			Fatal("No argument following -R\n");
		    break;
#ifdef STATS
		case 'S':	/* print some statistics */
		    ChangeFlag(Stats);
		    break;
#endif
		case 'c':	/* next arg is an output dvi file */
		    if (++argind >= argc)
			Fatal("No argument following -c\n");
		    outfile = argv[argind];
		    break;

		case 'd':	/* d selects Debug output */
		    if (*++tcp == '\0')
			debug = DEBUGuser;
		    else
			debug = DEBUGsys;
		    break;

		case 'f':	/* next arg is starting pagenumber */
		    if (++argind >= argc ||
			sscanf(argv[argind], "%d", &FirstPage) != 1)
			Fatal("Argument is not a valid integer\n");
		    break;

		case 'i':	/* next arg is a PostScript prologue file */
		    if (++argind >= argc)
			Fatal("No argument following -i\n");
		    break;

		case 'l':	/* l prohibits logging of errors */
		    G_logging = -1;
		    break;
#ifdef USEGLOBALMAG
		case 'm':	/* specify magnification to use */
		    switch(*++tcp) {

		    case '\0':	/* next arg is a magnification to use */
			if (++argind >= argc ||
			    sscanf(argv[argind], "%d", &usermag) != 1)
			    Fatal("Argument is not a valid integer\n", 0);
			break;
		    case '0': usermag = 1000; break;
		    case 'h': usermag = 1095; break;
		    case '1': usermag = 1200; break;
		    case '2': usermag = 1440; break;
		    case '3': usermag = 1728; break;
		    case '4': usermag = 2074; break;
		    case '5': usermag = 2488; break;
		    default: Fatal("%c is a bad mag step\n", *tcp);
		    }
		    break;
#endif
		case 'n':	/* next arg is number of copies to print */
		    if (++argind >= argc ||
			sscanf(argv[argind], "%d", &ncopies) != 1)
			Fatal("Argument is not a valid integer\n");
		    break;

		case 'o':	/* next arg is a PostScript command to send */
		    if (++argind >= argc)
			Fatal("No argument following -o\n");
		    dev_arg('o', argv[argind]);
		    break;

		case 'p':	/* p prohibits pre-font loading */
		    ChangeFlag(PreLoad);
		    if (PreLoad == FALSE)
			Reverse = FALSE;	/* must then process in forward order */
		    break;

		case 'q':	/* quiet operation */
		    ChangeFlag(G_quiet);
		    break;

		case 'r':	/* don't process pages in reverse order */
		    ChangeFlag(Reverse);
		    break;

		case 's':	/* next arg is a PostScript setup file */
		    if (++argind >= argc)
			Fatal("No argument following -s\n");
		    break;

		case 't':	/* next arg is ending pagenumber */
		    if (++argind >= argc ||
			sscanf(argv[argind], "%d", &LastPage) != 1)
			Fatal("Argument is not a valid integer\n");
		    break;

		case 'w':	/* don't print out warnings */
		    ChangeFlag(G_nowarn);
		    break;

		default:
		    usage(*tcp);
		}
	} else
	    break;
    }

    /* dvifilename, dvidirpath, dvifp, (rootname, G_Logname) are set */
    if (argind < argc) {
	tcp = rindex(argv[argind], DIR_SEP);	/* split into directory + file name */
	if (tcp == NULL)  {
	    dvidirpath[0] = '\0';
	    tcp = argv[argind];
	} else  {
	    (void)strcpy(dvidirpath, argv[argind]);
	    dvidirpath[tcp-argv[argind]+1] = '\0';
	    tcp += 1;
	}
	
	(void)strcpy(curname, tcp);
	tcp1 = rindex(tcp, '.');	/* split into file name + extension */
	if (tcp1 == NULL) {
	    (void)strcpy(rootname, curname);	/* not used now */
	    (void)strcat(curname, ".dvi");
	} else {
	    *tcp1 = '\0';
	    (void)strcpy(rootname, curname);	/* not used now */
	    *tcp1 = '.';
	}
	
	(void)strcpy(dvifilename, dvidirpath);
	(void)strcat(dvifilename, curname);
	if ((dvifp = BINARYOPEN(dvifilename)) == NULL)
	    Fatal("can't find DVI file \"%s\"", dvifilename);

	/* not used now */
	(void)strcpy(G_Logname, rootname);
	(void)strcat(G_Logname, ".log");

    } else {	/* get dvi file from stdin */
	dvidirpath[0] = '\0';

	if ((tmp = getenv("TMP")) == NULL)
	    tmp = TMP;
	(void)strcpy(dvifilename, tmp);
	(void)mktemp(strcat(dvifilename, DVITEMPLATE));
	(void)strcpy(rootname, dvifilename);	/* not used now */
	(void)strcat(dvifilename, ".dvi");
	if ((dvifp = BINARYWOPEN(dvifilename)) == NULL)
	    Fatal("can't create DVI file for stdin");
	stdindvi = TRUE;
	(void)signal(SIGHUP, sigabort);
	(void)signal(SIGINT, sigabort);
#ifdef MSDOS
	setmode(fileno(stdin), O_BINARY);
#endif
	for (; !ferror(stdin) && (ch = getchar()) != EOF; )
	    (void)putc(ch, dvifp);
	if (ferror(stdin))
	    Fatal("can't input DVI from stdin");
	(void)fseek(dvifp, 0L, 0);

	/* not used now */
	(void)strcpy(G_Logname, "dvi2.log");
    }
	
    if (nff == 0)
	read_fontdesc(fontdescfile, TRUE);
    argdvi = argind;
    for (argind = 1; argind < argdvi; argind++)
	switch (*(argv[argind]+1)) {
	    case 'F':	/* F selects different fontdesc */
		arg_fontdesc(argv[++argind]);
		break;
	    case 'R':	/* R selects different resolution */
		resolution = atoi(argv[++argind]);
		break;
	    case 'i':	/* next arg is a PostScript prologue file */
		add_include(argv[++argind], TRUE);
		break;
	    case 's':	/* next arg is a PostScript setup file */
		add_setup(argv[++argind], TRUE);
		break;
	}

    if (outfile == NULL) {
	outfp = stdout;
#ifdef MSDOS
	setmode(fileno(outfp), O_BINARY);
#endif
    } else if ((outfp = BINARYWOPEN(outfile)) == NULL)
	Fatal("can't write to output file \"%s\"", outfile);
}

usage(c)
char c;
{
    (void)fprintf(stderr, "%c is not a legal flag\n", c);
    (void)fprintf(stderr, "Usage: %s %s\n\t%s\n\t%s\n",
		  G_progname,
		  "[-d] [-f n] [-i file] [-l] [-m{0|h|1|2|3|4|5}] [-m mag]",
		  "[-n n] [-o option] [-q] [-r] [-s file] [-t n] [-w]",
		  "[-D var=val] [-F fontdesc] [-K] [-L] [-R resolution] [-S]",
		  "[dvifile]");
    (void)fprintf(stderr, "%s\n", version);
    AbortRun(2);
}


/*-->AbortRun*/
/**********************************************************************/
/***************************  AbortRun  *******************************/
/**********************************************************************/

void
AbortRun(code)
int code;
{
    if (stdindvi)
	(void)unlink(dvifilename);
    exit(code);
}


/*-->AllDone*/
/**********************************************************************/
/****************************** AllDone  ******************************/
/**********************************************************************/

void
AllDone()
{
    struct font_entry *p;

    dev_finish();
    if (!G_quiet)
	(void)fprintf(stderr,"\n");

#ifdef STATS
    if (Stats) {
	(void)fprintf(stderr, "Total chars   diff chars   raster bytes\n");
	(void)fprintf(stderr, "      #   %%        #   %%       #   %%\n");
	(void)fprintf(stderr, "------- ---   ------ ---   ----- ---\n");
	for (p = hdfontent; p != NULL; p = p->next) {
	    (void)fprintf(stderr, "%7d%4d", p->ncts, 100*p->ncts/Stnc);
	    if (Sndc != 0)
		(void)fprintf(stderr, "%9d%4d", p->ncdl, 100*p->ncdl/Sndc);
	    else
		(void)fprintf(stderr, "%9d  --", p->ncdl);
	    if (Snbpxl != 0)
		(void)fprintf(stderr, "%8d%4d", p->nbpxl, 100*p->nbpxl/Snbpxl);
	    else
		(void)fprintf(stderr, "%8d  --", p->nbpxl);
	    (void)fprintf(stderr, "  %s\n", p->name);
	}
	(void)fprintf(stderr, "\nTotal number of characters typeset: %d\n", Stnc);
	(void)fprintf(stderr, "Number of different characters downloaded: %d\n", Sndc);
	(void)fprintf(stderr, "Number of bytes of raster data downloaded: %d\n", Snbpxl);
	(void)fprintf(stderr, "Optimal # of bytes of raster data: %d\n", Sonbpx);
    }
#endif

    AbortRun(G_errenc ? 1 : 0);
}


/*-->Fatal*/
/**********************************************************************/
/******************************  Fatal  *******************************/
/**********************************************************************/
/* VARARGS1 */
void
Fatal(fmt, a, b, c)	/* issue a fatal error message */
char *fmt;		/* format */
char *a, *b, *c;	/* arguments */
{
    if (G_logging == 1 && G_logfile) {
	(void)fprintf(G_logfp, "%s: FATAL-- ", G_progname);
	(void)fprintf(G_logfp, fmt, a, b, c);
	(void)fprintf(G_logfp, "\n");
    }

    (void)fprintf(stderr,"\n");
    (void)fprintf(stderr, "%s: FATAL-- ", G_progname);
    (void)fprintf(stderr, fmt, a, b, c);
    (void)fprintf(stderr, "\n\n");
    AbortRun(2);
}


/*-->Warning*/
/**********************************************************************/
/*****************************  Warning  ******************************/
/**********************************************************************/
/* VARARGS1 */
void
Warning(fmt, a, b, c)	/* issue a warning */
char *fmt;		/* format   */
char *a, *b, *c;	/* arguments */
{
    if (G_logging == 0) {
	if (G_logfile)
	    G_logfp = fopen(G_Logname, "w+");
	else {
	    G_logfp = stderr;
	    if (G_nowarn) return;
	}
	G_logging = 1;
	if (G_logfp == NULL) G_logging = -1;
    }

    G_errenc = TRUE;
    if (G_logging == 1) {
	(void)fprintf(G_logfp, fmt, a, b, c);
	(void)fprintf(G_logfp,"\n");
    }
}
