/*
 * $Copyright:	$
 * Copyright (c) 1984, 1985, 1986, 1987, 1988, 1989, 1990 
 * Sequent Computer Systems, Inc.   All rights reserved.
 *  
 * This software is furnished under a license and may be used
 * only in accordance with the terms of that license and with the
 * inclusion of the above copyright notice.   This software may not
 * be provided or otherwise made available to, or used by, any
 * other person.  No title to or ownership of the software is
 * hereby transferred."
 *
 */
/*	Copyright (c) 1984 AT&T	*/
/*	  All Rights Reserved  	*/

/*	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T	*/
/*	The copyright notice above does not evidence any   	*/
/*	actual or intended publication of such source code.	*/

#ident	"$Header: makei10.c 1.2 89/10/10 $@(#)roff:troff.d/devi10/makei10.c	2.3"

#include	<stdio.h>
#include	"dev.h"


#define	NON_FATAL	0
#define	FATAL		1
#define	NO			0
#define	YES			1

#define	FNAME		4					/* longest allowed font name - at least 3 */
#define	DNAME		11					/* longest accepted device name */
#define	CLENGTH		2					/* max length of special char strings */
#define	FONTDIR		50					/* max length of *fontdir string */
#define	LINE_LENGTH	100					/* longest line in ASCII tables */
#define	MAXWIDTH	255					/* maximum number of width entries */
#define	MAXSYNS		75					/* no more synonyms than this */
#define	MAXBUILD	75					/* largest 'build' list */
#define	MAXFONTS	50					/* can map this many fonts */
#define	NFONT		4					/* search at most this many fonts */
#define	BMASK		0377				/* mask for lower eight bits */

#define	FONTSIZE	3 * MAXWIDTH + nchtab + (128 - 32) + sizeof(struct Font)
#define	PATHLENGTH	FONTDIR + 2 * DNAME + FNAME + 5
#define	TARGDIR		FONTDIR + DNAME + 5



char	mdev[DNAME+1] = "";				/* raster tbls assume this device */
char	tdev[DNAME+1] = "i10";			/* target typesetter - Imagen */
char	*ndev;							/* make ASCII tables for this device */

struct dev	dev;						/* *mdev DESC.out header goes here */
struct Font	*fontbase[NFONT];			/* each font's .out header stuff */

int		nchtab;							/* number of special chars in chtab */
short	*pstab;							/* point size table - not needed */
short	*chtab;							/* char's index in chname array */
char	*chname;						/* special character strings */
char	*fontstart;						/* can load fonts starting here */
char	*widthtab[NFONT];				/* font's width table - not needed */
char	*codetab[NFONT];				/* *mdev's codes for characters */
char	*fitab[NFONT];					/* position of characters on a font */

char	mapped[MAXFONTS][FNAME+1];		/* mapped these fonts - ASCII names */
char	fmap[NFONT+1][FNAME+1];			/* names of *mdev's fonts that we search */
char	new[MAXSYNS][CLENGTH+1];		/* synonym for corresponding char in old[][] */
char	old[MAXSYNS][CLENGTH+1];		/* old character name */
char	bldlist[MAXBUILD+1][CLENGTH+1];	/* these chars will be built up */

int		mapcount;						/* mapped this many of *ndev's fonts */
int		syncount = 0;					/* number of synonyms in *fontmap */
int		bldcount = 0;					/* number of build chars in *fontmap */
int		fcount;							/* number of original default fonts */
int		acount = 0;						/* add this many fonts to default */
int		iname;							/* internal name for 'related' fonts */
int		nfonts;							/* number of *mdev's fonts to check */
int		fsize;							/* all fonts given this much room */

char	*fontdir = "..";				/* troff's font directory */
char	*srcdir = "..";					/* ASCII font files kept here */
char	targdir[TARGDIR] = "rasti10";			/* target device's raster directory */
char	*rastdev = "RASTERDEV";			/* device name is in this file */
char	*fontmap = "FONTMAP";			/* font map file for device *ndev */

char	addfont[(NFONT-1)*MAXFONTS*(FNAME+1)] = "";	/* additional default fonts */

char	path[PATHLENGTH];				/* build file pathnames up here */

FILE	*descin;						/* *ndev's real ASCII DESC file */
FILE	*descout;						/* new ASCII DESC file for *ndev */
FILE	*fontin;						/* read font data from this ASCII file */
FILE	*fontout[NFONT+1];				/* ASCII output files for this font */
FILE	*fp_map;						/* file pointer for *fontmap file */
FILE	*fp_error = stderr;				/* error messages */

