#include <stdio.h>
#include <Vft.h>

/*****************************************************************************
	VFTINFO - print out data contained in .Vft file.  The -R option causes
		  the minirasters to be displayed in addition to the character
		  header data.  The -f option identifies the .Vft  file to  be
		  examined.
 *****************************************************************************/

#ifdef apm
#define swapb(s) ((short)(s))
#define SLEN	 23
char	fontdir[] = "";
#endif

/*
#ifdef mc68000
#define	swapb(s) ((short)(s))
#define SLEN	 63
char	fontdir[] = "/Fonts/Virtual/";
#else
#define	swapb(s) ((short)(((s & 0xFF)<<8) | ((s>>8) & 0xFF)))
#define SLEN	 23
char	fontdir[] = "/projects/nunix/Fonts/Virtual/";
#endif
*/

struct VFontHdr Fhdr;		/* header for .Vft file			*/
struct VCharDef Font[FONTSIZE];	/* character headers for .Vft file	*/

char	rdata[1000];		/* buffer to hold mini-raster data	*/
short	HSize, VSize;		/* scaled Horizonal & Vertical sizes	*/
short	count = -1, RasterS;	/* char count, scaled raster size	*/
char	outrast = 0;		/* 1 for detailed printout		*/
double	rfactor;		/* raster resolution factor		*/
FILE	*fid;

char	tname[80];
char	*fnp;
/*****************************************************************************
	FSOPEN - fopen file "name", "name.ext", or "/dir/name.ext"
 *****************************************************************************/
FILE *
fsopen(name, dir, ext, mode)
char *name, *dir, *ext, *mode;
{
	FILE	*fd;
	register char *fp1, *fp2;

	for (fp1 = tname, fp2 = dir; *fp1++ = *fp2++;); fnp = --fp1;
	for (fp2 = name; *fp1++ = *fp2++;); --fp1;
	if (mode[0] == 'w')
	{
		for (fp2 = fnp; *fp2; fp2++) if (strcmp(".ft", fp2) == 0)
		{
			fp1 = fp2;
			break;
		}
		for (fp2 = ext; *fp1++ = *fp2++;);
		fd = fopen(fnp = tname, mode);
	}
	else if ((fd = fopen(fnp, mode)) == NULL)
	{
		for (fp2 = ext; *fp1++ = *fp2++;);
		if ((fd = fopen(fnp, mode)) == NULL)
			fd = fopen(fnp = tname, mode);
	}
	return(fd);
}

/*****************************************************************************
	RESTORE - resets the terminal video mode and exits
 *****************************************************************************/
restore()
{
	printf("\033q\n");
	exit();
}

/*****************************************************************************
	ROUND - rounds a floating value
 *****************************************************************************/
round(x)
double x;
{
#ifdef pdp11
	union
	{
		long	i;
		struct
		{
			short	hi;
			short	lo;
		} l;
	} t;

	t.i = (x >= 0 ? x + 0.4999 : -(-x + 0.4999));
	return((t.l.hi == 0 || ~t.l.hi == 0) ? t.l.lo :
		(t.l.hi < 0 ? -32767 : 32767));
#else
	return(x >= 0 ? x + 0.4999 : -(-x + 0.4999));
#endif
}

/*****************************************************************************
	MAIN - main program loop
 *****************************************************************************/
