/*
 * Program to produce an .afm file for composit characters.
 *
 * Author:
 * 	Per Lindqvist
 *	pgd@compuram.bbt.se
 */
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <math.h>
#include <ctype.h>
#include <memory.h>

#include "parseAFM.h"

#define	max(A, B)	(A > B ? A : B)
#define	min(A, B)	(A < B ? A : B)

FILE *ifp, *ofp;
FontInfo *gfi;

int i_width;				/* Width of an i */
int i_llx;				/* left side bearing of i */
int xheight;				/* x-height */
int Xheight;				/* X-height */
int italicangle;			/* italic angle */
double sinfi, cosfi;

CharMetricInfo *findmetric ( char *nm );
void makesingleaccent ( char *basename , char *accentname );
void addkernpair ( char *name1 , char *name2 , int xamt , int yamt );
void outafm ( void );
void addcomposite(char *name, int no, char *args, ...);
void addmetrics(int code, int wx, int wy, char *name, int llx, int lly, int urx, int ury);
CompCharData *findcomp(char *nm);
int pkcomp(), cicomp(), cccomp();

/*
 * Some font data
 */
main(argc, argv)
	int argc;
	char **argv;
{
	CharMetricInfo *mp;

	argc--; argv++;		/* Skip program name */
	while (argc >= 0 && **argv == '-') {
		switch ((*argv)[1]) {
		default:
			fprintf(stderr, "Illegal switch %s\n", *argv);
			exit(1);
		}
		argc--;
		argv++;
	}
	if (argc < 1) {
		fprintf(stderr, "Usage: fixcomp infile {outfile}\n");
		exit(1);
	}
	ifp = fopen(argv[0], "r");
	if (ifp == NULL) {
		perror(argv[0]);
		exit(1);
	}

	switch (parseFile(ifp, &gfi, P_ALL)) {
        case parseError:
		fprintf(stderr, "*** ERROR: problem in parsing the AFM File.\n");
		exit(1);
		
	case earlyEOF:
		fprintf(stderr, "The AFM File ended prematurely.\n");
		exit(1);
		break;
        case storageProblem:
		fprintf(stderr, "*** ERROR: problem allocating storage.\n");
		exit(1);
		break;
	}
	fclose(ifp);

	ifp = fopen(argv[0], "r");
	if (ifp == NULL) {
		perror(argv[0]);
		exit(1);
	}

	if (argc > 1) {
		if ((ofp = fopen(argv[1], "w")) == NULL) {
			perror(argv[1]);
			exit(1);
		}
	} else
		ofp = stdout;

	/*
	 * Find some data needed later
	 */
	mp = findmetric("i");
	if (mp == NULL) {
		fprintf(stderr, "Cannot find metrics for letter 'i'\n");
		exit(1);
	}
	i_width = mp->charBBox.urx - mp->charBBox.llx; /* Width of an 'i' */
	i_llx = mp->charBBox.llx;	/* left side bearing of 'i' */
	xheight = gfi->gfi->xHeight;	/* Height of lower case 'x' */
	Xheight = gfi->gfi->capHeight;	/* height of capital 'X' */
	italicangle = (int)gfi->gfi->italicAngle;
	if (italicangle) {
		double angle;
		angle = -gfi->gfi->italicAngle/360.0*2*3.141592;
		sinfi = sin(angle);
		cosfi = cos(angle);
	}

	makeaccents();

	/*
	 * Sort the metrics table
	 */
	qsort(gfi->cmi, gfi->numOfChars, sizeof(CharMetricInfo), cicomp);

	/*
	 * Sort the kern pair table
	 */
	qsort(gfi->pkd, gfi->numOfPairs, sizeof(PairKernData), pkcomp);

	/*
	 * Sort the composites table
	 */
	qsort(gfi->ccd, gfi->numOfComps, sizeof(CompCharData), cccomp);

	/*
	 * Output the new afm file
	 */
	outafm();
	exit(0);
}

CharMetricInfo *
findmetric(nm)
	char *nm;
{
	register int i;

	for (i = 0; i < gfi->numOfChars; i++)
		if (strcmp(nm, gfi->cmi[i].name) == 0)
			return &gfi->cmi[i];
	return NULL;
}

