/*******************************************************************
*  Amish's I/O package for Type 1 font reading
********************************************************************/

#ifndef T1GST
#include "global.h"
#endif

/* Open the file */
F_FILE *T1Open(struct T1GlyphEngine *engine, char *fn)
{
	F_FILE *of;

	if (of = (F_FILE *)xalloc(engine, sizeof(F_FILE)))
	{
		if (readfont(fn, &(of->fbuf), &(of->fbuflen)) >= 0)
		{

// TetiSoft: Hack for %%VMusage:
			char *s = of->fbuf;
			char *e = (s + of->fbuflen) - 20;
			engine->VMusage1 = 0;
			engine->VMusage2 = 0;
			while (s < e)
			{
				if ((s[0] == '%') &&
				    (s[1] == '%') &&
				    (s[2] == 'V') &&
				    (s[3] == 'M') &&
				    (s[4] == 'u') &&
				    (s[5] == 's') &&
				    (s[6] == 'a') &&
				    (s[7] == 'g') &&
				    (s[8] == 'e') &&
				    (s[9] == ':'))
				{
					s += 10;						//skip name
					while ((s < e) && ((*s == ' ') || (*s == '\t')))	//skip white space
						s++;
					if (s >= e)
						break;
					while ((s < e) && isdigit(*s))
						engine->VMusage1 = engine->VMusage1 * 10 + (*s++ - '0');
					while ((s < e) && (*s != ' ') && (*s != '\t'))		//search white space
						s++;
					while ((s < e) && ((*s == ' ') || (*s == '\t')))	//skip white space
						s++;
					if (s >= e)
						break;
					while ((s < e) && isdigit(*s))
						engine->VMusage2 = engine->VMusage2 * 10 + (*s++ - '0');
					break;
				}
				s++;
			}

			of->curpos = 0;
			return of;
		}

		xfree(engine, of);
		of = NULL;
	}

	return of;
}


/* Read one character */
int T1Getc(F_FILE *f)
{
	if (f->fbuf == NULL)
		return EOF;			/* already closed */

	if (f->curpos == f->fbuflen)
		return EOF;

	return (f->fbuf)[(f->curpos)++];
}


/* Put back one character */
int T1Ungetc(int c, F_FILE *f)
{
	if (f && (c != EOF))
	{
		if (f->curpos > 0)
			(f->curpos)--;
	}

	return c;
}


/* Read n items into caller's buffer */
int T1Read(char *buffP, int size, int n, F_FILE *f)
{
	int acnt, rcnt;

	/* Number of bytes requested */
	rcnt = n * size;

	/* Number of bytes available */
	acnt = f->fbuflen - f->curpos;

	if (rcnt <= acnt)
	{
		memcpy((void *)buffP, (void *)(f->fbuf + f->curpos), rcnt);
		(f->curpos) += rcnt;
		return rcnt;
	}
	else
	{
		memcpy((void *)buffP, (void *)(f->fbuf + f->curpos), acnt);
		(f->curpos) = f->fbuflen;
		return acnt;
	}
}


/* Close the file */
int T1Close(struct T1GlyphEngine *engine, F_FILE *f)
{
	if (f)
	{
		freefont(f->fbuf);
		xfree(engine, f);
	}

	return 1;
}


/**
 * I commented out the following C version of T1eexec() because I have now
 * implemented it in assembly...
 **/

/* Eexec Decryption */
//F_FILE *T1eexec(F_FILE *f)
//{
//	int i, c;
//	unsigned char ch;
//	unsigned char randomP[4];
//	unsigned short r;
//	int pos;
//	static unsigned short c1 = 52845;
//	static unsigned short c2 = 22719;
//
//	/**
//	 * Get and initialize the key
//	 **/
//	randomP[0] = (f->fbuf)[(f->curpos)++];
//	randomP[1] = (f->fbuf)[(f->curpos)++];
//	randomP[2] = (f->fbuf)[(f->curpos)++];
//	randomP[3] = (f->fbuf)[(f->curpos)++];
//	r = 55665;
//	for (i=0; i < 4; i++)
//		r = (randomP[i] + r) * c1 + c2;
//
//	/**
//	 * Store the current file position
//	 **/
//	pos = f->curpos;
//
//	/**
//	 * Decrypt the rest of the file.  NOTE: ascii is not supported at this time
//	 **/
//	while (pos != f->fbuflen)
//	{
//		c = (f->fbuf)[pos];
//		ch = c ^ (r >> 8);
//		r = (c + r) * c1 + c2;
//		(f->fbuf)[pos++] = ch;
//	}
//
//	return f;
//}

/* TetiSoft: Added ASCII decryption */
static int ishexchar(int c)
{
	if(
	   ((c >= '0')&&(c <= '9'))||
	   ((c >= 'a')&&(c <= 'f'))||
	   ((c >= 'A')&&(c <= 'F'))
	) return 1;
	return 0;
}
void T1eexecASCII(F_FILE *f)
{
	unsigned int c1, c2;
	int stopat = 0;
	int len;
	int pos;
	int maxpos;
	unsigned char *p,*q,*end;

	p = f->fbuf;
	pos = f->curpos;
	if(!ishexchar(p[pos])||
	   !ishexchar(p[pos+1])||
	   !ishexchar(p[pos+2])||
	   !ishexchar(p[pos+3])||
	   !ishexchar(p[pos+4])||
	   !ishexchar(p[pos+5])||
	   !ishexchar(p[pos+6])||
	   !ishexchar(p[pos+7])
	  ) return;
	maxpos = f->fbuflen - 9;
	while(pos <= maxpos)
	{
		if((p[pos] == '\n') &&
		   (p[pos+1] == '0') &&
		   (p[pos+2] == '0') &&
		   (p[pos+3] == '0') &&
		   (p[pos+4] == '0') &&
		   (p[pos+5] == '0') &&
		   (p[pos+6] == '0') &&
		   (p[pos+7] == '0') &&
		   (p[pos+8] == '0'))
		{
			stopat=pos;
			break;
		}
		pos++;
	}
	if(!stopat)
		return;
	p = f->fbuf + f->curpos;
	q = f->fbuf + f->curpos;
	end = f->fbuf + stopat;
	len = 0;

	while(p < end)
	{
		while((*p == ' ')||(*p == '\t')||(*p == '\n')||(*p == '\r')||(*p == '\v')||(*p == '\f'))
		{
			p++;
			if(p > end)
				break;
		}
		c1 = *p++;
		if((c1 >= '0') && (c1 <= '9'))
			c1 -= '0';
		else if ((c1 >= 'a') && (c1 <= 'f'))
			c1 -= ('a' - 10);
		else if ((c1 >= 'A') && (c1 <= 'F'))
			c1 -= ('A' - 10);
		else
			return;
		while((*p == ' ')||(*p == '\t')||(*p == '\n')||(*p == '\r')||(*p == '\v')||(*p == '\f'))
		{
			p++;
			if(p > end)
				break;
		}
		c2 = *p++;
		if((c2 >= '0') && (c2 <= '9'))
			c2 -= '0';
		else if ((c2 >= 'a') && (c2 <= 'f'))
			c2 -= ('a' - 10);
		else if ((c2 >= 'A') && (c2 <= 'F'))
			c2 -= ('A' - 10);
		else
			return;
		*q++ = (c1 << 4) + c2;
		len++;
	}
	while(q < end)
		*q++ = ' ';
	f->fbuflen = f->curpos + len;
}
