#define VERSION "10 (July 1993)"

/*
vpltovpl.c. version 1. december 1990
            version 2. january 1992
            version 3. may 1992
            version 4. dec 1992
	    version 5. dec 28 1992
	    version 6. may 20 1993. removed progress indicators. 
                        put back with -DDEBUG
	    version 7. may 25 1993. cleaned up and re-used generation of 
                        extra file for dotlessj only (activated by -DSPECIAL)
	    version 8. july 12 1993. redo some of virtual font code;
	                   and generate the dotlessj missing char with vpl
			   rather than using a tiny PS font
	    version 9. july 14 1993. add in code to check if we are an
	                artificial small caps font, and do things right for
			that
	    version 10. july 1993. corrected aogonek

by Sebastian Rahtz

spqr@minster.york.ac.uk

(thanks also to Alexander Samarin for suggestions;
and Michael Doob and Craig Platt for ideas on how to do dotlessj)

Take an existing .vpl file, create extra characters for new composite
characters for extended TeX layout, and add them to the end of the
file

[
where necessary write a tiny new font metric file for extra characters;
abandoned in version 8
]

Parameters: 1) name of vpl file (which is going to be overwritten)
            2) name of original AFM file


a quite dreadfully written C program converted from an Icon program:
--------------------------------------------------------
# vplovx.icn version 1
#
# Sebastian Rahtz October 1990
#
--------------------------------------------------------

bits pinched from other people. notably the `findchar' and `newchar'
functions, with associated material, taken from afm2tfm almost verbatim

*/
#include "vpltovpl.h"


char vplname[LINELENGTH], afmname[LINELENGTH];
char command[LINELENGTH], plname[LINELENGTH];
char basefont[100];
float uppergap,lowergap = -1.0 ;
FILE *vplfile, *afmfile, *plfile;
char entry[MAXENTRY];
int SCFont = 0;
float fontat=.8;

struct character {
	struct character *next;
	char *name;
	float width,height,depth,charic;
	} *chars,*vchars[MAXCHARS] ;
	
/*---------------------------*/
struct character * findchar(p)
char *p ;
{
   register struct character *ai ;

   for (ai=chars; ai; ai = ai->next)
{
      if (strcmp(p, ai->name)==0)
         return(ai) ;
}
   return(NULL) ;
}

/*--------------------------*/
float width(key)
char *key;
{
 register struct character *ai;
 ai = findchar(key);
 if (ai == NULL)
{
#ifdef DEBUG
	fprintf(stderr,"No width for %s\n",key);
#endif
	return (0);
}
 else
	return (ai->width);
}

/*--------------------------*/
float height(key) 
char *key;
{
 register struct character *ai;
 ai = findchar(key);
 if (ai == NULL)
{
#ifdef DEBUG
	fprintf(stderr,"No height for %s\n",key);
#endif
	return (0);
}
 else
	return (ai->height);
}


/*--------------------------*/
float depth(key) 
char *key;
{
 register struct character *ai;
 ai = findchar(key);
 if (ai == NULL)
{
#ifdef DEBUG
	fprintf(stderr,"No depth for %s\n",key);
#endif
	return (0);
}
 else
	return (ai->depth);
}

/*--------------------------*/
float charic(key) 
char *key;
{
 register struct character *ai;
 ai = findchar(key);
 if (ai == NULL)
{
#ifdef DEBUG
	fprintf(stderr,"No charic for %s\n",key);
#endif
	return (0);
}
 else
	return (ai->charic);
}

/*--------------------------*/
void error(s)
register char *s ;
{
   extern void exit() ;

   (void)fprintf(stderr, "%s\n", s) ;
   if (*s == '!')
      exit(1) ;
}
/*--------------------------*/
char * mymalloc(len)
unsigned long len ;
{   
   register char *p ;
   int i ;
#ifdef SMALLMALLOC
   if (len > 65500L)
      error("! can't allocate more than 64K!") ;
#endif
   p = malloc((unsigned)len) ;
   if (p==NULL)
      error("! out of memory") ;
   for (i=0; i<len; i++)
      p[i] = 0 ;
   return(p) ;
}

/*--------------------------*/
char * namespace() {
   register char *q;
   q = mymalloc(6) ;
   return(q) ;
}

/*--------------------------*/
struct character * anewchar() {
   register struct character *ai ;
   ai = (struct character *)mymalloc((unsigned long)sizeof(struct character)) ;
   ai->width = 0 ;
   ai->name = NULL ;
   ai->height = 0 ;
   ai->depth = 0 ;
   ai->charic = 0 ;
   ai->next = chars ;
   chars = ai ;
   return(ai) ;
}

/*--------------------------*/
int count(line)
char *line;
{
/* count the parentheses in a line, add +1 for a '(', -1 for a ')' */
  char *p;
  int cnt = 0;

  for (p=line; *p; p++) {
    if (*p=='(')
      cnt += 1;
    if (*p==')')
      cnt -= 1;
  }
  return(cnt);
}

#ifndef MSDOS
/*--------------------------*/

