/*
 * 5799-CGZ (C) COPYRIGHT IBM CORPORATION 1986,1987
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header: ibm_font_tools.c,v 12.0 88/11/11 12:37:41 root dec88 $ */
/* $Source: /ibm/acis/usr/src/ibm/fdb_ca/src/RCS/ibm_font_tools.c,v $ */

#ifndef lint
static char *rcsid = "$Header: ibm_font_tools.c,v 12.0 88/11/11 12:37:41 root dec88 $";
#endif

/* 
 * ibm_font_tools: a collection of routines for manipulating ibm fonts
 */
/*-------------------include project and standard type defs*/
#include "itc.h"
#include "stddefs.h"
/*------------------include appropriate header files*/
#include <stdio.h>
#include "font_tools.h"
#include "palloc.h"
#include "etoa.h"
#include "symtab.h"
#include "bits.h"

/*--------------------include ibm font processing definitions*/
#include "ibmfonts.h"
typedef struct	{
    unsigned int length;
    unsigned int type_id;
    unsigned int flags;
    unsigned int sequence_num;
} header_type;

#define header_length 9
#ifdef ibm3820
 int FNI_cnt =0;
 int FNO_cnt =0;
#endif


struct pattern_map {
    lnatural x_extent;
    lnatural y_extent;
    lnatural pattern_address;
};

static struct pattern_map *CurrentPatterns = NULL;
/* the Structured Field type ids are listed below */

		     /* Code page			  */
#define BCP 0xA887   /* Begin code page 		  */
#define CPD 0xA687   /* Code page descriptor		  */
#define CPC 0xA787   /* Code page control		  */
#define CPI 0x8C87   /* Code page index 		  */
#define ECP 0xA987   /* End code page			  */
		     /* Font				  */
#define BFN 0xA889   /* Begin font			  */
#define FND 0xA689   /* Font descriptor 		  */
#define FNP 0xAC89   /* Font position			  */
#define FNL 0xB089   /* Font ligature table		  */
#define FNC 0xA789   /* Font control			  */
#define FNO 0xAE89   /* Font orientation		  */
#define FNI 0x8C89   /* Font index			  */
#define FNG 0xEE89   /* Font graphic patterns		  */
#define FNM 0xA289   /* Font Patterns Map		  */
#define EFN 0xA989   /* End font			  */
		     /* Coded font			  */
#define BCF 0xA88A   /* Begin coded font		  */
#define CFD 0xA687   /* Coded font descriptor		  */
#define CFC 0xA78A   /* Coded font control		  */
#define CFI 0x8C8A   /* Coded font index		  */
#define ECF 0xA98A   /* End coded font			  */
#define MCF 0xAB8A   /* Map coded font			  */
#define NOOP 0xEEEE  /* No operation			  */

/* the index to the SF type names are below */

#define ERR_index  0   /* Unknown SF type id		    */
#define BCP_index  1   /* Begin code page		    */
#define CPD_index  2   /* Code page descriptor		    */
#define CPC_index  3   /* Code page control		    */
#define CPI_index  4   /* Code page index		    */
#define ECP_index  5   /* End code page 		    */
#define BFN_index  6   /* Begin font			    */
#define FND_index  7   /* Font descriptor		    */
#define FNP_index  8   /* Font position 		    */
#define FNL_index  9   /* Font ligature table		    */
#define FNC_index 10   /* Font control			    */
#define FNO_index 11   /* Font orientation		    */
#define FNI_index 12   /* Font index			    */
#define FNG_index 13   /* Font graphic patterns 	    */
#define EFN_index 14   /* End font			    */
#define BCF_index 15   /* Begin coded font		    */
#define CFD_index 16   /* Coded font descriptor, bug	    */
#define CFC_index 17   /* Coded font control		    */
#define CFI_index 18   /* Coded font index		    */
#define ECF_index 19   /* End coded font		    */
#define MCF_index 20   /* Map coded font		    */
#define NOOP_index 21  /* No operation			    */
#define FNM_index 22   /* Font Patterns Map		    */
#define max_sf_type_index 21

string sf_type_names[] = {
     "Unknown SF type id",
     "Begin code pagen",
     "Code page descriptor",
     "Code page control",
     "Code page index",
     "End code page",
     "Begin font",
     "Font descriptor",
     "Font position",
     "Font ligature table",
     "Font control",
     "Font orientation",
     "Font index",
     "Font graphic patterns",
     "End font",
     "Begin coded font",
     "Coded font descriptor",
     "Coded font control",
     "Coded font index",
     "End coded font",
     "Map coded font",
     "No operation, SF",
     "Font Patterns Map",
};