char	**argv;							/* so everyone can use them */
int		argc;

int		silent = NO;



/*****************************************************************************/


main(agc, agv)


	int		agc;
	char	*agv[];


{


	/********************************************************************
	 *																	*
	 *		This program takes troff's ASCII font and device tables for	*
	 *	one or more typesetters and converts them into a form that can	*
	 *	be used with the raster tables located in the target device's	*
	 *	font directory. These new tables are written into appropriate	*
	 *	'dev' directories located in the *targdir directory.			*
	 *																	*
	 *		The program expects to find a file called RASTERDEV in		*
	 *	*targdir. The first string in this file is the name of the		*
	 *	device whose tables were used to make the raster files - the	*
	 *	rest of the file is skipped. In addition each new device must	*
	 *	have an appropriate 'dev' directory in *targdir, and each of	*
	 *	these directories must contain a file called FONTMAP, that		*
	 *	tells the program how to map *ndev's fonts.						*
	 *																	*
	 *		After the command line options are processed, the name of	*
	 *	the master device is read from the file *rastdev, provided the	*
	 *	string *mdev hasn't already been set. Then this device name is	*
	 *	used, in combination with *fontdir, to locate *mdev's binary	*
	 *	'.out' tables. Routine getdesc() reads the entire DESC.out		*
	 *	into memory, and then alloctes enough additional memory to hold	*
	 *	NFONT binary font files. Once this initialization stuff is done	*
	 *	the program enters a loop that treats the rest of the command	*
	 *	line arguments as device names. Each of these devices will have	*
	 *	a new set of ASCII font tables written out to the appropriate	*
	 *	'dev' directory in *targdir.									*
	 *																	*
	 *		The first step for each new device is to essentially copy	*
	 *	the first part of its real ASCII DESC file from *fontdir to the	*
	 *	appropriate 'dev' directory in *targdir. Routine startdesc()	*
	 *	handles this job, but it only reads up to the default font		*
	 *	count in the real DESC file. Once it has the default font count	*
	 *	startdesc() has really finished its job. It doesn't even write	*
	 *	this number out to the new DESC file, because we are probably	*
	 *	going to be adding some default fonts to the new DESC file.		*
	 *																	*
	 ********************************************************************/


	argv = agv;							/* global so everyone can use them */
	argc = agc;

	getoptions();
	getmdev();							/* get 'master' device name */
	getdesc();							/* get *mdev's DESC.out file */

	if ( silent == NO )
		printf("master device = %s\n\n", mdev);

	while ( --argc > 0 )  {				/* got another device */
		ndev = *++argv;					/* make tables for this guy */
		if ( silent == NO )
			printf("making tables for device %s\n", ndev);
		startdesc();					/* up to default font list */
		makefonts();					/* for all fonts listed in FONTMAP */
		finishdesc();					/* complete *ndev's new DESC file */
	}	/* End while */

}	/* End of main */


/*****************************************************************************/


getoptions()


{


	/********************************************************************
	 *																	*
	 *		Called from the main program to handle the command line		*
	 *	options.														*
	 *																	*
	 ********************************************************************/


	while ( argc > 1  &&  argv[1][0] == '-' )  {

		switch ( argv[1][1] )  {

			case 's':
						silent = YES;
						break;

			case 'm':
						strcpy(mdev, &argv[1][2]);
						if ( strlen(mdev) > DNAME )
							error(FATAL, "device name %s too long", mdev);
						break;

			case 'F':
						fontdir = &argv[1][2];
						break;

			case 'S':
						srcdir = &argv[1][2];
						break;

			default:
						error(NON_FATAL, "illegal option %c", argv[1][1]);
						break;

		}	/* End switch */

		argv++;
		argc--;

	}	/* End while */

}	/* End of getoptions */


/*****************************************************************************/


getmdev()


