#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 fd = -1;
    int ch;
    char prfontdesc[STRSIZE];

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

		case 'D':	/* D defines a variable */
		    if (*++tcp != '\0')
			;
		    else if (++argind >= argc)
			Fatal("No argument following -D\n");
		    else
			tcp = argv[argind];
		    arg_define(tcp);
		    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 'P':	/* P selects `printer' */
		    if (*++tcp == '\0' && ++argind >= argc)
			Fatal("No argument following -P\n");
		    nff++;
		    break;

		case 'R':	/* R selects different resolution */
		    if (*++tcp == '\0' && ++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;

#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;

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

		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 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  {
	    if (strlen(argv[argind])+1 >= PATHLEN)
		Fatal("can't make DVI file name");
	    (void)strcpy(dvidirpath, argv[argind]);
	    dvidirpath[tcp-argv[argind]+1] = '\0';
	    tcp += 1;
	}
	
	if (strlen(tcp)+4+1 >= PATHLEN)
	    Fatal("can't make DVI file name");
	(void)strcpy(curname, tcp);
	tcp1 = rindex(tcp, '.');	/* split into file name + extension */
	if (tcp1 == NULL)
	    (void)strcat(curname, ".dvi");
	else
	    *tcp1 = '.';
	
	if (strlen(dvidirpath)+strlen(curname)+1 >= PATHLEN)
	    Fatal("can't make DVI file name");
	(void)strcpy(dvifilename, dvidirpath);
	(void)strcat(dvifilename, curname);
	if ((dvifp = BINARYOPEN(dvifilename)) == NULL)
	    Fatal("can't find DVI file \"%s\"", dvifilename);

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

	if (((tmp = getenv("TMP")) == NULL) &&
            ((tmp = getenv("TEMP")) == NULL))
	    tmp = TMP;
	if (strlen(tmp)+strlen(DVITEMPLATE)+1 >= PATHLEN)
	    Fatal("can't make DVI file name for stdin");
	(void)strcpy(dvifilename, tmp);
	(void)strcat(dvifilename, DVITEMPLATE);
#ifdef WIN32
	{
	   char *p;
	   for(p=dvifilename; *p; p++) {
	      if(isknj(*p) && *(p+1)) {
		 p++;
		 continue;
	      }
	      if(*p == '\\') *p = '/';
	   }
	}
#endif
#ifdef HAVE_MKSTEMP
	if ((fd = mkstemp(dvifilename)) == -1 ||
	    (dvifp = fdopen(fd, "w+")) == NULL) {
	    if (fd != -1) {
		unlink(dvifilename);
		close(fd);
	    }
	    Fatal("can't create DVI file for stdin");
	}
#else
	if (mktemp(dvifilename) == NULL ||
	    (dvifp = BINARYWOPEN(dvifilename)) == NULL)
	    Fatal("can't create DVI file for stdin");
#endif
	stdindvi = TRUE;
#if !defined(MSDOS) && !defined(WIN32)
	(void)signal(SIGHUP, sigabort);
	(void)signal(SIGINT, sigabort);
#endif
#if defined(MSDOS) || defined(WIN32)
	setmode(fileno(stdin), O_BINARY);
	SET_BINARY(fileno(stdin));
	/*SET_BINARY(fileno(stdiout));*/
#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, SEEK_SET);
    }
	
    /* definitions given in arguments are processed above, and
       some default definitions are added before reading fontdescfile.
     */
    default_def();

    sprintf(prfontdesc, "%s.0", fontdescfile);
    read_fontdesc(prfontdesc, TRUE);
    if (nff == 0)
	read_fontdesc(fontdescfile, TRUE);
    argdvi = argind;
    for (argind = 1; argind < argdvi; argind++)
	switch (*(argv[argind]+1)) {
	    case 'D':
		if (*(argv[argind]+2) == '\0')
		    ++argind;
		break;
	    case 'F':	/* F selects different fontdesc */
		arg_fontdesc(argv[++argind]);
		break;
	    case 'P':	/* P selects `printer' */
		if (*(argv[argind]+2) != '\0')
		    tcp = argv[argind]+2;
		else
		    tcp = argv[++argind];
		sprintf(prfontdesc, "%s.%s", fontdescfile, tcp);
		arg_fontdesc(prfontdesc);
		break;
	    case 'R':	/* R selects different resolution */
		if (*(argv[argind]+2) != '\0')
		    tcp = argv[argind]+2;
		else
		    tcp = argv[++argind];
		resolution = atoi(tcp);
		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;
	    case 'c':  case 'f':  case 'n':  case 'o':  case 't':
		++argind;
		break;
	}

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

usage(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] [-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 */
{
    (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 */
{
    G_errenc = TRUE;
    if (G_nowarn)
	return;
    (void)fprintf(stderr, fmt, a, b, c);
    (void)fprintf(stderr,"\n");
}
