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

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

/*
 *font_tools: a collection of routines for manipulating 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 "etoa.h"
#include "symtab.h"
#include "bits.h"

string error_table[] = {
    "Reserved error code\n",
    "No separator character found\n",
    "Code prefix is not 0xd3\n",
    "Length goes beyond the end of the file\n",
    "There were bytes left over\n",
    "Unknown structured field type identifier\n",
    "Length too long in call to Get_????\n",
    "This is a double byte font and it is not supported\n",
    "There is more pattern data than is specified for type_id = FNC\n",
};

/*
 * procedure print_hex: prints a section of memory in hex
 */
print_hex (outfile, start_pos, end_pos, offset)
in FILE *outfile;
in byte *start_pos;
in byte *end_pos;
in int offset;
{
    byte *pos;
    int i;
    int j;

    fprintf (outfile, 
	"Hex dump: start = %#x, end = %#x, offset in data object = %#x\n",
	start_pos, end_pos, offset);
    pos = start_pos;

    while (pos <= end_pos) {
	fprintf (outfile, "%08x  %08x  ", offset, pos);
	for (j=0; j<4; j++) {
	    for (i=0; (i<4) && (pos <= end_pos); i++) {
		fprintf (outfile, "%02x ", *pos++);
	    }
	    fprintf (outfile, " ");
	}
	fprintf (outfile, "\n");
	offset = offset + 16;
    }
}


/*
 * procedure font_error: prints a error message and dump 16 bytes from
 * position of the font.  end_position is the last byte that may be printed
 * and offset_in_file is a integer offset equivalent to position.
 */
font_error (error_num, position, end_position, offset_in_file)
int error_num;
byte *position;
byte *end_position;
int offset_in_file;
{
    int count;

    fprintf (stderr, "\nError in font file: ");
    if (error_num >= MIN_ERROR_NUM && error_num <= MAX_ERROR_NUM) {
	fprintf (stderr, "%s", error_table[error_num]);
    } else {
	fprintf (stderr, "UNKNOWN ERROR NUMBER -- %d\n", error_num);
    }
    if (position != 0) {
	count = end_position - position;
	count = (count > 63) ? 63 : count;
	end_position = position + count;

	fprintf (stderr, "%d bytes of the file follow starting at offset %#x\n",
	    count + 1, offset_in_file);
	print_hex (stderr, position, end_position, offset_in_file);
	fprintf (stderr, "\n");
    }
}

/*
 * function get_lnatural: coverts a series of bytes in a data area to a
 * lnatural (unsigned long int) and returns the value.  An error msg will
 * be issued if an attemp to pass the end of the data area is made and 0
 * returned.
 */
lnatural get_lnatural (data_start, data_end, offset, count)
in byte *data_start;		/* start of the data area */
in byte *data_end;		/* last byte in the data area */
in natural offset;		/* data_start + offset is first byte of num */
in natural count;		/* length in bytes of number */
{
    lnatural number;
    byte *pos;

    number = 0;
    pos = data_start + offset;
    if (pos + count > data_end + 1) {
	font_error (data_overrun, pos, data_end, 0);
	return (number);
    }

    for (; count > 0; count--) {
	number = (number * 256) + *pos++;
    }
    return (number);
}

/*
 * procedure get_name: copies bytes in a data area to a string.	An error msg
 * produced if an atempt is made to pass the end of
 * the data area and the string returned will be truncated.
 */
int get_name (pool, data_start, data_end, offset, len, name)
inout char *pool;		/* palloc pool */
in byte *data_start;		/* start of the data area */
in byte *data_end;		/* last byte in the data area */
in natural offset;		/* data_start + offset is first byte of num */
in natural len; 		/* The number of characters to be returned */
out string *name;		/* A null terminated string will be returned
				   if there is no data (i.e., len=0 or 
				   data_start=NULL or data starts with 
				   0xffff) then the string will be NULL */
{
    byte *pos;
    string new_name;

    if (data_start != NULL) {
        pos = data_start + offset;
	if (pos + len > data_end + 1) {
	    font_error (data_overrun, pos, data_end, 0);
	    len = (data_end - pos)+1;
	}
	if ( (len == 0) || (len == 1 && *pos == 0xff) ||
	     (*pos == 0xff && *(pos+1) == 0xff) ) 
	    *name = "";
	else 
	{
	    new_name = (string) malloc (len+1);
	    *name = new_name;

	    data_end = pos + len;
	    while (pos < data_end) {
		*new_name++ = etoa_trans[*pos++];
	    }
/* (ef) 7/24/86 -- strings should be NUL terminated */
	    *new_name= '\0';
	}
    } else {
	*name = "";
    }
    return (0);
}

/*
 * procedure pval: prints a field value
 */
int pval (pval_type, fname, value, cname)
in natural pval_type;			/* the kind of value to print */
in string fname;			/* the field name */
in string value;			/* the field value, it type depends on
					   pval_type */
in string cname;			/* only present when this is a code
					   type value, then this is the code
					   symbolic value or when pval_type is
					   a pair then this is the second
					   value */
{
    char tstring[20];			/* tempory string buffer */
    char tstring2[20];
    

    if (pval_type == pval_int || pval_type == pval_code) {
	sprintf (tstring, "%d", (int) value);
	value = (string) tstring;
    } else if (pval_type == pval_pair) {
	sprintf (tstring, "%d", (int) value);
	value = (string) tstring;
	sprintf (tstring2, "%d", (int) cname);
	cname = (string) tstring2;
    }
	
    if (pval_type == pval_code) {
	printf ("$%s %s %s\n", fname, value, cname);
    } else if (pval_type == pval_pair) {
	printf ("$%s %s,%s\n", fname, value, cname);
    } else {
	printf ("$%s %s\n", fname, value);
    }
}