float max(float a, float b)
{
if (a > b )
	return (a) ;
else 
	return (b) ;
} 
#endif
/*--------------------------*/
void vchar(charnum,charname,charwd,charht,chardp,
           charic,oldchar,accent,moveright,moveup,WhichFont)
int charnum; /*  number of new character*/
char *charname; /* name of new character*/
float   charwd; /*   width of character*/
float   charht; /*   height of character*/
float   chardp; /*   depth of character*/
float   charic; /*   italic correction of character*/
char    *oldchar; /*  number of old character*/
char    *accent; /*   string of accent number*/
float   moveright; /* (can be negative)*/
float   moveup; /*    (can be negative)*/
int WhichFont ; /* for small caps. 0 or 1 */
{
#ifdef DEBUG
fprintf(stderr,"generate character %s from %s and %s: %f %f\n",
charname,oldchar,accent,moveup,moveright);
#endif
fprintf(vplfile,"(CHARACTER O %d (comment %s: %.2f %.2f)\n",charnum,charname,moveright,moveup);

if (charwd  != 0 )
	 fprintf(vplfile,"   (CHARWD R %.2f)\n",charwd);
if (charht  != 0 )
	 fprintf(vplfile,"   (CHARHT R %.2f)\n",charht);
if (chardp  != 0 )
	 fprintf(vplfile,"   (CHARDP R %.2f)\n",chardp);
if (charic  != 0 )
	 fprintf(vplfile,"   (CHARIC R %.2f)\n",charic);
/* WhichFont will be 0 normally, but 1 if we are a small caps font */
fprintf(vplfile,"   (MAP (SELECTFONT D %d)\n",WhichFont);
fprintf(vplfile,"      (SETCHAR %s)\n",oldchar);
if (moveright  != 0.0)
	 fprintf(vplfile,"      (MOVERIGHT R %.2f)\n",-moveright);
if (moveup  != 0.0  )
	 fprintf(vplfile,"      (MOVEUP R %.2f)\n",moveup);
fprintf(vplfile,"      (SETCHAR %s)\n",accent);
fprintf(vplfile,"      )\n");
fprintf(vplfile,"   )\n");
}

/*----------------------*/
void upperacc(number,c,accent,name)
int number;
char *c,*accent,*name;
{
float xdepth,xheight,xmoveup;
#ifdef DEBUG
fprintf(vplfile,"(COMMENT UPPERACC with  %d: %s, %s, %s )\n",number,c,accent,name);
#endif
xdepth=depth(accent);
if (xdepth > 0.0) 
/*
# its an underneath accent
# no need to move up
*/
 { 
   xheight=height(c);
   xmoveup=0.0;
 }
else
 {
   xdepth=depth(c);
   xheight=height(accent);
   xmoveup=uppergap;
  }
vchar(number,
	name,
	width(c),
	xheight+xmoveup,
	xdepth,
	charic(c),
	c,
	accent,
	(float) ( ( width(c) / 2.0  )   + (  width(accent) / 2.0 ) ),
	xmoveup,0);
}
/*--------------------------*/
void loweracc(number,c,accent,name,movedown)
int number;
float movedown;
char *c,*accent,*name;
{
float moveup,adepth,xheight,xdepth,xmoveup;
float CDepth,CHeight,CWidth,ADepth,AHeight,AWidth,CIc;
char CharName[5];
char LastChar;
strcpy(CharName,c);
/* if we are in small caps, uppercase the character name */
if (SCFont == 1 )
  {
  LastChar=CharName[strlen(CharName)-1]; 
  CharName[strlen(CharName)-1]=toupper(LastChar);
  /* 
  for a small caps font, we need to reduce the dimensions to the size
  of the small caps font; we have derived this from the vpl file earlier
  as `fontat'
  */
  ADepth=depth(accent) * fontat;
  AWidth=width(accent) * fontat  ;
  AHeight=height(accent) * fontat + SC_ACCENT_RAISE ;
  CWidth=width(CharName) * fontat  ;
  CHeight=height(CharName) * fontat  ;
  CDepth=depth(CharName) * fontat  ;
  CIc=charic(CharName) * fontat  ;
}
else
  {
  ADepth=depth(accent);
  AWidth=width(accent) ;
  AHeight=height(accent) ;
  CWidth=width(CharName) ;
  CHeight=height(CharName) ;
  CDepth=depth(CharName) ;
  CIc=charic(CharName) ;
}
#ifdef DEBUG
fprintf(vplfile,"(COMMENT LOWERACC with  %d: %s, %s, %s %f)\n",number,CharName,accent,name,movedown);
#endif
xdepth=ADepth;
if (xdepth > 0.0 )
 { 
   xheight=CHeight;
   xmoveup=0.0;
 }
else
 {
   xdepth=CDepth;
   xheight=AHeight;
   xmoveup=lowergap;
  }
if (movedown != 0.0 )
	xmoveup= xmoveup+movedown;

vchar(number,
	name,
	CWidth,
	xheight+xmoveup,
	xdepth,
	CIc,
	CharName,
	accent,
	(float) ( ( CWidth / 2.0  )   + (  AWidth / 2.0 ) ),
      	xmoveup,
        SCFont
        );
}