{


	FILE	*fd;						/* used for *rastdev file */


	/********************************************************************
	 *																	*
	 *		Called from the main program to get the name of the device	*
	 *	that was used to make the raster tables for the target device.	*
	 *	If the string *mdev has already been set, possibly by an		*
	 *	option, nothing is done. Otherwise we expect to find the name	*
	 *	as the first string in the file *targdir/*rastdev.				*
	 *																	*
	 ********************************************************************/


	if ( *mdev != '\0' )  return;		/* got the name somewhere else */

	sprintf(path, "%s/%s", targdir, rastdev);
	if ( (fd = fopen(path, "r")) == NULL )
		error(FATAL, "can't open file %s", path);

	if ( fscanf(fd, "%14s", mdev) != 1 )
		error(FATAL, "no device name in file %s", rastdev);

	if ( strlen(mdev) > DNAME )
		error(FATAL, "master device name %s too long", mdev);

	fclose(fd);							/* won't need this file again */

}	/* End of getmdev */


/*****************************************************************************/


getdesc()


{


	int		fin;						/* DESC.out's file descriptor */
	char	*filebase;					/* memory block for DESC.out file */
	char	*malloc();					/* memory allocation routine */


	/********************************************************************
	 *																	*
	 *		Called from the main program to read in the DESC.out file	*
	 *	for typesetter *mdev. Even though we only will use a small part	*
	 *	of this file, the whole thing is read into memory. I also		*
	 *	decided not to use the font space that is already allocated in	*
	 *	the DESC.out file. If you want to use this space just change	*
	 *	the initialization of fontstart.								*
	 *																	*
	 ********************************************************************/


	sprintf(path, "%s/dev%s/DESC.out", fontdir, mdev);
	if ( (fin = open(path, 0)) < 0 )
		error(FATAL, "can't open file %s", path);

	read(fin, &dev, sizeof(struct dev));	/* struct dev comes first */

	nchtab = dev.nchtab;					/* FONTSIZE needs this number */
	fsize = FONTSIZE;						/* space given to each font */

	if ( (filebase = malloc(dev.filesize)) == NULL )
		error(FATAL, "no memory available");

	read(fin, filebase, dev.filesize);		/* get rest of the DESC.out file */
	pstab = (short *) filebase;				/* this table is never used */
	chtab = pstab + dev.nsizes + 1;
	chname = (char *) (chtab + dev.nchtab);

	if ( (fontstart = malloc(NFONT * fsize)) == NULL )
		error(FATAL, "no memory available");

	close(fin);								/* won't need this guy again */

}	/* End of getdesc */


/*****************************************************************************/


startdesc()


{


	char	cmd[LINE_LENGTH];			/* DESC file commands go here */
	int		c;							/* used as a character */


	/********************************************************************
	 *																	*
	 *		Called from main() to begin making *ndev's ASCII DESC file.	*
	 *	The real DESC file is read up to the default font list. Later	*
	 *	routine finishdesc() is called to complete the new DESC file.	*
	 *	I did things this way because we need to know the original		*
	 *	number of default fonts for device *ndev before we make the		*
	 *	new font tables, and we can't write the default font list out	*
	 *	to the new DESC file until we have built all the new font		*
	 *	tables for *ndev.												*
	 *																	*
	 *		Since I have claimed dev.spare2 in routine finishdesc() we	*
	 *	should probably check if the command we just read was 'spare2'.	*
	 *	I'll take care of this later on.								*
	 *																	*
	 ********************************************************************/


	sprintf(path, "%s/dev%s/DESC", srcdir, ndev);
	if ( (descin = fopen(path, "r")) == NULL )
		error(FATAL, "can't open file %s", path);

	sprintf(path, "%s/dev%s/DESC", targdir, ndev);
	if ( (descout = fopen(path, "w")) == NULL )
		error(FATAL, "can't write file %s", path);

	while ( fscanf(descin, "%s", cmd) != EOF )  {
		fprintf(descout, "%s", cmd);
		if ( strcmp(cmd, "fonts") == 0 )  {
			fscanf(descin, "%s", cmd);
			fcount = atoi(cmd);
			return;
		} else if ( strcmp(cmd, "charset") == 0 )
			error(FATAL, "bad DESC file format");
		else while ( putc(c=getc(descin), descout) != '\n'  &&  c != EOF ) ;
	}	/* End while */

	error(FATAL, "bad DESC file");		/* shouldn't get here! */

}	/* End of startdesc */


/*****************************************************************************/


finishdesc()