/*
 * Field translation tables, these table contain values of fields used
 * in the standard font data base.  The index to the table is a value
 * from a field in the IBM font description.
 */

/*-----------------IBM FND.font selection to fd.typeface*/
/*
 *  The index to this array is the upper 5 bits of a 2 byte field
 */

string fd_typeface[] = {

    "roman",                                    /* 00000 */
    "roman",                                    /* 00001 */
    "roman_outline",                            /* 00010 */
    "roman_outline",                            /* 00011 */
    "roman_reversed",                           /* 00100 */
    "roman_reversed",                           /* 00101 */
    "roman_reversed_outline",                   /* 00110 */
    "roman_reversed_outline",                   /* 00111 */
    "roman_underlined",                         /* 01000 */
    "roman_underlined",                         /* 01001 */
    "roman_underlined_outline",                 /* 01010 */
    "roman_underlined_outline",                 /* 01011 */
    "roman_underlined_reversed",                /* 01100 */
    "roman_underlined_reversed",                /* 01101 */
    "roman_underlined_reversed_outline",        /* 01110 */
    "roman_underlined_reversed_outline",        /* 01111 */
    "italic",                                   /* 10000 */
    "italic",                                   /* 10001 */
    "italic_outline",                           /* 10010 */
    "italic_outline",                           /* 10011 */
    "italic_reversed",                          /* 10100 */
    "italic_reversed",                          /* 10101 */
    "italic_reversed_outline",                  /* 10110 */
    "italic_reversed_outline",                  /* 10111 */
    "italic_underlined",                        /* 11000 */
    "italic_underlined",                        /* 11001 */
    "italic_underlined_outline",                /* 11010 */
    "italic_underlined_outline",                /* 11011 */
    "italic_underlined_reversed",               /* 11100 */
    "italic_underlined_reversed",               /* 11101 */
    "italic_underlined_reversed_outline",       /* 11110 */
    "italic_underlined_reversed_outline",       /* 11111 */
};

/*----------------------IBM FND.font weigth to fs.weigth_class*/
/* This is indexed by the integer value of a one byte field */
string font_weight_class[] = {
    "unassigned",
    "ultra_light",
    "extra_light",
    "light",
    "semi_light",
    "medium",
    "semi_bold",
    "bold",
    "extra_bold",
    "ultra_bold",
};

/*------------------------IBM FND.font width to fd.width_class*/
/* This is indexed by the integer value of a one byte field */
string font_width_class[] = {
    "unassigned",
    "ultra_condensed",
    "extra_condensed",
    "condensed",
    "semi_condensed",
    "medium",
    "semi_expanded",
    "expanded",
    "extra_expanded",
    "ultra_expanded",
};

/*------------------procedure to print a font descriptor*/
int ibm_print_fd (fd)
in ibm_fd_type *fd;
{
    pval (pval_str, "ibm_id", fd->bfn_name);
    pval (pval_str, "source", fd->source);
    pval (pval_str, "ibm_fnd_family", fd->fnd_family);
    pval (pval_str, "ibm_fnd_weight_class", fd->fnd_weight_class);
    pval (pval_str, "ibm_fnd_width_class", fd->fnd_width_class);
    pval (pval_int, "ibm_fnd_vertical_size", fd->fnd_vertical_size);
#ifndef ibm3820
    pval (pval_int, "ibm_fnd_print_direction", fd->fnd_print_direction);
    pval (pval_int, "ibm_fnd_rotation", fd->fnd_rotation);
#endif
    pval (pval_str, "ibm_fnd_typeface", fd->fnd_typeface);
#ifndef ibm3820
    pval (pval_int, "ibm_fnd_underscore_width", fd->fnd_underscore_width);
    pval (pval_int, "ibm_fnd_underscore_position", fd->fnd_underscore_position);
    pval (pval_str, "ibm_fnc_spaceing", fd->fnc_spaceing);
#endif
    pval (pval_str, "ibm_fnc_box", fd->fnc_box);
    pval (pval_int, "ibm_fnc_max_x", fd->fnc_max_x);
    pval (pval_int, "ibm_fnc_max_y", fd->fnc_max_y);
    pval (pval_int, "ibm_fnc_patterns_size", fd->fnc_patterns_size);
#ifndef ibm3820
    pval (pval_int, "ibm_fnc_uniform_inline_offset", fd->fnc_uniform_inline_offset);
    pval (pval_int, "ibm_fno_x_orientation", fd->fno_x_orientation);
#endif
    pval (pval_int, "ibm_fno_y_orientation", fd->fno_y_orientation);
    pval (pval_int, "ibm_fno_uniform_baseline_offset",
        fd->fno_uniform_baseline_offset);
    pval (pval_int, "ibm_fno_uniform_character_increment",
        fd->fno_uniform_character_increment);
    pval (pval_int, "ibm_fno_variable_space_increment",
        fd->fno_variable_space_increment);
    pval (pval_int, "ibm_fno_baseline_extent", fd->fno_baseline_extent);
    pval (pval_str, "ibm_fno_fixed_width", fd->fno_fixed_width);
    pval (pval_int, "ibm_fno_em_space", fd->fno_em_space);
    pval (pval_int, "ibm_fno_figure_space", fd->fno_figure_space);
    pval (pval_int, "ibm_fno_default_baseline_increment",
        fd->fno_default_baseline_increment);
}


