/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT (C) Microsoft Corporation, 1989                                 */
/* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
/*                                                                           */
/*    The following IBM OS/2 WARP source code is provided to you solely for  */
/*    the purpose of assisting you in your development of OS/2 WARP device   */
/*    drivers. You may use this code in accordance with the IBM License      */
/*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
/*    Copyright statement may not be removed.                                */
/*                                                                           */
/*****************************************************************************/
/**************************************************************************
 *
 * SOURCE FILE NAME = FONTPREP.C
 *
 * DESCRIPTIVE NAME = Font preperation utility
 *
 *
 * VERSION = V2.0
 *
 * DATE      02/25/88
 *
 * DESCRIPTION This program runs the AFM2BIN compiler on all available
 *             Adobe ".afm" files, checks all Adobe ".ppd" files to
 *             make sure that we have covered all of the fonts that
 *             any of our printers support, and then generates two
 *             source code include files:  "fontres.h" is a header
 *             that lets our driver at runtime convert the name of a
 *             requested font from an ascii string to a resource
 *             number.  "psfont.rc" is a list of all the font resource
 *             numbers and their associated data files that is used by
 *             the resource compiler at driver build time.
 *
 * FUNCTIONS
 *                 GetFileNames
 *                 LoadDiskFile
 *                 GetFontSupported
 *                 FindOneFontAndVersion
 *                 MakeIncFiles
 *                 main
 *
 *
 * NOTES
 *
 *  Usage:         fontprep [-v]
 *                      v = verbose mode
 *
 *  Assumptions:   (1)  All .afm files are in directory "..\afm"
 *                 (2)  All .ppd files are in directory "..\ppd"
 *                 (3)  All include files are in directory "..\inc\"
 *
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/

#define INCL_BASE
#define INCL_DOSFILEMGR
#include <os2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <search.h>
#include "fontprep.h"

/*
** Global variables
                                                                             */

FILELIST flAfmFiles,                   /* List of all .afm files found       */
         flPpdFiles;                   /* List of all .ppd files found       */
FONTLIST fntlFonts;                    /* List of all fonts we have .afms
                                          for                                */
CHAR     cDataBuf[MAX_BUFFSIZE];       /* Buffer for reading in files        */
PSZ      pszCurrentDir[40];            /* Recall our initial working
                                       ** directory                          */

int CompareStrings (const void *pString1, const void *pString2)
{
  return( strcmp( (const char *) pString1, (const char *) pString2 ) );
}

/***************************************************************************
 *
 * FUNCTION NAME = GetFileNames
 *
 * DESCRIPTION   = Given a filename containing wildcards and an empty
 *                 structure, stuff the structure with a list of all
 *                 explicit filenames that match the wildcard
 *                 expression.
 *
 * INPUT         = pszWildCardName - wildcarded name
 *                 pflFileNameList - filename list
 *
 * OUTPUT        = NONE.
 *
 * RETURN-NORMAL = NONE.
 * RETURN-ERROR  = NONE.
 *
 *************************************************************************   */

void GetFileNames(PSZ pszWildCardName,PFILELIST pflFileNameList)
{
  CHAR szPath[MAX_FILENAMESIZE];
  SHORT i;
  ULONG sCount;
  HDIR sHandle;
  FILEFINDBUF3 flInfo;
  APIRET rc;

  i = 0;
  sHandle = HDIR_SYSTEM;               /* Search handle                      */
  sCount = 1;                          /* We want one match at a time        */

  strcpy( szPath, pszWildCardName );   /* Wild carded name                 */

  rc = DosFindFirst( szPath, &sHandle, 0, &flInfo, sizeof( flInfo ),
                &sCount, FIL_STANDARD );

  while (sCount && ( !rc ) )
  {
    strcpy( pflFileNameList->pszFileName[i++], flInfo.achName );
    rc = DosFindNext( sHandle, (PVOID) &flInfo, sizeof( flInfo ), &sCount );
  }
  pflFileNameList->sNumFiles = i;      /* Total number of matches found      */

  /*
  ** the sort is to allow the builders to be unconcerned about the order
  ** that the files are in
  */
  qsort( pflFileNameList->pszFileName[0], i, MAX_FILENAMESIZE, CompareStrings );
}

/***************************************************************************
 *
 * FUNCTION NAME = LoadDiskFile
 *
 * DESCRIPTION   = Load the specified disk file into the input buffer
 *                 and return the file's length in bytes.  If the file
 *                 is longer than MAX_BUFFSIZE, we will only read in a
 *                 portion of the file.
 *
 * INPUT         = pszFileName - diskfile name
 *
 * OUTPUT        = NONE.
 *
 * RETURN-NORMAL = NONE.
 * RETURN-ERROR  = NONE.
 *
 *************************************************************************   */