{


	char	fname[FNAME+1];				/* names of the default fonts */
	int		i, j;						/* for loop indices */
	int		c;							/* used as a char with getc() */


	/********************************************************************
	 *																	*
	 *		Called from the main program after all the fonts for *ndev	*
	 *	have been mapped. Routine startdesc() read *descin up to the	*
	 *	first default font name, and it wrote *descout up to the count	*
	 *	part of the default font list. Most likely we will now have		*
	 *	more default fonts than we started with, so dev.spare2 can be	*
	 *	used by post-processors to get at the original number.			*
	 *																	*
	 ********************************************************************/


	fprintf(descout, " %d", fcount + acount);	/* new default font count */

	for ( i = 0; i < fcount; i++ )  {			/* check each default font */
		fscanf(descin, "%s", fname);
		fprintf(descout, " %s", fname);
		for ( j = 0; j < mapcount; j++ )		/* did we map this font? */
			if ( strcmp(fname, &mapped[j][0]) == 0 )
				break;
		if ( j >= mapcount )					/* didn't find it */
			error(NON_FATAL, "missing default font file %s", fname);
	}	/* End for */

	fprintf(descout, "%s", addfont);			/* finish the default font list */
	fprintf(descout, "\nspare2 %d", fcount);	/* post-processor can use it */

	while ( (c = getc(descin)) != EOF ) putc(c, descout);

	fclose(descin);								/* may have more devices */
	fclose(descout);

}	/* End of finishdesc */


/*****************************************************************************/


makefonts()


{


	char	cmd[LINE_LENGTH];			/* font file commands go here */
	int		c;							/* used as a character */
	int		i;							/* for loop index */


	/********************************************************************
	 *																	*
	 *		Called from main() to make all the ASCII font files listed	*
	 *	in *ndev's FONTMAP file. All the stuff up to the charset part	*
	 *	of each ASCII font file is essentially copied into the new		*
	 *	font file. The name field is changed to the name of the second	*
	 *	font from appropriate lines in the FONTMAP file. All 'related'	*
	 *	fonts are given the same internal number. The lower eight bits	*
	 *	of this number contains the font position where post-processors	*
	 *	can expect to find related fonts to search if a character is	*
	 *	not found on the primary font. This additional search should be	*
	 *	done before checking the special fonts. The ligature stuff is	*
	 *	not really needed - leave it in for now.						*
	 *																	*
	 ********************************************************************/


	mapcount = 0;						/* fonts mapped so far for *ndev */

	sprintf(path, "%s/dev%s/%s", targdir, ndev, fontmap);
	if ( (fp_map = fopen(path, "r")) == NULL )
		error(FATAL, "can't open file %s", path);

	while ( readmap() != 0 )  {			/* not done with FONTMAP file yet */

		if ( silent == NO )
			printf("font %s\n", &mapped[mapcount][0]);

		for ( i = 1; i < NFONT + 1; i++ )
			fontout[i] = NULL;

		sprintf(path, "%s/dev%s/%s", srcdir, ndev, &mapped[mapcount][0]);
		if ( (fontin = fopen(path, "r")) == NULL )
			error(FATAL, "can't open file %s", path);

		sprintf(path, "%s/dev%s/%s", targdir, ndev, &mapped[mapcount][0]);
		if ( (fontout[0] = fopen(path, "w")) == NULL )
			error(FATAL, "can't open file %s", path);

		for ( i = 0; i < nfonts; i++ )		/* get the '.out' font files */
			loadfont(&fmap[i][0], i);

		iname = (mapcount * (BMASK + 1)) + fcount + acount + 1;

		while ( fscanf(fontin, "%s", cmd) == 1)  {
			fprintf(fontout[0], "%s", cmd);
			if ( strcmp(cmd, "name") == 0 )  {
				 fprintf(fontout[0], " %s\n", &fmap[0][0]);
				 while ( (c = getc(fontin)) != '\n'  &&  c != EOF ) ;
			} else if ( strcmp(cmd, "internalname") == 0 )  {
				 fprintf(fontout[0], " %d\n", iname);
				 while ( (c = getc(fontin)) != '\n'  &&  c != EOF ) ;
			} else if ( strcmp(cmd, "ligatures") == 0 )  {
				 get_ligs();
				 while ( (c = getc(fontin)) != '\n'  &&  c != EOF ) ;
			} else if ( strcmp(cmd, "charset") == 0 )
				 copy_chars();
			else while ( putc(c=getc(fontin), fontout[0]) != '\n' && c != EOF ) ;
		}	/* End while */

		mapcount++;						/* finished mapping this font */

		fclose(fontin);
		for ( i = 0; i < NFONT + 1; i++ )
			if ( fontout[i] != NULL )
				fclose(fontout[i]);

	}	/* End while */

	fclose(fp_map);

}	/* End of makefonts */


