/*
//
//   ADOBE SYSTEMS INCORPORATED
//   Copyright (C) 2000-2003 Adobe Systems Incorporated
//   All rights reserved.
//
//   NOTICE: Adobe permits you to use, modify, and distribute this file
//   in accordance with the terms of the Adobe license agreement
//   accompanying it. If you have received this file from a source other
//   than Adobe, then your use, modification, or distribution of it
//   requires the prior written permission of Adobe.
//
*/
/*
 * MyPDFLibUtils.cpp
 *
 */
 
#include "MyPDFLibUtils.h"

#include "PDFInit.h"
#include "PDFLCalls.h"
#include "ASCalls.h"
#include "PDCalls.h"
#include <limits.h>

#if WIN_PLATFORM
#include "Windows.h"
#endif

#if MAC_PLATFORM
#include "macutils.h"
#else
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#endif

ExtensionID   gExtensionID  = 0; 
static   void *  scratchFourBytes;

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

               Memory Allocators
               Very simple memory management w/o error checking.

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

static   void *  MyPDFLMemAllocProc( void * clientData,  ASSize_t  size)
{
                return  malloc(size);
}

static   void *  MyPDFLMemRealloc( void * clientData,  void * ptr,  ASSize_t  size)
{
                return  realloc(ptr, size);
}

static   void   MyPDFLMemFree( void  *clientData,  void * ptr)
{
                if  (ptr !=  NULL)
                               free(ptr);
}

static   ASSize_t   MyPDFLMemAvail( void  *clientData)
{
                return  INT_MAX;
}

/* This variable is passed as a part of PDFLData for PDFLInit. */
static  TKAllocatorProcs  gMyPDFLMemAllocProcs  = {
                MyPDFLMemAllocProc,                          /* ASMemAllocProc */
                MyPDFLMemRealloc,                              /* ASMemReallocProc */
                MyPDFLMemFree,                                    /* ASMemFreeProc */
                MyPDFLMemAvail,                                  /* ASMemAvailProc */
                NULL                                                                         /* clientData */
};

static  TKAllocatorProcs*  PDFLGetMemAllocProcs()
{
                return  &gMyPDFLMemAllocProcs;
}

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

               Macintosh only
               - We take a note of app's FSSpec.

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


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

               Directory List Handler

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

static   void   CopyStrToASUTF16(ASUTF16Val  *utf,  const   char  *s) 
{
        while  ((*utf++ = *s++) != (ASUTF16Val) '\0' )
               ;
}

#if WIN_PLATFORM

static   int   PDFLGetDirList_Win(ASUTF16Val  ***dirListP)
{
                static     ASUTF16Val            *sDirListP[2];
                static     ASUTF16Val            sDirList[2][MAX_PATH];    /* to avoid malloc */
                static     int                          sDirCount = -1;

                if  (sDirCount == -1)
               {
                                for  ( int  i=0; i<2; i++)
                                               sDirListP[i] = sDirList[i];

                               sDirCount = 0;

                                char  aFolder[_MAX_PATH];

/*****************************************************************************
Important Note;
Correct resource paths are required here for PDF Library to locate the
fonts and CMaps. The default resource paths provided here for the Windows
platform should work as is, regardless of the PDFL SDK installation
path. Please adjust paths for Mac and UNIX platforms as well.
******************************************************************************/

#ifdef LOAD_PLUGIN
                                strcpy_safe(aFolder,  sizeof (aFolder),  "..\\..\\..\\..\\..\\Resource\\Font" );
                                CopyStrToASUTF16(sDirList[sDirCount++], aFolder);
                                strcpy_safe(aFolder,  sizeof (aFolder),  "..\\..\\..\\..\\..\\Resource\\CMap" );
                                CopyStrToASUTF16(sDirList[sDirCount++], aFolder);
#else
                                strcpy_safe(aFolder,  sizeof (aFolder),  "..\\..\\..\\Resource\\Font" );
                                CopyStrToASUTF16(sDirList[sDirCount++], aFolder);
                                strcpy_safe(aFolder,  sizeof (aFolder),  "..\\..\\..\\Resource\\CMap" );
                                CopyStrToASUTF16(sDirList[sDirCount++], aFolder);
#endif
               }

               *dirListP = sDirListP;
                return  sDirCount;
}

#elif MAC_PLATFORM

#define MAX_PATH 1024
// Sub-directories of resource directory
const   unsigned   int  NO_OF_RESOURCE_DIR = 2;
const   char * SUB_RESOURCE_DIR[ NO_OF_RESOURCE_DIR ] = {  "Font" ,  "CMap"  }; 

int  PDFLGetDirList_Mac(  char *** dirListP );

                //Simply add font and cmap to resourceDirectory
