#include	"defs.h"
#include	"globals.h"

static struct DVIBuftype
{
	int32           TotByteLen, curstrindex;
	int32           maxlen;
	short		*Dstring;
}               GDVIBuf;

/*
 * NOTATION:: All procedures that put a dvi-command into the temporary buffer are prefixed with "cmd"... Functions that deal
 * with reading .tfm files are prefixed with "T" or have "tfm" in their names. Functions that deal with reading DVI files are
 * prefixed with a "D".
 */

/*--------------------------------------------*/
void 
cmd1byte(cmd)
	int32           cmd;
{
	char           *realloc PP((char *, unsigned));

	if (GDVIBuf.curstrindex >= GDVIBuf.maxlen)
	{			/* buffer full */
		GDVIBuf.maxlen *= 2;
		GDVIBuf.Dstring = (short *) realloc((char *)GDVIBuf.Dstring, (unsigned)sizeof(*GDVIBuf.Dstring) * GDVIBuf.maxlen);
	}
	GDVIBuf.Dstring[GDVIBuf.curstrindex] = cmd;
	/* insert command byte */
	GDVIBuf.TotByteLen++;
	GDVIBuf.curstrindex++;
}


/*---------------------------------------------------*/
void 
cmd2byte(cmd)
	int32           cmd;
{
	cmd1byte((cmd >> 8) & 0xff);
	cmd1byte(cmd & 0xff);
}

/*---------------------------------------------------*/
void 
cmd4byte(cmd)
	int32           cmd;
{
	cmd1byte((cmd >> 24) & 0xff);
	cmd1byte((cmd >> 16) & 0xff);
	cmd1byte((cmd >> 8) & 0xff);
	cmd1byte(cmd & 0xff);
}


/*---------------------------------------------------*/
/*
 * ### may be system dependent as integers are assumed to be signed 32-bits
 */

void 
cmdSigned(i, numbytes)
	int32           i, numbytes;
{
	int32           tmp;

	if (numbytes == 4)
	{
		cmd4byte(i);
		return;
	}
	tmp = i;
	if (numbytes == 3)
	{
		if (tmp < 0)
			tmp += TWO24;
		cmd1byte(tmp / TWO16);
		tmp &= TWO16 - 1;
		cmd1byte(tmp / 256);
	}
	if (numbytes == 2)
	{
		if (tmp < 0)
			tmp += TWO16;
		cmd1byte(tmp / 256);
	}
	if (numbytes == 1)
	{
		if (tmp < 0)
			tmp += 256;
	}
	cmd1byte(tmp & 255);	/* for all */

	/* <= 3 bytes */
}

/*---------------------------------------------------*/
int 
Tgetc()
{
	int             c;

	if ((c = getc(tfmfile)) == EOF)
	{
		complain(ERRREALBAD);
		fprintf(logfile, " early EOF of tfm file! \n");
		return (0);
	}
	return (c & 0xff);
}


/*---------------------------------------------------*/
void 
readtfmword()
{
	b0 = Tgetc();
	b1 = Tgetc();
	b2 = Tgetc();
	b3 = Tgetc();
}


/*---------------------------------------------------*/
int32 
Dgetc()
{
	int             c;

	if ((c = getc(dvifile)) == EOF)
		return (0);
	return (c & 0xff);
}

/*---------------------------------------------------*/
int32 
Dget1byte()
{
	int             c;

	if ((c = getc(dvifile)) == EOF)
		return (0);
	else
	{
		cmd1byte(c);
		return (c & 0xff);;
	}
}


/*---------------------------------------------------*/
int32 
Dsign1byte()
{
	int32           c;

	c = Dgetc();
	if (c >= 128)
		c -= 256;
	cmd1byte(c);
	return (c);
}


/*---------------------------------------------------*/
int32 
Dget2byte()
{
	int32           a, b;

	a = Dgetc();
	b = Dgetc();
	cmd1byte(a);
	cmd1byte(b);
	return ((a << 8) | b);
}