SHORT LoadDiskFile(PSZ pszFileName)
{
  FILE *hFileHandle;
  SHORT sLength;

  hFileHandle = fopen( pszFileName, "r" );

  if (hFileHandle == NULL )
  {
    printf("Cannot open %s", pszFileName);
    DosSetCurrentDir( (PCHAR) pszCurrentDir );
    exit(1);
  }
  sLength = (SHORT)fread( &cDataBuf, 1, MAX_BUFFSIZE, hFileHandle);
  fclose(hFileHandle);
  return (sLength);
}

/***************************************************************************
 *
 * FUNCTION NAME = GetFontSupported
 *
 * DESCRIPTION   = Given the filename of an Adobe .afm file, this
 *                 function determines the name of the font supported,
 *                 and its version string.
 *
 * INPUT         = pszAfmFileName - .afm file to check
 *                 pszFontName    - where to put the font name supported
 *                 pszFontFull    - full font name
 *                 pszVersion     - where to put the version string
 *
 * OUTPUT        = NONE.
 *
 * RETURN-NORMAL = NONE.
 * RETURN-ERROR  = NONE.
 *
 *************************************************************************   */

void GetFontSupported(PSZ pszAfmFileName,PSZ pszFontName,PSZ pszFontFull,PSZ
                       pszVersion)
{
  SHORT sLength,iLength;
  PSZ pszBuf;
  PSZ pszFontSupported;
  PSZ pszFullName;
  PSZ pszVersionSupported;

  /*
  ** Load the .afm file and pretend it is one long ascii string
                                                                             */

  sLength = LoadDiskFile(pszAfmFileName);
  pszBuf = cDataBuf;
  pszBuf[sLength] = '\0';

  /*
  ** Find where in the .afm file the font name is given
                                                                             */

  pszFontSupported = strstr(pszBuf, "FontName ");

  if (pszFontSupported)
  {

    /*
    ** Copy this font name to the caller's buffer
                                                                             */

    pszFontSupported += 9;
    pszBuf = pszFontSupported;

    while (*pszBuf > 31)
      pszBuf++;
    *pszBuf++ = '\0';
    strcpy(pszFontName, pszFontSupported);

    /*
    ** Find where in the .afm file is fullname supported
                                                                             */

    pszFullName = strstr(pszBuf, "FullName ");
    pszFullName += 9;
    pszBuf = pszFullName;
    iLength = 01;

    /*
    ** some of the font full names can be greater than 32 bytes
    ** truncate them to 31 bytes .
                                                                             */

    while (*pszBuf > 31 && iLength++ < MAX_FONTNAMELEN)
      pszBuf++;
    *pszBuf++ = '\0';
    strcpy(pszFontFull, pszFullName);

    /*
    ** Find where in the .afm file the version string is given
                                                                             */

    pszVersionSupported = strstr(pszBuf, "Version ");

    if (pszVersionSupported)
    {

      /*
      ** Copy this version string to the caller's buffer
                                                                             */

      pszVersionSupported += 8;
      pszBuf = pszVersionSupported;

      while (*pszBuf > 31)
        pszBuf++;
      *pszBuf = '\0';
      strcpy(pszVersion, pszVersionSupported);
    }

    else

      /*
      ** If we couldn't find the version string, set caller's buffer to null
                                                                             */

      *pszVersion = '\0';
  }

  else
  {

    /*
    ** If we couldn't find the font name, set both caller's buffers to null
                                                                             */

    *pszFontName = '\0';
    *pszFontFull = '\0';
    *pszVersion = '\0';
  }
}

/***************************************************************************
 *
 * FUNCTION NAME = FindOneFontAndVersion
 *
 * DESCRIPTION   = Find the given font name and version string in the
 *                 list of all fonts supported.  If we do find a
 *                 match, do nothing with it.  But if there is no
 *                 match, issue a warning message.
 *
 *          
 *                 ADOBE INFORMS US THAT DIFFERENCES BETWEEN TWO VERSIONS
 *                 OF THE SAME FONT ARE INSIGNIFICANT FOR OUR USES.
 *                 THEREFORE, OUR DRIVER WILL DISREGARD VERSION NUMBER
 *                 AND JUST MAINTAIN ONE VERSION OF EACH FONT.
 *
 * INPUT         = PSZFONTNAME - FONT NAME TO LOOK FOR
 *                 PSZVERSION  - VERSION TO LOOK FOR
 *                 PFNTLFONTS  - LIST OF ALL FONTS SUPPORTED
 *                 FVERBOSE    - SHALL WE BE VERBOSE ABOUT THIS?
 *
 * OUTPUT        = NONE.
 *
 * RETURN-NORMAL = NONE.
 * RETURN-ERROR  = NONE.
 *
 **************************************************************************/

