/*
 * Copyright 1990 by Baylor College of Medicine ALL RIGHTS RESERVED. 
 *
 * This program is subject to a license agreement between 
 * Baylor College of Medicine and MIT. Any use inconsistent with
 * said license and any use by persons other than the faculty, 
 * students and staff at MIT or any use on a computer not operated 
 * as part of the Athena Computing Environment (ACE) is expressly 
 * prohibited.
 */
/*******************************************************************************
* SYSTEM...: Virtual Notebook System
*
* MODULE...: vns_to_ps.c
*
* PURPOSE..:
*   Convert vns fonts to reasonable PostScript fonts.
*
*   The basic idea is to:
*
*     1. Convert the VNS font description into a Family,Weight,Slant,Size
*      description.
*     2. Look up in a table the closest matching PostScript font.
*
* TAG: VNSPS
*
* REVISIONS:
*   Christopher St. John        May 1990 Initial Coding
*   Ross Dargahi                December 1990
*
*******************************************************************************/

#define VNS_TO_PS_C    /*define source name for includes*/

/*******************************************************************************
Include Files
*******************************************************************************/

#include <stdio.h>
#include <strings.h>
#include <ctype.h>
#include "page_to_ps.h"

/*******************************************************************************
Private Defines
*******************************************************************************/

#define FIXED_FONT_NAME    "fixed"
#define VARIABLE_FONT_NAME "variable"
#define DEFAULT_FONT       "helvetica"
#define DEFAULT_WEIGHT     "medium"
#define DEFAULT_SLANT      "r"
#define DEFAULT_PIXEL_SIZE "12"
#define WILD_CHAR          '*'

/*******************************************************************************
Private Data Structures
*******************************************************************************/

typedef struct FontTransTableType 
{
  char   *vnsfont;
  int    bold;
  int    italic;
  char   *psfont;
  P_Bool used;
} FontTransTable;

/*******************************************************************************
Private Global Declarations
*******************************************************************************/

static FontTransTable fonttable[] =  /*Format: vnsfont_family, is bold,
                                               is slanted, PSfont*/
{
  {"helvetica",0,0,"Helvetica",P_NO},
  {"helvetica",1,0,"Helvetica-Bold",P_NO},
  {"helvetica",0,1,"Helvetica-Oblique",P_NO},
  {"helvetica",1,1,"Helvetica-BoldOblique",P_NO},

  {"courier",0,0,"Courier",P_NO},
  {"courier",1,0,"Courier-Bold",P_NO},
  {"courier",0,1,"Courier-Oblique",P_NO},
  {"courier",1,1,"Courier-Bold-Oblique",P_NO},

  {"times",0,0,"Times-Roman",P_NO},
  {"times",1,0,"Times-Bold",P_NO},
  {"times",0,1,"Times-Italic",P_NO},
  {"times",1,1,"Times-BoldItalic",P_NO},

  {"new century schoolbook",0,0,"NewCenturySchlbk-Roman",P_NO},
  {"new century schoolbook",1,0,"NewCenturySchlbk-Bold",P_NO},
  {"new century schoolbook",0,1,"NewCenturySchlbk-Italic",P_NO},
  {"new century schoolbook",1,1,"NewCenturySchlbk-BoldItalic",P_NO},

  {"symbol",0,0,"Symbol",P_NO},

  {NULL,0,0,NULL,0}
};

/*******************************************************************************
Private Function Prototypes
*******************************************************************************/

static char *mystrdup();
static char *tops();
static void toxlfd();

/*******************************************************************************
****************************    PUBLIC FUNCTIONS    ****************************
*******************************************************************************/

void vnstops(fontdesc, rpsfont, rpssize)

char *fontdesc;  /*VNS font description*/
char **rpsfont;  /*returned postscript font*/
char **rpssize;  /*returned font size*/

/*Convert a vns style font description into a PostScript font description. 
Place the results in rpsfont and rpssize. These are malloced and must be freed
by the caller. rpsfont and rpssize are _guaranteed_ to be some valid font 
specification, and are _always_ free'able.*/

{
  char *family_name;
  char *pixel_size;
  char *pssize;
  char *psfont;
  char *slant;
  char *weight_name;

  toxlfd(fontdesc,&family_name,&weight_name,&slant,&pixel_size);

  /*take lookup information and obtain postscript font*/

  if (!(psfont = tops(family_name,weight_name,slant)))
     if (!(psfont = tops(DEFAULT_FONT,weight_name,slant)))
        psfont = tops(DEFAULT_FONT,DEFAULT_WEIGHT,DEFAULT_SLANT);

  /*set the return values*/

  *rpssize = (char *)mystrdup(pixel_size);
  *rpsfont = (char *)mystrdup(psfont);

  /*free temporary storage*/

  free(family_name);
  free(weight_name);
  free(slant);
  free(pixel_size);

  return;

} /*vnstops*/    
  
/*******************************************************************************
****************************    PRIVATE FUNCTIONS    ***************************
*******************************************************************************/

static char *mystrdup(s)

char *s; /*string to be duplicated*/

/*The regular strdup crashes if passed a NULL pointer, this one just returns
null.*/

{
  if (s == NULL)
     return(NULL);
  else
     return((char *)strdup(s));

} /*mystrdup*/