/*--------------------------*/
generatenormal()
{
char *c,*ctwo;
upperacc(200,"C A",BREVE,"Abreve");
/* upperacc(201,"C A",OGONEK,"Agonek");  NOW DONE AS SPECIAL LATER*/
upperacc(202,"C C",ACUTE,"Cacute");
upperacc(203,"C C",CARON,"Ccaron");
upperacc(204,"C D",CARON,"Dcaron");
upperacc(205,"C E",CARON,"Ecaron");
upperacc(206,"C E",OGONEK,"Eogonek");
upperacc(207,"C G",BREVE,"Gbreve");
upperacc(210,"C L",ACUTE,"Lacute");
upperacc(213,"C N",ACUTE,"Nacute");
upperacc(214,"C N",CARON,"Ncaron");
upperacc(216,"C O",HUNGARUMLAUT,"Ohungarumlaut");
upperacc(217,"C R",ACUTE,"Racute");
upperacc(220,"C R",CARON,"Rcaron");
upperacc(221,"C S",ACUTE,"Sacute");
upperacc(223,"C S",CEDILLA,"Scedilla");
upperacc(224,"C T",CARON,"Tcaron");
upperacc(225,"C T",CEDILLA,"Tcedilla");
upperacc(226,"C U",HUNGARUMLAUT,"Uhungarumlaut");
upperacc(227,"C U",RING,"Uring ");
upperacc(231,"C Z",ACUTE,"Zacute");
upperacc(233,"C Z",DOTACCENT,"Zdotaccent");
upperacc(235,"C I",DOTACCENT,"Idotaccent");
if (SCFont == 1)
  {
/* small caps capital D bar hack. */
c = "O 137" ; ctwo = "C D";
fprintf(vplfile,"(CHARACTER O 236 \n");
fprintf(vplfile,"   (CHARWD R %.2f)\n",width(ctwo)*fontat);
fprintf(vplfile,"   (CHARHT R %.2f)\n",max(height(c),height(ctwo))*fontat);
fprintf(vplfile,"   (CHARIC R %.2f)\n",max(charic(c),charic(ctwo))*fontat);
fprintf(vplfile,"   (CHARDP R %.2f)\n",max(depth(c),depth(ctwo))*fontat);
fprintf(vplfile,"   (MAP");
fprintf(vplfile,"      (SELECTFONT D 1)\n"); 
fprintf(vplfile,"      (PUSH)\n"); 
fprintf(vplfile,"      (MOVERIGHT R -100)\n"); 
fprintf(vplfile,"      (MOVEDOWN R -75)\n"); 
fprintf(vplfile,"      (SETCHAR O 25)\n");
fprintf(vplfile,"      (POP)\n"); 
fprintf(vplfile,"      (SETCHAR C D)\n");
fprintf(vplfile,"      )\n");
fprintf(vplfile,"   )\n");
}
else
   loweracc(236,"C d",BAR,"dbar",325.0);
loweracc(240,"C a",BREVE,"abreve",0.0);
loweracc(242,"C c",ACUTE,"cacute",0.0);
loweracc(243,"C c",CARON,"ccaron",0.0);
loweracc(245,"C e",CARON,"ecaron",0.0);
loweracc(246,"C e",OGONEK,"eogonek",0.0);
loweracc(247,"C g",BREVE,"gbreve",0.0);
if (SCFont == 1)
  loweracc(250,"C l",ACUTE,"lacute",100.0);
else
  loweracc(250,"C l",ACUTE,"lacute",200.0);
loweracc(253,"C n",ACUTE,"nacute",0.0);
loweracc(254,"C n",CARON,"ncaron",0.0);
loweracc(256,"C o",HUNGARUMLAUT,"ohungarumlaut",0.0);
loweracc(257,"C r",ACUTE,"racute",0.0);
loweracc(260,"C r",CARON,"rcaron",0.0);
loweracc(261,"C s",ACUTE,"sacute",0.0);
loweracc(263,"C s",CEDILLA,"scedilla",0.0);
loweracc(265,"C t",CEDILLA,"tcedilla",0.0);
loweracc(266,"C u",HUNGARUMLAUT,"uhungarumlaut",0.0);
loweracc(267,"C u",RING,"uring ",0.0);
loweracc(271,"C z",ACUTE,"zacute",0.0);
loweracc(273,"C z",DOTACCENT,"zdotaccent",0.0);
}
/*--------------------------*/
generatespecial()
{
register struct character *ai ;
char *c,*ctwo;
ai = findchar("O 241");
   if (ai == NULL)
{
if (SCFont == 1)
  {
   char *c,*ctwo;
   c="C A";
   ctwo=OGONEK; 
   vchar(241,"aogonek",width(c)*fontat,height(c)*fontat,depth(ctwo)*fontat,charic(c)*fontat,
     c,ctwo,width(c)*fontat * .25,0.0,1);
 }
else
  {
   c="C a";
   ctwo=OGONEK; 
   vchar(241,"aogonek",width(c),height(c),depth(ctwo),charic(c),
     c,ctwo,width(c)*.20,0.0,0);
 }
}
c="C A";
ctwo=OGONEK;
vchar(201,"Aogonek",width(c),height(c),depth(ctwo),charic(c),
  c,ctwo,width(c) *0.35,0.0,0);

c="C I";
ctwo="C J";
vchar(234,"IJ",(width(c)+width(ctwo)),
  max(height(c),height(ctwo)),max(depth(c),depth(ctwo)),
  max(charic(c),charic(ctwo)),c,ctwo,0.0,0.0,0);

if (SCFont == 1 )
  {
    c="C I";
    ctwo="C J" ;
    vchar(274,"ij",(width(c)+width(ctwo)*fontat)-100.0,
      max(height(c),height(ctwo))*fontat,max(depth(c),depth(ctwo))*fontat,
      max(charic(c),charic(ctwo))*fontat,c,ctwo,50.0,0.0,SCFont);
   c="C r";
   ai = findchar("O 32");
   if (ai == NULL)
      ctwo="C j";
   else
      ctwo="O 32";
   vchar(215,"Eng",(width(c)+width(ctwo))-100.0 ,
    max(height(c),height(ctwo)),max(depth(c),depth(ctwo)),
    max(charic(c),charic(ctwo)),c,ctwo,100.0,-50.0,0);
  }
else
  {
    c="C i";
    ctwo="C j" ;
    vchar(274,"ij",(width(c)+width(ctwo))-100.0,
     max(height(c),height(ctwo)),max(depth(c),depth(ctwo)),
     max(charic(c),charic(ctwo)),c,ctwo,50.0,0.0,SCFont);

   ai = findchar("O 32");
   if (ai == NULL)
      ctwo="C j";
   else
      ctwo="O 32";
   c="C r";
   vchar(215,"Eng",(width(c)+width(ctwo))-100.0 ,
       max(height(c),height(ctwo)),max(depth(c),depth(ctwo)),
       max(charic(c),charic(ctwo)),c,ctwo,100.0,-50.0,0);
  }

c="C r";
ai = findchar("O 32");
   if (ai == NULL)
      ctwo="C j";
   else
      ctwo="O 32";
vchar(255,"eng",(width(c)+width(ctwo))-100.0,
max(height(c),height(ctwo)),max(depth(c),depth(ctwo)),
max(charic(c),charic(ctwo)),c,ctwo,100.0,-50.0,0);

c="C S";
vchar(337,"Germandbls",width(c)*2,height(c),depth(c),charic(c),c,c,0.0,0.0,0);
c="C L";
ctwo=QUOTE;
vchar(211,"Lquote",width(c),height(c),depth(c),charic(c),c,ctwo,200.0,-50.0,0);

if (SCFont == 1 )
  loweracc(244,"C D",CARON,"dquote",0.0);
else
{
  c="C d";
  ctwo=QUOTE;
  vchar(244,"dquote",width(c),height(c),depth(c),charic(c),c,ctwo,
  100.0,0.0,SCFont);
}

if (SCFont == 1 )
 loweracc(264,"C T",CARON,"tquote",0.0);
else
{
  c="C t";
  ctwo=QUOTE;
 vchar(264,"tquote",width(c),height(c),depth(c),charic(c),c,ctwo,
 100.0,0.0,SCFont);
}

if (SCFont == 1 )
  c="C L";
else
  c="C l";
ctwo=QUOTE;
vchar(251,"lquote",width(c),height(c),depth(c),charic(c),c,ctwo,100.0,0.0,SCFont);

fprintf(vplfile,"(CHARACTER O 027 (comment cwm)\n");
fprintf(vplfile,"   (CHARWD R 0)\n");
fprintf(vplfile,"   (CHARHT R 0)\n");
fprintf(vplfile,"   (CHARDP R 0)\n");
fprintf(vplfile,"   (MAP");
fprintf(vplfile,"      (MOVERIGHT R 0)\n");
fprintf(vplfile,"      )\n");
fprintf(vplfile,"   )\n");

/* the visible space character; must be same width as numbers;
constructed from 3 rules.
*/
 c="C 0";
fprintf(vplfile,"(CHARACTER O 040 (comment visiblespace)\n");
fprintf(vplfile,"   (CHARWD R %.2f)\n",width(c));
fprintf(vplfile,"   (CHARHT R 500)\n");
fprintf(vplfile,"   (CHARDP R 0)\n");
fprintf(vplfile,"   (MAP");
fprintf(vplfile,"      (MOVERIGHT R 100)\n");
fprintf(vplfile,"      (SETRULE R 400 R 35)\n");
fprintf(vplfile,"      (SETRULE R 35 R 400)\n");
fprintf(vplfile,"      (SETRULE R 400 R 35)\n");
fprintf(vplfile,"      (MOVERIGHT R 70)\n");
fprintf(vplfile,"      )\n");
fprintf(vplfile,"   )\n");


/* now a set of characters that are found in some fonts, but need to be
generated if they are not found in the AFM file */
 ai = findchar("O 375");
 if (ai == NULL)
	loweracc(375,"C y",ACUTE,"yacute",0.0);
 ai = findchar("O 335");
 if (ai == NULL)
	 upperacc(335,"C Y",ACUTE,"Yacute");
 ai = findchar("O 320");
 if (ai == NULL)
{
/* Eth hack. */
c = "O 137" ; ctwo = "C D";
fprintf(vplfile,"(CHARACTER O 320 (comment Eth)\n");
fprintf(vplfile,"   (CHARWD R %.2f)\n",width(ctwo));
fprintf(vplfile,"   (CHARHT R %.2f)\n",max(height(c),height(ctwo)));
fprintf(vplfile,"   (CHARIC R %.2f)\n",max(charic(c),charic(ctwo)));
fprintf(vplfile,"   (CHARDP R %.2f)\n",max(depth(c),depth(ctwo)));
fprintf(vplfile,"   (MAP");
fprintf(vplfile,"      (PUSH)\n"); 
fprintf(vplfile,"      (MOVERIGHT R -100)\n"); 
fprintf(vplfile,"      (MOVEDOWN R -75)\n"); 
fprintf(vplfile,"      (SETCHAR O 25)\n");
fprintf(vplfile,"      (POP)\n"); 
fprintf(vplfile,"      (SETCHAR C D)\n");
fprintf(vplfile,"      )\n");
fprintf(vplfile,"   )\n");
}
 ai = findchar("O 336");
 if (ai == NULL)
{
 c="C 0";
fprintf(vplfile,"(CHARACTER O 336 (comment Thorn )\n");
fprintf(vplfile,"   (CHARWD R %.2f)\n",width(c));
fprintf(vplfile,"   (CHARHT R 700)\n");
fprintf(vplfile,"   (CHARDP R 0)\n");
fprintf(vplfile,"   (MAP");
fprintf(vplfile,"      (SETRULE R 500 R %.2f)\n",width(c));
fprintf(vplfile,"      )\n");
fprintf(vplfile,"   )\n");
/*
Thorn junk it

c = "C l" ; ctwo = "C b";
fprintf(vplfile,"(CHARACTER O 336 (comment Thorn)\n");
fprintf(vplfile,"   (CHARWD R %.2f)\n",width(ctwo));
fprintf(vplfile,"   (CHARHT R %.2f)\n",max(height(c),height(ctwo)));
fprintf(vplfile,"   (CHARIC R %.2f)\n",max(charic(c),charic(ctwo)));
fprintf(vplfile,"   (CHARDP R %.2f)\n",max(depth(c),depth(ctwo)));
fprintf(vplfile,"   (MAP");
fprintf(vplfile,"      (MOVEDOWN R 400)\n");
fprintf(vplfile,"      (SETCHAR C l)\n");
fprintf(vplfile,"      (MOVEDOWN R -400)\n");
fprintf(vplfile,"      (MOVERIGHT R -%.2f)\n",width(c));
fprintf(vplfile,"      (SETCHAR C b)\n");
fprintf(vplfile,"      )\n");
fprintf(vplfile,"   )\n");
*/
}
 ai = findchar("O 360");
 if (ai == NULL)
{
if (SCFont == 1)
{
/* small caps capital D bar hack. */
c = "O 137" ; ctwo = "C D";
fprintf(vplfile,"(CHARACTER O 360 \n");
fprintf(vplfile,"   (CHARWD R %.2f)\n",width(ctwo)*fontat);
fprintf(vplfile,"   (CHARHT R %.2f)\n",max(height(c),height(ctwo))*fontat);
fprintf(vplfile,"   (CHARIC R %.2f)\n",max(charic(c),charic(ctwo))*fontat);
fprintf(vplfile,"   (CHARDP R %.2f)\n",max(depth(c),depth(ctwo))*fontat);
fprintf(vplfile,"   (MAP");
fprintf(vplfile,"      (SELECTFONT D 1)\n"); 
fprintf(vplfile,"      (PUSH)\n"); 
fprintf(vplfile,"      (MOVERIGHT R -100)\n"); 
fprintf(vplfile,"      (MOVEDOWN R -75)\n"); 
fprintf(vplfile,"      (SETCHAR O 25)\n");
fprintf(vplfile,"      (POP)\n"); 
fprintf(vplfile,"      (SETCHAR C D)\n");
fprintf(vplfile,"      )\n");
fprintf(vplfile,"   )\n");
}
else
{
 c="C 0";
fprintf(vplfile,"(CHARACTER O 360 (comment eth)\n");
fprintf(vplfile,"   (CHARWD R %.2f)\n",width(c));
fprintf(vplfile,"   (CHARHT R 700)\n");
fprintf(vplfile,"   (CHARDP R 0)\n");
fprintf(vplfile,"   (MAP");
fprintf(vplfile,"      (SETRULE R 500 R %.2f)\n",width(c));
fprintf(vplfile,"      )\n");
fprintf(vplfile,"   )\n");
}
/* eth junked
c = "C x" ; ctwo = "C o";
fprintf(vplfile,"(CHARACTER O 360 (comment eth)\n");
fprintf(vplfile,"   (CHARWD R %.2f)\n",width(c));
fprintf(vplfile,"   (CHARHT R %.2f)\n",max(height(c),height(ctwo)));
fprintf(vplfile,"   (CHARIC R %.2f)\n",max(charic(c),charic(ctwo)));
fprintf(vplfile,"   (CHARDP R %.2f)\n",max(depth(c),depth(ctwo)));
fprintf(vplfile,"   (MAP");
fprintf(vplfile,"      (MOVEDOWN R -400)\n");
fprintf(vplfile,"      (SETCHAR C x)\n");
fprintf(vplfile,"      (MOVEDOWN R 400)\n");
fprintf(vplfile,"      (MOVERIGHT R -850)\n");
fprintf(vplfile,"      (SETCHAR C o)\n");
fprintf(vplfile,"      )\n");
fprintf(vplfile,"   )\n");
*/
}
 ai = findchar("O 376");
 if (ai == NULL)
{
 c="C 0";
fprintf(vplfile,"(CHARACTER O 376 (comment thorn)\n");
fprintf(vplfile,"   (CHARWD R %.2f)\n",width(c));
fprintf(vplfile,"   (CHARHT R 700)\n");
fprintf(vplfile,"   (CHARDP R 0)\n");
fprintf(vplfile,"   (MAP");
fprintf(vplfile,"      (SETRULE R 500 R %.2f)\n",width(c));
fprintf(vplfile,"      )\n");
fprintf(vplfile,"   )\n");
/* thorn; junked
c = "C l" ; ctwo = "C b";
fprintf(vplfile,"(CHARACTER O 376 (comment thorn)\n");
fprintf(vplfile,"   (CHARWD R %.2f)\n",width(c));
fprintf(vplfile,"   (CHARHT R %.2f)\n",max(height(c),height(ctwo)));
fprintf(vplfile,"   (CHARIC R %.2f)\n",max(charic(c),charic(ctwo)));
fprintf(vplfile,"   (CHARDP R %.2f)\n",max(depth(c),depth(ctwo)));
fprintf(vplfile,"   (MAP");
fprintf(vplfile,"      (PUSH)");
fprintf(vplfile,"      (MOVEDOWN R 300)\n");
fprintf(vplfile,"      (SETCHAR C l)\n",c);
fprintf(vplfile,"      (MOVEDOWN R -300)\n");
fprintf(vplfile,"      (POP)");
fprintf(vplfile,"      (SETCHAR C b)\n",ctwo);
fprintf(vplfile,"      )\n");
fprintf(vplfile,"   )\n");
*/
}
/* 
ff, ffi, ffl ligatures are not faked if they are not in 
the font; why should we make up for sloppiness of
font designers? so long as the ligature table doesnt mention them,
no problem (since no-one puts them in by hand, i hope)
*/

 ai = findchar("O 32");
 if (ai == NULL)
{
/* 
dotless j. tricky, as it is driver-dependent, using SPECIALs
*/
if (SCFont==1)
  {
c="C J";
fprintf(vplfile,"(CHARACTER O 32 (comment dotlessj)\n");
fprintf(vplfile,"   (CHARWD R %.2f)\n",width(c)*fontat);
fprintf(vplfile,"   (CHARHT R %.2f)\n",height(ctwo)*fontat);
fprintf(vplfile,"   (CHARDP R %.2f)\n",depth(c)*fontat);
fprintf(vplfile,"   (CHARIC R %.2f)\n",charic(c)*fontat);
fprintf(vplfile,"   (MAP (SELECTFONT D 1)\n" );
fprintf(vplfile,"      (SETCHAR C J)\n");
fprintf(vplfile,"      )\n");
fprintf(vplfile,"   )\n");
}  
else
  {
c="C j";
ctwo="O 31";
fprintf(vplfile,"(CHARACTER O 32 (comment dotlessj)\n");
fprintf(vplfile,"   (CHARWD R %.2f)\n",width(c));
fprintf(vplfile,"   (CHARHT R %.2f)\n",height(ctwo));
fprintf(vplfile,"   (CHARDP R %.2f)\n",depth(c));
fprintf(vplfile,"   (CHARIC R %.2f)\n",charic(c));
fprintf(vplfile,"   (MAP (SELECTFONT D 0)\n" );
/* 
first attempt was to pass a \special to dvips which draws a white circle
over the dot of a j. From Doob and Platt in Proceedings of Tug93 

   these are absolute PostScript instructions, remember, and this has to work
   at any size. Doob and Platt do a 1.5pt circle which is fine
   for 10pt type, but what about 100pt? We will try to cope with 
   it by doing a solid white rule above and to the right of where we are;
   it extends the width of the j, and the height is the difference between the
   height of a dotless i and a dotless j

   there is a problem with this; if we are already using some gray or
   colour command, we don't want to set the tone back to black regardless, 
   do we... sigh. we have to have made a note earlier

fprintf(vplfile,"      (SPECIAL ps: currentgray /DotlessJGray exch def)\n");
fprintf(vplfile,"      (SPECIAL ps: 1 setgray)\n");
fprintf(vplfile,"      (MOVEUP R %.2f)\n",height(ctwo)*1.02);
fprintf(vplfile,"      (PUSH)\n");
fprintf(vplfile,"      (SETCHAR C j)\n");
fprintf(vplfile,"      (POP)\n");
fprintf(vplfile,"      (SETRULE R %.2f R %.2f)\n",height(c)-height(ctwo),width(c));
fprintf(vplfile,"      (SPECIAL ps:  DotlessJGray setgray)\n");

but the problem with all that is  that the white blob covers any accent
on the dotlessj!

*/

/* instead we set up a clipping path
which covers all of the \dotless i's height + depth of the j,
ie all the j except its dot (with luck....) */
fprintf(vplfile,"      (SPECIAL ps: gsave newpath 0 0 moveto (\\31) true charpath flattenpath pathbbox /IHeight exch def pop pop pop grestore gsave  newpath 0 0 moveto (\\152) true charpath flattenpath pathbbox pop exch /JDepth exch def /JRight exch def /JLeft exch def grestore gsave newpath)\n");
fprintf(vplfile,"      (PUSH)\n");
fprintf(vplfile,"      (MOVEDOWN R %.2f)\n",depth(c));
fprintf(vplfile,"      (SPECIAL ps: JLeft JDepth rmoveto JLeft neg JRight add 0 rlineto 0 JDepth neg IHeight add rlineto JLeft neg JRight add neg 0 rlineto 0 JDepth neg IHeight add neg rlineto closepath clip)\n");
fprintf(vplfile,"      (POP)\n");
fprintf(vplfile,"      (SPECIAL ps: (\\152) show grestore)\n");
fprintf(vplfile,"      )\n");
fprintf(vplfile,"   )\n");
}
}
}