void
makesingleaccent(basename, accentname)
	char *basename, *accentname;
{
	CharMetricInfo *bmp, *amp, *cmp;
	Pcc *pcc1, pcc2;
	int basew, basebb[4];
	int bw, bh, aw, ah;	/* base char, and accent width and height */
	int axo;		/* Accent x-offset */
	int ayo;		/* Accent y-offset */
	BBox bb;
	char name[40];
	int i, j;
	int new;
	char *bname, *aname;
	int below = 0;

	/*
	 * Form name of new character
	 */
	new = 1;
	sprintf(name, "%s%s", basename, accentname);
	for (i = 0; i < gfi->numOfChars; i++) {
		if (strcmp(name, gfi->cmi[i].name) == 0) {
			fprintf(stderr, "Warning: Redefiniton of %s\n", name);
			new = 0;
			break;
		}
	}
	
	/*
	 * Find metric information for both base character and accent
	 */
	bmp = findmetric(basename);
	if (bmp == NULL) {
		fprintf(stderr, "Warning: Cannot find base character: %s\n", basename);
		return;
	}

	/*
	 * Find the accent.
	 * Fake accent names are handled here
	 */
	amp = findmetric(accentname);
	if (amp == NULL) {
		if (strcmp(accentname, "overdot") == 0)
			amp = findmetric("dotaccent");
		else if (strcmp(accentname, "underdot") == 0)
			amp = findmetric("dotaccent");
		else if (strcmp(accentname, "undercomma") == 0)
			amp = findmetric("comma");
		else if (strcmp(accentname, "czechaccent") == 0)
			if (isupper(*basename))
				amp = findmetric("caron");
			else
				amp = findmetric("quoteright");
		else if (strcmp(accentname, "letaccent") == 0) {
			/*
			 * this is an upside-down comma,
			 */
			amp = findmetric("quoteleft");
		} else if (strcmp(accentname, "underdotmacron") == 0) {
			/*
			 * For the time beeing, we exclude the macron
			 */
			amp = findmetric("dotaccent");
			accentname = "underdot";
		} else if (strcmp(accentname, "breveoverdot") == 0) {
			/*
			 * For the time beeing, we exclude the breve
			 */
			amp = findmetric("dotaccent");
		} else if (strcmp(accentname, "dash") == 0) {
			amp = findmetric("macron");
		}
	}
	if (amp == NULL) {
		fprintf(stderr, "Warning: Cannot find accent: %s\n", accentname);
		return;
	}
	aname = amp->name;

	/*
	 * The base character i is special, insofar as the dotless
	 * i has to be used when the accent is above the character.
	 */
	if (strcmp(basename, "i") == 0 && amp->charBBox.lly > xheight) {
		bmp = findmetric("dotlessi");
	}
	bname = bmp->name;

	/*
	 * find width of the bounding boxes, and center
	 * the accent bounding box, on the base character bounding box
	 */
	bw = bmp->charBBox.urx - bmp->charBBox.llx;
	aw = amp->charBBox.urx - amp->charBBox.llx;
	bh = bmp->charBBox.ury - bmp->charBBox.lly;
	ah = amp->charBBox.ury - amp->charBBox.lly;
	
	below = strcmp(accentname, "ogonek") == 0
		|| strncmp(accentname, "underdot", 5) == 0;

	/*
	 * Here is the centering of the accent above (below) the base
	 * character.
	 *
	 * cmp is the metrics for the character to use for centering.
	 */
	if (below && strcmp(basename, "r") == 0)
		cmp = findmetric("i");
	else
		cmp = bmp;

	axo = (cmp->charBBox.urx - cmp->charBBox.llx)/2 - i_width/2
		+ bmp->charBBox.llx - i_llx;
					/* Accent x offset */
	ayo = 0;			/* Accent y offset */
	
	/*
	 * Handle some special cases
	 */
	if (strcmp(accentname, "ogonek") == 0) {
		/*
		 * The ogonek is right-justified, unless
		 * the base character is one of DFGIJOPSTUVYcefilorstvy
		 */
		if (strlen(basename) == 1 && strchr("DFGIJOPSTUVYcefilorstvy", *basename)) {
			/* The ogonek is centered */
		} else {
			/* The ogonek is right-justified */
			axo = bmp->charBBox.llx + bw - (amp->charBBox.llx + aw);
		}
	} else if (strcmp(accentname, "underdot") == 0) {
		/*
		 * Manufacture the underdot accent by
		 * moving dotaccent down to the same position below x
		 * as it normally is above x.
		 */
		ayo = -(2*(amp->charBBox.lly - xheight) + xheight +
			(amp->charBBox.ury - amp->charBBox.lly));
	} else if (strcmp(accentname, "undercomma") == 0) {
		/*
		 * Manufacture the undercomma accent by moving
		 * the comma down to the same position as the underdot
		 */
		CharMetricInfo *mp;
		mp = findmetric("dotaccent");
		ayo = -((mp->charBBox.lly - xheight) + amp->charBBox.ury);
		axo += mp->charBBox.llx - amp->charBBox.llx;
	} else if (strcmp(accentname, "czechaccent") == 0) {
		if (islower(*basename)) {
			/*
			 * this is actually an apostrophe, which should
			 * come directly after the letter.
			 */
			ayo = 0;
			axo = bmp->charBBox.llx + bw - amp->charBBox.llx;
		}
	} else if (strcmp(accentname, "dash") == 0) {
		/*
		 * Dash through the letter.
		 */
		ayo = -(Xheight-xheight)/2;
		axo += aw/2;
	} else if (strcmp(accentname, "letaccent") == 0) {
		/*
		 * The lettish accent has to be raised a little bit
		 */
		ayo += findmetric("dotaccent")->charBBox.llx - amp->charBBox.llx;
	}
	if (below && strcmp(basename, "r") == 0)
		axo = 0;

	/*
	 * Accents above the character has to be adjusted
	 * up for capitals, and to the right for italic/slanted styles.
	 */
	if (!below && (isupper(*basename)
		|| strlen(basename) == 1 && strchr("fl", *basename))) {
		ayo += Xheight - xheight;
		if (italicangle) {
			int hyp = (int)((Xheight-xheight) / cosfi);
			axo += (int)(hyp * sinfi);
		}
	} else if (below && italicangle && strcmp(accentname, "ogonek") != 0) {
		int hyp = (int)(xheight / cosfi);
		axo -= (int)(hyp * sinfi);
	}

	/*
	 * Note: due to the realloc() in addmetrics, bmp, and amp
	 * cannot be used any more, after this call
	 */
	addmetrics(-1, bmp->wx, bmp->wy, name, 
		   min(bmp->charBBox.llx, amp->charBBox.llx + axo),
		   min(bmp->charBBox.lly, amp->charBBox.lly + ayo),
		   max(bmp->charBBox.urx, amp->charBBox.urx + axo),
		   max(bmp->charBBox.ury, amp->charBBox.ury + ayo));

	addcomposite(name, 2, bname, 0, 0, aname, axo, ayo);


	/*
	 * Add kern pairs to kern pair table
	 */
	if (new) {
		for (i = 0, j = gfi->numOfPairs; i < j; i++) {
			if (strcmp(gfi->pkd[i].name1, basename) == 0)
				addkernpair(name, gfi->pkd[i].name2,
					    gfi->pkd[i].xamt, gfi->pkd[i].yamt);
			if (strcmp(gfi->pkd[i].name2, basename) == 0)
				addkernpair(gfi->pkd[i].name1, name, 
					    gfi->pkd[i].xamt, gfi->pkd[i].yamt);
		}
	}
}