/******************************************************************************/
static int xlfdtometrics(font_name)

char *font_name;

/*Using the XLFD given, get back a set of font descriptions sufficient to 
exactly place each character as on the X display. Assume that we are connected
to some server.*/

{
/*
  XFontStruct *font;
  int h;

  font = XLoadQueryFont(contect.dpy,font_name);

  h = font->ascent + font->descent;
  return h;
*/

} /*xlfdtometrics*/

/******************************************************************************/
static void toxlfd(fontdesc,family_name,weight_name,slant,pixel_size)

char *fontdesc;
char **family_name;
char **weight_name;
char **slant;
char **pixel_size;

/*Take a XLFD description and break it apart malloc's room for family_name, 
weight_name, slant, pixel_size. All of these _must_ be freed by the caller...*/

{
  char tfont[255];
  char *foundry;
  char *setwidth_name;
  char *add_style_name;
  char last,this;
  int i,j;

  /*Make a temporary copy of the fontdesc so we can use strtok function. Note
   *that the convention in X is that font description/name char *s must be 255 
   *characters or less.*/

  if (fontdesc != NULL)
   {
     last = '\0';

     /*If we want to use strtok, we cannot have two delimiters side by side or
      *both will be skipped when what we want is for a blank (or something) to 
      *be read in. So replace all the occurences of "--" with "-*-", which
      *gives an incorrect XLFD string but at this point it does not matter...*/

     for (i = 0, j = 0; i < 255 && j < 255 && fontdesc[i] != '\0'; i++)
      {
        this = fontdesc[i];

        if (isascii(this)&&(isgraph(this)||isspace(this)))
         {
           if (last=='-' && this == '-')
            {
              tfont[j++]='*';
            }

           tfont[j++]=this;
           last=this;
         }
      }

     tfont[j]='\0';
   }

  foundry = NULL;
  *family_name = NULL;
  *weight_name = NULL;
  *slant = NULL;
  setwidth_name = NULL;
  add_style_name = NULL;
  *pixel_size = NULL;

  if (fontdesc != NULL && strlen(tfont) != 0) 
     if (strcmp(tfont,FIXED_FONT_NAME) == 0)
      {
        *family_name   = (char *)mystrdup((char *)"courier");
        *weight_name   = (char *)mystrdup((char *)"medium");
        *slant         = (char *)mystrdup((char *)"r");
        *pixel_size    = (char *)mystrdup((char *)"10");
      } 
     else if (strcmp(tfont,VARIABLE_FONT_NAME)==0)
      {
        *family_name   = (char *)mystrdup((char *)"helvetica");
        *weight_name   = (char *)mystrdup((char *)"medium");
        *slant         = (char *)mystrdup((char *)"r");
        *pixel_size    = (char *)mystrdup((char *)"12");
      }
     else 
      { /* Assume is is in XLFD format */
        foundry        = (char *)strtok(tfont,"-");
        *family_name   = (char *)mystrdup(strtok(NULL,"-"));
        *weight_name   = (char *)mystrdup(strtok(NULL,"-"));
        *slant         = (char *)mystrdup(strtok(NULL,"-"));
        setwidth_name  = (char *)strtok(NULL,"-");
        add_style_name = (char *)strtok(NULL,"-");
        *pixel_size    = (char *)mystrdup(strtok(NULL,"-"));
      }

  /*At this point we guarantee that family_name,weight_name slant and
   *pixel_size are all either NULL or pointing to a valid string.*/

  if (!(*family_name) || **family_name == WILD_CHAR)
   {
     if (*family_name)
        free(*family_name);

     *family_name = (char *)mystrdup(DEFAULT_FONT);
   }

  if (!(*weight_name) || **weight_name == WILD_CHAR)
   {
     if (*weight_name) 
        free(*weight_name);

     *weight_name = (char *)mystrdup(DEFAULT_WEIGHT);
   }
   
  if (!(*slant) || **slant == WILD_CHAR)
   {
     if (*slant)
        free(*slant);

     *slant = (char *)mystrdup(DEFAULT_SLANT);
   }
   
  if (**slant == 'o')
     **slant = 'i';

  if (!(*pixel_size) || **pixel_size == WILD_CHAR)
   {
     if (*pixel_size)
        free(*pixel_size);

     *pixel_size = (char *)mystrdup(DEFAULT_PIXEL_SIZE);
   }

  return;

} /*toxlfd*/

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

static char *tops(family_name,weight_name,slant)

char *family_name;
char *weight_name;
char *slant;

/*Convert a family name, weight and slant to a PostScript font name using a
table. Does not malloc any memory. Do not free the returned value and copy it
if you want to keep it.*/

{
  char *psfont;
  int i;

  psfont = NULL;

  for (i = 0; fonttable[i].vnsfont != NULL; i++)
     if (strcmp(fonttable[i].vnsfont, family_name) == 0 &&
         fonttable[i].bold == (strcmp(weight_name, "bold") == 0) &&
         fonttable[i].italic == (strcmp(slant, "i") == 0))
        psfont = (char *)(fonttable[i].psfont);

  return(psfont);

} /*tops*/

/*******************************************************************************
Private undefines
*******************************************************************************/

#undef VNS_TO_PS_C