void FindOneFontAndVersion(PSZ pszFontName,PSZ pszVersion,PFONTLIST pfntlFonts,
                            BOOL fVerbose)
{
  SHORT i;
  BOOL j;


  for (i = 0; j && (i < pfntlFonts->sNumFonts); i++)
  {
    j = strcmp(pszFontName, pfntlFonts->pszFontName[i]);
  }

  if (j)
    printf("Warning: Font \042%s\042 version \042%s\042 unsupported\n",
       pszFontName, pszVersion);

  else

    if (fVerbose)
      printf("Font \042%s\042 version \042%s\042 is supported\n", pszFontName,
         pszVersion);
}

/***************************************************************************
 *
 * FUNCTION NAME = MakeIncFiles
 *
 * DESCRIPTION   = This function plants two text files in the include
 *                 subdirectory.
 *
 *                 fontres.h : Contains an array mapping font name strings
 *                             to resource numbers for use by the driver
 *                             at run time
 *                 psfont.rc : Contains a list of all .pfm files and the
 *                             resource number to be assigned to each                                    NONE.
 *
 * INPUT         = pflAfmFileNames - List of all .afm files
 *                 pfntlFontNames  - List of all fonts supported
 *
 * OUTPUT        = NONE.
 *
 * RETURN-NORMAL = NONE.
 * RETURN-ERROR  = NONE.
 *
 *************************************************************************   */

void MakeIncFiles(PFILELIST pflAfmFileNames,PFONTLIST pfntlFontNames)
{
  FILE *fFileHandle1,*fFileHandle2;
  SHORT i,j;
  CHAR szName[MAX_FILENAMESIZE];

  /*
  ** Open both files and write the headers
  */
#if 0
//if (DosQueryPathInfo("psfont.rc", 2)) == -1)
//{
//  printf("changing psfont.rc to be writable.\n");
//
//  if (chmod("psfont.rc", S_IWRITE) == -1)
//    perror("mode of psfont.rc could not be changed.\n");
//}
#endif
  fFileHandle1 = fopen("psfont.rc", "w");

  if (!fFileHandle1)
  {
    perror("psfont.rc could not be opened.\n");
    exit(1);
  }
  fprintf(fFileHandle1, "\n#define   FONTGRP    300\n\n");

#if 0
//if ((access("fontres.h", 2)) == -1)
//{
//  printf("changing fontres.h to be writable.\n");
//
//  if (chmod("fontres.h", S_IWRITE) == -1)
//    perror("mode of fontres.h could not be changed.\n");
//}
#endif
  fFileHandle2 = fopen("fontres.h", "w");

  if (!fFileHandle2)
  {
    perror("fontres.h could not be opened.\n");
    exit(1);
  }
  fprintf(fFileHandle2, "\n/*******************************************/");
  fprintf(fFileHandle2, "\n/* inc\\fontres.h                           */");
  fprintf(fFileHandle2, "\n/*                                         */");
  fprintf(fFileHandle2, "\n/* This file contains a list of all the    */");
  fprintf(fFileHandle2, "\n/* fonts we have in our resources.  The    */");
  fprintf(fFileHandle2, "\n/* index of each font name in the list     */");
  fprintf(fFileHandle2, "\n/* corresponds to its resource number.     */");
  fprintf(fFileHandle2, "\n/*                                         */");
  fprintf(fFileHandle2, "\n/* This file was generated by the font     */");
  fprintf(fFileHandle2, "\n/* preparation utility, fontprep.          */");
  fprintf(fFileHandle2, "\n/*******************************************/");
  fprintf(fFileHandle2, "\n\n#define     FONTGRP   300\n\n");
  fprintf(fFileHandle2, "PCHAR FontResourceName[] =\n   { \042-\042, ");
  fprintf(fFileHandle2,
     "                           \057* There is no resource zero *\057\n");

  /*
  ** For each font we support, write out appropriate information
                                                                             */

  for (i = 0; i < pflAfmFileNames->sNumFiles; i++)
  {
    fprintf(fFileHandle1, "RESOURCE  FONTGRP%5d  LOADONCALL  afm\\", (i+1));

    for (j = 0; pflAfmFileNames->pszFileName[i][j] != '.'; j++)
      szName[j] = pflAfmFileNames->pszFileName[i][j];
    szName[j] = '\0';
    fprintf(fFileHandle1, "%s.pfm\n", szName);
    fprintf(fFileHandle2, "     \042");
    fprintf(fFileHandle2, "%s\042", pfntlFontNames->pszFontName[i]);
    fprintf(fFileHandle2, ",\n");
  }
  fprintf(fFileHandle2, "       0\n  } ;\n\n");
  fprintf(fFileHandle2, "PCHAR FontFullName[] =\n   { \042-\042, ");
  fprintf(fFileHandle2,
     "                           \057* There is no resource zero *\057\n");

  /*
  ** For each font we support, write out appropriate information
                                                                             */

  for (i = 0; i < pflAfmFileNames->sNumFiles; i++)
  {
    fprintf(fFileHandle2, "     \042");
    fprintf(fFileHandle2, "%s\042", pfntlFontNames->pszFullName[i]);
    fprintf(fFileHandle2, ",\n");
  }

  /*
  ** Write out the trailers and close the files
                                                                             */

  fprintf(fFileHandle1, "\n");
  fclose(fFileHandle1);
  fprintf(fFileHandle2, "       0\n  } ;\n\n");
  fclose(fFileHandle2);
}