/*---------------------------------------------------*/
int32 
Dsign2byte()
{
	int32           a, b;

	a = Dgetc();
	b = Dgetc();
	cmd1byte(a);
	cmd1byte(b);
	if (a < 128)
		return ((a >> 8) | b);
	else
		return ((a - 256) * 256 + b);
}


/*---------------------------------------------------*/
int32 
Dget3byte()
{
	int32           a, b, c;

	a = Dgetc();
	b = Dgetc();
	c = Dgetc();
	cmd1byte(a);
	cmd1byte(b);
	cmd1byte(c);
	return ((a << 16) | (b << 8) | c);
}


/*---------------------------------------------------*/
int32 
Dsign3byte()
{
	int32           a, b, c;

	a = Dgetc();
	b = Dgetc();
	c = Dgetc();
	cmd1byte(a);
	cmd1byte(b);
	cmd1byte(c);
	if (a < 128)
		return ((a << 16) | (b << 8) | c);
	else
		return ((a - 256) * 256 + b) * 256 + c;
}


/*---------------------------------------------------*/
int32 
Dsign4byte()
{
	int32           a, b, c, d;

	a = Dgetc();
	b = Dgetc();
	c = Dgetc();
	d = Dgetc();
	cmd1byte(a);
	cmd1byte(b);
	cmd1byte(c);
	cmd1byte(d);
	if (a < 128)
		return (((a * 256 + b) * 256 + c) * 256 + d);
	else
		return ((((a - 256) * 256 + b) * 256 + c) * 256 + d);
}


/*---------------------------------------------------*/
/*
 * write a byte out to the ouput file, but if we encounter the font flag, define the new fonts, and continue
 */
void 
OutputByte(b)
	int32           b;
{
	if (b == OURFONTFLAG)
	{			/* our special macro-flag */
		b = NOP;	/* nullify it */
		if (!didnewfonts)
		{
			didnewfonts = true;
			defineNewfonts();	/* expand the defns in the outfile itself */
		}
	}			/* if */
	putc(b, outputfil);
	TotBytesWritten++;	/* keep count of all bytes */
}


/*---------------------------------------------------*/
void 
Output2Byte(i)
	int32           i;
{
	OutputByte((i >> 8) & 0xff);
	OutputByte(i & 0xff);
}


/*---------------------------------------------------*/
void 
Output4Byte(i)
	int32           i;
{
	OutputByte((i >> 24) & 0xff);
	OutputByte((i >> 16) & 0xff);
	OutputByte((i >> 8) & 0xff);
	OutputByte(i & 0xff);
}

/*---------------------------------------------------*/
void 
InitDVIBuf()
{
	GDVIBuf.maxlen = 2048;
	GDVIBuf.Dstring = (short *) xmalloc(sizeof(*GDVIBuf.Dstring) * 2048);
	GDVIBuf.TotByteLen = 0;
	GDVIBuf.curstrindex = 0;
}


/*---------------------------------------------------*/
void 
ClearDVIBuf()
{
	GDVIBuf.TotByteLen = 0;
	GDVIBuf.curstrindex = 0;
}


/*---------------------------------------------------*/
void 
WriteDVIBuf()
{
	int32           i;
	int32           b;

	for (i = 0; i < GDVIBuf.curstrindex; i++)
	{
		b = GDVIBuf.Dstring[i];
		OutputByte(b);
	}
	ClearDVIBuf();
}


/*---------------------------------------------------*/
void 
BackupInBuf(nbytes)
	int             nbytes;
{
	GDVIBuf.curstrindex -= nbytes;	/* points to position to-be-filled */
	GDVIBuf.TotByteLen -= nbytes;
}


/*-----------------------------------------------------*/
int32 
DVIMark()
{
	return (GDVIBuf.TotByteLen);
}