int  PDFLGetDirList_Mac(  char *** dirListP ) {       
               
                char  resourceDirectory[MAX_PATH];
                static     char        *sDirListP[NO_OF_RESOURCE_DIR];
                static     char        sDirList[NO_OF_RESOURCE_DIR][MAX_PATH];
                static     int                          sDirCount = -1;
               
                if  (sDirCount == -1)
               {
                                for  ( int  i=0; i<NO_OF_RESOURCE_DIR; i++)
                                               sDirListP[i] = sDirList[i];
                               
                               sDirCount = 0;

                               CFBundleRef bundleRef = CFBundleGetMainBundle();
                               CFURLRef baseURL = CFBundleCopyBundleURL(bundleRef);
#ifdef LOAD_PLUGIN
                               CFURLRef resourceURL = CFURLCreateWithFileSystemPathRelativeToBase (kCFAllocatorDefault,
                                                                                                                                                                                                                                                                                                               CFSTR( "../../../../../../Resource/" ),
                                                                                                                                                                                                                                                                                                               kCFURLPOSIXPathStyle,  true , baseURL);
#else
                               CFURLRef resourceURL = CFURLCreateWithFileSystemPathRelativeToBase (kCFAllocatorDefault,
                                                                               CFSTR( "../../../../Resource/" ),
                                                                               kCFURLPOSIXPathStyle,  true , baseURL);
#endif
                               CFURLGetFileSystemRepresentation (resourceURL,  true , ( unsigned   char *)resourceDirectory,  MAX_PATH);
               
                               CFRelease(baseURL);
                               CFRelease(resourceURL);

                                char  fontPath[ NO_OF_RESOURCE_DIR   ][  MAX_PATH  ];
                                for (  int  i = 0; i < NO_OF_RESOURCE_DIR; i++ ) {
                                                strncpy_safe(fontPath[ i ],  sizeof (fontPath[ i ]), resourceDirectory,  sizeof (resourceDirectory));
                                                strcat_safe(fontPath[ i ],  sizeof (fontPath[ i ]),  "/" );
                                                strcat_safe(fontPath[ i ],  sizeof (fontPath[ i ]), SUB_RESOURCE_DIR[ i ]);
                               }
       
                                for (  int  i = 0; i < NO_OF_RESOURCE_DIR; i++ )
                                                strncpy_safe(sDirList[ i ],  MAX_PATH, fontPath[ i ],  sizeof (fontPath[ i ]));
                                               
                               sDirCount = NO_OF_RESOURCE_DIR;
               }

       *dirListP = sDirListP;
       
        return  NO_OF_RESOURCE_DIR;
}

#elif UNIX_PLATFORM

static   int  PDFLGetDirList_Unx( char  ***dirListP)
{
                static     char        *sDirListP[2];
                static     char        sDirList[2][256];              /* to avoid malloc */
                static     int                          sDirCount = -1;

                if  (sDirCount == -1)
               {
                                for  ( int  i=0; i<2; i++)
                                               sDirListP[i] = sDirList[i];

                               sDirCount = 0;

                                char  aFolder[256];

#ifdef LOAD_PLUGIN
                                strcpy_safe(aFolder,  sizeof (aFolder),  "../../../../../Resource/Font" );
                                strncpy_safe(sDirList[sDirCount],  sizeof (sDirList[sDirCount]), aFolder,  sizeof (aFolder));
                               sDirCount++;
                                strcpy_safe(aFolder,  sizeof (aFolder),  "../../../../../Resource/CMap" );
                                strncpy_safe(sDirList[sDirCount],  sizeof (sDirList[sDirCount]), aFolder,  sizeof (aFolder));
                               sDirCount++;
#else
                                strcpy_safe(aFolder,  sizeof (aFolder),  "../../../Resource/Font" );
                                strncpy_safe(sDirList[sDirCount],  sizeof (sDirList[sDirCount]), aFolder,  sizeof (aFolder));
                               sDirCount++;
                                strcpy_safe(aFolder,  sizeof (aFolder),  "../../../Resource/CMap" );
                                strncpy_safe(sDirList[sDirCount],  sizeof (sDirList[sDirCount]), aFolder,  sizeof (aFolder));
                               sDirCount++;
#endif
               }
               *dirListP = sDirListP;
                return  sDirCount;
}

#endif

static   int   PDFLGetDirList( void  *list)
{
               #if WIN_PLATFORM
                                return   PDFLGetDirList_Win((ASUTF16Val  ***)list);
               #elif MAC_PLATFORM
                /*
                               Current Mac code should work, but causes library to blow up,
                               so commenting out code for time being

               */
                                return  PDFLGetDirList_Mac(( char ***)list);
               #elif UNIX_PLATFORM
                                return  PDFLGetDirList_Unx(( char  ***)list);
               #endif
}
#ifdef LOAD_PLUGIN
const   unsigned   int  NO_OF_PLUGIN_DIRS = 1;  /* Currently we ship only 1 Plugin. We can increase this number and 
                                                                                                                                                                                   put the Plugin path in sDirList if there are more plugins */
