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

int h;			/* current horizontal position	*/
int v;			/* current vertical position	*/
int dir;		/* current direction		*/
int *move;		/* &h or &v */
BOOLEAN chmove;		/* TRUE if char moves */

#define	MoveDown	DC_movedown
#define	MoveOver	DC_moveover
#define	SetRule		DC_setrule

/*
 * convert dvi to printer language
 */

int command;	/* current command				*/
int sp = 0;			/* stack pointer	*/
struct {
    int h, v, w, x, y, z;	/* what's on stack */
    int d;			/* pTeX */
} stack[STACKSIZE];		/* stack		*/

dviconv(hdfidx)
struct font_index *hdfidx;
{
    int SkipMode = FALSE;	/* in skip mode flag		*/
    int count[10];	/* the 10 counters at begining of each page	*/
    int basedir;
    int i;		/* command parameter; loop index		*/
    int k;		/* temporary parameter		*/
    int val, val2;      /* temporarys to hold command information*/
    byte par[4], par2[4];	/* temporarys to hold command information*/
    int w;		/* current horizontal spacing	*/
    int x;		/* current horizontal spacing	*/
    int y;		/* current vertical spacing	*/
    int z;		/* current vertical spacing	*/
    /*long cpagep;	/* current page pointer		*/
    long ppagep;	/* previous page pointer	*/

    /* initialize for virtual font */
    w = x = y = z = 0;
    basedir = dir;

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

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

	case SET_RULE:
	    DC_getbytes(par, 4);
	    DC_getbytes(par2, 4);
	    if (!SkipMode) SetRule(par, par2, TRUE);
	    break;

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

	case PUT_RULE:
	    DC_getbytes(par, 4);
	    DC_getbytes(par2, 4);
	    if (!SkipMode) SetRule(par, par2, FALSE);
	    break;

	case NOP:
	    break;

	case BOP:
	    /*cpagep = ftell(dc_file) - 1;*/
	    for (i=0; i<=9; i++)
		count[i] = DC_getuint(4);
	    ppagep = DC_getuint(4);

	    h = v = w = x = y = z = 0;
	    setdir(HOR, FALSE);
	    basedir = HOR;
	    sp = 0;
	    setcurfont((struct font_entry *)NULL);
	    dev_initpage();

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

	    if (!SkipMode) {
		dev_bop(count);
		if (!G_quiet)
		    (void)fprintf(stderr, "[%d", count[0]);
	    }
	    break;

	case EOP:
	    if (!SkipMode) {
		dev_eop();
#ifdef STATS
		if (Stats)
		    (void)fprintf(stderr,
			    " - %d total ch,  %d diff ch,  %d pxl bytes]\n",
			    Stnc-Stnc0, Sndc-Sndc0, Snbpxl-Snbpx0);
		else
#endif
		    if (!G_quiet) {
			(void)fprintf(stderr,"] ");
			if ((++ndone % 10) == 0) (void)putc('\n', stderr);
			(void)fflush(stderr);
		    }
	    }
	    if (Reverse)
		if (ppagep > 0)
		    (void)fseek(dc_file, ppagep, 0);
		else
		    return;
	    break;

	case PUSH:
	    if (sp >= STACKSIZE)
		Fatal("stack overflow");
	    stack[sp].h = h;
	    stack[sp].v = v;
	    stack[sp].w = w;
	    stack[sp].x = x;
	    stack[sp].y = y;
	    stack[sp].z = z;
	    stack[sp].d = dir;
	    sp++;
	    dev_push();
	    break;

	case POP:
	    --sp;
	    if (sp < 0)
		Fatal("stack underflow");
	    h = stack[sp].h;
	    v = stack[sp].v;
	    w = stack[sp].w;
	    x = stack[sp].x;
	    y = stack[sp].y;
	    z = stack[sp].z;
	    setdir(stack[sp].d, FALSE);
	    dev_pop();
	    break;

	case RIGHT1:case RIGHT2:case RIGHT3:case RIGHT4:
	    DC_getbytes(par, command-RIGHT1+1);
	    if (!SkipMode) MoveOver(par, command-RIGHT1+1, 0);
	    break;

	case W0:
	    if (!SkipMode) MoveOver(par, 0, w);
	    break;

	case W1:case W2:case W3:case W4:
	    DC_getbytes(par, command-W1+1);
	    w = makeint(par, command-W1+1);
	    if (!SkipMode) MoveOver(par, command-W1+1, w);
	    break;

	case X0:
	    if (!SkipMode) MoveOver(par, 0, x);
	    break;

	case X1:case X2:case X3:case X4:
	    DC_getbytes(par, command-X1+1);
	    x = makeint(par, command-X1+1);
	    if (!SkipMode) MoveOver(par, command-X1+1, x);
	    break;

	case DOWN1:case DOWN2:case DOWN3:case DOWN4:
	    DC_getbytes(par, command-DOWN1+1);
	    if (!SkipMode) MoveDown(par, command-DOWN1+1, 0);
	    break;

	case Y0:
	    if (!SkipMode) MoveDown(par, 0, y);
	    break;

	case Y1:case Y2:case Y3:case Y4:
	    DC_getbytes(par, command-Y1+1);
	    y = makeint(par, command-Y1+1);
	    if (!SkipMode) MoveDown(par, command-Y1+1, y);
	    break;

	case Z0:
	    if (!SkipMode) MoveDown(par, 0, z);
	    break;

	case Z1:case Z2:case Z3:case Z4:
	    DC_getbytes(par, command-Z1+1);
	    z = makeint(par, command-Z1+1);
	    if (!SkipMode) MoveDown(par, command-Z1+1, z);
	    break;

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

	case XXX1:case XXX2:case XXX3:case XXX4:
	    k = DC_getuint(command-XXX1+1);
	    DC_getbytes(SpecialStr, k);
	    if (!SkipMode) dev_dospecial(SpecialStr, k);
	    break;

	case FNT_DEF1:case FNT_DEF2:case FNT_DEF3:case FNT_DEF4:
	    DC_skipbytes(command-FNT_DEF1+1);
	    SkipFontDef();
	    break;

	case PRE:
	    Fatal("PRE occurs within file");
	    break;

	case POST:
	    return;

	case POST_POST:
	    Fatal("POST_POST with no preceding POST");
	    break;

	case DIR:
	    setdir(basedir+DC_getuint(1), TRUE);
	    break;

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

	}
}

initdir()
{
    dir = VER;
    setdir(HOR, FALSE);
}

setdir(d, dev)
int d;
BOOLEAN dev;
{
    d = d%NDIR;
    if (dir != d) {
	dir = d;
	if (d == HOR) {
	    move = &h;
	    setdirhor();
	} else if (d == VER) {
	    move = &v;
	    setdirver();
	} else
	    Fatal("direction %d not supported", d);
	if (dev)
	    dev_dir(d);
    }
}