main(argc, argv)
int argc;
char **argv;
{
	register short i;
	register char *argptr;
	char ch;

	signal(2, restore);
	while (--argc)
	{
		argptr = *++argv;
		if (*argptr == '-') switch (*++argptr)
		{
		case 'R':
			outrast++;
			continue;
		case 'f':
			fid = fsopen(++argptr, fontdir, ".Vft", "r");
			if (fid == NULL)
			{
				fprintf(stderr,
					"can't find %s, %s.Vft, or %s%s.Vft\n",
					argptr, argptr, fontdir, argptr);
				exit(1);
			}
			fread(&Fhdr, sizeof(Fhdr), 1, fid);
			fread(Font, sizeof(Font), 1, fid);
			rfactor = (double)(swapb(Fhdr.FontRes))/2400.0;
			if (rfactor == 0) rfactor = 1.0;
			else printf("RASTER RESOLUTION =\t\t%d(pixels/inch)\n",
				swapb(Fhdr.FontRes));
			printf("MAX HEIGHT ABOVE BASELINE =\t%d\n",
				swapb(Fhdr.FontHab));
			printf("MAX HEIGHT BELOW BASELINE =\t%d\n",
				swapb(Fhdr.FontHbb));
			continue;
		default:
			fprintf(stderr, "unrecognized option '%c'\n", *argptr);
			exit();
		}
		else
		{
			if (*argptr != '0') sscanf(argptr, "%c", &ch);
			else sscanf(argptr, "%o", &ch);
			fontinfo(ch);
		}
	}
	if (count < 0) for (i = 0; i < FONTSIZE; i++) fontinfo(i);
}

/*****************************************************************************
	FONTINFO - prints out data for character 'ch'
 *****************************************************************************/
fontinfo(ch)
register char ch;
{
	register short	*s1;
	register char j;
	register struct VCharDef *nhp;

	RasterS = 0;
	nhp = &Font[ch];
#ifdef pdp11
	s1 = &nhp->Raster;
	*s1 = swapb(*s1); *++s1 = swapb(*s1);
#endif
	HSize = swapb(nhp->HSize);
	HSize = round(rfactor * (double)HSize);
	VSize = swapb(nhp->VSize);
	VSize = round(rfactor * (double)VSize);
	RasterS = VSize * ((HSize + 15) >> 4) * 2;
	if (RasterS == 0) return;

	if (outrast || ((++count % SLEN) == 0)) 
	{
		if (outrast) count = SLEN - 1;
		printf("\n%s\n", fnp);
		printf("\033pASCII   CHAR  HSIZE   VSIZE    HADJ");
		printf("    VADJ   HINCR   VINCR"); 
		if (Fhdr.FontRes)
			printf("    MRPTR   SIZE");
		printf("\033q\n");
	}

	printf("0x%x\t'", ch);
	if ((j = ch) < ' ')
	{
		putchar('^');
		j += 64;
	}
	printf("%c'\t%d\t%d\t%d\t%d\t%d\t%d\t", j, swapb(nhp->HSize),
		swapb(nhp->VSize), swapb(nhp->HAdj), swapb(nhp->VAdj),
		swapb(nhp->HIncr), swapb(nhp->VIncr));

	if (Fhdr.FontRes && nhp->Raster)
	{
		printf("%D\t%d\n", nhp->Raster, RasterS);
		if (outrast) rastinfo(ch);
	}
	else putchar('\n');

}

/*****************************************************************************
	RASTINFO - displays miniraster for character 'ch'
 *****************************************************************************/
rastinfo(ch)
{
	long rrptr, offset = sizeof(struct VFontHdr);
	short h, v;
	register short *rsptr, rl, i, bit, bitcnt;
	unsigned short rs;

	offset += ((ch + 1) * sizeof(struct VCharDef)) - sizeof(long);
	rrptr = Font[ch].Raster;
	h = (HSize + 15) >> 4;		/* # of shorts in raster line	*/
	v = VSize;			/* # of raster lines		*/

	fseek(fid, offset + rrptr, 0);
	fread(rdata, h*v*2, 1, fid);

	putchar('\n');
	rsptr = (short *)rdata;
	for (rl = 0; rl < v; rl++)	/* iterate over raster lines	*/
	{
		bitcnt = 0;
		for (i = 0; i < h; i++)	/* iterate over shorts in line	*/
		{
			rs = swapb(*rsptr); rsptr++;
			for (bit = 0; bit < 16; bit++)	/* over bits	*/
			{
				if (rs & 1) putchar('X'); else putchar('-');
				if (++bitcnt >= HSize) break;
				rs >>= 1;
			}
		}
		putchar('\n');
	}
	printf("\n\n");
}