#if WIN_PLATFORM
static   int  PDFLGetPluginDirList_Win(ASUTF16Val  ***dirListP)
{
                static     ASUTF16Val            *sDirListP[NO_OF_PLUGIN_DIRS]; 
                static     ASUTF16Val            sDirList[NO_OF_PLUGIN_DIRS][MAX_PATH];    /* to avoid malloc */
                static     int                          sDirCount = -1;

                if  (sDirCount == -1)
               {
                                for  ( int  i=0; i<NO_OF_PLUGIN_DIRS; i++)
                                               sDirListP[i] = sDirList[i];

                               sDirCount = 0;

                                char  aFolder[_MAX_PATH];

                                /*****************************************************************************
                               Important Note;
                               Correct resource paths are required here for PDF Library to locate the
                               fonts and CMaps. The default resource paths provided here for the Windows
                               platform should work as is, regardless of the PDFL SDK installation
                               path. Please adjust paths for Mac and UNIX platforms as well.
                               ******************************************************************************/

#ifndef _WIN64
                                strcpy_safe(aFolder,  sizeof (aFolder),  "..\\..\\..\\Libs\\Winintel" );
#else 
                                strcpy_safe(aFolder,  sizeof (aFolder),  "..\\..\\..\\Libs\\Windows_x64" );
#endif
                                CopyStrToASUTF16(sDirList[sDirCount++], aFolder);
               }

               *dirListP = sDirListP;
                return  sDirCount;
}
#elif MAC_PLATFORM

static   int  PDFLGetPluginDirList_Mac( char  ***dirListP)
{
        static   char              *sDirListP[NO_OF_PLUGIN_DIRS];
        static   char              sDirList[NO_OF_PLUGIN_DIRS][MAX_PATH];        /* to avoid malloc */
        static             int                  sDirCount = -1;
       
        if  (sDirCount = -1)
       {
                for  ( int  i=0; i<NO_OF_PLUGIN_DIRS; i++)
                       sDirListP[i] = sDirList[i];
               
               sDirCount = 0;
               
               CFBundleRef bundleRef = CFBundleGetMainBundle();
               CFURLRef baseURL = CFBundleCopyBundleURL(bundleRef);
#ifndef __LP64__
               CFURLRef resourceURL = CFURLCreateWithFileSystemPathRelativeToBase (kCFAllocatorDefault,
                                                                                                                                                       CFSTR( "../../../../Libs/mac" ),
                                                                                                                                                       kCFURLPOSIXPathStyle,  true , baseURL);
#else
               CFURLRef resourceURL = CFURLCreateWithFileSystemPathRelativeToBase (kCFAllocatorDefault,
                                                                                                                                                       CFSTR( "../../../../Libs/mac_x64" ),
                                                                                                                                                       kCFURLPOSIXPathStyle,  true , baseURL);
#endif
                //CFURLRef tempURL;
                char  pluginPath[NO_OF_PLUGIN_DIRS][MAX_PATH];
                for  (  int  i=0; i < NO_OF_PLUGIN_DIRS; i++) {
                        //tempURL = CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault, resourceURL, CFSTR(""), true);
                       CFURLGetFileSystemRepresentation (resourceURL,  true , (UInt8*)pluginPath[ i ],  MAX_PATH);
                       strcpy( sDirList[ i ], pluginPath[ i ] );
               }
               
               sDirCount = NO_OF_PLUGIN_DIRS;
               CFRelease(baseURL);
               CFRelease(resourceURL); 
               
       }
       *dirListP = sDirListP;
        return  sDirCount;
       
}
#elif UNIX_PLATFORM

static   int  PDFLGetPluginDirList_Unx( char  ***dirListP)
{
                static     char        *sDirListP[NO_OF_PLUGIN_DIRS];
                static     char        sDirList[NO_OF_PLUGIN_DIRS][256];              /* to avoid malloc */
                static     int                          sDirCount = -1;

                if  (sDirCount == -1)
               {
                                for  ( int  i=0; i<NO_OF_PLUGIN_DIRS; i++)
                                               sDirListP[i] = sDirList[i];

                               sDirCount = 0;
                                char  aFolder[256];
#ifdef LINUX32
                                strcpy_safe(aFolder,  sizeof (aFolder),  "../../../Libs/linux" );
#elif LINUX64
                                strcpy_safe(aFolder,  sizeof (aFolder),  "../../../Libs/linux_x64" );
#elif SOLARIS
                                strcpy_safe(aFolder,  sizeof (aFolder),  "../../../Libs/sparcsol" );
#elif AIX
                                strcpy_safe(aFolder,  sizeof (aFolder),  "../../../Libs/aix" );
#endif
                                strncpy_safe(sDirList[sDirCount],  sizeof (sDirList[sDirCount]), aFolder,  sizeof (aFolder));
                               sDirCount++;
               }
               *dirListP = sDirListP;
                return  sDirCount;
}
#endif
static   int  PDFLGetPluginDirList( void  *list)
{
#if WIN_PLATFORM
                return  PDFLGetPluginDirList_Win((ASUTF16Val  ***)list);
#elif MAC_PLATFORM
                return  PDFLGetPluginDirList_Mac(( char  ***)list);
#elif UNIX_PLATFORM
                return  PDFLGetPluginDirList_Unx(( char  ***)list);
#endif
}
#endif

