#include <stdio.h>
#include "term.h"
#include "font.h"

static	short	get16();
static	long	get32();

extern	char	*calloc();

/*
 *	Read in the font file fname and return the addresses of the first
 *	character structure and the first raster in *cptr and *rptr
 *
 *	Returns pointer to the filled-in font structure, or NULL on error.
 */
b_font *
getfont(fname)
char	*fname;
{
	b_char	*c;
	u_long	*r;
	u_short	nchars, nrasters;
	FILE	*fp;
	int	i;
	b_font *newfont;	/* return value under construction */

	if ((fp = fopen(fname, "r")) == NULL) {
		error("Can't open font file %s\n", fname);
		return(NULL);
	}

	newfont = (b_font *) malloc(sizeof(b_font));
	if (newfont == NULL) {
		error("Out of memory in getfont()\n");
		return(NULL);
	}

	nchars = get16(fp);
	nrasters = get16(fp);

	newfont -> bf_nchars = nchars;

	/* Allocate memory for character structures */
	c = (b_char *) calloc((unsigned) nchars, sizeof(b_char));
	if (c == NULL) {
		error("Not enough memory for characters from %s\n", fname);
		return(NULL);
	}

	newfont -> bf_char = c;

	/* Allocate memory for rasters */
	r = (u_long *) calloc((unsigned) nrasters, sizeof(u_long));
	if (r == NULL) {
		error("Not enough memory for rasters from %s\n", fname);
		return(NULL);
	}

	newfont -> bf_raster = r;

	for (i = 0; i < nchars; i++) {
		c[i].bc_width		= get16(fp);
		c[i].bc_height		= get16(fp);
		c[i].bc_xoffs		= get16(fp);
		c[i].bc_yoffs		= get16(fp);
		c[i].bc_raster_index	= get32(fp);
		c[i].bc_effective_width	= get32(fp);
	} 

	for (i = 0; i < nrasters; i++)
		r[i] = get32(fp);

	(void) fclose(fp);

	return(newfont);
}

/* get a 16 bit quantity from stream fp */
static short
get16(fp)
FILE *fp;
{
	short i;

	i = (short) getc(fp) << 8;
	i += (short) getc(fp);
	return(i);
}
	
/* get a 32 bit quantity from stream fp */
static long
get32(fp)
FILE *fp;
{
	long i;

	i = (long) getc(fp) << 24;
	i += (long) getc(fp) << 16;
	i += (long) getc(fp) << 8;
	i += (long) getc(fp);
	return(i);
}

/*
 *	Set a bitmapped character
 */
term_bmchar(h, v, f, c)
int h, v;		/* where to put the reference point */
b_font *f;		/* the in-core font structure */
int c;			/* which char we want (index into f->bf_char) */
{
	struct b_char *b_c;	/* quick access to f->bf_char[c] */
	u_long *raster;		/* pointer to start of rasters for this char */
	register u_long r;	/* current raster being output */
	int i, j, k;		/* loop vars */
	u_short cwidth;		/* width of current char in pixels */

	/* set local fast copies of various things */
	b_c = &(f->bf_char[c]);
	cwidth = b_c->bc_width;
	raster = &(f->bf_raster[b_c->bc_raster_index]);

	for (i=0; i < b_c->bc_height; i++) {

		/* do whole words first */
		for (j = 0; j < cwidth/32; j++) {
			r = *raster++;

			for (k=0; k < 32; k++) {
				if (r & 0x80000000) {
					term_dot(h + 32*j + k, v + i);
				}
				r <<= 1;
			}
		}
		
		/* now do remaining bytes */
		/* j is left at an appropriate value by the above loop */
		if (cwidth%32 != 0) {
			r = *raster++;

			for (k=0; k < cwidth%32; k++) {
				if (r & 0x80000000) {
					term_dot(h + 32*j + k, v + i);
				}
				r <<= 1;
			}
		}
	}
}

main(argc, argv)
char **argv;
{
	int x, y;
	int i, j;

	b_font *font;
	char *fontfile = argv[1];
	int c;

	font = getfont(fontfile);
	if (font == NULL) {
		fprintf(stderr, "Cannot read font file \"%s\".\n", fontfile);
		exit(1);
	}

	/* Test routine to plot one character in the middle of the screen */
	term_init();

	y = 0;
	for (i=2; i<argc; i++) {
		x = 0;
		for (j=0; (c = argv[i][j]) != '\0'; j++) {
			term_bmchar(x, y, font, c);
			x += font->bf_char[c].bc_effective_width;
		}
		y += 33;
	}

	term_deinit();

	printf("%d\n", x);

	exit(0);
}

error(str)
char *str;
{
	set_bitmap(0);
	fputs(str, stderr);
}