/*
 *  procedure pcdata: prints a character data structure
 */
int pcdata (cdata, ibm_fd)
in struct ibm_cdata *cdata;
in ibm_fd_type *ibm_fd;
{
    char box[120][120];		/* used to build the print image in */
    natural x, y;
    byte *pat_pos;
    natural row_offset;
    char *pos;
    
    
    pval (pval_str, "$", "Character defintion");
    pval (pval_str, "source", cdata->source);
    pval (pval_str, "ibm_fni_id", cdata->fni_id);
    pval (pval_int, "ibm_fni_character_increment", cdata->fni_char_inc);
    pval (pval_int, "ibm_fni_box_size_x", cdata->fni_box_size_x);
    pval (pval_int, "ibm_fni_box_size_y", cdata->fni_box_size_y);
    pval (pval_int, "ibm_fni_pattern_offset", cdata->fni_pattern_offset);
    pval (pval_int, "ibm_fni_a_space", cdata->fni_a_space);
    pval (pval_int, "ibm_fni_b_space", cdata->fni_b_space);
    pval (pval_int, "ibm_fni_c_space", cdata->fni_c_space);

    /* test for graphic pattern availability , print message and return if
       not available */
    if (cdata->fni_pattern_offset >= ibm_fd->fng_patterns_fill) {
	pval (pval_str, "ibm_fng_graphic_pattern", "Pattern not available");
	return;
    }

    pval (pval_str, "ibm_fng_graphic_pattern", "");
    /* print the graphic pattern */
    /* explode the bits */
    pat_pos = cdata->fni_pattern_offset + ibm_fd->fng_patterns;
    for (y=0; y<cdata->fni_box_size_y; y++) {
	row_offset = y*cdata->fni_box_size_x;
	for (x=0; x<cdata->fni_box_size_x; x++) {
	    box[y][x] = (bit_test (pat_pos, row_offset+x)) ? '*' : ' ';
	}
    }

    
    if (cdata->fni_box_size_y > ibm_fd->fno_uniform_baseline_offset) {
	for (x=0; x<cdata->fni_box_size_x; x++) {
	    pos = &box[ibm_fd->fno_uniform_baseline_offset][x];
	    *pos = (*pos == ' ') ? '-' : *pos;
	}
    }

    for (y=0; y<cdata->fni_box_size_y; y++) {
	printf ("%4d|", y);
	for (x=0; x<cdata->fni_box_size_x; x++) {
	    putchar (box[y][x]);
	}
	printf ("|\n");
    }

}

/*
 *  procedure short_pcdata: prints a little of a character data structure
 */
int short_pcdata (cdata, ibm_fd)
in struct ibm_cdata *cdata;
in ibm_fd_type *ibm_fd;
{
    printf ("%s\n", cdata->fni_id);
}


/*
 * procedure strip_cdata: reduces the pattern box to its minimun
 */