/*
 * Add a kern pair
 */
void
addkernpair(char *name1, char *name2, int xamt, int yamt)
{
	PairKernData *pp;

	gfi->pkd = (PairKernData *)realloc(gfi->pkd, (gfi->numOfPairs+1) * sizeof(PairKernData));
	pp = &gfi->pkd[gfi->numOfPairs];
	gfi->numOfPairs++;
	pp->name1 = strdup(name1);
	pp->name2 = strdup(name2);
	pp->xamt = xamt;
	pp->yamt = yamt;
}

/*
 * Output the new afm file
 */
void
outafm()
{
	int i, j;
	char *lkc;

	fprintf(ofp, "StartFontMetrics %s\n", gfi->gfi->afmVersion);
	/* Comments are lost */
	fprintf(ofp, "FontName %s\n", gfi->gfi->fontName);
	fprintf(ofp, "EncodingScheme %s\n", gfi->gfi->encodingScheme);
	fprintf(ofp, "FullName %s\n", gfi->gfi->fullName);
	fprintf(ofp, "FamilyName %s\n", gfi->gfi->familyName);
	fprintf(ofp, "Weight %s\n", gfi->gfi->weight);
	fprintf(ofp, "ItalicAngle %g\n", (double)gfi->gfi->italicAngle);
	fprintf(ofp, "IsFixedPitch %s\n", gfi->gfi->isFixedPitch ? "true" : "false");
	fprintf(ofp, "UnderlinePosition %d\n", gfi->gfi->underlinePosition);
	fprintf(ofp, "UnderlineThickness %d\n", gfi->gfi->underlineThickness);
	fprintf(ofp, "Version %s\n", gfi->gfi->version);
	fprintf(ofp, "Notice %s\n", gfi->gfi->notice);
	fprintf(ofp, "FontBBox %d %d %d %d\n",
		gfi->gfi->fontBBox.llx, gfi->gfi->fontBBox.lly, gfi->gfi->fontBBox.urx, gfi->gfi->fontBBox.ury);
	fprintf(ofp, "CapHeight %d\n", gfi->gfi->capHeight);
	fprintf(ofp, "XHeight %d\n", gfi->gfi->xHeight);
	fprintf(ofp, "Descender %d\n", gfi->gfi->descender);
	fprintf(ofp, "Ascender %d\n", gfi->gfi->ascender);
	fprintf(ofp, "StartCharMetrics %d\n", gfi->numOfChars);
	for (i = 0; i < gfi->numOfChars; i++) {
		fprintf(ofp, "C %2d ; ", gfi->cmi[i].code);
		if (gfi->cmi[i].wy)
			fprintf(ofp, "W %d %d ; ",
				gfi->cmi[i].wx, gfi->cmi[i].wy);
		else
			fprintf(ofp, "WX %d ; ", gfi->cmi[i].wx);
		fprintf(ofp, "N %s ; ", gfi->cmi[i].name);
		fprintf(ofp, "B %d %d %d %d ;",
			gfi->cmi[i].charBBox.llx, gfi->cmi[i].charBBox.lly,
			gfi->cmi[i].charBBox.urx, gfi->cmi[i].charBBox.ury);
		if (gfi->cmi[i].ligs) {
			Ligature *lp;
			for (lp = gfi->cmi[i].ligs; lp != NULL; lp = lp->next) {
				fprintf(ofp, " L %s %s ;", lp->succ, lp->lig);
			}
		}
		putc('\n', ofp);
	}
	fprintf(ofp, "EndCharMetrics\n");
	if (gfi->numOfPairs || gfi->numOfTracks) {
		fprintf(ofp, "StartKernData\n");
		if (gfi->numOfPairs) {
			fprintf(ofp, "StartKernPairs %d\n", gfi->numOfPairs);
			lkc = NULL;
			for (i = 0; i < gfi->numOfPairs; i++) {
				if (strcmp(lkc, gfi->pkd[i].name1) != 0) {
					lkc = gfi->pkd[i].name1;
					putc('\n', ofp);
				}
				if (gfi->pkd[i].yamt)
					fprintf(ofp, "KP %s %s %d %d\n",
						gfi->pkd[i].name1, gfi->pkd[i].name2,
						gfi->pkd[i].xamt, gfi->pkd[i].yamt);
				else
					fprintf(ofp, "KPX %s %s %d\n",
						gfi->pkd[i].name1, gfi->pkd[i].name2,
						gfi->pkd[i].xamt);
			}
			fprintf(ofp, "EndKernPairs\n");
		}
		fprintf(ofp, "EndKernData\n");
	}

	if (gfi->numOfComps) {
		fprintf(ofp, "StartComposites %d\n", gfi->numOfComps);
		for (i = 0; i < gfi->numOfComps; i++) {
			fprintf(ofp, "CC %s %d ;",
				gfi->ccd[i].ccName, gfi->ccd[i].numOfPieces);
			for (j = 0; j < gfi->ccd[i].numOfPieces; j++)
				fprintf(ofp, " PCC %s %d %d ;",
					gfi->ccd[i].pieces[j].pccName,
					gfi->ccd[i].pieces[j].deltax,
					gfi->ccd[i].pieces[j].deltay);
			putc('\n', ofp);
		}
		fprintf(ofp, "EndComposites\n");
	}
	fprintf(ofp, "EndFontMetrics\n");
}

	
/*
 * Add a composite character to the composite table
 */