#if WIN_PLATFORM

                //add Unicode resource to unicodeDirectory
static   int   PDFLGetUnicodeDir_Win(ASUTF16Val  **dirListP)
{
                static     ASUTF16Val            *sDirListP;
                static     ASUTF16Val            sDirList[MAX_PATH];          /* to avoid malloc */
                static     int                          sDirCount = -1;

                if  (sDirCount == -1)
               {
                               sDirListP = sDirList;

                               sDirCount = 0;

                                char  aFolder[_MAX_PATH];

/*****************************************************************************
Important Note;
Correct resource paths are required here for PDF Library to locate the
Unicode resource. The default resource paths provided here for the Windows
platform should work as is, regardless of the PDFL SDK installation
path. Please adjust paths for Mac and UNIX platforms as well.
******************************************************************************/
#ifdef LOAD_PLUGIN
                                strcpy_safe(aFolder,  sizeof (aFolder),  "..\\..\\..\\..\\..\\Resource\\Unicode" );
#else
                                strcpy_safe(aFolder,  sizeof (aFolder),  "..\\..\\..\\Resource\\Unicode" );
#endif
                                CopyStrToASUTF16(sDirList, aFolder);
                               sDirCount++;
               }

               *dirListP = sDirListP;
                return  sDirCount;
}

                //add CMap resource to cMapDirectory
static   int   PDFLGetCMapDir_Win(ASUTF16Val  **dirListP)
{
                static     ASUTF16Val            *sDirListP;
                static     ASUTF16Val            sDirList[MAX_PATH];          /* to avoid malloc */
                static     int                          sDirCount = -1;

                if  (sDirCount == -1)
               {
                               sDirListP = sDirList;

                               sDirCount = 0;

                                char  aFolder[_MAX_PATH];

/*****************************************************************************
Important Note;
Correct resource paths are required here for PDF Library to locate the
Unicode resource. The default resource paths provided here for the Windows
platform should work as is, regardless of the PDFL SDK installation
path. Please adjust paths for Mac and UNIX platforms as well.
******************************************************************************/
#ifdef LOAD_PLUGIN
                                strcpy_safe(aFolder,  sizeof (aFolder),  "..\\..\\..\\..\\..\\Resource\\CMap" );                       
#else
                                strcpy_safe(aFolder,  sizeof (aFolder),  "..\\..\\..\\Resource\\CMap" );
#endif
                                CopyStrToASUTF16(sDirList, aFolder);
                               sDirCount++;
               }

               *dirListP = sDirListP;
                return  sDirCount;
}
#elif MAC_PLATFORM

int  PDFLGetUnicodeDir_Mac(  char ** dirListP );       
                //add Unicode resource to unicodeDirectory
int  PDFLGetUnicodeDir_Mac(  char ** dirListP ) {       
               
                static   int  sDirCount = -1;
                char  resourceDirectory[MAX_PATH];
                static     char        *sDirListP;
                static     char        sDirList[MAX_PATH];          /* to avoid malloc */
               
                if  (sDirCount == -1)
               {
               
                               sDirListP = sDirList;
                               
                               sDirCount = 0;

                               CFBundleRef bundleRef = CFBundleGetMainBundle();
                               CFURLRef baseURL = CFBundleCopyBundleURL(bundleRef);
#ifdef LOAD_PLUGIN
                               CFURLRef resourceURL = CFURLCreateWithFileSystemPathRelativeToBase (kCFAllocatorDefault,
                                                                                                                                                                                                                                                                                                               CFSTR( "../../../../../../Resource/" ),
                                                                                                                                                                                                                                                                                                               kCFURLPOSIXPathStyle,  true , baseURL);
#else
                               CFURLRef resourceURL = CFURLCreateWithFileSystemPathRelativeToBase (kCFAllocatorDefault,
                                                                                                                                                                                                                                                                                                               CFSTR( "../../../../Resource/" ),
                                                                                                                                                                                                                                                                                                               kCFURLPOSIXPathStyle,  true , baseURL);
#endif
                               CFURLGetFileSystemRepresentation (resourceURL,  true , ( unsigned   char *)resourceDirectory,  MAX_PATH);
               
                               CFRelease(baseURL);
                               CFRelease(resourceURL);
       
                                static   char  fontPath[  MAX_PATH  ];
                                strncpy_safe(fontPath,  sizeof (fontPath), resourceDirectory,  sizeof (resourceDirectory));
                                strcat_safe(fontPath,  sizeof (fontPath),  "/" );
                                strcat_safe(fontPath,  sizeof (fontPath),  "Unicode" );           
       
                                strncpy_safe(sDirList,  MAX_PATH, fontPath,  sizeof (fontPath));
                               sDirCount++;
               }
       
       *dirListP = sDirListP;
                       
        return            sDirCount;
}