/*****************************************************************************/


readmap()


{


	char	buff[20];
	int		c;							/* used as a character */


	/********************************************************************
	 *																	*
	 *		This routine continues reading the FONTMAP file until it	*
	 *	has processed the next font mapping instruction. Any 'build'	*
	 *	lists that are encountered replace the last list, and will		*
	 *	therefore apply to the next font map. The first font mentioned	*
	 *	in a font map line is the name of the primary font for the		*
	 *	current mapping instruction. This is *ndev's ASCII font file	*
	 *	that we will be reading and usually writing. The rest of the	*
	 *	fonts following the 'into' are the names of *mdev's fonts that	*
	 *	are searched when we do the character lookups. These searches	*
	 *	are done using the '.out' font files, which are read in from	*
	 *	*mdev's normal font directory.									*
	 *																	*
	 ********************************************************************/


	if ( mapcount >= MAXFONTS )
		error(FATAL, "too many fonts in %s file", fontmap);

	while ( fscanf(fp_map, "%19s", buff) == 1 )  {
		if ( strcmp(buff, "synonyms") == 0 )
			readsyns();
		else if ( strcmp(buff, "build") == 0 )
			readbuild();
		else if ( strcmp(buff, "nobuild") == 0 )
			bldcount = 0;
		else if ( strcmp(buff, "map") == 0 )
			return(readfonts());
		else if ( buff[0] = '#' )
			while ( (c = getc(fp_map)) != '\n'  &&  c != EOF ) ;
		else error(FATAL, "don't know command %s", buff);
	}	/* End while */

	return(0);

}	/* End of readmap */


/*****************************************************************************/


readfonts()


{


	int		c;							/* character used with getc() */


	/********************************************************************
	 *																	*
	 *		Called from readmap() to read the next font map line for	*
	 *	device *ndev from the file *fp_map.								*
	 *																	*
	 ********************************************************************/


	nfonts = 0;

	if ( fscanf(fp_map, "%s into", &mapped[mapcount][0]) != 1 )
		error(FATAL, "map file synatx error");

	if ( FNAME < 3 )					/* we may have trouble later on */
		error(FATAL, "constant FNAME less than 3");

	if ( strlen(&mapped[mapcount][0]) > FNAME )
		error(FATAL, "font name %s too long", &mapped[mapcount][0]);

	while ( nfonts < NFONT )  {
		while ( (c = getc(fp_map)) == ' '  ||  c == '\t') ;
		if ( c == '\n'  ||  c == EOF )
			break;
		ungetc(c, fp_map);
		fscanf(fp_map, "%s", &fmap[nfonts][0]);
		if ( strlen(&fmap[nfonts++][0]) > FNAME )
			error(FATAL, "font name %s too long", &fmap[nfonts-1][0]);
	}	/* End while */

	if ( nfonts >= NFONT )
		while ( (c = getc(fp_map)) != '\n'  &&  c != EOF ) ;

	strcpy(&fmap[nfonts][0], "bld");

	return(nfonts);

}	/* End of readfonts */


/*****************************************************************************/


readbuild()


{


	/********************************************************************
	 *																	*
	 *		Called from readmap() to read a 'build' list from *fontmap.	*
	 *	This list consists of those characters that will be built up	*
	 *	by the post-processor. They will be written out to a special	*
	 *	font file named *fmap[0].bld with a character code of 0. The	*
	 *	list is terminated by the string "end".							*
	 *																	*
	 ********************************************************************/


	bldcount = 0;						/* throw the last copy list out */

	while ( bldcount < MAXBUILD )  {
		if ( fscanf(fp_map, "%s", &bldlist[bldcount][0]) != 1 )
			error(FATAL, "bad build list format");

		if ( strcmp(&bldlist[bldcount][0], "end") == 0 )
			return;

		if ( strlen(&bldlist[bldcount][0]) > CLENGTH )
			error(FATAL, "copy name %s too long", &bldlist[bldcount][0]);

		bldcount++;
	}	/* End while */

	error(FATAL, "too many build characters");

}	/* End of readbuild */


/*****************************************************************************/


readsyns()