/***************************************************************************
 *
 * FUNCTION NAME = main
 *
 * DESCRIPTION   = Mainline function
 *
 * INPUT         = argc - number of commandline arguments
 *                 argv - pointer to array of commandline arguments
 *
 * OUTPUT        = NONE.
 *
 * RETURN-NORMAL = NONE.
 * RETURN-ERROR  = NONE.
 *
 *************************************************************************   */

main(int argc,char **argv)
{
  BOOL fVerbose = FALSE;               /* Operate in verbose mode?           */
  SHORT i;
  ULONG  ulPathLength = sizeof( pszCurrentDir );
  CHAR szCommandLine[MAX_LINESIZE];    /* Command to invoke afm2bin          */

  /*
  ** Parse the command line arguments
                                                                             */

  printf(
  "\nMicrosoft (R) PostScript Driver Font Preparation Utility  Version 1.00\n")
     ;
  printf("Copyright (c) Microsoft Corp 1988.  All rights reserved.\n\n");

  if (argc != 1)
  {

    if ((argc == 2) && (argv[1][1] == 'v') && (!argv[1][2]) && ((*argv[1] ==
       '/') || (*argv[1] == '-')))
    {
      fVerbose = TRUE;
    }

    else
    {
      printf("Usage: %s [-v]\n  where v = verbose mode", argv[0]);
      exit(1);
    }
  }

  /*
  ** Get our initial working directory so that we may return
  */
  if (DosQueryCurrentDir( 0, (PBYTE) pszCurrentDir, &ulPathLength ) != 0)
  {
    printf("Can't get current directory");
    exit(1);
  }

#if 0
//if ( DosSetCurrentDir ("..\\afm") )
//{
//  printf("Can't find the afm subdirectory");
//  DosSetCurrentDir( (PCHAR) pszCurrentDir );
//  exit(1);
//}
#endif
  GetFileNames("*.afm", &flAfmFiles);
  fntlFonts.sNumFonts = flAfmFiles.sNumFiles;

  for (i = 0; i < flAfmFiles.sNumFiles; i++)
  {
    GetFontSupported(flAfmFiles.pszFileName[i], fntlFonts.pszFontName[i],
       fntlFonts.pszFullName[i], fntlFonts.pszVersion[i]);
    strcpy(szCommandLine, "afm2bin ");
    strcat(szCommandLine, flAfmFiles.pszFileName[i]);

    if (fVerbose)
      printf("\nInvoking afm2bin compiler: %s\n", szCommandLine);
    system(szCommandLine);
  }

  if (fVerbose)
  {
    printf("\nA total of %d fonts will be supported.\n\n", fntlFonts.sNumFonts)
       ;

    for (i = 0; i < fntlFonts.sNumFonts; i++)
    {
      printf("    #%2d: %s", (i+1), fntlFonts.pszFontName[i]);
      printf(" (%s)\n", fntlFonts.pszVersion[i]);
    }
  }

  /*
  ** Given the information we have collected, generate the include files
                                                                             */

  if ( DosSetCurrentDir ("..\\inc"))
  {
    printf("Can't find the inc subdirectory");
    DosSetCurrentDir( (PCHAR) pszCurrentDir );
    exit(1);
  }
  printf("\n\nGenerating include files in INC directory.\n");
  MakeIncFiles(&flAfmFiles, &fntlFonts);

  /*
  ** Restore state, do a summary, and exit
                                                                             */

   DosSetCurrentDir( (PCHAR) pszCurrentDir );
  printf("\nThe PostScript printer driver will support %d printers\n",
     flPpdFiles.sNumFiles);
  printf("and a total of %d different fonts.\n", flAfmFiles.sNumFiles);

  if (fVerbose)
    printf("\nOperation complete\n");
  exit(0);
}