int  PDFLGetCMapDir_Mac(  char ** dirListP );       
                //add CMap resource to cMapDirectory
int  PDFLGetCMapDir_Mac(  char ** dirListP ) {       
               
                static   int  sDirCount = -1;
                char  resourceDirectory[MAX_PATH];
                static     char        *sDirListP;
                static     char        sDirList[MAX_PATH];          /* to avoid malloc */
               
                if  (sDirCount == -1)
               {
                               sDirListP = sDirList;
                               
                               sDirCount = 0;

                               CFBundleRef bundleRef = CFBundleGetMainBundle();
                               CFURLRef baseURL = CFBundleCopyBundleURL(bundleRef);
#ifdef LOAD_PLUGIN
                               CFURLRef resourceURL = CFURLCreateWithFileSystemPathRelativeToBase (kCFAllocatorDefault,
                                                                                                                                                                                                                                                                                                               CFSTR( "../../../../../../Resource/" ),
                                                                                                                                                                                                                                                                                                               kCFURLPOSIXPathStyle,  true , baseURL);
#else
                               CFURLRef resourceURL = CFURLCreateWithFileSystemPathRelativeToBase (kCFAllocatorDefault,
                                                                                                                                                                                                                                                                                                               CFSTR( "../../../../Resource/" ),
                                                                                                                                                                                                                                                                                                               kCFURLPOSIXPathStyle,  true , baseURL);
#endif
                               CFURLGetFileSystemRepresentation (resourceURL,  true , ( unsigned   char *)resourceDirectory,  MAX_PATH);
                               
                               CFRelease(baseURL);
                               CFRelease(resourceURL);
       
                                static   char  fontPath[  MAX_PATH  ];
                                strncpy_safe(fontPath,  sizeof (fontPath), resourceDirectory,  sizeof (resourceDirectory));
                                strcat_safe(fontPath,  sizeof (fontPath),  "/" );
                                strcat_safe(fontPath,  sizeof (fontPath),  "CMap" );

                                strncpy_safe(sDirList,  MAX_PATH, fontPath,  sizeof (fontPath));
                               sDirCount++;
               }
       
       *dirListP = sDirListP;
                       
        return            sDirCount;
}

#elif UNIX_PLATFORM

                //add Unicode resource to unicodeDirectory
static   int  PDFLGetUnicodeDir_Unx( char  **dirListP)
{
                static     char        *sDirListP;
                static     char        sDirList[256];    /* to avoid malloc */
                static     int                          sDirCount = -1;

                if  (sDirCount == -1)
               {
                               sDirListP = sDirList;

                                char  aFolder[256];
#ifdef LOAD_PLUGIN
                                strcpy_safe(aFolder,  sizeof (aFolder),  "../../../../../Resource/Unicode" );
#else
                                strcpy_safe(aFolder,  sizeof (aFolder),  "../../../Resource/Unicode" );
#endif
                                strncpy_safe(sDirList,  sizeof (sDirList), aFolder,  sizeof (aFolder));
                               sDirCount = 1;
               }
               *dirListP = sDirListP;

                return  sDirCount;
}

int  PDFLGetCMapDir_Unx(  char ** dirListP );       
                //add CMap resource to cMapDirectory
int  PDFLGetCMapDir_Unx(  char ** dirListP ) {   
                static     char        *sDirListP;
                static     char        sDirList[256];    /* to avoid malloc */
                static     int                          sDirCount = -1;

                if  (sDirCount == -1)
               {
                               sDirListP = sDirList;

                                char  aFolder[256];
#ifdef LOAD_PLUGIN
                                strcpy_safe(aFolder,  sizeof (aFolder),  "../../../../../Resource/CMap" );
#else
                                strcpy_safe(aFolder,  sizeof (aFolder),  "../../../Resource/CMap" );
#endif
                                strncpy_safe(sDirList,  sizeof (sDirList), aFolder,  sizeof (aFolder));
                               sDirCount = 1;
               }
               *dirListP = sDirListP;
                return  sDirCount;
}

#endif

#if WIN_PLATFORM