int strip_cdata (cdata, ibm_fd)
in struct ibm_cdata *cdata;
inout ibm_fd_type *ibm_fd;
{
    char box[120][120];			/* used to build the print image in */
    natural x, y, newx, newy;
    byte *pat_pos;
    natural row_offset, new_row_offset;
    natural left_column, right_column, top_row, bottom_row;
    natural new_row_width;
    char *pos;
    
    
    pval (pval_str, "$", "Character defintion");
    pval (pval_str, "ibm_fni_id", cdata->fni_id);
    pval (pval_int, "ibm_fni_character_increment", cdata->fni_char_inc);
    pval (pval_int, "ibm_fni_box_size_x", cdata->fni_box_size_x);
    pval (pval_int, "ibm_fni_box_size_y", cdata->fni_box_size_y);
    pval (pval_int, "ibm_fni_pattern_offset", cdata->fni_pattern_offset);
    pval (pval_int, "ibm_fni_a_space", cdata->fni_a_space);
    pval (pval_int, "ibm_fni_b_space", cdata->fni_b_space);
    pval (pval_int, "ibm_fni_c_space", cdata->fni_c_space);

    /*
     * test for graphic pattern availability , print message and return if
     * not available
     */
    if (cdata->fni_pattern_offset >= ibm_fd->fng_patterns_fill) {
	pval (pval_str, "ibm_fng_graphic_pattern", "Pattern not available");
	return;
    }

    pval (pval_str, "ibm_fng_graphic_pattern", "");
    /* print the graphic pattern */
    /* explode the bits */
    pat_pos = cdata->fni_pattern_offset + ibm_fd->fng_patterns;
    for (y=0; y<cdata->fni_box_size_y; y++) {
	row_offset = y*cdata->fni_box_size_x;
	for (x=0; x<cdata->fni_box_size_x; x++) {
	    box[y][x] = (bit_test (pat_pos, row_offset+x)) ? '*' : ' ';
	}
    }

    /* determin the bounding box */
    top_row = 0;	/* if no dots then use top row as top */
    for (y=0; y<cdata->fni_box_size_y; y++) {
	for (x=0; x<cdata->fni_box_size_x; x++) {
	    if (box[y][x] == '*') {
		top_row = y;
		goto top_found;
	    }
	}
    }
    top_found:;
    bottom_row =  0; 	/* if no dots then use top row as bottom */
    for ( y=cdata->fni_box_size_y-1; y>0; y--) {	/* no need to check
							   row 0 because it
							   is the default */
	for (x=0; x<cdata->fni_box_size_x; x++) {
	    if (box[y][x] == '*') {
		bottom_row = y;
		goto bottom_found;
	    }
	}
    }
    bottom_found:;
    if (cdata->fni_a_space>0) {
	left_column = cdata->fni_a_space;
    } else {
	left_column = 0;
    }

    if (cdata->fni_b_space <= 0) {
	right_column = 0;
    } else {
	right_column = (left_column + cdata->fni_b_space) - 1;
    }
    
    if (cdata->fni_box_size_y > ibm_fd->fno_uniform_baseline_offset) {
	for (x=0; x<cdata->fni_box_size_x; x++) {
	    pos = &box[ibm_fd->fno_uniform_baseline_offset][x];
	    *pos = (*pos == ' ') ? '-' : *pos;
	}
    }

    for (y=0; y<cdata->fni_box_size_y; y++) {
	printf ("%4d|", y);
	for (x=0; x<cdata->fni_box_size_x; x++) {
	    putchar (box[y][x]);
	}
	printf ("|\n");
    }

    /*---------------print itc fields*/
    /*-------------copy minimum bounding box */
    new_row_width = (cdata->fni_b_space/8 + 1)*8;
    for (y=top_row, newy = 0; y<=bottom_row; y++, newy++) {
	row_offset = y*cdata->fni_box_size_x;
	new_row_offset = newy*new_row_width;
	for (x=left_column, newx = 0; x<=right_column; x++, newx++) {
	    bit_set(pat_pos, new_row_offset+newx,
	         (bit_test (pat_pos, row_offset+x)) );
	}
    }
    cdata->fni_box_size_x = cdata->fni_b_space;
    cdata->fni_box_size_y = (bottom_row - top_row) + 1;
    /* explode the bits */
    for (y=0; y<cdata->fni_box_size_y; y++) {
	row_offset = y*new_row_width;
	for (x=0; x<cdata->fni_box_size_x; x++) {
	    box[y][x] = (bit_test (pat_pos, row_offset+x)) ? '*' : ' ';
	}
    }

    for (y=0; y<cdata->fni_box_size_y; y++) {
	printf ("%4d|", y);
	for (x=0; x<cdata->fni_box_size_x; x++) {
	    putchar (box[y][x]);
	}
	printf ("|\n");
    }
}

/*
 * action routines follow, each has the same parameter list as follows:
 *
 *   in natural sf_index;  the code for the SF type id
 *   in header_type *header;  a pointer to the header struc for this structured
 *     field
 *   in byte *data_start; a pointer to the first data byte, null if there
 *     is no data
 *   in byte *data_end; a pointer to the last data byte
 *   in int offset_in_file; the offset in the font where this structered field
 *      began
 */

/*
 * procedure generic print: printes the header a little of the data for any
 * structured field
 */