void
addcomposite(char *name, int no, char *args, ...)
{
	int i;
	char **argp = &args;
	CompCharData *ccp;
	Pcc *pp;
	int new;

	if ((ccp = findcomp(name)) == NULL) {
		gfi->ccd = (CompCharData *)realloc(gfi->ccd, (gfi->numOfComps+1)*sizeof(CompCharData));
		ccp = &gfi->ccd[gfi->numOfComps];
		gfi->numOfComps++;
	}
	ccp->ccName = strdup(name);
	ccp->numOfPieces = no;
	pp = (Pcc *)calloc(no, sizeof(Pcc));
	if (pp == NULL) {
		perror("Memory allocation error");
		exit(1);
	}
	for (i = 0; i < no; i++) {
		pp[i].pccName = strdup(*argp++);
		pp[i].deltax = (int)*argp++;
		pp[i].deltay = (int)*argp++;
	}
	ccp->pieces = pp;
}

void
addmetrics(int code, int wx, int wy, char *name, int llx, int lly, int urx, int ury)
{
	register CharMetricInfo *mp;

	if ((mp = findmetric(name)) == NULL) {
		gfi->cmi = (CharMetricInfo *)realloc(gfi->cmi, (gfi->numOfChars+1) * sizeof(CharMetricInfo));
		mp = &gfi->cmi[gfi->numOfChars];
		gfi->numOfChars++;
	}
	mp->code = code;
	mp->wx = wx;
	mp->wy = wy;
	mp->name = strdup(name);
	mp->charBBox.llx = llx;
	mp->charBBox.lly = lly;
	mp->charBBox.urx = urx;
	mp->charBBox.ury = ury;
	mp->ligs = NULL;
}