{


	/********************************************************************
	 *																	*
	 *		Called from readmap() to read a synonym list from the		*
	 *	*fontmap. The list is terminated by any pair of identical		*
	 *	character strings whose length is no more than CLENGTH.			*
	 *	This synonym stuff is probably not needed. It was added to the	*
	 *	program early on.												*
	 *																	*
	 ********************************************************************/


	syncount = 0;						/* throw the last list out */

	while ( syncount < MAXSYNS )  {
		if ( fscanf(fp_map, "%s %s", &new[syncount][0], &old[syncount][0]) != 2 )
			error(FATAL, "bad synonym list format");

		if ( strlen(&new[syncount][0]) > CLENGTH )
			error(FATAL, "synonym name %s too long", &new[syncount][0]);

		if ( strlen(&old[syncount][0]) > CLENGTH )
			error(FATAL, "synonym name %s too long", &old[syncount][0]);

		if ( strcmp(&new[syncount][0], &old[syncount][0]) == 0 )
			return;

		syncount++;						/* its a real synonym */
	}	/* End while */

	error(FATAL, "too many synonyms");

}	/* End of readsyns */


/*****************************************************************************/


get_ligs()


{


	char	lig;


	/********************************************************************
	 *																	*
	 *		Called from makefonts() to build up an appropriate ligature	*
	 *	list for the current font. This routine should not be needed	*
	 *	because the new tables will probably only be used by post-		*
	 *	processors, and they usually won't look at the font.ligfont		*
	 *	field. It is the right way to do things, so I decided to leave	*
	 *	the routine in for now - just in case.							*
	 *																	*
	 ********************************************************************/


	lig = fontbase[0]->ligfont;

	if ( lig & LFI )
		fprintf(fontout[0], " fi");
	if ( lig & LFL )
		fprintf(fontout[0], " fl");
	if ( lig & LFF )
		fprintf(fontout[0], " ff");
	if ( lig & LFFI )
		fprintf(fontout[0], " ffi");
	if ( lig & LFFL )
		fprintf(fontout[0], " ffl");

	fprintf(fontout[0], " 0\n");

}	/* End of get_ligs */


/*****************************************************************************/


copy_chars()


{


	char	ch[10];						/* standard stuff from makedev */
	char	width[10];
	char	kern[10];
	char	code[10];
	char	nch[10];					/* look this char up - synonym */
	char	buff[LINE_LENGTH];			/* next line from charset part */
	int		index;						/* found character on this font */
	int		i;							/* for loop index */


	/********************************************************************
	 *																	*
	 *		Called from makefonts() to copy the charset portion of the	*
	 *	current font file to the appropriate place in the *tdev			*
	 *	directory.														*
	 *																	*
	 ********************************************************************/


	index = -1;							/* needed because of synonyms */
	putc('\n', fontout[0]);				/* comes after 'charset' command */

	while ( fgets(buff, sizeof(buff), fontin) != NULL )  {

		if ( sscanf(buff, "%s %s %s %s", ch, width, kern, code) < 2 )
			continue;

		if ( width[0] == '"' )  {
			if ( index >= 0 )
				fprintf(fontout[index], "%s\t%s\n", ch, width);
			continue;
		}	/* End if */

		strcpy(nch, ch);
		for ( i = 0; i < syncount; i++ )
			if ( strcmp(ch, &old[i][0]) == 0 )  {
				strcpy(nch, &new[i][0]);
				break;
			}	/* End if */

		if ( (index = lookup(code, nch)) < 0 )  {
			if ( silent == NO )
				printf("  char %s not found\n", ch);
			continue;
		} else if ( fontout[index] == NULL )
			startfont(index);

		fprintf(fontout[index], "%s\t%s\t%s\t%s\n", ch, width, kern, code);

	}	/* End while */

}	/* End of copy_chars */


/*****************************************************************************/


startfont(index)


	int		index;						/* font's name is in fmap[index] */