sf_print (sf_index, header, data_start, data_end, offset_in_file, ibm_fd)
inout ibm_fd_type *ibm_fd;
in natural sf_index;
in header_type *header;
in byte *data_start;
in byte *data_end;
in int offset_in_file;
{
    printf ("\nStructured field -%s- follows:\n",
	sf_type_names[sf_index]);
    printf ("    Offset in file is %#x\n", offset_in_file);
    printf ("    Length = %d;  data length is %d\n", header->length,
	header->length - (header_length));
    printf ("    Type id = %#x\n", header->type_id);
    printf ("    Flags = %#x\n", header->flags);
    printf ("    Sequence number = %d\n", header->sequence_num);

    if (data_start == NULL) {
	printf ("No data for this field\n");
    } else {
	printf ("The data for this field is \n");
	print_hex (stdout, data_start, data_end, offset_in_file + header_length);
    }
}

/*
 * procedure handle_NOOP: Skip over a no operation SF
 */
handle_NOOP (sf_index, header, data_start, data_end, offset_in_file, ibm_fd)
inout ibm_fd_type *ibm_fd;
in natural sf_index;
in header_type *header;
in byte *data_start;
in byte *data_end;
in int offset_in_file;
{
#ifdef debug
    fprintf (stderr, "Procedure to handle no operation called.\n");
#endif

}

/*
 *  procedure font_begin: start a new font definition
 */
font_begin (sf_index, header, data_start, data_end, offset_in_file, ibm_fd)
inout ibm_fd_type *ibm_fd;
in natural sf_index;
in header_type *header;
in byte *data_start;
in byte *data_end;
in int offset_in_file;
{


    /* initialize the current font descriptor */
    ibm_fd->bfn_name = "Not set: name";
    ibm_fd->fnd_family = "Not set: family";
    ibm_fd->fnd_typeface = "Not set: style";
    ibm_fd->fnd_weight_class = "Not set: weight class";
    ibm_fd->fnd_width_class = "Not set: width class";
    ibm_fd->fnd_vertical_size = 0;
    ibm_fd->fnd_horizontial_size = 0;
#ifndef ibm3820
    ibm_fd->fnd_print_direction = 0;
    ibm_fd->fnd_rotation = 0;
#endif

    ibm_fd->source = "(c) Copyright IBM Corporation 1984";

    /*  font definition name */
    get_name (ibm_fd->pool, data_start, data_end, 0, 8, &ibm_fd->bfn_name);
    if (strlen(ibm_fd->bfn_name) == 0) {
	ibm_fd->bfn_name = "Don't care";
    }

    /* initialize ibm_fd */
    ibm_fd->fni_c_index = NULL;
    ibm_fd->fnc_patterns_size = 0;
    ibm_fd->fng_patterns_fill = 0;
    ibm_fd->fng_patterns = NULL;

}

/*
 *  procedure handle_FND: parse a font descriptor SF
 */
handle_FND (sf_index, header, data_start, data_end, offset_in_file, ibm_fd)
inout ibm_fd_type *ibm_fd;
in natural sf_index;
in header_type *header;
in byte *data_start;
in byte *data_end;
in int offset_in_file;
{
    int temp;

    get_name (ibm_fd->pool, data_start, data_end, 0, 32, &ibm_fd->fnd_family);

    temp = get_lnatural(data_start, data_end, 32, 1);
    ibm_fd->fnd_weight_class = font_weight_class[temp];

    temp = get_lnatural(data_start, data_end, 33, 1);
    ibm_fd->fnd_width_class = font_width_class[temp];

    ibm_fd->fnd_vertical_size = get_lnatural (data_start, data_end, 36, 2);

#ifndef ibm3820
    ibm_fd->fnd_print_direction = get_lnatural (data_start, data_end, 48, 2);
    ibm_fd->fnd_rotation = get_lnatural (data_start, data_end, 54, 2);
#endif
    temp = get_lnatural (data_start, data_end, 64, 2);
    temp = temp >> 11;
    ibm_fd->fnd_typeface = fd_typeface[temp];

#ifndef ibm3820
    ibm_fd->fnd_underscore_width = get_lnatural (data_start, data_end, 69, 3);
    ibm_fd->fnd_underscore_position = get_lnatural (data_start, data_end,
        72, 2);
#endif
}

/*
 *  procedure font_position: parse a font position SF
 */
font_position (sf_index, header, data_start, data_end, offset_in_file, ibm_fd)
inout ibm_fd_type *ibm_fd;
in natural sf_index;
in header_type *header;
in byte *data_start;
in byte *data_end;
in int offset_in_file;
{
}

/*
 * procedure font_control: parse a font control SF
 */
