/*
 * This is the font specific bit of textool.
 * This version supports PXL format files, which are easy to use but big.
 */

#include "defs.h"
#include <stdio.h>
#include <sys/file.h>				/* for access() stuff */
#include <pixrect/pixrect_hs.h>		/* for LoadAChar() */
char *index();
char *rindex();
char *sprintf();
char *strcpy();

/* procedures in sunstuff */
extern void	Fatal();
extern void	Warning();

/* procedures in dvistuff */
extern float	ActualFactor();
extern int	NoSignExtend();
extern FILE	*OpenFontFile();

/* procedures here */
void	FindFontFile();
void	LoadAChar();
void	ReadCharDefs();

/* a few global variables and data structures */
#include "globals.h"

/* now to the real code */

/*-->FindFontFile*/
/**********************************************************************/
/************************  FindFontFile  ******************************/
/**********************************************************************/

void
FindFontFile(tfontptr, mag)
struct font_entry *tfontptr;
unsigned int mag;
{
	char *direct, *tcp, *tcp1;
	int found;
	char curarea[STRSIZE];

	tfontptr->font_mag = (int)((ActualFactor((int)(((float)tfontptr->s/
				(float)tfontptr->d)*1000.0 + 0.5)) * 
#ifdef USEGLOBALMAG
				ActualFactor(mag) *
#endif
				(float)RESOLUTION * 5.0) + 0.5);
	if (tfontptr->a != 0) {
		sprintf(tfontptr->name, "%s.%dpxl", tfontptr->n, tfontptr->font_mag);
	}
	else {
		direct = PXLpath;
		found = FALSE;
		do { 
			tcp = index(direct, ':');
			if (tcp == NULL)
				tcp = strlen(direct) + direct;
			strncpy(curarea, direct, tcp-direct);
			tcp1 = curarea + (tcp - direct);
			*tcp1++ = '/';
			*tcp1++ = '\0';

			sprintf(tfontptr->name, "%s%s.%dpxl",
				curarea, tfontptr->n, tfontptr->font_mag);
			found = (access(tfontptr->name, R_OK) == 0);
			if (*tcp)
				direct = tcp + 1;
			else
				direct = tcp;
		} while ( !found && *direct != '\0');
	}
}


/*-->LoadAChar*/
/**********************************************************************/
/*****************************  LoadAChar  ****************************/
/**********************************************************************/

void
LoadAChar(ptr)
register struct char_entry *ptr;
{
	register Pixrect *pr;
	register int nshorts, i, col, nints;
	register short *dp, *sp;
	int buffer[8];
	FILE *pxlfp;

	pxlfp = OpenFontFile();
	if (ptr->where.address.fileOffset == 0) {
		ptr->where.address.pixrectptr = NULL;
		return;
	}
	fseek(pxlfp, ptr->where.address.fileOffset, 0);
	if ((pr = mem_create(ptr->width, ptr->height, 1)) == NULL) {
		Fatal("Couldn't allocate pixrect");
		return;
	}
	nshorts = (ptr->width + 15) >> 4;
				/*
				 * the following test is done because
				 * some bogus font files once caused
				 * the pixrect to be overfilled, damaging
				 * other font data structures
				 */
	if (nshorts != (((struct mpr_data *)pr->pr_data)->md_linebytes >> 1)) {
		Fatal("Pixrect too narrow for font");
		return;
	}
	nints = (nshorts + 1) >> 1;
	dp = ((struct mpr_data *)pr->pr_data)->md_image;
	for (col = 0; col < ptr->height; col++) {
		fread(buffer, 4, nints, pxlfp);
		sp = (short *)&buffer[0];
		for (i = nshorts; i > 0; i--)
			*dp++ = *sp++;
	}
	ptr->where.address.pixrectptr = pr;
	ptr->where.isloaded = TRUE;
}


/*-->ReadCharDefs*/
/**********************************************************************/
/*****************************  ReadCharDefs  *************************/
/**********************************************************************/

void
ReadCharDefs(tfontptr, pxlfp)
struct font_entry *tfontptr;
FILE *pxlfp;
{
	int t, i;
	register struct char_entry *tcharptr; /* temporary char_entry pointer */

	if ((t = NoSignExtend(pxlfp, 4)) != PXLID) {
		Fatal("PXL ID = %d, can only process PXL ID = %d files",
				t, PXLID);
		return;
	}
	fseek(pxlfp, -20, 2);
	t = NoSignExtend(pxlfp, 4);
	if ((tfontptr->c != 0) && (t != 0) && (tfontptr->c != t))
		Warning("font = \"%s\",\n-->font checksum = %d,\n-->dvi checksum = %d",
				tfontptr->name, tfontptr->c, t);
	(void)NoSignExtend(pxlfp, 4);	/* throw away magnification */
	(void)NoSignExtend(pxlfp, 4);	/* throw away design size */

	fseek(pxlfp, NoSignExtend(pxlfp, 4) * 4, 0);

	for (i = FIRSTPXLCHAR; i <= LASTPXLCHAR; i++) {
		tcharptr = &(tfontptr->ch[i]);
		tcharptr->width = NoSignExtend(pxlfp, 2);
		tcharptr->height = NoSignExtend(pxlfp, 2);
		tcharptr->xOffset= SignExtend(pxlfp, 2);
		tcharptr->yOffset = SignExtend(pxlfp, 2);
		tcharptr->where.isloaded = FALSE;
		tcharptr->where.address.fileOffset = NoSignExtend(pxlfp, 4) << 2;
		tcharptr->tfmw = ((float)NoSignExtend(pxlfp, 4)*(float)tfontptr->s) /
			(float)(1<<20);
	}
	if (BigPreLoad)	/* load all char pixrects */
	for (i = FIRSTPXLCHAR; i <= LASTPXLCHAR; i++)
		LoadAChar(&(tfontptr->ch[i]));
}