/*--------------------------*/
int getentry()
/* 
read characters until we have a lump with a matching number
of opening and closing brackets. this must be a VPL entity
*/ 
{
   register int c,seen,count ;
   char *cs;
   seen = count = 0 ;
   cs=entry;
   while( (c=getc(vplfile)) != EOF)
   	{
		if ( c != '\n')
   			*cs++ = c ;
   		if (c=='(')
   			{ seen=1 ; count++;}
   		else
			if (c==')')
   				count--;
		if ( (seen != 0) && (count==0))
   		{
		*cs='\0';
		return (0);
		}
	}
   return (1);
}

/*--------------------------*/
void process()
/* 
get each VP entry one by one and store away the metric entries
for each character
*/
{
int x,i,charno;
char *p;
char *q;
char name1[2];
char name2[4];
char namevalue[6];
float value;
struct character *ac;
while ( (x=getentry()) != 1)
{
          if (strncmp(entry,"(CHARACTER",10) == 0) {
   			ac = anewchar();
#ifdef DEBUG
   	fprintf(stderr,".");
#endif
          	sscanf(entry,"(CHARACTER %s %s",name1,name2);
		strcpy(namevalue,strcat(strcat(name1," "),name2));
		ac->name=namespace();
		strcpy(ac->name,namevalue);
		if (( p=strstr(entry,"CHARWD")) != NULL)
   			sscanf(p,"CHARWD R %f",&ac->width);
		if ((p=strstr(entry,"CHARIC")) != NULL)
   			sscanf(p,"CHARIC R %f",&ac->charic);
		if ((p=strstr(entry,"CHARHT")) != NULL)
   			sscanf(p,"CHARHT R %f",&ac->height);
		if ((p=strstr(entry,"CHARDP")) != NULL)
   			sscanf(p,"CHARDP R %f",&ac->depth);
		      }
		  else
              if (strncmp(entry,"(FAMILY ",8) == 0) {
/* its a small caps font maybe; look for things like  (FAMILY TeX-ptmr0-CSC) */
		if ( strncmp(entry+strlen(entry)-4,"CSC)",4) == 0 ) 
		  SCFont=1;
	      }
	  else
              if (strncmp(entry,"(MAPFONT D 1",12) == 0) {
/* in our small caps font, this tells us the size of the smallcaps */
		if ((p=strstr(entry,"FONTAT")) != NULL)
 		  sscanf(p,"FONTAT D %d",&i);
		fontat = (float) i / 1000 ;
		lowergap= lowergap + SC_ACCENT_RAISE;
		      }
#ifdef DEBUG
   	fprintf(stderr,"\n");
#endif

	}
}
/*--------------------------*/
void generateligs()
{
fprintf(vplfile,"(LIGTABLE\n");
fprintf(vplfile,"   (LABEL O 136 ) (COMMENT circumflex)\n");
fprintf(vplfile,"   (LIG C A O 302)\n");
fprintf(vplfile,"   (LIG C E O 312)\n");
fprintf(vplfile,"   (LIG C I O 316)\n");
fprintf(vplfile,"   (LIG C O O 324)\n");
fprintf(vplfile,"   (LIG C U O 333)\n");
fprintf(vplfile,"   (LIG C a O 342)\n");
fprintf(vplfile,"   (LIG C e O 352)\n");
fprintf(vplfile,"   (LIG C i O 356)\n");
fprintf(vplfile,"   (LIG C o O 364)\n");
fprintf(vplfile,"   (LIG C u O 373)\n");
fprintf(vplfile,"   (STOP)\n");
fprintf(vplfile,"   (LABEL O 176 ) (COMMENT tilde) \n");
fprintf(vplfile,"   (LIG C A O 303 )\n");
fprintf(vplfile,"   (LIG C N O 321 )\n");
fprintf(vplfile,"   (LIG C O O 325 )\n");
fprintf(vplfile,"   (LIG C n O 361 )\n");
fprintf(vplfile,"   (LIG C o O 365 )\n");
fprintf(vplfile,"   (LIG C a O 343 )\n");
fprintf(vplfile,"   (STOP)\n");
fprintf(vplfile,"   (LABEL  O 42 ) (COMMENT dieresis)\n");
fprintf(vplfile,"   (LIG C Y O 230)\n");
fprintf(vplfile,"   (LIG C y O 270)\n");
fprintf(vplfile,"   (LIG C A O 304)\n");
fprintf(vplfile,"   (LIG C E O 313)\n");
fprintf(vplfile,"   (LIG C I O 317)\n");
fprintf(vplfile,"   (LIG C O O 326)\n");
fprintf(vplfile,"   (LIG C U O 334)\n");
fprintf(vplfile,"   (LIG C a O 344)\n");
fprintf(vplfile,"   (LIG C i O 357)\n");
fprintf(vplfile,"   (LIG C o O 366)\n");
fprintf(vplfile,"   (LIG C u O 374)\n");
fprintf(vplfile,"   (STOP)\n");
fprintf(vplfile,"   )\n");
return;
}

