Back to index

tetex-bin  3.0
t1env.c
Go to the documentation of this file.
00001 /*--------------------------------------------------------------------------
00002   ----- File:        t1env.c 
00003   ----- Author:      Rainer Menzner (Rainer.Menzner@web.de)
00004   ----- Date:        2002-11-27
00005   ----- Description: This file is part of the t1-library. It implements
00006                      the reading of a configuration file and path-searching
00007                    of type1-, afm- and encoding files.
00008   ----- Copyright:   t1lib is copyrighted (c) Rainer Menzner, 1996-2002.
00009                      As of version 0.5, t1lib is distributed under the
00010                    GNU General Public Library Lincense. The
00011                    conditions can be found in the files LICENSE and
00012                    LGPL, which should reside in the toplevel
00013                    directory of the distribution.  Please note that 
00014                    there are parts of t1lib that are subject to
00015                    other licenses:
00016                    The parseAFM-package is copyrighted by Adobe Systems
00017                    Inc.
00018                    The type1 rasterizer is copyrighted by IBM and the
00019                    X11-consortium.
00020   ----- Warranties:  Of course, there's NO WARRANTY OF ANY KIND :-)
00021   ----- Credits:     I want to thank IBM and the X11-consortium for making
00022                      their rasterizer freely available.
00023                    Also thanks to Piet Tutelaers for his ps2pk, from
00024                    which I took the rasterizer sources in a format
00025                    independ from X11.
00026                      Thanks to all people who make free software living!
00027 --------------------------------------------------------------------------*/
00028   
00029 
00030 #define T1ENV_C
00031 
00032 
00033 #include <stdio.h>
00034 #include <stdlib.h>
00035 #include <string.h>
00036 #if defined(_MSC_VER)
00037 # include <io.h>
00038 # include <sys/types.h>
00039 # include <sys/stat.h>
00040 #else
00041 # include <unistd.h>
00042 #endif
00043 #include <sys/types.h>
00044 #include <sys/stat.h>
00045 #include <ctype.h>
00046 
00047 
00048 #include "../type1/types.h"
00049 #include "parseAFM.h" 
00050 #include "../type1/objects.h" 
00051 #include "../type1/spaces.h"  
00052 #include "../type1/util.h" 
00053 #include "../type1/fontfcn.h"
00054 #include "../type1/fontmisc.h"
00055 
00056 #include "sysconf.h"
00057 #include "t1types.h"
00058 #include "t1extern.h"
00059 #include "t1env.h"
00060 #include "t1misc.h"
00061 #include "t1base.h"
00062 
00063 
00064 /* The following static variables are used to store information on the distinct
00065    file search paths:
00066 
00067    -1         t1lib has not yet been initialized!
00068     0         t1lib has been initialized and default paths have been setup
00069     n (>0)    there are n path elements for current search path type, either built
00070               from a FontDataBase file or from explicit fucntion calls.
00071 */
00072            
00073 static int pfab_no=-1;
00074 static int afm_no=-1;
00075 static int enc_no=-1;
00076 static int fdb_no=-1;
00077 
00078 static char path_sep_char='\0';
00079 static char path_sep_string[2];
00080 
00081 static char pathbuf[2048];
00082 
00083 /* Define some default search paths */
00084 #ifndef VMS
00085 static char T1_pfab[]=".";
00086 static char T1_afm[]=".";
00087 static char T1_enc[]=".";
00088 #else
00089 static char T1_pfab[]="sys$disk:[]";
00090 static char T1_afm[]="sys$disk:[]";
00091 static char T1_enc[]="sys$disk:[]";
00092 #endif
00093 char T1_fdb[]="FontDataBase";
00094 
00095 
00096 /* keywords recognized in config file */
00097 static const char enc_key[]="ENCODING";
00098 static const char pfab_key[]="TYPE1";
00099 static const char afm_key[]="AFM";
00100 static const char fdb_key[]="FONTDATABASE";
00101 
00102 
00103 /* qstrncpy(): Copy bytes from srcP to to destP. srcP is count bytes long
00104    and destP is the number of quoted characters shorter. That is, count
00105    refers to the number of characters including the escapement chars in
00106    srcP! */
00107 static void qstrncpy( char *destP, const char *srcP, long nochars)
00108 {
00109   long i;
00110   long j;
00111   
00112   i=0;  /* dest-index */
00113   j=0;  /* src-index */
00114   
00115   while (j<nochars) {
00116     if (srcP[j]=='\\') {
00117       if (srcP[j+1]=='"') { 
00118        j++;                /* escaped quotation character --> omit escape char. */
00119       }
00120     }
00121     else {                  /* normal character */
00122       destP[i++]=srcP[j++];
00123     }
00124   }
00125 }
00126 
00127 
00128 
00129 
00130 /* Setup the default paths for searching the distinct file types. If
00131    paths have been setup explicitly, skip the step of setting up a default path. */
00132 void intT1_SetupDefaultSearchPaths( void) 
00133 {
00134 
00135   path_sep_char=PATH_SEP_CHAR;
00136   sprintf( path_sep_string, "%c", path_sep_char);
00137   
00138   /* We set the number of stored path elements 0 so that we can distiguish
00139      between explicitly setup paths and default paths in intT1_ScanConfigFile(). */
00140   if (pfab_no==-1) {
00141     T1_PFAB_ptr=(char**) calloc( 2, sizeof(char*));
00142     T1_PFAB_ptr[0]=(char*)malloc(strlen(T1_pfab)+1);
00143     strcpy(T1_PFAB_ptr[0],T1_pfab);
00144     pfab_no=0;
00145   }
00146   
00147   if (afm_no==-1) {
00148     T1_AFM_ptr=(char**) calloc( 2, sizeof(char*));
00149     T1_AFM_ptr[0]=(char*)malloc(strlen(T1_afm)+1);
00150     strcpy(T1_AFM_ptr[0],T1_afm);
00151     afm_no=0;
00152   }
00153   
00154   if (enc_no==-1) {
00155     T1_ENC_ptr=(char**) calloc( 2, sizeof(char*));
00156     T1_ENC_ptr[0]=(char*)malloc(strlen(T1_enc)+1);
00157     strcpy(T1_ENC_ptr[0],T1_enc);
00158     enc_no=0;
00159   }
00160 
00161   if (fdb_no==-1) {
00162     T1_FDB_ptr=(char**) calloc( 2, sizeof(char*));
00163     T1_FDB_ptr[0]=(char*)malloc(strlen(T1_fdb)+1);
00164     strcpy(T1_FDB_ptr[0],T1_fdb);
00165     fdb_no=0;
00166   }
00167 }
00168 
00169 
00170 /* This function is called from T1_CloseLib(). We have to indicate the state
00171    of a non-initialzed t1lib! */
00172 void intT1_FreeSearchPaths( void) 
00173 {
00174   int i;
00175   
00176   i=0;
00177   if (T1_PFAB_ptr!=NULL) {
00178     while (T1_PFAB_ptr[i]!=NULL) {
00179       free(T1_PFAB_ptr[i]);
00180       T1_PFAB_ptr[i]=NULL;
00181     }
00182     free( T1_PFAB_ptr);
00183   }
00184   i=0;
00185   if (T1_AFM_ptr!=NULL) {
00186     while (T1_AFM_ptr[i]!=NULL) {
00187       free(T1_AFM_ptr[i]);
00188       T1_AFM_ptr[i]=NULL;
00189     }
00190     free( T1_AFM_ptr);
00191   }
00192   i=0;
00193   if (T1_ENC_ptr!=NULL) {
00194     while (T1_ENC_ptr[i]!=NULL) {
00195       free(T1_ENC_ptr[i]);
00196       T1_ENC_ptr[i]=NULL;
00197     }
00198     free( T1_ENC_ptr);
00199   }
00200   i=0;
00201   if (T1_FDB_ptr!=NULL) {
00202     while (T1_FDB_ptr[i]!=NULL) {
00203       free(T1_FDB_ptr[i]);
00204       T1_FDB_ptr[i]=NULL;
00205     }
00206     free( T1_FDB_ptr);
00207   }
00208   /* indicate t1lib non-initialized */
00209   pfab_no=-1;
00210   afm_no=-1;
00211   enc_no=-1;
00212   fdb_no=-1;
00213   
00214   return;
00215 }
00216 
00217 
00218 /* ScanConfigFile(): Read a configuration file and scan and save the
00219    environment strings used for searching pfa/pfb-, afm- and encoding
00220    files as well as the name of the font database file. */
00221 int intT1_ScanConfigFile( void)
00222 {
00223   
00224   char *env_str;
00225   char *linebuf;
00226   char *usershome;
00227   char *cnffilepath;
00228   char *globalcnffilepath;
00229   static int linecnt;
00230   char local_path_sep_char;
00231   int quoted=0;
00232   int quotecnt=0;
00233   FILE *cfg_fp;
00234   int filesize, i, j, k;
00235   int ignoreline=0;
00236 
00237   char*** destP=NULL;
00238   int *idestP=NULL;
00239   char* curr_key=NULL;
00240   
00241   /* First, get the string stored in the environment variable: */
00242   env_str=getenv(ENV_CONF_STRING);
00243   linecnt=1;
00244 
00245   if (env_str==NULL) {
00246     /* environment variable not set, try to open default file
00247        in user's home directory and afterwards global config file */
00248     if ((usershome=getenv("HOME"))!=NULL) {
00249       cnffilepath=(char *)malloc((strlen(usershome) +
00250                               strlen(T1_CONFIGFILENAME) + 2
00251                               ) * sizeof(char));
00252       if (cnffilepath==NULL){
00253        T1_errno=T1ERR_ALLOC_MEM;
00254        return(-1);
00255       }
00256       strcpy( cnffilepath, usershome);
00257     }
00258     else {
00259       cnffilepath=(char *)malloc((strlen(T1_CONFIGFILENAME) + 2
00260                               ) * sizeof(char));
00261     }
00262     strcat( cnffilepath, DIRECTORY_SEP);
00263     strcat( cnffilepath, T1_CONFIGFILENAME);
00264 
00265     globalcnffilepath=(char*)malloc((strlen(GLOBAL_CONFIG_DIR) +
00266                                  strlen(GLOBAL_CONFIG_FILE) + 2
00267                                  ) * sizeof(char));
00268     if (globalcnffilepath==NULL){
00269       T1_errno=T1ERR_ALLOC_MEM;
00270       return(-1);
00271     }
00272     strcpy( globalcnffilepath, GLOBAL_CONFIG_DIR);
00273     strcat( globalcnffilepath, DIRECTORY_SEP);
00274     strcat( globalcnffilepath, GLOBAL_CONFIG_FILE);
00275     
00276     if ((cfg_fp=fopen( cnffilepath, "rb"))==NULL){
00277       sprintf( err_warn_msg_buf, "Could not open configfile %s",
00278               cnffilepath);
00279       T1_PrintLog( "ScanConfigFile()", err_warn_msg_buf, T1LOG_STATISTIC);
00280       /* Try global config file */
00281       if ((cfg_fp=fopen( globalcnffilepath, "rb"))==NULL){
00282        sprintf( err_warn_msg_buf, "Could not open global configfile %s",
00283                globalcnffilepath);
00284        T1_PrintLog( "ScanConfigFile()", err_warn_msg_buf, T1LOG_WARNING);
00285       }
00286       else{
00287        sprintf( err_warn_msg_buf, "Using %s as Configfile (global)",
00288                cnffilepath);
00289        T1_PrintLog( "ScanConfigFile()", err_warn_msg_buf, T1LOG_STATISTIC);
00290       }
00291     }
00292     else{
00293       sprintf( err_warn_msg_buf, "Using %s as Configfile (user's)",
00294               cnffilepath);
00295       T1_PrintLog( "ScanConfigFile()", err_warn_msg_buf, T1LOG_STATISTIC);
00296     }
00297     free( cnffilepath);
00298     free( globalcnffilepath);
00299     if (cfg_fp==NULL){
00300       T1_PrintLog( "ScanConfigFile()",
00301                  "Neither user's nor global Configfile has been found",
00302                  T1LOG_WARNING);
00303       return(0);
00304     }
00305   }
00306   else {
00307     /* open specified file for reading the configuration */
00308     if ((cfg_fp=fopen(env_str,"rb"))==NULL){
00309       T1_PrintLog( "ScanConfigFile()",
00310                  "Configfile as specified by Environment has not been found",
00311                  T1LOG_WARNING);
00312       return(0);  /* specified file could not be openend
00313                    => no config paths read */
00314     }
00315     else {
00316       sprintf( err_warn_msg_buf, "Using %s as Configfile (environment)",
00317               env_str);
00318       T1_PrintLog( "ScanConfigFile()", err_warn_msg_buf, T1LOG_STATISTIC);
00319     }
00320   }
00321   
00322 
00323   /* cfg_fp points now to a valid config file */
00324   /* Get the file size */
00325   fseek( cfg_fp, 0, SEEK_END);
00326   filesize=ftell(cfg_fp);
00327   /* Reset fileposition to start */
00328   fseek( cfg_fp, 0, SEEK_SET);
00329   
00330   if ((linebuf=(char *)calloc( filesize+1,
00331                             sizeof(char)))==NULL){
00332     T1_errno=T1ERR_ALLOC_MEM;
00333     return(-1);
00334   }
00335   
00336   fread((char *)linebuf, sizeof(char), filesize, cfg_fp);
00337   fclose(cfg_fp);
00338   
00339   i=0;
00340 
00341   /* this might be overwritten on a per file basis */
00342   local_path_sep_char=path_sep_char;
00343 
00344   while(i<filesize) {
00345     ignoreline=0;
00346     j=i;     /* Save index of beginning of line */
00347     while ((linebuf[i]!='=') && (linebuf[i]!='\n') && (i<filesize)) {
00348       i++;
00349     } 
00350     if (i==filesize) {
00351       free( linebuf);
00352       return(i);
00353     }
00354     
00355     if (strncmp( enc_key, &linebuf[j], 8)==0) {
00356       /* setup target */
00357       destP=&T1_ENC_ptr;
00358       idestP=&enc_no;
00359       curr_key=(char*)enc_key;
00360     }
00361     else if (strncmp( "TYPE1", &linebuf[j], 5)==0) {
00362       /* setup target */
00363       destP=&T1_PFAB_ptr;
00364       idestP=&pfab_no;
00365       curr_key=(char*)pfab_key;
00366     }
00367     else if (strncmp( afm_key, &linebuf[j], 3)==0) {
00368       /* setup target */
00369       destP=&T1_AFM_ptr;
00370       idestP=&afm_no;
00371       curr_key=(char*)afm_key;
00372     }
00373     else if (strncmp( fdb_key, &linebuf[j], 12)==0) {
00374       /* setup target */
00375       destP=&T1_FDB_ptr;
00376       idestP=&fdb_no;
00377       curr_key=(char*)fdb_key;
00378     }
00379     else {
00380       ignoreline=1;
00381       T1_PrintLog( "ScanConfigFile()", "Ignoring line %d",
00382                  T1LOG_DEBUG, linecnt);
00383     }
00384 
00385     /* If appropriate, scan this line. */
00386     if (ignoreline==0) { 
00387       /* Check for an explicitly assigned value */
00388       if (*idestP==0) { /* default paths are currently setup, get rid of them */
00389        free((*destP)[0]);
00390       }
00391       else { /* append to existing paths */
00392        T1_PrintLog( "ScanConfigFile()",
00393                    "Appending to existing %s search path",
00394                    T1LOG_DEBUG, curr_key);
00395       }
00396       while ( (!isspace((int)linebuf[i])) && (i<filesize) ) {
00397        k=++i;      /* index to current path element */
00398        (*idestP)++;
00399        quotecnt=0;
00400        if (linebuf[i]=='"') { /* We have a quoted string */
00401          quoted=1;
00402          k=++i;
00403          while ( 1) {
00404            if ( linebuf[i]=='"' ) {    /* we find a quote-char */ 
00405              if ( linebuf[i-1]!='\\' ) 
00406               break;                     /* not escaped --> end of path specification */
00407              else
00408               quotecnt++;
00409            }                           /* some other char */
00410            if (linebuf[i]=='\n') { /* a newline in a quoted string? Perhabs, quotes do not match! */
00411              T1_PrintLog( "ScanConfigFile()",
00412                         "Newline in quoted %s-string in line %d, column %d, of config file! Closing quote missing?", 
00413                         T1LOG_WARNING, curr_key, linecnt, i-j+1);
00414              j=i+1;                /* resynchronize linecount */
00415              linecnt++;           
00416            }
00417            if (i<filesize) {            /* filesize not exceeded? */
00418              i++;
00419            }
00420            else {                       /* issue error msg because end of quotation is missing */
00421              T1_PrintLog( "ScanConfigFile()", "Unterminated quoted string in config file",
00422                         T1LOG_ERROR);
00423              return -1;
00424            }
00425          }
00426        }
00427        else {
00428          quoted=0;
00429          while ( (linebuf[i]!=local_path_sep_char) && (!isspace((int)linebuf[i])) && (i<filesize) )
00430            i++;
00431        }
00432        if (((*destP)=(char**)realloc( (*destP), ((*idestP)+1)*sizeof(char*)))==NULL) {
00433          T1_errno=T1ERR_ALLOC_MEM;
00434          return(-1);
00435        }
00436        if (((*destP)[(*idestP)-1]=(char*)malloc((i-k-quotecnt+1)*sizeof(char)))==NULL) {
00437          T1_errno=T1ERR_ALLOC_MEM;
00438          return(-1);
00439        }
00440        if (quoted==0) {
00441          strncpy( (*destP)[*idestP-1], &(linebuf[k]), i-k);
00442          (*destP)[(*idestP)-1][i-k]='\0';
00443        }
00444        else {
00445          qstrncpy( (*destP)[(*idestP)-1], &(linebuf[k]), i-k);
00446          (*destP)[(*idestP)-1][i-k-quotecnt]='\0';
00447          i++;         /* step over closing quote */
00448        }
00449        (*destP)[(*idestP)]=NULL;     /* indicate end of string list */
00450       }
00451     }
00452 
00453     /* skip remaining of line or file */
00454     while ((linebuf[i]!='\n')&&(i<filesize))
00455       i++;
00456     i++;
00457     linecnt++;
00458   }
00459   /* file should now be read in */
00460   free( linebuf);
00461   
00462   return(i);
00463   
00464 }
00465 
00466 
00467 
00468 /* intT1_Env_GetCompletePath( ): Get a full path name from the file specified by
00469    argument 1 in the environment specified by argument 2. Return the pointer
00470    to the path string or NULL if no file was found.*/
00471 char *intT1_Env_GetCompletePath( char *FileName,
00472                              char **env_ptr )
00473 {
00474   struct stat filestats;    /* A structure where fileinfo is stored */
00475   int fnamelen, i, j;
00476   char *FullPathName;
00477   char *StrippedName;
00478   
00479 
00480   if (FileName==NULL)
00481     return(NULL);
00482   fnamelen=strlen(FileName);
00483 
00484   /* We check whether absolute or relative pathname is given. If so,
00485      stat() it and if appropriate, return that string immediately. */
00486   if ( (FileName[0]==DIRECTORY_SEP_CHAR)
00487        ||
00488        ((fnamelen>1) && (FileName[0]=='.') &&
00489        (FileName[1]==DIRECTORY_SEP_CHAR))
00490        ||
00491        ((fnamelen>2) && (FileName[0]=='.') &&
00492        (FileName[1]=='.') && (FileName[2]==DIRECTORY_SEP_CHAR))
00493 #if defined(MSDOS) | defined(_WIN32) | defined (__EMX__)
00494        ||
00495        ((isalpha(FileName[0])) && (FileName[1]==':'))
00496 #endif
00497 #ifdef VMS
00498        || (strchr(FileName,':') != NULL)
00499 #endif
00500        )
00501     {
00502     /* Check for existence of the path: */
00503     if (!stat( FileName, &filestats)) {
00504       if (t1lib_log_file!=NULL) {
00505        sprintf( err_warn_msg_buf, "stat()'ing complete path %s successful",
00506                FileName);
00507        T1_PrintLog( "intT1_Env_GetCompletePath()", err_warn_msg_buf,
00508                    T1LOG_DEBUG);
00509       }
00510       /* Return a copy of the string */
00511       if ((FullPathName=(char *)malloc( fnamelen + 1))==NULL) {
00512        T1_errno=T1ERR_ALLOC_MEM;
00513        return(NULL);
00514       }
00515       strcpy( FullPathName, FileName);
00516       return(FullPathName);
00517     }
00518     if (t1lib_log_file!=NULL){
00519       sprintf( err_warn_msg_buf, "stat()'ing complete path %s failed",
00520               FileName);
00521       T1_PrintLog( "intT1_Env_GetCompletePath()", err_warn_msg_buf,
00522                  T1LOG_DEBUG);
00523     }
00524     /* Trying to locate absolute path spec. failed. We try to recover
00525        by removing the path component and searching in the remaining search
00526        path entries. This depends on the OS. */
00527     i=fnamelen-1;
00528     StrippedName=&(FileName[i]);
00529     while ( FileName[i]!=DIRECTORY_SEP_CHAR
00530 #if defined(VMS)
00531            /* What exactly to do for VMS? */
00532 #elif defined(MSDOS) | defined(_WIN32) | defined (__EMX__) | defined(_MSC_VER)
00533            /* We take a drive specification into account. This means we
00534               step back until the directory separator or a drive specifier
00535               appears! */
00536            && FileName[i]!=':'
00537 #endif
00538            ) {
00539       i--;
00540     }
00541     i++;
00542     StrippedName=&FileName[i];
00543     if (t1lib_log_file!=NULL){
00544       sprintf( err_warn_msg_buf, "path %s stripped to %s",
00545               FileName, StrippedName);
00546       T1_PrintLog( "intT1_Env_GetCompletePath()", err_warn_msg_buf,
00547                  T1LOG_DEBUG);
00548     }
00549   }
00550   else{ /* We have a relative path name */
00551     StrippedName=&FileName[0];
00552   }
00553 
00554   i=0;
00555   while (env_ptr[i]!=NULL) {
00556     /* Copy current path element: */
00557     strcpy( pathbuf, env_ptr[i]);
00558     /* cut a trailing directory separator */
00559     j=strlen(pathbuf);
00560     if (pathbuf[j-1]==DIRECTORY_SEP_CHAR)
00561       pathbuf[j--]='\0';
00562     /* Add the directory separator: */
00563 #ifdef VMS
00564     { char *p= strrchr(pathbuf, DIRECTORY_SEP_CHAR);
00565       if (p && *(p+1) ==  '\0')
00566        *p = '\0';
00567     } 
00568 #endif 
00569     strcat( pathbuf, DIRECTORY_SEP);
00570     /* And finally the filename: */
00571     strcat( pathbuf, StrippedName);
00572     
00573     /* Check for existence of the path: */
00574     if (!stat( pathbuf, &filestats)) {
00575       if ((FullPathName=(char*)malloc( (j+fnamelen+2)*sizeof(char)))==NULL) {
00576        T1_errno=T1ERR_ALLOC_MEM;
00577        return(NULL);
00578       }
00579       strcpy( FullPathName, pathbuf);
00580       if (t1lib_log_file!=NULL){
00581        sprintf( err_warn_msg_buf, "stat()'ing %s successful",
00582                FullPathName);
00583        T1_PrintLog( "intT1_Env_GetCompletePath()", err_warn_msg_buf,
00584                    T1LOG_DEBUG);
00585       }
00586       return(FullPathName);
00587     }
00588     if (t1lib_log_file!=NULL){
00589       sprintf( err_warn_msg_buf, "stat()'ing %s failed",
00590               pathbuf);
00591       T1_PrintLog( "intT1_Env_GetCompletePath()", err_warn_msg_buf,
00592                  T1LOG_DEBUG);
00593     }
00594     /* We didn't find the file --> try next path entry */
00595     i++;
00596   }
00597   /* If we get here, no file was found at all, so return a NULL-pointer */
00598   return(NULL);
00599 }
00600 
00601 
00602 
00603 /* T1_SetFileSearchPath(): Set the search path to find files of the
00604    specified type and return 0 if successful and -1 otherwise. An existing
00605    path is overwritten rigorously, unless the database already contains fonts.
00606    In the latter case the function returns with an error status.
00607    Multiple path types may be specified as a bitmask!
00608 */
00609 int T1_SetFileSearchPath( int type, char *pathname)
00610 {
00611 
00612   int i;
00613   int pathlen;
00614   
00615   
00616   if (pathname==NULL){
00617     T1_errno=T1ERR_INVALID_PARAMETER;
00618     return(-1);
00619   }
00620 
00621   /* We do not allow to change the searchpath if the database already
00622      contains one or more entries. */
00623   if (T1_GetNoFonts()>0){
00624     sprintf( err_warn_msg_buf, "Path %s not set, database is not empty",
00625             pathname);
00626     T1_PrintLog( "T1_SetFileSearchPath()", err_warn_msg_buf,
00627                T1LOG_STATISTIC);
00628     T1_errno=T1ERR_OP_NOT_PERMITTED;
00629     return(-1);
00630   }
00631 
00632   pathlen=strlen(pathname)+1;
00633   /* Throw away a possibly existing path */
00634   if (type & T1_PFAB_PATH){
00635     if (pfab_no==-1) {
00636       T1_PFAB_ptr=NULL; /* realloc() will do a malloc() */
00637     }
00638     else {
00639       /* throw away current paths */
00640       i=0;
00641       while (T1_PFAB_ptr[i]!=NULL) {
00642        free (T1_PFAB_ptr[i++]);
00643       }
00644     }
00645     if ((T1_PFAB_ptr=(char**)realloc( T1_PFAB_ptr, 2*sizeof(char*)))==NULL) {
00646       T1_errno=T1ERR_ALLOC_MEM;
00647       return(-1);
00648     }
00649     if ((T1_PFAB_ptr[0]=(char*)malloc(pathlen*sizeof(char)))==NULL) {
00650       T1_errno=T1ERR_ALLOC_MEM;
00651       return(-1);
00652     }
00653     strcpy( T1_PFAB_ptr[0], pathname);
00654     T1_PFAB_ptr[1]=NULL;
00655     pfab_no=1;
00656   }
00657   if (type & T1_AFM_PATH){
00658     if (afm_no==-1) {
00659       T1_AFM_ptr=NULL; /* realloc() will do a malloc() */
00660     }
00661     else {
00662       /* throw away current paths */
00663       i=0;
00664       while (T1_AFM_ptr[i]!=NULL) {
00665        free (T1_AFM_ptr[i++]);
00666       }
00667     }
00668     if ((T1_AFM_ptr=(char**)realloc( T1_AFM_ptr, 2*sizeof(char*)))==NULL) {
00669       T1_errno=T1ERR_ALLOC_MEM;
00670       return(-1);
00671     }
00672     if ((T1_AFM_ptr[0]=(char*)malloc(pathlen*sizeof(char)))==NULL) {
00673       T1_errno=T1ERR_ALLOC_MEM;
00674       return(-1);
00675     }
00676     strcpy( T1_AFM_ptr[0], pathname);
00677     T1_AFM_ptr[1]=NULL;
00678     afm_no=1;
00679   }
00680   if (type & T1_ENC_PATH){
00681     if (enc_no==-1) {
00682       T1_ENC_ptr=NULL; /* realloc() will do a malloc() */
00683     }
00684     else {
00685       /* throw away current paths */
00686       i=0;
00687       while (T1_ENC_ptr[i]!=NULL) {
00688        free (T1_ENC_ptr[i++]);
00689       }
00690     }
00691     if ((T1_ENC_ptr=(char**)realloc( T1_ENC_ptr, 2*sizeof(char*)))==NULL) {
00692       T1_errno=T1ERR_ALLOC_MEM;
00693       return(-1);
00694     }
00695     if ((T1_ENC_ptr[0]=(char*)malloc(pathlen*sizeof(char)))==NULL) {
00696       T1_errno=T1ERR_ALLOC_MEM;
00697       return(-1);
00698     }
00699     strcpy( T1_ENC_ptr[0], pathname);
00700     T1_ENC_ptr[1]=NULL;
00701     enc_no=1;
00702   }
00703   
00704   return(0);
00705   
00706 }
00707 
00708 
00709 
00710 /* T1_GetFileSearchPath(): Return the specified file search path
00711    or NULL if an error occurred. Note: We do only one path at a
00712    time, so that if a bitmask is specified, the first match wins.
00713    The returned path is formatted using the actual PATH_SEP_CHAR. */
00714 char *T1_GetFileSearchPath( int type)
00715 {
00716   static char *out_ptr;
00717   int i;
00718   int pathlen;
00719   char **src_ptr=NULL;
00720   
00721 
00722   if (out_ptr!=NULL)
00723     free( out_ptr);
00724   out_ptr=NULL;
00725   
00726   if (type & T1_PFAB_PATH) {
00727     src_ptr=T1_PFAB_ptr;
00728   }
00729   else  if (type & T1_AFM_PATH) {
00730     src_ptr=T1_AFM_ptr;
00731   }
00732   else if (type & T1_ENC_PATH) {
00733     src_ptr=T1_ENC_ptr;
00734   }
00735   else if (type & T1_FDB_PATH) {
00736     src_ptr=T1_FDB_ptr;
00737   }
00738   
00739   
00740   i=0;
00741   pathlen=0;
00742   while (src_ptr[i]!=NULL) {
00743     pathlen +=strlen( src_ptr[i++]);
00744     pathlen+=1; /* path separator */
00745   }
00746   if ((out_ptr=(char *)malloc(pathlen+1))==NULL) {
00747     T1_errno=T1ERR_ALLOC_MEM;
00748     return( NULL);
00749   }
00750   strcpy( out_ptr, src_ptr[0]);
00751   i=1;
00752   while (src_ptr[i]!=NULL) {
00753     strcat( out_ptr, path_sep_string);
00754     strcat( out_ptr, src_ptr[i++]);
00755   }
00756   
00757   return( out_ptr);
00758 
00759 }
00760 
00761 
00762 /* T1_AddToFileSearchPath(): Add the specified path element to
00763    the specified search path. If the existing path is the default path,
00764    it will not be replaced by the new path element. Since this function might
00765    be called before initialization, we have to be aware that even the default
00766    path could be missing. Multiple path types may be specified as a bitmask!
00767    Return value is 0 if successful and -1 otherwise */
00768 int T1_AddToFileSearchPath( int pathtype, int mode, char *pathname)
00769 {
00770   int i;
00771   int pathlen;
00772   char* newpath = NULL;
00773   int nofonts;
00774   
00775   
00776   if (pathname==NULL)
00777     return(-1);
00778 
00779   nofonts=T1_GetNoFonts();
00780   
00781   pathlen=strlen(pathname);
00782   
00783   if (pathtype & T1_PFAB_PATH){
00784     /* Allocate meory for string */
00785     if ((newpath=(char*)malloc( (pathlen+1)*sizeof(char)))==NULL)  {
00786       T1_errno=T1ERR_ALLOC_MEM;
00787       return(-1);
00788     }
00789     /* Check for and handle the existing path configuration */
00790     if (pfab_no==0) {   /* do not free the default path but establish it
00791                         as a regularly setup path, if database not empty! */
00792       if (nofonts>0) {
00793        pfab_no++;
00794       }
00795       else {
00796        free( T1_AFM_ptr[0]);
00797       }
00798     }
00799     if (pfab_no==-1) {  /* not initialized! */
00800       pfab_no=0;
00801       T1_PFAB_ptr=NULL; /* realloc() will do the malloc()! */
00802     }
00803     if ((T1_PFAB_ptr=(char**)realloc( T1_PFAB_ptr, (++pfab_no+1)*sizeof(char*)))==NULL) {
00804       T1_errno=T1ERR_ALLOC_MEM;
00805       return(-1);
00806     }
00807     /* Insert the new path element: */
00808     if (mode & T1_PREPEND_PATH){ /* prepend */
00809       i=pfab_no-2;
00810       while (i>=0) {
00811        T1_PFAB_ptr[i+1]=T1_PFAB_ptr[i];
00812        i--;
00813       }
00814       T1_PFAB_ptr[0]=newpath;
00815     }
00816     else{ /* append */
00817       T1_PFAB_ptr[pfab_no-1]=newpath;
00818     }
00819     T1_PFAB_ptr[pfab_no]=NULL;
00820   }
00821   if (pathtype & T1_AFM_PATH){
00822     /* Allocate meory for string */
00823     if ((newpath=(char*)malloc( (pathlen+1)*sizeof(char)))==NULL)  {
00824       T1_errno=T1ERR_ALLOC_MEM;
00825       return(-1);
00826     }
00827     /* Check for and handle the existing path configuration */
00828     if (afm_no==0) {   /* do not free the default path but establish it
00829                        as a regularly setup path, if database not empty! */
00830       if (nofonts>0) {
00831        afm_no++;
00832       }
00833       else {
00834        free( T1_AFM_ptr[0]);
00835       }
00836     }
00837     if (afm_no==-1) {  /* not initialized! */
00838       afm_no=0;
00839       T1_AFM_ptr=NULL; /* realloc() will do the malloc()! */
00840     }
00841     if ((T1_AFM_ptr=(char**)realloc( T1_AFM_ptr, (++afm_no+1)*sizeof(char*)))==NULL) {
00842       T1_errno=T1ERR_ALLOC_MEM;
00843       return(-1);
00844     }
00845     /* Insert the new path element */
00846     if (mode & T1_PREPEND_PATH){ /* prepend */
00847       i=afm_no-2;
00848       while (i>=0) {
00849        T1_AFM_ptr[i+1]=T1_AFM_ptr[i];
00850        i--;
00851       }
00852       T1_AFM_ptr[0]=newpath;
00853     }
00854     else{ /* append */
00855       T1_AFM_ptr[afm_no-1]=newpath;
00856     }
00857     T1_AFM_ptr[afm_no]=NULL;
00858   }
00859   if (pathtype & T1_ENC_PATH){
00860     /* Allocate meory for string */
00861     if ((newpath=(char*)malloc( (pathlen+1)*sizeof(char)))==NULL)  {
00862       T1_errno=T1ERR_ALLOC_MEM;
00863       return(-1);
00864     }
00865     /* Check for and handle the existing path configuration */
00866     if (enc_no==0) {    /* do not free the default path but establish it
00867                         as a regularly setup path, if database not empty! */
00868       if (nofonts>0) {
00869        enc_no++;
00870       }
00871       else {
00872        free( T1_ENC_ptr[0]);
00873       }
00874     }
00875     if (enc_no==-1) {  /* not initialized! */
00876       enc_no=0;
00877       T1_ENC_ptr=NULL; /* realloc() will do the malloc()! */
00878     }
00879     if ((T1_ENC_ptr=(char**)realloc( T1_ENC_ptr, (++enc_no+1)*sizeof(char*)))==NULL) {
00880       T1_errno=T1ERR_ALLOC_MEM;
00881       return(-1);
00882     }
00883     /* Insert the new path element: */
00884     if (mode & T1_PREPEND_PATH){ /* prepend */
00885       i=enc_no-2;
00886       while (i>=0) {
00887        T1_ENC_ptr[i+1]=T1_ENC_ptr[i];
00888        i--;
00889       }
00890       T1_ENC_ptr[0]=newpath;
00891     }
00892     else{ /* append */
00893       T1_ENC_ptr[enc_no-1]=newpath;
00894     }
00895     T1_ENC_ptr[enc_no]=NULL;
00896   }
00897   
00898   /* Copy new path to where it belongs ... */
00899   if (newpath)
00900     strcpy(newpath, pathname);
00901   
00902   return(0);
00903   
00904 }
00905 
00906 
00907 
00908 /* T1_SetFontDataBase(): Set a new name for the font database. It replaces the default
00909    name and any names specified previously with this function.
00910    Return value: 0 if OK, and -1 if filename not valid or an allocation
00911    error occurred */
00912 int T1_SetFontDataBase( char *filename)
00913 {
00914   int pathlen;
00915   int i;
00916   int result=0;
00917   
00918   
00919   /* chekc filename */
00920   if (filename==NULL) {
00921     T1_errno=T1ERR_INVALID_PARAMETER;
00922     return -1;
00923   }
00924 
00925   /* this function must be called before any font is in the database, that is, usually,
00926      before initialization! */
00927   if ( pFontBase!=NULL && pFontBase->no_fonts>0) {
00928     T1_errno=T1ERR_OP_NOT_PERMITTED;
00929     return -1;
00930   }
00931 
00932   
00933   pathlen=strlen(filename)+1;
00934   /* Throw away a possibly existing font database-statement */
00935   if (fdb_no==-1) {  
00936     T1_FDB_ptr=NULL; /* realloc() will do a malloc() */
00937   }
00938   else { 
00939     /* throw away current paths */
00940     i=0;
00941     while (T1_FDB_ptr[i]!=NULL) {
00942       free (T1_FDB_ptr[i++]);
00943     }
00944   }
00945 
00946   if ((T1_FDB_ptr=(char**)realloc( T1_FDB_ptr, 2*sizeof(char*)))==NULL) {
00947     T1_errno=T1ERR_ALLOC_MEM;
00948     return -1;
00949   }
00950   
00951   if ((T1_FDB_ptr[0]=(char*)malloc(pathlen*sizeof(char)))==NULL) {
00952     T1_errno=T1ERR_ALLOC_MEM;
00953     return -1;
00954   }
00955   strcpy( T1_FDB_ptr[0], filename);
00956   T1_FDB_ptr[1]=NULL;
00957   fdb_no=1;
00958 
00959   /* Load database immediately if t1lib already is initailzed */
00960   if (T1_CheckForInit()==0) {
00961     if ((result=intT1_scanFontDBase(T1_FDB_ptr[0]))==-1) {
00962       T1_PrintLog( "T1_AddFontDataBase()", "Fatal error scanning Font Database File %s (T1_errno=%d)",
00963                  T1LOG_WARNING, T1_FDB_ptr[0], T1_errno);
00964     }
00965     if (result>-1)
00966       pFontBase->no_fonts+=result;
00967     result=pFontBase->no_fonts;
00968   }
00969   return result;
00970   
00971 }
00972 
00973 
00974 /* T1_AddFontDataBase(): Add a new font database file to the list. If the
00975    lib is already initialzed, then the new database is immediately loaded.
00976    Otherwise it is simply appended to the list and loaded at the time of
00977    initialization.
00978    Returns: -1    an error occured
00979              0    successfully inserted but not loaded because lib not initilized
00980             n>0  the highest defined FontID
00981 */
00982 int T1_AddFontDataBase( int mode, char *filename) 
00983 {
00984   int i;
00985   int pathlen;
00986   int result=0;
00987   char* newpath;
00988   
00989   
00990   if (filename==NULL) {
00991     T1_errno=T1ERR_INVALID_PARAMETER;
00992     return(-1);
00993   }
00994   
00995   pathlen=strlen(filename);
00996   
00997   /* Allocate memory for string */
00998   if ((newpath=(char*)malloc( (pathlen+1)*sizeof(char)))==NULL)  {
00999     T1_errno=T1ERR_ALLOC_MEM;
01000     return(-1);
01001   }
01002   strcpy( newpath, filename);
01003   /* Check for and handle the existing path configuration */
01004   if (fdb_no==0) {   /* defauls setup, free the path */
01005     free( T1_FDB_ptr[0]);
01006   }
01007   if (fdb_no==-1) {  /* not initialized! */
01008     fdb_no=0;
01009     T1_FDB_ptr=NULL; /* realloc() will do the malloc()! */
01010   }
01011   
01012   if ((T1_FDB_ptr=(char**)realloc( T1_FDB_ptr, (++fdb_no+1)*sizeof(char*)))==NULL) {
01013     T1_errno=T1ERR_ALLOC_MEM;
01014     return(-1);
01015   }
01016   /* Insert the new database. If t1lib is already initialzed, the database can only
01017      be appended. Otherwise. prepending is also possible.*/
01018   if ((mode & T1_PREPEND_PATH) && (T1_CheckForInit()!=0) ) { /* prepend */
01019     i=fdb_no-2;
01020     while (i>=0) {
01021       T1_FDB_ptr[i+1]=T1_FDB_ptr[i];
01022       i--;
01023     }
01024     T1_FDB_ptr[0]=newpath;
01025     result=0;
01026   }
01027   else { /* append */
01028     T1_FDB_ptr[fdb_no-1]=newpath;
01029     if (T1_CheckForInit()==0) {
01030       if ((result=intT1_scanFontDBase(T1_FDB_ptr[fdb_no-1]))==-1) {
01031        T1_PrintLog( "T1_AddFontDataBase()", "Fatal error scanning Font Database File %s (T1_errno=%d)",
01032                    T1LOG_WARNING, T1_FDB_ptr[fdb_no-1], T1_errno);
01033       }
01034       if (result>-1)
01035        pFontBase->no_fonts+=result;
01036       result=pFontBase->no_fonts;
01037     }
01038   }
01039   T1_FDB_ptr[fdb_no]=NULL;
01040   return result;
01041   
01042 }
01043 
01044