font_control (sf_index, header, data_start, data_end, offset_in_file, ibm_fd)
inout ibm_fd_type *ibm_fd;
in natural sf_index;
in header_type *header;
in byte *data_start;
in byte *data_end;
in int offset_in_file;
{
    int temp;

    if (get_lnatural(data_start, data_end, 2, 1) != 0) {
	font_error (double_byte_font, data_start, data_end, offset_in_file);
	exit(1);
    }
    temp = get_lnatural (data_start, data_end, 3, 1);
#ifndef ibm3820
    if (temp & 0x4) {
	ibm_fd->fnc_spaceing = "kerned";
    } else {
	ibm_fd->fnc_spaceing = "fixed_width";
    }
#endif

    if (temp & 0x2) {
	ibm_fd->fnc_box = "fixed_size";
    } else {
	ibm_fd->fnc_box = "varible";
    }

    ibm_fd->fnc_max_x = get_lnatural (data_start, data_end, 10, 2) + 1;

    ibm_fd->fnc_max_y = get_lnatural (data_start, data_end, 12, 2) + 1;

    ibm_fd->fnc_patterns_size = get_lnatural (data_start, data_end, 17, 3) ;
    ibm_fd->fng_patterns = (byte *) malloc (ibm_fd->fnc_patterns_size);
    
#ifndef ibm3820
    ibm_fd->fnc_uniform_inline_offset = get_lnatural (data_start, data_end,
        20, 2);
#endif
}

/*
 * procedure font_orientation: parse a font orientation SF
 */
font_orientation (sf_index, header, data_start, data_end, offset_in_file, ibm_fd)
inout ibm_fd_type *ibm_fd;
in natural sf_index;
in header_type *header;
in byte *data_start;
in byte *data_end;
in int offset_in_file;
{
    int temp;

#ifdef ibm3820
    int i, orientation;
    
    FNO_cnt = -1;

    for (i =0; i < 4;i++) {
	orientation = get_lnatural (data_start, data_end, 2, 2);
        if (orientation != 0x0000)  {
	    data_start += 24;
	}
	else  {
            ibm_fd->fno_y_orientation = orientation;
	    FNO_cnt = i;
	    break;
	}
    }
#else
    ibm_fd->fno_x_orientation = get_lnatural (data_start, data_end, 0, 2);
    ibm_fd->fno_y_orientation = get_lnatural (data_start, data_end, 2, 2);
#endif

    ibm_fd->fno_uniform_baseline_offset = get_lnatural (data_start, data_end,
        4, 2);

    ibm_fd->fno_uniform_character_increment = get_lnatural (data_start,
        data_end, 6, 2);

    ibm_fd->fno_variable_space_increment = get_lnatural (data_start,
        data_end, 8, 2);

    ibm_fd->fno_baseline_extent = get_lnatural (data_start, data_end, 10, 2);

    temp = get_lnatural (data_start, data_end, 12, 1);
    temp = temp & 0x01;
    ibm_fd->fno_fixed_width = (temp) ? "yes" : "no"; 

    ibm_fd->fno_em_space = get_lnatural (data_start, data_end, 14, 2);

    ibm_fd->fno_figure_space = get_lnatural (data_start, data_end, 18, 2);

    ibm_fd->fno_default_baseline_increment = get_lnatural (data_start,
        data_end, 22, 2);
}

/*
 * procedure font_index: parse a font index SF
 */