static   int   PDFLGetColorProfileDirList_Win(ASUTF16Val  ***dirListP)
{
                static     ASUTF16Val            *sDirListP[1];
                static     ASUTF16Val            sDirList[1][MAX_PATH];    /* to avoid malloc */
                static     int                          sDirCount = -1;

                if  (sDirCount == -1)
               {
                                for  ( int  i=0; i<1; i++)
                                               sDirListP[i] = sDirList[i];

                               sDirCount = 0;

                                char  aFolder[_MAX_PATH];

/*****************************************************************************
Important Note;
Correct resource paths are required here for PDF Library to locate the
color profiles. The default resource paths provided here for the Windows
platform should work as is, regardless of the PDFL SDK installation
path. Please adjust paths for Mac and UNIX platforms as well.
******************************************************************************/
#ifdef LOAD_PLUGIN
                                strcpy_safe(aFolder,  sizeof (aFolder),  "..\\..\\..\\..\\..\\Resource\\Color\\Profiles" );
#else
                                strcpy_safe(aFolder,  sizeof (aFolder),  "..\\..\\..\\Resource\\Color\\Profiles" );
#endif
                                CopyStrToASUTF16(sDirList[sDirCount++], aFolder);
               }

               *dirListP = sDirListP;
                return  sDirCount;
}

#elif MAC_PLATFORM

#define MAX_PATH 1000
int  PDFLGetColorProfileDirList_Mac(  char *** dirListP );

                //Simply add color profile to resourceDirectory
int  PDFLGetColorProfileDirList_Mac(  char *** dirListP ) {       
               
                static   int  sDirCount = -1;
                char  resourceDirectory[MAX_PATH];
                static     char        *sDirListP[1];
                static     char        sDirList[1][MAX_PATH];    /* to avoid malloc */
               
                if  (sDirCount == -1)
               {
                                for  (  int  i = 0; i < 1; i++ )
                                               sDirListP[i] = sDirList[i];

                               sDirCount = 0;

                               CFBundleRef bundleRef = CFBundleGetMainBundle();
                               CFURLRef baseURL = CFBundleCopyBundleURL(bundleRef);
#ifdef LOAD_PLUGIN
                               CFURLRef resourceURL = CFURLCreateWithFileSystemPathRelativeToBase (kCFAllocatorDefault,
                                                                                                                                                                                                                                                                                                               CFSTR( "../../../../../../Resource/Color" ),
                                                                                                                                                                                                                                                                                                               kCFURLPOSIXPathStyle,  true , baseURL);
#else
                               CFURLRef resourceURL = CFURLCreateWithFileSystemPathRelativeToBase (kCFAllocatorDefault,
                                                                                                                                                                                                                                                                                                               CFSTR( "../../../../Resource/Color" ),
                                                                                                                                                                                                                                                                                                               kCFURLPOSIXPathStyle,  true , baseURL);
#endif
                               CFURLGetFileSystemRepresentation (resourceURL,  true , ( unsigned   char *)resourceDirectory,  MAX_PATH);
                               
                               CFRelease(baseURL);
                               CFRelease(resourceURL);
                       
                                static   char  colorPath[  MAX_PATH  ];
                               strcpy( colorPath, resourceDirectory );
                               strcat( colorPath,  "/"  );
                               strcat( colorPath,  "Profiles"  );                     
                       
                                strncpy_safe(sDirList[sDirCount++],  MAX_PATH, colorPath,  sizeof (colorPath));
               }
       
         *dirListP = sDirListP;
                       
        return            sDirCount;
}

#elif UNIX_PLATFORM

static   int  PDFLGetColorProfileDirList_Unx( char  ***dirListP)
{
                static     char        *sDirListP[1];
                static     char        sDirList[1][256];              /* to avoid malloc */
                static     int                          sDirCount = -1;

                if  (sDirCount == -1)
               {
                                for  ( int  i=0; i<1; i++)
                                               sDirListP[i] = sDirList[i];

                               sDirCount = 0;

                                char  aFolder[256];

#ifdef LOAD_PLUGIN
                                strcpy_safe(aFolder,  sizeof (aFolder),  "../../../../../Resource/Color/Profiles" );
#else
                                strcpy_safe(aFolder,  sizeof (aFolder),  "../../../Resource/Color/Profiles" );
#endif
                                strncpy_safe(sDirList[sDirCount],  sizeof (sDirList[sDirCount]), aFolder,  sizeof (aFolder));
                               sDirCount++;
               }
               *dirListP = sDirListP;
                return  sDirCount;
}
#endif

//Call this function to add Unicode resource to unicodeDirectory in PDFLDataRec
static   int   PDFLGetUnicodeDir( void  *dir)
{
               #if WIN_PLATFORM
                                return   PDFLGetUnicodeDir_Win((ASUTF16Val  **)dir);
               #elif MAC_PLATFORM
                                return  PDFLGetUnicodeDir_Mac(( char **)dir);
               #elif UNIX_PLATFORM
                                return  PDFLGetUnicodeDir_Unx(( char **)dir);
               #endif
}

