#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#define BUFSIZE 0x10000

static char buffer[BUFSIZE];

/*
 * extracts fonts from a messdos pci file
 */

typedef struct Codepage_l {
    unsigned short a1;
    unsigned short next;
    unsigned short a2;
    unsigned short a3;
    char name[8];
    unsigned short pagenr;
    unsigned short a4;
    unsigned short a5;
    unsigned short a6;
    unsigned short ptr;
    unsigned short a7;
    unsigned short a8;
    unsigned short nfonts;
    unsigned short size;
} Codepage_t;

typedef struct Font_l {
    unsigned char height;
    unsigned char width;
    unsigned char a1;
    unsigned char a2;
    unsigned char a3;
    unsigned char a4;
} Font_t;

void print_font(int nr, Font_t *font, char *reqresol, char *type)
{
    int i,j;
    char filename[80], resolution[32];
    FILE *file;
    unsigned char *p;

    sprintf(resolution,"%dx%d", font->width, font->height);
    if(!reqresol || !strcmp(reqresol, "*") || !strcmp(resolution,reqresol))
	printf(" font: width=%2d height=%2d, a1=%d a2=%d, a3=%d, a4=%d\n",
	       font->width, font->height, font->a1, font->a2, font->a3,
	       font->a4);

    if(!reqresol || (strcmp(resolution,reqresol) && strcmp(reqresol,"*")))
       return;

    p = (unsigned char *) (font+1);

    if(!strcmp(type, "linux" )) {
	sprintf(filename, "vga%d:%dx%d.lnx", nr, font->width, font->height);
	file = fopen(filename, "w");
	for(i=0; i<256; i++) {	
	    for(j=0; j< font->height; j++)
		fputc(*(p++), file);
	    for(j=0; j< font->height; j++)
		fputc(' ', file);	    
	}
	fclose(file);
	return;
    } else if(!strcmp(type, "pcf")) {
	sprintf(filename, "bdftopcf >vga%d:%dx%d.pcf", nr, font->width,
		font->height);
	file = popen(filename, "w");
    } else if(!strcmp(type, "pcf.gz")) {
	sprintf(filename, "bdftopcf | gzip >vga%d:%dx%d.pcf.gz", nr,
		font->width, font->height);
	file = popen(filename, "w");
    } else {/* bdf font */
	sprintf(filename, "vga%d:%dx%d.bdf", nr, font->width,
		font->height);
	file = fopen(filename, "w");
    }
 
    fprintf(file, "COMMENT vga\n");
    fprintf(file, "STARTFONT 2.1\n");
    fprintf(file, "FONT vga%d:%dx%d\n", nr, font->width, font->height);
    fprintf(file, "SIZE %d 75 75\n", font->height);
    fprintf(file, "FONTBOUNDINGBOX %d %d 0 -%d\n",
	    font->width, font->height, font->height / 4);
    fprintf(file, "STARTPROPERTIES 3\n");
    fprintf(file, "FONT_DESCENT %d\n", font->height / 4);
    fprintf(file, "FONT_ASCENT %d\n", font->height - font->height / 4);
    fprintf(file,"DEFAULT_CHAR 0\n");
    fprintf(file,"ENDPROPERTIES\n");
    fprintf(file,"CHARS 256\n");

    for(i=0; i<256; i++) {	
	fprintf(file,"STARTCHAR C%04x\n", i);
	fprintf(file,"ENCODING %d\n", i);
	fprintf(file,"SWIDTH 666 0\n");
	fprintf(file,"DWIDTH %d 0\n", font->width);
	fprintf(file,"BBX %d %d 0 -%d\n", font->width, font->height,
		font->height / 4);
	fprintf(file,"BITMAP\n");
	for(j=0; j< font->height; j++)
	    fprintf(file,"%02x\n", *(p++));
	fprintf(file,"ENDCHAR\n");	
    }
    fprintf(file,"ENDFONT\n");
    fclose(file);
}

void main(int argc, char **argv)
{
    Codepage_t *page;
    Font_t *font;
    int size, npages, i, j, reqpage=0;
    char *reqresol = 0;

    size = read(0, buffer+1, BUFSIZE-1);
    if(size < 0) {
	perror("read");
	exit(1);
    }

    if(argc > 1)
	reqpage = strtoul(argv[1],0,0);
    if(argc > 2) {
	reqresol = argv[2];
	if( argc == 3) {
	    fprintf(stderr, "Missing output font type\n");
	    exit(1);
	}
    }
    
    size++;
    npages = * (short *) (buffer + 0x18);
    page = (Codepage_t *) (buffer+ 0x1a);
    for(i=0; i<npages; i++) {
	if(argc < 2 || reqpage == page->pagenr  || !reqpage)
	    printf("%8.8s:%3d %04x %04x %04x %04x %04x %04x %04x %04x %04x ptr=%04x size=%04x\n",
		   page->name, page->pagenr,
		   page->a1, page->a2, page->a3, page->a4, 
		   page->a5, page->a6, page->a7, page->a8,
		   page->nfonts, page->ptr, page->size);
	font = (Font_t *) (page+1);
	if(argc >= 2 && (reqpage == page->pagenr || !reqpage))
	    for(j=0; j<page->nfonts; j++) {
		print_font(page->pagenr, font, reqresol, argv[3]);
		font = (Font_t *) ( ((char *) (font+1)) + 256 * font->height);
	    }
	    
	page = (Codepage_t *) (buffer+ 1 + page->next);
    }
    exit(0);
}