font_index (sf_index, header, data_start, data_end, offset_in_file, ibm_fd)
inout ibm_fd_type *ibm_fd;
in natural sf_index;
in header_type *header;
in byte *data_start;
in byte *data_end;
in int offset_in_file;
{
    byte *pos;
    struct ibm_cdata *cdata;
#ifdef ibm3820
    int i;
    struct pattern_map *c;
#endif

    pos = data_start;
    
    ibm_fd->fni_c_index = symtab_create (250);
#ifdef ibm3820
    while (pos + 26 < data_end) {
#else
    while (pos + 22 < data_end) {
#endif
	cdata = (struct ibm_cdata *) malloc (sizeof(struct ibm_cdata));
	get_name (ibm_fd->pool, pos, data_end, 0, 8, &cdata->fni_id);

	cdata->source = "(c) Copyright IBM Corporation 1984";

	cdata->fni_char_inc = get_lnatural (pos, data_end, 8, 2);
#ifdef ibm3820
        cdata->fni_ascender = get_lnatural(pos, data_end, 10, 2);
        cdata->fni_descender = get_lnatural(pos,  data_end, 12, 2);
        i = get_lnatural (pos,  data_end,  16,  2);
	c = CurrentPatterns + i;
	cdata->fni_box_size_x = c->x_extent + 1;
	cdata->fni_box_size_y = c->y_extent + 1;
	cdata->fni_pattern_offset = c->pattern_address;
	cdata->fni_baseline_offset = get_lnatural(pos, data_end, 26, 2);
#else
	cdata->fni_box_size_x = get_lnatural (pos, data_end, 10, 2) + 1;
	cdata->fni_box_size_y = get_lnatural (pos, data_end, 12, 2) + 1;
	cdata->fni_pattern_offset = get_lnatural (pos, data_end, 14, 4) * 8;
#endif

	cdata->fni_a_space = get_lnatural (pos, data_end, 18, 2);
	if (cdata->fni_a_space & 0x8000) {
	    cdata->fni_a_space -= 0x10000;
	}

	cdata->fni_b_space = get_lnatural (pos, data_end, 20, 2);

	cdata->fni_c_space = get_lnatural (pos, data_end, 22, 2);
	if (cdata->fni_c_space & 0x8000) {
	    cdata->fni_c_space -= 0x10000;
	}
	/* The following code checks to see if the box is 0 wide,
	 * and corrects the box size. Box size is defined as zero
	 * origin, so need to know if it is REALLY zero.
	 */
	if (cdata->fni_b_space == 0) {
	  cdata->fni_box_size_x = 0;
	  cdata->fni_box_size_y = 0;
	}
	symtab_add (ibm_fd->fni_c_index, cdata->fni_id, cdata);
#ifdef DEBUG
	pcdata(cdata,ibm_fd);
#endif
#ifdef ibm3820
	pos += 28;
#else
	pos += 24;    
#endif
    }
}


font_pattern_map(sf_index, header, data_start, data_end, offset_in_file, ibm_fd)
inout ibm_fd_type *ibm_fd;
in natural sf_index;
in header_type *header;
in byte *data_start;
in byte *data_end;
in int offset_in_file;
{
    struct pattern_map *c;
    byte *pos;

    if (CurrentPatterns != NULL) free(CurrentPatterns);

    CurrentPatterns = (struct pattern_map *)
    	malloc ((data_end - data_start + 7) / 8 * sizeof(struct pattern_map));

    c = CurrentPatterns;
    pos = data_start;
    
    while (pos < data_end)  {
        c->x_extent = get_lnatural(pos, data_end, 0, 2);
	c->y_extent = get_lnatural(pos, data_end, 2, 2);
	c->pattern_address = get_lnatural(pos, data_end, 4, 4);
	c++;
	pos += 8;
    }
}

/*
 * procedure font_graphic_pattern: parse a font graphic_pattern SF
 */
font_graphic_pattern (sf_index, header, data_start, data_end, offset_in_file, ibm_fd)
inout ibm_fd_type *ibm_fd;
in natural sf_index;
in header_type *header;
in byte *data_start;
in byte *data_end;
in int offset_in_file;
{
    byte *pos;
    byte *pat_pos;
    natural space_left;
    natural new_data;
	
    space_left = (ibm_fd->fnc_patterns_size - ibm_fd->fng_patterns_fill) ;
    new_data = (data_end - data_start) + 1;
    if (new_data > space_left) {
	font_error (pattern_overrun, data_start, data_end, 0);
	data_end = (data_start + space_left) - 1;
    }

    pos = data_start;
    pat_pos = ibm_fd->fng_patterns + ibm_fd->fng_patterns_fill;
    ibm_fd->fng_patterns_fill += new_data;
    while (pos <= data_end) {
	*pat_pos++ = *pos++;
    }
}

/*
 * procedure end_font: parse a font end SF
 */
end_font (sf_index, header, data_start, data_end, offset_in_file, ibm_fd)
inout ibm_fd_type *ibm_fd;
in natural sf_index;
in header_type *header;
in byte *data_start;
in byte *data_end;
in int offset_in_file;
{
}


/*
 * procedure font_parse_ibm: parses an IBM font that begins at font and is
 * font_size long. As each structured field is parse an appropriate action
 * routine is called to handle it.
 */
int font_parse_ibm (font, font_size, ibm_fd)
byte *font;
natural font_size;
inout ibm_fd_type *ibm_fd;
{
    byte *font_pos;
    byte *font_end;
    int offset_in_file;
    byte *start_field;
    header_type header;
    byte *data_start;
    byte *data_end;

    font_pos = font;
    font_end = font + font_size; /* font_end points to the first character
				    past the end of font */
    while ((font_end - font_pos) >= header_length) {

	start_field = font_pos;
	offset_in_file = start_field - font;

	if (*font_pos++ != 0x5a) {
	    font_error (no_separator, start_field, font_end, offset_in_file);
	    exit(0);
	}

	header.length = get_lnatural (font_pos, font_end, 0, 2);

	if (get_lnatural(font_pos, font_end, 2, 1) != 0xd3) {
	    font_error (bad_code_prefix, start_field, font_end, offset_in_file);
	    exit(0);
	}

	header.type_id = get_lnatural (font_pos, font_end, 3, 2);

	header.flags = get_lnatural (font_pos, font_end, 5, 1);

	header.sequence_num = get_lnatural(font_pos, font_end, 6, 2);

	data_start = font_pos + header_length - 1;
	data_end = data_start + (header.length - header_length);
	if (data_start > data_end) {
	    data_start = NULL;
	}
	if (data_end >= font_end) {
	    font_error (bad_length, start_field, font_end, offset_in_file);
	    exit(0);
	}
	font_pos = data_end + 1;

	if (header.type_id == BCP) {
	    sf_print (BCF_index, &header, data_start, data_end,
		offset_in_file, ibm_fd);
	}
	else if (header.type_id == CPD) {
	    sf_print (CPD_index, &header, data_start, data_end,
		offset_in_file, ibm_fd);
	}
	else if (header.type_id == CPC) {
	    sf_print (CPC_index, &header, data_start, data_end,
		offset_in_file, ibm_fd);
	}
	else if (header.type_id == CPI) {
	    sf_print (CPI_index, &header, data_start, data_end,
		offset_in_file, ibm_fd);
	}
	else if (header.type_id == ECP) {
	    sf_print (ECP_index, &header, data_start, data_end,
		offset_in_file, ibm_fd);
	}
	else if (header.type_id == BFN) {
	    font_begin (BFN_index, &header, data_start, data_end,
		offset_in_file, ibm_fd);
	}
	else if (header.type_id == FND) {
	    handle_FND (FND_index, &header, data_start, data_end,
		offset_in_file, ibm_fd);
	}
	else if (header.type_id == FNP) {
	    font_position (FNP_index, &header, data_start, data_end,
		offset_in_file, ibm_fd);
	}
	else if (header.type_id == FNL) {
	    sf_print (FNL_index, &header, data_start, data_end,
		offset_in_file, ibm_fd);
	}
	else if (header.type_id == FNC) {
	    font_control (FNC_index, &header, data_start, data_end,
		offset_in_file, ibm_fd);
	}
	else if (header.type_id == FNO) {
	    font_orientation (FNO_index, &header, data_start, data_end,
		offset_in_file, ibm_fd);
	}
	else if (header.type_id == FNI) {
#ifdef ibm3820
	  if (FNI_cnt++ == FNO_cnt) 
#endif
	    font_index (FNI_index, &header, data_start, data_end,
		offset_in_file, ibm_fd);
	}
	else if (header.type_id == FNG) {
	    font_graphic_pattern (FNG_index, &header, data_start, data_end,
		offset_in_file, ibm_fd);
	}
	else if (header.type_id == FNM) {
	    font_pattern_map(FNM_index, &header, data_start, data_end, offset_in_file, ibm_fd);
	}
	else if (header.type_id == EFN) {
	    end_font (EFN_index, &header, data_start, data_end,
		offset_in_file, ibm_fd);
#ifdef ibm3820
	    FNO_cnt =0;
	    FNI_cnt =0;
#endif
	}
	else if (header.type_id == BCF) {
	    sf_print (BCF_index, &header, data_start, data_end,
		offset_in_file, ibm_fd);
	}
	else if (header.type_id == CFD) {
	    sf_print (CFD_index, &header, data_start, data_end,
		offset_in_file, ibm_fd);
	}
	else if (header.type_id == CFC) {
	    sf_print (CFC_index, &header, data_start, data_end,
		offset_in_file, ibm_fd);
	}
	else if (header.type_id == CFI) {
	    sf_print (CFI_index, &header, data_start, data_end,
		offset_in_file, ibm_fd);
	}
	else if (header.type_id == ECF) {
	    sf_print (ECF_index, &header, data_start, data_end,
		offset_in_file, ibm_fd);
	}
	else if (header.type_id == MCF) {
	    sf_print (MCF_index, &header, data_start, data_end,
		offset_in_file, ibm_fd);
	}
	else if (header.type_id == NOOP) {
	    handle_NOOP (NOOP_index, &header, data_start, data_end,
		offset_in_file, ibm_fd);
	}

	else {
	    font_error (unknown_sf_type_id, 0, 0, 0);
	    sf_print (ERR_index, &header, data_start, data_end,
		offset_in_file, ibm_fd);
	}
    }
    if (font_pos < font_end) {
	font_error (left_over_bytes, font_pos, font_end,
		offset_in_file);
	exit(0);
    }
}