//Call this function to add CMap resource to cMapDirectory in PDFLDataRec
static   int   PDFLGetCMapDir( void  *dir)
{
#if WIN_PLATFORM
                return   PDFLGetCMapDir_Win((ASUTF16Val  **)dir);
#elif MAC_PLATFORM
                return  PDFLGetCMapDir_Mac(( char **)dir);
#elif UNIX_PLATFORM
                return  PDFLGetCMapDir_Unx(( char **)dir);
#endif
}

static   int   PDFLGetColorProfileDirList( void  *list)
{
               #if WIN_PLATFORM
                                return   PDFLGetColorProfileDirList_Win((ASUTF16Val  ***)list);
               #elif MAC_PLATFORM
                                return  PDFLGetColorProfileDirList_Mac(( char ***)list);
               #elif UNIX_PLATFORM
                                return  PDFLGetColorProfileDirList_Unx(( char  ***)list);
               #endif
}

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

               PDFLInit and PDFLTerm wrapper

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

int   MyPDFLInit()
{
               PDFLDataRec         pdflData;
               memset(&pdflData, 0,  sizeof (PDFLDataRec));

               pdflData.size =  sizeof (PDFLDataRec);
       pdflData.allocator =  PDFLGetMemAllocProcs();
               pdflData.listLen     =  PDFLGetDirList(&pdflData.dirList);
                PDFLGetCMapDir(&pdflData.cMapDirectory);
                PDFLGetUnicodeDir(&pdflData.unicodeDirectory);
               pdflData.colorProfileDirListLen =  PDFLGetColorProfileDirList(&pdflData.colorProfileDirList);

#ifdef LOAD_PLUGIN
               pdflData.pluginDirListLen = PDFLGetPluginDirList(&pdflData.pluginDirList);  /* specify plugin path */
#endif

#ifdef PLUGIN
                return  PDFLInitHFT(&pdflData);
#else
                return  PDFLInit(&pdflData);
#endif
}

void   MyPDFLTerm()
{
#ifdef PLUGIN
               PDFLTermHFT();
#else
               PDFLTerm();
#endif
}

PDDoc   MyPDDocOpen( const   char  *fileName)
{
                ASFileSys  asFileSys =  ASGetDefaultFileSys();

                volatile   ASPathName  asPathName   =  NULL;
                volatile   PDDoc                    pdDoc                     =  NULL;

                DURING
                                /* Create asPathName from file.*/

                               #if MAC_PLATFORM
                               asPathName =  GetMacPath(fileName);
                               #else
                               asPathName =  ASFileSysCreatePathName(asFileSys,  ASAtomFromString( "Cstring" ), fileName, 0);
                               #endif

                                /* Open pdDoc from asPathName.*/
                               pdDoc =  PDDocOpen(asPathName,  NULLNULL,  true );
                               fprintf(stdout,  "Successfully opened %s\n" , fileName);

                HANDLER
                               fprintf(stderr,  "Unable to open %s\n" , fileName);
                               pdDoc =  NULL;
                END_HANDLER

                /* Release asPathName.*/
                if  (asPathName)
                                ASFileSysReleasePath(asFileSys, asPathName);

                return  pdDoc;
}

ASDouble   FixedToDouble(ASFixed  x)
{
                return  (ASDouble) x /  FIXED_SCALE;
}

ASFixed   DoubleToFixed(ASDouble  d)
{
               d *=  FIXED_SCALE;
                if  (d <  ASFixedNegInf)
               {
                               fprintf(stderr,  "Truncation Error: Value set to minimum negative Fixed value during conversion from ASDouble to ASFixed." );
                                return   ASFixedNegInf;
               }
                else   if  (d >  ASFixedPosInf)
               {
                               fprintf(stderr,  "Truncation Error: Value set to maximum positive Fixed value during conversion from ASDouble to ASFixed." );
                                return   ASFixedPosInf;
               }
                else
                                return  (ASFixed) d;
}

void   FixedToDoubleMatrix(ASDoubleMatrix  *out,  ASFixedMatrix  *in)   
{     
               out->a  =  FixedToDouble(in->a);
               out->b  =  FixedToDouble(in->b);
               out->c  =  FixedToDouble(in->c);
               out->d  =  FixedToDouble(in->d);
               out->h  =  FixedToDouble(in->h);
               out->v  =  FixedToDouble(in->v);
}

void   DoubleToFixedMatrix(ASFixedMatrix  *out,  ASDoubleMatrix  *in)   
{     
               out->a  =  DoubleToFixed(in->a);
               out->b  =  DoubleToFixed(in->b);
               out->c  =  DoubleToFixed(in->c);
               out->d  =  DoubleToFixed(in->d);
               out->h  =  DoubleToFixed(in->h);
               out->v  =  DoubleToFixed(in->v);
}

