#include	"defs.h"
#include	"commands.h"
#include	"dconv.h"
#include	"set.h"
#include	"global.h"

/*
 * prescan fonts and mark chars used in dvi
 */
scanfont(PreLoad, hdfip)
BOOLEAN PreLoad;	/* TRUE if all necessary fonts are loaded */
struct font_index **hdfip;	/* *hdfip is not changed if PreLoad */
{
    int SkipMode = FALSE;	/* in skip mode flag		*/
    int command;	/* current command				*/
    int count[10];	/* the 10 counters at begining of each page	*/
    int sp;			/* stack pointer	*/
    struct {
	int d;			/* pTeX */
    } stack[STACKSIZE];		/* stack		*/
    int basedir;
    int i;		/* command parameter; loop index		*/
    int k;		/* temporary parameter		*/
    int val, val2;      /* temporarys to hold command information*/

    basedir = dir;
    sp = 0;

    while (TRUE)
	switch (command=DC_getcommand()) {

	case SET1:case SET2:case SET3:case SET4:
	    val = DC_getuint(command-SET1+1);
	    if (!SkipMode) MarkChar(val);
	    break;

	case SET_RULE:
	case PUT_RULE:
	    DC_skipbytes(8);
	    break;

	case PUT1:case PUT2:case PUT3:case PUT4:
	    val = DC_getuint(command-PUT1+1);
	    if (!SkipMode) MarkChar(val);
	    break;

	case NOP:
	    break;

	case BOP:
	    /* vf check */
	    for (i=0; i<=9; i++)
		count[i] = DC_getuint(4);
	    (void)DC_getuint(4);

	    dir = HOR;
	    basedir = HOR;
	    sp = 0;
	    setcurfont((struct font_entry *)NULL);

	    SkipMode = (count[0] < FirstPage || count[0] > LastPage);

	    if (!G_quiet) {
		(void)fprintf(stderr, ".");
		(void)fflush(stderr);
	    }
	    break;

	case EOP:
	    break;

	case PUSH:
	    if (sp >= STACKSIZE)
		Fatal("stack overflow");
	    stack[sp].d = dir;
	    sp++;
	    break;

	case POP:
	    --sp;
	    if (sp < 0)
		Fatal("stack underflow");
	    dir = stack[sp].d;
	    break;

	case RIGHT4:
	case X4:
	case W4:
	case Y4:
	case Z4:
	case DOWN4:
	    DC_skipbytes(4);
	    break;

	case RIGHT3:
	case X3:
	case W3:
	case Y3:
	case Z3:
	case DOWN3:
	    DC_skipbytes(3);
	    break;

	case RIGHT2:
	case X2:
	case W2:
	case Y2:
	case Z2:
	case DOWN2:
	    DC_skipbytes(2);
	    break;

	case RIGHT1:
	case X1:
	case W1:
	case Y1:
	case Z1:
	case DOWN1:
	    DC_skipbytes(1);
	    break;

	case X0:
	case W0:
	case Y0:
	case Z0:
	    break;

	case FNT1:case FNT2:case FNT3:case FNT4:
	    k = DC_getuint(command-FNT1+1);
	    if (!SkipMode) SetFntNum(k, *hdfip);
	    break;

	case XXX1:case XXX2:case XXX3:case XXX4:
	    if ((k = DC_getuint(command-XXX1+1))+1 > SpecialSize) {
		SpecialSize = k+1;
		if ((SpecialStr = realloc(SpecialStr, (unsigned)SpecialSize))
		    == NULL)
		    Fatal("can't malloc space for special");
	    }
	    DC_getbytes(SpecialStr, k);
	    if (!SkipMode) dev_predospecial(SpecialStr, k);
	    break;

	case FNT_DEF1:case FNT_DEF2:case FNT_DEF3:case FNT_DEF4:
	    /* vf check */
	    k = DC_getuint(command-FNT_DEF1+1);
	    if (PreLoad || HasBeenRead(k, *hdfip))
		SkipFontDef();
	    else
		ReadFontDef(k, hdfip);
	    break;

	case PRE:
	    /* vf check */
	    Fatal("PRE occurs within file");
	    break;

	case POST:
	    return;
	    break;

	case POST_POST:
	    /* vf check */
	    Fatal("POST_POST with no preceding POST");
	    break;

	case DIR:
	    dir = (basedir+DC_getuint(1))%NDIR;
	    break;

	default:
	    if (command >= FONT_00 && command <= FONT_63) {
		if (!SkipMode) SetFntNum(command-FONT_00, *hdfip);
	    } else if (command >= SETC_000 && command <= SETC_127) {
		if (!SkipMode) MarkString(command);
	    } else
		Fatal("%d is an undefined command", command);
	    break;

	}
}
