#ifndef lint
static char *sccsid = "%W% (UKC) %G%";
#endif  lint

/*
 *	Convert canon font format on stdin to ditroff font table on stdout.
 *	At UKC, get the fonts from the file server with fs
 */

#include <stdio.h>

#define debug (void)

typedef unsigned short u_short;
typedef unsigned long u_long;

u_short get16();
u_long	get32();
char *calloc();

struct character {
	u_short width;
	u_short height;
	short xoffs;
	short yoffs;
	u_long raster_index;
	u_long effective_width;
};

static u_short nchars;
static u_short raster_size;
static struct character *character;	/* the per-character structures */
static u_long *rasters;			/* the rasters, read from the file */

static int max_up = 0, max_down = 0;	/* The highest/lowest any character rises/falls above/below the reference point */

static printflag = 0;	/* Debugging print of info in font file */
static int size = 10;	/* Size of canon font; widths are to be conv'd to 10 point */

main(argc, argv)
char **argv;
{
	register FILE *ifp;
	register int i;
	u_long n_rasters;	/* for checking purposes */
	int down;

	for (i=1; i<argc; i++) {
		if (argv[i][0] == '-') {
			switch(argv[i][1]) {
			case 'p':
				printflag = 1;
				break;
			case 's':	/* Convert widths at n point to 10 pt */
				size = atoi(&argv[i][2]);
				if (size==0) {
					fputs("cantowtab: Usage: -s14\n", stderr);
					exit(1);
				}
				break;
			default:
				fprintf(stderr, "cantowtab: Unknown flag '%s'.\n", argv[i]);
			}
		}
	}

	ifp = stdin;
	nchars = get16(ifp);
	raster_size = get16(ifp);
	if (printflag) printf("nchars = %ud, raster_size = %ud\n", nchars, raster_size);
	character = (struct character *) calloc ( nchars, sizeof(struct character) );
	if (character == NULL) {
		fprintf(stderr, "cantowtab: Not enough memory for %d characters.\n", nchars);
		exit(1);
	}

	n_rasters = 0; max_up = max_down = 0;

	if (printflag) printf("CH# WID HEI XOF YOF INDEX EWD MXD\n");
	for (i=0; i<nchars; i++) {
		character[i].width = get16(ifp);
		character[i].height = get16(ifp);
		character[i].xoffs = (short) get16(ifp);
		character[i].yoffs = (short) get16(ifp);
		character[i].raster_index = get32(ifp);
		character[i].effective_width = get32(ifp);
		n_rasters += (character[i].width+31)/32 * character[i].height;
		if (character[i].yoffs > max_up) max_up = character[i].yoffs;
		down = (int) character[i].height - character[i].yoffs;
		if (down > max_down) max_down = down;
		if (printflag) printf("%3d %3d %3d %3d %3d %5d %3d %3d\n",
				i,
				character[i].width,
				character[i].height,
				character[i].xoffs,
				character[i].yoffs,
				character[i].raster_index,
				character[i].effective_width,
				max_down);
	}
	if (n_rasters < raster_size) {
		fprintf(stderr, "cantowtab: Hum. Only %d of the %d available rasters are used.\n", n_rasters, raster_size);
	}
	if (printflag) {
		printf("max_up = %d, max_down = %d.\n", max_up, max_down);
		exit(0);
	}

	rasters = (u_long *) calloc (raster_size, sizeof(u_long));
	if (rasters == NULL) {
		fprintf(stderr, "cantowtab: Not enough memory for %d rasters.\n", raster_size);
		exit(1);
	}
	for (i=0; i<raster_size; i++) {
		rasters[i] = get32(ifp);
	}

	puts("charset");
	for (i=0; i<nchars; i++) {
		setchar(i);
	}
	exit(0);
}

setchar(i)
{
	u_short charwidth;

	u_short width	= character[i].width;
	u_short height	= character[i].height;
	short xoffs	= character[i].xoffs;
	short yoffs	= character[i].yoffs;

	if (width == 0 || height == 0) return;
	if (character[i].raster_index + (character[i].width+31)/32*character[i].height > raster_size) {
		fprintf(stderr, "cantowtab: character %d has illegal index(%d+%d*%d/%d).\n", i, character[i].raster_index, (character[i].width+31)/32, character[i].height, raster_size);
		return;
	}

	if(i>32 && i<127) putchar(i);
	else printf("%u", i);
	putchar('\t');
	/* the following width munging formula is perfect for unitwidth=10 */
	printf("%d\t0\t%u\n", (character[i].effective_width*10+size-6)/size, i);
}

#define cget(ifp) ((ch = getc(ifp))==EOF ? preof() : (ch&255))

u_short
get16(ifp)
FILE *ifp;
{
	register u_short i;
	register int ch;

	i = (u_short) cget(ifp) << 8;
	i += (u_short) cget(ifp);
	debug(stderr, "get16: %d\n", i);
	return(i);
}
	
u_long
get32(ifp)
FILE *ifp;
{
	register u_long i;
	register int ch;

	i = (u_long) cget(ifp) << 24;
	i += (u_long) cget(ifp) << 16;
	i += (u_long) cget(ifp) << 8;
	i += (u_long) cget(ifp);
	debug(stderr, "get32: %d\n", i);
	return(i);
}

preof()
{
	fprintf(stderr, "Premature EOF.\n");
	exit(1);
}

debugch(i, ch)
struct character ch;
{
	fprintf(stderr, "%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
		i,
		ch.width,
		ch.height,
		ch.xoffs,
		ch.yoffs,
		ch.raster_index,
		ch.effective_width);
}