/*
 * sort compare routines
 */
int
pkcomp(p1, p2)
	PairKernData *p1, *p2;
{
	int k;

	k = strcmp(p1->name1, p2->name1);
	if (k == 0)
		k = strcmp(p1->name2, p2->name2);
	return k;
}

int
cicomp(p1, p2)
	CharMetricInfo *p1, *p2;
{
	int k;

	k = p1->code - p2->code;
	if (k == 0)
		k = strucmp(p1->name, p2->name);
	else if (p1->code == -1)
		return 1;
	else if (p2->code == -1)
		return -1;
	return k;
}

/*
 *
 */
int
cccomp(p1, p2)
	CompCharData *p1, *p2;
{
	return strucmp(p1->ccName, p2->ccName);
}

int
strucmp(s1, t1)
	char *s1, *t1;
{
	register char *s = s1, *t = t1;

	while (tolower(*s) == tolower(*t)) {
		if (!*s)
			return strcmp(s1, t1);
		s++; t++;
	}
	
	return tolower(*s) - tolower(*t);
}

makebothaccents(char *basechar, char *accent)
{
	char name[40];

	makesingleaccent(basechar, accent);
	if (islower(*basechar)) {
		strcpy(name, basechar);
		*name = toupper(*name);
		makesingleaccent(name, accent);
	}
}