/*--------------------------*/
main(argc,argv)
int argc;
char *argv[];
{
struct character *ai;
int x,b1,b2,b3,b4,b5,lastext,i;
char *fcopy;
char line[LINELENGTH], cname1[30],cname2[30],cname3[30], *p;
  if (argc!=3) {
    fprintf(stderr,"Usage: %s vplfilename afmfilename\n",argv[0]);
    exit(1);
  }
#ifdef DEBUG
  fprintf(stderr,"This is VPLtoVPL C version VERSION\n");
#endif
  /* check for existence of vpl file */
  (void)strcpy(vplname,argv[1]);
  fcopy=vplname;
  if ( (p=SEARCH(vplname,'.')) == (char *)NULL)
     strcat(vplname,".vpl");
  else
     strcpy(p,".vpl");
  if ( (vplfile = fopen(vplname,"r")) == (FILE *)NULL) {
    fprintf(stderr,"Can't open %s\n",vplname);
    exit(1);
  }
  /* open .afm file */
  (void)strcat(afmname,argv[2]);
  if ( (afmfile = fopen(afmname,"r")) == (FILE *)NULL) {
    fprintf(stderr,"Can't open %s\n",afmname);
    exit(1);
  }
/* get the base name of the font */
strcpy(basefont, fcopy) ;
lastext = -1 ;
for (i=0; basefont[i]; i++)
      if (basefont[i] == '.')
         lastext = i ;
      else if (basefont[i] == '/' || basefont[i] == ':')
         lastext = -1 ;
if (lastext != -1) basefont[lastext]='\0';

/* remove the last character */

*(basefont+strlen(basefont)-1)='\0';

/* read AFM file to find correct raising of accents over uppercase and
lowercase letters */
while ( fgets(line,LINELENGTH,afmfile) != (char *)NULL ) {
	if (lowergap > 0.0 && uppergap > 0.0)
		break;
        if (strncmp(line,"CC ",3) == 0) {
/* look for lines like this:
CC Aacute 2 ; PCC A 0 0 ; PCC acute 195 214 ;
*/
  		sscanf(line,"CC %s %d ; PCC %s %d %d ; PCC %s %d %d",
        		cname1,&b1,cname2,&b2,&b3,cname3,&b4,&b5);
      		if (strcmp(cname1,"Ucircumflex")==0)
      			uppergap = (float)b5;
      		else
       			if (strcmp(cname1,"ucircumflex")==0)
        			lowergap = (float)b5;
  			}
}
#ifdef DEBUG
fprintf(stderr,"read AFM file to find %f & %f, proceeding to main work\n",uppergap,lowergap);
#endif
process();
fclose(vplfile);
#ifdef DEBUG
for (ai=chars; ai; ai = ai->next)
{
	fprintf(vplfile,"(COMMENT %s: wd %.2f ht %.2f dp %.2f ci %.2f)\n",ai->name,
	ai->width,
	ai->height,
	ai->depth,
	ai->charic
	);
}
#endif
if ( (vplfile = fopen(vplname,"a")) == (FILE *)NULL) {
    fprintf(stderr,"Can't open %s for update\n",vplname);
    exit(1);
  }
#ifdef DEBUG
fprintf(stderr,"proceeding to normal characters\n");
#endif
 generatenormal();
#ifdef DEBUG
fprintf(stderr,"proceeding to special work\n");
#endif
 generatespecial();
/* 
i think this is getting a bit much; these do things like make "A do \"A

 generateligs();
*/
 fclose(afmfile);

}