{


	char	*nfont[2*FNAME+1];			/* name of the new font */


	/********************************************************************
	 *																	*
	 *		When this routine is called, we have found a character		*
	 *	from font mapped[mapcount] on fmap[index]. It is the first		*
	 *	time we needed this font so we have to create a new font file	*
	 *	with all the appropriate header stuff. This routine will never	*
	 *	be called with index equal to 0, since when a character is		*
	 *	found on fmap[0] it is written to *ndev's new ASCII font file	*
	 *	called mapped[mapcount][0]. This string is set in readfonts()	*
	 *	to the name of the first font in the current 'map' line in file	*
	 *	*fp_map, and the appropriate ASCII output file has already been	*
	 *	opened for writing in routine makefonts().						*
	 *																	*
	 ********************************************************************/


	strcat(strcat(strcpy(nfont, &mapped[mapcount][0]), "."), &fmap[index][0]);

	sprintf(path, "%s/dev%s/%s", targdir, ndev, nfont);
	if ( (fontout[index] = fopen(path, "w")) == NULL )
		error(FATAL, "can't write file %s", path);

	fprintf(fontout[index], "name %s\n", index != nfonts ? &fmap[index][0] : &fmap[0][0]);
	fprintf(fontout[index], "internalname %d\n", iname);
	fprintf(fontout[index], "charset\n");

	acount++;
	strcat(strcat(addfont, " "), nfont);	/* will be a default font */

}	/* End of startfont */


/*****************************************************************************/


lookup(code, ch)


	char	*code;						/* use this device code */
	char	*ch;						/* for this character */


{


	int		buildit;					/* did we find it in the build list? */
	int		c;							/* ch's index */
	int		j;							/* found on this font */
	int		i;							/* chars index on font j */


	/********************************************************************
	 *																	*
	 *		Called from copy_chars() to lookup the device code for the	*
	 *	character ch. If *ch isn't found we return -1, otherwise we		*
	 *	return the font's index where *ch was found.					*
	 *																	*
	 ********************************************************************/


	buildit = 0;							/* not in the build list */
	for ( i = 0; i < bldcount; i++ )		/* check the build list */
		if ( strcmp(ch, &bldlist[i][0]) == 0 )  {
			strcpy(code, "0");
			buildit = 1;
		}	/* End if */

	if ( ch[1] == '\0' )				/* ASCII character */
		c = ch[0];
	else  {								/* special troff character string */
		 for ( c = 0; c < nchtab; c++ )
			if ( strcmp(&chname[chtab[c]], ch) == 0 )
				break;
		 if ( c >= nchtab )
			return(buildit == 0 ? -1 : nfonts);
		c += 128;						/* special chars start at 128 */
	}	/* End if */

	c -= 32;							/* forget non-graphic characters */
	j = 0;

	while ( j < nfonts  &&  (i = fitab[j][c] & BMASK) == 0 )
		j++;

	if ( j >= nfonts  ||  i == 0 )		/* didn't find it on any font */
		return(buildit == 0 ? -1 : nfonts);

	sprintf(code, "%d", codetab[j][i] & BMASK);
	return(j);

}	/* End of lookup */


/*****************************************************************************/


loadfont(str, pos)


	char	*str;						/* name of the font to load */
	int		pos;						/* read font data into this position */


{


	char	*fontpos;					/* this font's position */
	int		fin;						/* font's .out file descriptor */
	int		nw;							/* number of width entries for font */


	/********************************************************************
	 *																	*
	 *		Called from makefonts() to load the .out file for font *str	*
	 *	from the 'master' device's real font directory.					*
	 *																	*
	 ********************************************************************/


	sprintf(path, "%s/dev%s/%s.out", fontdir, mdev, str);
	if ( (fin = open(path, 0)) < 0 )
		error(FATAL, "can't open file %s", path);

	fontpos = fontstart + (fsize * pos);
	read(fin, fontpos, fsize);

	fontbase[pos] = (struct Font *) fontpos;
	nw = fontbase[pos]->nwfont & BMASK;

	widthtab[pos] = (char *) fontpos + sizeof(struct Font);
	codetab[pos] = (char *) widthtab[pos] + 2 * nw;
	fitab[pos] = (char *) widthtab[pos] + 3 * nw;

	close(fin);

}	/* End of loadfont */


/*****************************************************************************/


error(kind, str, a1, a2)


	int			kind;
	char		*str;
	unsigned	a1, a2;


{


	/********************************************************************
	 *																	*
	 *		Print the error message *str, and quit if the error was		*
	 *	FATAL.															*
	 *																	*
	 ********************************************************************/


	fprintf(fp_error, "make%s: ", tdev);

	if ( kind == NON_FATAL )
		fprintf(fp_error, "warning - ");

	fprintf(fp_error, str, a1);
	putc('\n', fp_error);

	if ( kind == FATAL )
		exit(1);

}	/* End of error */


/*****************************************************************************/