makeaccents()
{
/* Key to country codes */
/* CS=Czechoslovakia */
/* ED=Estonia */
/* ES=Spain */
/* HU=Hungary */
/* IS=Iceland */
/* LE=Lativa */
/* LT=Lithuania */
/* NL=Netherland */
/* NO=Norway */
/* PL=Poland */
/* PT=Portugal  */
/* SE=Sweden */
/* SK=Sanskrit */
/*  makebothaccents("a", "acute");	/* std,CS,ES,HU,IS,NL,PT,RO */
  makebothaccents("a", "breve");	/* RO */
/*  makebothaccents("a", "circumflex");	/* std,FR,NL,RO */
/*  makebothaccents("a", "dieresis");	/* std,NL,DE,ED,FI */
/*  makebothaccents("a", "grave");	/* std,NL,FR,IT,RO */
  makebothaccents("a", "macron");	/* LE,SK */
  makebothaccents("a", "ogonek");	/* LT,PL */
/*  makebothaccents("a", "ring");	/* std,FI,NO,SE */
/*  makebothaccents("a", "tilde");	/* std,PT */
  makebothaccents("c", "acute");	/* PL,YU */
  makebothaccents("c", "caron");	/* CS,ED,LE,LT,YU */
/*  makebothaccents("c", "cedilla");	/* std,FR,PT */
  makesingleaccent("d", "dash");	/* YU */
  makebothaccents("d", "czechaccent");	/* CS */
  makebothaccents("d", "underdot");	/* SK */
/*  makebothaccents("e", "acute");	/* std,CS,DE,ES,FR,HU,IS,NL,PT,RO */
  makebothaccents("e", "caron");	/* CS */
/*  makebothaccents("e", "circumflex");	/* std,FR,NL,PT,RO */
/*  makebothaccents("e", "dieresis");	/* std,FR,NL,SE */
/*  makebothaccents("e", "grave");	/* std,FR,IT,NL,RO */
  makebothaccents("e", "macron");	/* LE */
  makebothaccents("e", "ogonek");	/* LT,PL */
  makebothaccents("e", "overdot");	/* LT */
  makebothaccents("g", "letaccent");	/* LE */
  makebothaccents("h", "underdot");	/* SK */
/*  makebothaccents("i", "acute");	/* std,CS,ES,HU,IS,NL,PT */
/*  makebothaccents("i", "circumflex");	/* std,FR,IT,NL,RO */
/*  makebothaccents("i", "dieresis");	/* std,FR,NL */
/*  makebothaccents("i", "grave");	/* std,IT,NL */
  makebothaccents("i", "macron");	/* LE,SK */
  makebothaccents("i", "ogonek");	/* LT */
  makebothaccents("k", "undercomma");	/* LE */
 makesingleaccent("l", "breveoverdot");	/* SK */
/*  makebothaccents("l", "slash");	/* std,PL */
  makebothaccents("l", "undercomma");	/* LE */
  makebothaccents("l", "underdot");	/* SK */
  makebothaccents("m", "overdot");	/* SK */
  makebothaccents("n", "acute");	/* PL */
  makebothaccents("n", "caron");	/* CS */
  makebothaccents("n", "overdot");	/* SK */
/*  makebothaccents("n", "tilde");	/* std,ES */
  makebothaccents("n", "undercomma");	/* LE */
  makebothaccents("n", "underdot");	/* SK */
/*  makebothaccents("o", "acute");	/* std,CS,ES,HU,IS,NL,PL,PT */
/*  makebothaccents("o", "circumflex");	/* std,FR,NL,PT */
/*  makebothaccents("o", "dieresis");	/* std,ED,FI,HU,IS,NL,SE */
/*  makebothaccents("o", "grave");	/* std,IT,NL */
  makebothaccents("o", "hungarumlaut");/* HU */
  makebothaccents("o", "macron");	/* LE */
/*  makebothaccents("o", "slash");	/* std,NO */
/*  makebothaccents("o", "tilde");	/* std,ED,PT */
  makebothaccents("r", "caron");	/* CS */
  makebothaccents("r", "undercomma");	/* LE */
  makebothaccents("r", "underdot");	/* SK */
  makebothaccents("r", "underdotmacron");/* SK */
  makebothaccents("s", "acute");	/* PL,SK */
/*  makebothaccents("s", "caron");	/* std,CS,ED,LE,LT,YU */
  makebothaccents("s", "undercomma");	/* RO */
  makebothaccents("s", "underdot");	/* SK */
  makebothaccents("t", "czechaccent");	/* CS */
  makebothaccents("t", "undercomma");	/* RO */
  makebothaccents("t", "underdot");	/* SK */
/*  makebothaccents("u", "acute");	/* std,CS,ES,HU,IS,NL,PT */
/*  makebothaccents("u", "circumflex");	/* std,FR,NL */
/*  makebothaccents("u", "dieresis");	/* std,DE,ED,HU,NL */
/*  makebothaccents("u", "grave");	/* std,FR,IT,NL */
  makebothaccents("u", "hungarumlaut");/* HU */
  makebothaccents("u", "macron");	/* LE,LT,SK */
  makebothaccents("u", "ogonek");	/* LT */
  makebothaccents("u", "ring");	/* CS */
/*  makebothaccents("y", "acute");	/* std,CS,IS */
  makebothaccents("z", "acute");	/* PL */
/*  makebothaccents("z", "caron");	/* std,CS,ED,LE,LT,YU */
  makebothaccents("z", "overdot");	/* PL */
  
}

CompCharData*
findcomp(char *nm)
{
	register int i;

	for (i = 0; i < gfi->numOfComps; i++)
		if (strcmp(nm, gfi->ccd[i].ccName) == 0)
			return &gfi->ccd[i];
	return NULL;
}