void   FixedToDoubleRect(ASDoubleRect  *out,  ASFixedRect  *in)
{
               out->left  =  FixedToDouble(in->left);
               out->right  =  FixedToDouble(in->right);
               out->top  =  FixedToDouble(in->top);
               out->bottom  =  FixedToDouble(in->bottom);   
}

void   DoubleToFixedRect(ASFixedRect  *out,  ASDoubleRect  *in)
{
               out->left  =  DoubleToFixed(in->left);
               out->right  =  DoubleToFixed(in->right);
               out->top  =  DoubleToFixed(in->top);
               out->bottom  =  DoubleToFixed(in->bottom);   
}

void   DisplayError(ASErrorCode  errCode)
{
                if (errCode == 0)                return ;

                char  errStr[250];
                ASGetErrorString(errCode, errStr,  sizeof (errStr));
               fprintf(stderr,  "[Error %d] %s\n" , errCode, errStr);
}

void   DisplayErrorAndWarnings(PDDoc  pdDoc,  ASErrorCode  errCode,  ASBool  printWarnings)
{
                if (!pdDoc)            return ;

                char  errStr[250], pdDocErrStr[80], outputErrStr[350];
                ASErrorCode  pdDocErrCode;

                ASInt32  warningCount = 0, errorCount = 0;
                ASBool  match =  false ;
               
                ASInt32  numPDDocErr =  PDDocGetNumErrors(pdDoc);
                for (ASInt32  i = 0; i < numPDDocErr; i++)
               {
                                PDDocGetNthError(pdDoc, i, &pdDocErrCode, pdDocErrStr,  sizeof (pdDocErrStr));
                                ASGetErrorString(pdDocErrCode, errStr,  sizeof (errStr));

                                /* errStr can sometimes be a format string and it will give detailed error
                                     information when combined with pdDocErrStr. */
                                sprintf_safe(outputErrStr,  sizeof (outputErrStr), errStr, pdDocErrStr);

                                if (pdDocErrCode == errCode)
                               {
                                               fprintf(stderr,  "[Error %d] %s, %s\n" , errCode, outputErrStr, pdDocErrStr);
                                               match =  true ;
                                               errorCount++;
                               }
                                else
                               {
                                               fprintf(stdout,  "[Warning %d] %s, %s\n" , pdDocErrCode, outputErrStr, pdDocErrStr);
                                               warningCount++;
                               }
               }

                if (errCode && !match)
               {
                                DisplayError(errCode);
                               errorCount++;
               }

               fprintf(stdout,  "%d error(s), %d warning(s)\n" , errorCount, warningCount);
}

#ifndef WIN_PLATFORM
size_t  strnlen_safe ( const   char  *str,  size_t  maxSize)
{
                if (!str)                return  0;
                size_t  n;
                for  (n = 0; n < maxSize && *str; n++, str++);
                return  n;             
}
size_t  strlen_safe ( const   char  *str)
{
                if (!str)                return  0;
                size_t  n;
                for  (n = 0; *str !=  '\0' ; n++, str++);
                return  n;             
}
static   void  copyChars ( char  *dest,  const   char  *src,  size_t  numChars)
{
                while (numChars-- > 0)
                               *(dest++) = *(src++);
}
int   strncpy_safe  ( char  *dest,  size_t  dest_size,  const   char  *src,  size_t  n)
{
                if (!dest || !src || dest_size == 0)
                                return  ERROR_SAFE_INVALID_PARAM;

                size_t  len = strnlen_safe (src, n);
                if  (len < dest_size)
               {
                               copyChars (dest, src, len);
                               dest [len] =  '\0' ;
                                return  0;
               }
                else
               {
                               copyChars (dest, src, dest_size - 1);
                               dest [dest_size - 1] =  '\0' ;
                                return  ERROR_SAFE_BUFFER_OVERFLOW;
               }
               
}
int   strcpy_safe  ( char  *dest,  size_t  dest_size,  const   char  *src)
{
                if (!dest || !src || dest_size == 0)
                                return  ERROR_SAFE_INVALID_PARAM;

                return   strncpy_safe  (dest, dest_size, src, strlen_safe (src));
}
int   strncat_safe  ( char  *dest,  size_t  dest_size,  const   char  *src,  size_t  n)
{
                if (!dest || !src || dest_size == 0)
                                return  ERROR_SAFE_INVALID_PARAM;

                size_t  dest_len = strnlen_safe (dest, dest_size);
                if (dest_size <= dest_len)
                                return  ERROR_SAFE_INVALID_PARAM;

                char  *new_dest = dest + dest_len;
                return   strncpy_safe(new_dest, dest_size - dest_len, src, n);
}
int   strcat_safe  ( char  *dest,  size_t  dest_size,  const   char  *src)
{
                if (!dest || !src || dest_size == 0)
                                return  ERROR_SAFE_INVALID_PARAM;

                return   strncat_safe  (dest, dest_size, src, strlen_safe (src));
}
#endif