1 /*--------------------------------------------------------------------------
2   ----- File:        t1env.c
3   ----- Author:      Rainer Menzner (Rainer.Menzner@web.de)
4   ----- Date:        2001-11-12
5   ----- Description: This file is part of the t1-library. It implements
6                      the reading of a configuration file and path-searching
7 		     of type1-, afm- and encoding files.
8   ----- Copyright:   t1lib is copyrighted (c) Rainer Menzner, 1996-2001.
9                      As of version 0.5, t1lib is distributed under the
10 		     GNU General Public Library Lincense. The
11 		     conditions can be found in the files LICENSE and
12 		     LGPL, which should reside in the toplevel
13 		     directory of the distribution.  Please note that
14 		     there are parts of t1lib that are subject to
15 		     other licenses:
16 		     The parseAFM-package is copyrighted by Adobe Systems
17 		     Inc.
18 		     The type1 rasterizer is copyrighted by IBM and the
19 		     X11-consortium.
20   ----- Warranties:  Of course, there's NO WARRANTY OF ANY KIND :-)
21   ----- Credits:     I want to thank IBM and the X11-consortium for making
22                      their rasterizer freely available.
23 		     Also thanks to Piet Tutelaers for his ps2pk, from
24 		     which I took the rasterizer sources in a format
25 		     independ from X11.
26                      Thanks to all people who make free software living!
27 --------------------------------------------------------------------------*/
28 
29 
30 #define T1ENV_C
31 
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #if defined(_MSC_VER)
37 # include <io.h>
38 # include <sys/types.h>
39 # include <sys/stat.h>
40 #else
41 # include <unistd.h>
42 #endif
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 #include <ctype.h>
46 
47 
48 #include "../type1/types.h"
49 #include "parseAFM.h"
50 #include "../type1/objects.h"
51 #include "../type1/spaces.h"
52 #include "../type1/util.h"
53 #include "../type1/fontfcn.h"
54 #include "../type1/fontmisc.h"
55 
56 #include "sysconf.h"
57 #include "t1types.h"
58 #include "t1extern.h"
59 #include "t1env.h"
60 #include "t1misc.h"
61 #include "t1base.h"
62 
63 
64 /* The following static variables are used to store information on the distinct
65    file search paths:
66 
67    -1         t1lib has not yet been initialized!
68     0         t1lib has been initialized and default paths have been setup
69     n (>0)    there are n path elements for current search path type, either built
70               from a FontDataBase file or from explicit fucntion calls.
71 */
72 
73 static int pfab_no=-1;
74 static int afm_no=-1;
75 static int enc_no=-1;
76 static int fdb_no=-1;
77 
78 static char path_sep_char='\0';
79 static char path_sep_string[2];
80 
81 static char pathbuf[2048];
82 
83 /* Define some default search paths */
84 #ifndef VMS
85 static char T1_pfab[]=".";
86 static char T1_afm[]=".";
87 static char T1_enc[]=".";
88 #else
89 static char T1_pfab[]="sys$disk:[]";
90 static char T1_afm[]="sys$disk:[]";
91 static char T1_enc[]="sys$disk:[]";
92 #endif
93 char T1_fdb[]="FontDataBase";
94 
95 
96 /* keywords recognized in config file */
97 static const char enc_key[]="ENCODING";
98 static const char pfab_key[]="TYPE1";
99 static const char afm_key[]="AFM";
100 static const char fdb_key[]="FONTDATABASE";
101 
102 
103 /* qstrncpy(): Copy bytes from srcP to to destP. srcP is count bytes long
104    and destP is the number of quoted characters shorter. That is, count
105    refers to the number of characters including the escapement chars in
106    srcP! */
qstrncpy(char * destP,const char * srcP,long nochars)107 static void qstrncpy( char *destP, const char *srcP, long nochars)
108 {
109   long i;
110   long j;
111 
112   i=0;  /* dest-index */
113   j=0;  /* src-index */
114 
115   while (j<nochars) {
116     if (srcP[j]=='\\') {
117       if (srcP[j+1]=='"') {
118 	j++;                /* escaped quotation character --> omit escape char. */
119       }
120     }
121     else {                  /* normal character */
122       destP[i++]=srcP[j++];
123     }
124   }
125 }
126 
127 
128 
129 
130 /* Setup the default paths for searching the distinct file types. If
131    paths have been setup explicitly, skip the step of setting up a default path. */
intT1_SetupDefaultSearchPaths(void)132 void intT1_SetupDefaultSearchPaths( void)
133 {
134 
135   path_sep_char=PATH_SEP_CHAR;
136   sprintf( path_sep_string, "%c", path_sep_char);
137 
138   /* We set the number of stored path elements 0 so that we can distiguish
139      between explicitly setup paths and default paths in intT1_ScanConfigFile(). */
140   if (pfab_no==-1) {
141     T1_PFAB_ptr=(char**) calloc( 2, sizeof(char*));
142     T1_PFAB_ptr[0]=(char*)malloc(strlen(T1_pfab)+1);
143     strcpy(T1_PFAB_ptr[0],T1_pfab);
144     pfab_no=0;
145   }
146 
147   if (afm_no==-1) {
148     T1_AFM_ptr=(char**) calloc( 2, sizeof(char*));
149     T1_AFM_ptr[0]=(char*)malloc(strlen(T1_afm)+1);
150     strcpy(T1_AFM_ptr[0],T1_afm);
151     afm_no=0;
152   }
153 
154   if (enc_no==-1) {
155     T1_ENC_ptr=(char**) calloc( 2, sizeof(char*));
156     T1_ENC_ptr[0]=(char*)malloc(strlen(T1_enc)+1);
157     strcpy(T1_ENC_ptr[0],T1_enc);
158     enc_no=0;
159   }
160 
161   if (fdb_no==-1) {
162     T1_FDB_ptr=(char**) calloc( 2, sizeof(char*));
163     T1_FDB_ptr[0]=(char*)malloc(strlen(T1_fdb)+1);
164     strcpy(T1_FDB_ptr[0],T1_fdb);
165     fdb_no=0;
166   }
167 }
168 
169 
170 /* This function is called from T1_CloseLib(). We have to indicate the state
171    of a non-initialzed t1lib! */
intT1_FreeSearchPaths(void)172 void intT1_FreeSearchPaths( void)
173 {
174   int i;
175 
176   i=0;
177   if (T1_PFAB_ptr!=NULL) {
178     while (T1_PFAB_ptr[i]!=NULL) {
179       free(T1_PFAB_ptr[i]);
180       T1_PFAB_ptr[i]=NULL;
181     }
182     free( T1_PFAB_ptr);
183   }
184   i=0;
185   if (T1_AFM_ptr!=NULL) {
186     while (T1_AFM_ptr[i]!=NULL) {
187       free(T1_AFM_ptr[i]);
188       T1_AFM_ptr[i]=NULL;
189     }
190     free( T1_AFM_ptr);
191   }
192   i=0;
193   if (T1_ENC_ptr!=NULL) {
194     while (T1_ENC_ptr[i]!=NULL) {
195       free(T1_ENC_ptr[i]);
196       T1_ENC_ptr[i]=NULL;
197     }
198     free( T1_ENC_ptr);
199   }
200   i=0;
201   if (T1_FDB_ptr!=NULL) {
202     while (T1_FDB_ptr[i]!=NULL) {
203       free(T1_FDB_ptr[i]);
204       T1_FDB_ptr[i]=NULL;
205     }
206     free( T1_FDB_ptr);
207   }
208   /* indicate t1lib non-initialized */
209   pfab_no=-1;
210   afm_no=-1;
211   enc_no=-1;
212   fdb_no=-1;
213 
214   return;
215 }
216 
217 
218 /* ScanConfigFile(): Read a configuration file and scan and save the
219    environment strings used for searching pfa/pfb-, afm- and encoding
220    files as well as the name of the font database file. */
intT1_ScanConfigFile(void)221 int intT1_ScanConfigFile( void)
222 {
223 
224   char *env_str;
225   char *linebuf;
226   char *usershome;
227   char *cnffilepath;
228   char *globalcnffilepath;
229   static int linecnt;
230   char local_path_sep_char;
231   int quoted=0;
232   int quotecnt=0;
233   FILE *cfg_fp;
234   int filesize, i, j, k;
235   int ignoreline=0;
236 
237   char*** destP=NULL;
238   int *idestP=NULL;
239   char* curr_key=NULL;
240 
241   /* First, get the string stored in the environment variable: */
242   env_str=getenv(ENV_CONF_STRING);
243   linecnt=1;
244 
245   if (env_str==NULL) {
246     /* environment variable not set, try to open default file
247        in user's home directory and afterwards global config file */
248     if ((usershome=getenv("HOME"))!=NULL) {
249       cnffilepath=(char *)malloc((strlen(usershome) +
250 				  strlen(T1_CONFIGFILENAME) + 2
251 				  ) * sizeof(char));
252       if (cnffilepath==NULL){
253 	T1_errno=T1ERR_ALLOC_MEM;
254 	return(-1);
255       }
256       strcpy( cnffilepath, usershome);
257     }
258     else {
259       cnffilepath=(char *)malloc((strlen(T1_CONFIGFILENAME) + 2
260 				  ) * sizeof(char));
261     }
262     strcat( cnffilepath, DIRECTORY_SEP);
263     strcat( cnffilepath, T1_CONFIGFILENAME);
264 
265     globalcnffilepath=(char*)malloc((strlen(GLOBAL_CONFIG_DIR) +
266 				     strlen(GLOBAL_CONFIG_FILE) + 2
267 				     ) * sizeof(char));
268     if (globalcnffilepath==NULL){
269       T1_errno=T1ERR_ALLOC_MEM;
270       return(-1);
271     }
272     strcpy( globalcnffilepath, GLOBAL_CONFIG_DIR);
273     strcat( globalcnffilepath, DIRECTORY_SEP);
274     strcat( globalcnffilepath, GLOBAL_CONFIG_FILE);
275 
276     if ((cfg_fp=fopen( cnffilepath, "rb"))==NULL){
277       sprintf( err_warn_msg_buf, "Could not open configfile %s",
278 	       cnffilepath);
279       T1_PrintLog( "ScanConfigFile()", err_warn_msg_buf, T1LOG_STATISTIC);
280       /* Try global config file */
281       if ((cfg_fp=fopen( globalcnffilepath, "rb"))==NULL){
282 	sprintf( err_warn_msg_buf, "Could not open global configfile %s",
283 		 globalcnffilepath);
284 	T1_PrintLog( "ScanConfigFile()", err_warn_msg_buf, T1LOG_WARNING);
285       }
286       else{
287 	sprintf( err_warn_msg_buf, "Using %s as Configfile (global)",
288 		 cnffilepath);
289 	T1_PrintLog( "ScanConfigFile()", err_warn_msg_buf, T1LOG_STATISTIC);
290       }
291     }
292     else{
293       sprintf( err_warn_msg_buf, "Using %s as Configfile (user's)",
294 	       cnffilepath);
295       T1_PrintLog( "ScanConfigFile()", err_warn_msg_buf, T1LOG_STATISTIC);
296     }
297     free( cnffilepath);
298     free( globalcnffilepath);
299     if (cfg_fp==NULL){
300       T1_PrintLog( "ScanConfigFile()",
301 		   "Neither user's nor global Configfile has been found",
302 		   T1LOG_WARNING);
303       return(0);
304     }
305   }
306   else {
307     /* open specified file for reading the configuration */
308     if ((cfg_fp=fopen(env_str,"rb"))==NULL){
309       T1_PrintLog( "ScanConfigFile()",
310 		   "Configfile as specified by Environment has not been found",
311 		   T1LOG_WARNING);
312       return(0);  /* specified file could not be openend
313 		     => no config paths read */
314     }
315     else {
316       sprintf( err_warn_msg_buf, "Using %s as Configfile (environment)",
317 	       env_str);
318       T1_PrintLog( "ScanConfigFile()", err_warn_msg_buf, T1LOG_STATISTIC);
319     }
320   }
321 
322 
323   /* cfg_fp points now to a valid config file */
324   /* Get the file size */
325   fseek( cfg_fp, 0, SEEK_END);
326   filesize=ftell(cfg_fp);
327   /* Reset fileposition to start */
328   fseek( cfg_fp, 0, SEEK_SET);
329 
330   if ((linebuf=(char *)calloc( filesize+1,
331 			       sizeof(char)))==NULL){
332     T1_errno=T1ERR_ALLOC_MEM;
333     return(-1);
334   }
335 
336   fread((char *)linebuf, sizeof(char), filesize, cfg_fp);
337   fclose(cfg_fp);
338 
339   i=0;
340 
341   /* this might be overwritten on a per file basis */
342   local_path_sep_char=path_sep_char;
343 
344   while(i<filesize) {
345     ignoreline=0;
346     j=i;     /* Save index of beginning of line */
347     while ((linebuf[i]!='=') && (linebuf[i]!='\n') && (i<filesize)) {
348       i++;
349     }
350     if (i==filesize) {
351       free( linebuf);
352       return(i);
353     }
354 
355     if (strncmp( enc_key, &linebuf[j], 8)==0) {
356       /* setup target */
357       destP=&T1_ENC_ptr;
358       idestP=&enc_no;
359       curr_key=(char*)enc_key;
360     }
361     else if (strncmp( "TYPE1", &linebuf[j], 5)==0) {
362       /* setup target */
363       destP=&T1_PFAB_ptr;
364       idestP=&pfab_no;
365       curr_key=(char*)pfab_key;
366     }
367     else if (strncmp( afm_key, &linebuf[j], 3)==0) {
368       /* setup target */
369       destP=&T1_AFM_ptr;
370       idestP=&afm_no;
371       curr_key=(char*)afm_key;
372     }
373     else if (strncmp( fdb_key, &linebuf[j], 12)==0) {
374       /* setup target */
375       destP=&T1_FDB_ptr;
376       idestP=&fdb_no;
377       curr_key=(char*)fdb_key;
378     }
379     else {
380       ignoreline=1;
381       T1_PrintLog( "ScanConfigFile()", "Ignoring line %d",
382 		   T1LOG_DEBUG, linecnt);
383     }
384 
385     /* If appropriate, scan this line. */
386     if (ignoreline==0) {
387       /* Check for an explicitly assigned value */
388       if (*idestP==0) { /* default paths are currently setup, get rid of them */
389 	free((*destP)[0]);
390       }
391       else { /* append to existing paths */
392 	T1_PrintLog( "ScanConfigFile()",
393 		     "Appending to existing %s search path",
394 		     T1LOG_DEBUG, curr_key);
395       }
396       while ( (!isspace((int)linebuf[i])) && (i<filesize) ) {
397 	k=++i;      /* index to current path element */
398 	(*idestP)++;
399 	quotecnt=0;
400 	if (linebuf[i]=='"') { /* We have a quoted string */
401 	  quoted=1;
402 	  k=++i;
403 	  while ( 1) {
404 	    if ( linebuf[i]=='"' ) {    /* we find a quote-char */
405 	      if ( linebuf[i-1]!='\\' )
406 		break;                     /* not escaped --> end of path specification */
407 	      else
408 		quotecnt++;
409 	    }                           /* some other char */
410 	    if (linebuf[i]=='\n') { /* a newline in a quoted string? Perhabs, quotes do not match! */
411 	      T1_PrintLog( "ScanConfigFile()",
412 			   "Newline in quoted %s-string in line %d, column %d, of config file! Closing quote missing?",
413 			   T1LOG_WARNING, curr_key, linecnt, i-j+1);
414 	      j=i+1;                /* resynchronize linecount */
415 	      linecnt++;
416 	    }
417 	    if (i<filesize) {            /* filesize not exceeded? */
418 	      i++;
419 	    }
420 	    else {                       /* issue error msg because end of quotation is missing */
421 	      T1_PrintLog( "ScanConfigFile()", "Unterminated quoted string in config file",
422 			   T1LOG_ERROR);
423 	      return -1;
424 	    }
425 	  }
426 	}
427 	else {
428 	  quoted=0;
429 	  while ( (linebuf[i]!=local_path_sep_char) && (!isspace((int)linebuf[i])) && (i<filesize) )
430 	    i++;
431 	}
432 	if (((*destP)=(char**)realloc( (*destP), ((*idestP)+1)*sizeof(char*)))==NULL) {
433 	  T1_errno=T1ERR_ALLOC_MEM;
434 	  return(-1);
435 	}
436 	if (((*destP)[(*idestP)-1]=(char*)malloc((i-k-quotecnt+1)*sizeof(char)))==NULL) {
437 	  T1_errno=T1ERR_ALLOC_MEM;
438 	  return(-1);
439 	}
440 	if (quoted==0) {
441 	  strncpy( (*destP)[*idestP-1], &(linebuf[k]), i-k);
442 	  (*destP)[(*idestP)-1][i-k]='\0';
443 	}
444 	else {
445 	  qstrncpy( (*destP)[(*idestP)-1], &(linebuf[k]), i-k);
446 	  (*destP)[(*idestP)-1][i-k-quotecnt]='\0';
447 	  i++;         /* step over closing quote */
448 	}
449 	(*destP)[(*idestP)]=NULL;     /* indicate end of string list */
450       }
451     }
452 
453     /* skip remaining of line or file */
454     while ((linebuf[i]!='\n')&&(i<filesize))
455       i++;
456     i++;
457     linecnt++;
458   }
459   /* file should now be read in */
460   free( linebuf);
461 
462   return(i);
463 
464 }
465 
466 
467 
468 /* intT1_Env_GetCompletePath( ): Get a full path name from the file specified by
469    argument 1 in the environment specified by argument 2. Return the pointer
470    to the path string or NULL if no file was found.*/
intT1_Env_GetCompletePath(char * FileName,char ** env_ptr)471 char *intT1_Env_GetCompletePath( char *FileName,
472 				 char **env_ptr )
473 {
474   struct stat filestats;    /* A structure where fileinfo is stored */
475   int fnamelen, i, j;
476   char *FullPathName;
477   char *StrippedName;
478 
479 
480   if (FileName==NULL)
481     return(NULL);
482   fnamelen=strlen(FileName);
483 
484   /* We check whether absolute or relative pathname is given. If so,
485      stat() it and if appropriate, return that string immediately. */
486   if ( (FileName[0]==DIRECTORY_SEP_CHAR)
487        ||
488        ((fnamelen>1) && (FileName[0]=='.') &&
489 	(FileName[1]==DIRECTORY_SEP_CHAR))
490        ||
491        ((fnamelen>2) && (FileName[0]=='.') &&
492 	(FileName[1]=='.') && (FileName[2]==DIRECTORY_SEP_CHAR))
493 #if defined(MSDOS) | defined(_WIN32) | defined (__EMX__)
494        ||
495        ((isalpha(FileName[0])) && (FileName[1]==':'))
496 #endif
497 #ifdef VMS
498        || (strchr(FileName,':') != NULL)
499 #endif
500        )
501     {
502     /* Check for existence of the path: */
503     if (!stat( FileName, &filestats)) {
504       if (t1lib_log_file!=NULL) {
505 	sprintf( err_warn_msg_buf, "stat()'ing complete path %s successful",
506 		 FileName);
507 	T1_PrintLog( "intT1_Env_GetCompletePath()", err_warn_msg_buf,
508 		     T1LOG_DEBUG);
509       }
510       /* Return a copy of the string */
511       if ((FullPathName=(char *)malloc( fnamelen + 1))==NULL) {
512 	T1_errno=T1ERR_ALLOC_MEM;
513 	return(NULL);
514       }
515       strcpy( FullPathName, FileName);
516       return(FullPathName);
517     }
518     if (t1lib_log_file!=NULL){
519       sprintf( err_warn_msg_buf, "stat()'ing complete path %s failed",
520 	       FileName);
521       T1_PrintLog( "intT1_Env_GetCompletePath()", err_warn_msg_buf,
522 		   T1LOG_DEBUG);
523     }
524     /* Trying to locate absolute path spec. failed. We try to recover
525        by removing the path component and searching in the remaining search
526        path entries. This depends on the OS. */
527     i=fnamelen-1;
528     StrippedName=&(FileName[i]);
529     while ( FileName[i]!=DIRECTORY_SEP_CHAR
530 #if defined(VMS)
531 	    /* What exactly to do for VMS? */
532 #elif defined(MSDOS) | defined(_WIN32) | defined (__EMX__) | defined(_MSC_VER)
533 	    /* We take a drive specification into account. This means we
534 	       step back until the directory separator or a drive specifier
535 	       appears! */
536 	    && FileName[i]!=':'
537 #endif
538 	    ) {
539       i--;
540     }
541     i++;
542     StrippedName=&FileName[i];
543     if (t1lib_log_file!=NULL){
544       sprintf( err_warn_msg_buf, "path %s stripped to %s",
545 	       FileName, StrippedName);
546       T1_PrintLog( "intT1_Env_GetCompletePath()", err_warn_msg_buf,
547 		   T1LOG_DEBUG);
548     }
549   }
550   else{ /* We have a relative path name */
551     StrippedName=&FileName[0];
552   }
553 
554   i=0;
555   while (env_ptr[i]!=NULL) {
556     /* Copy current path element: */
557     strcpy( pathbuf, env_ptr[i]);
558     /* cut a trailing directory separator */
559     j=strlen(pathbuf);
560     if (pathbuf[j-1]==DIRECTORY_SEP_CHAR)
561       pathbuf[j--]='\0';
562     /* Add the directory separator: */
563 #ifdef VMS
564     { char *p= strrchr(pathbuf, DIRECTORY_SEP_CHAR);
565       if (p && *(p+1) ==  '\0')
566        *p = '\0';
567     }
568 #endif
569     strcat( pathbuf, DIRECTORY_SEP);
570     /* And finally the filename: */
571     strcat( pathbuf, StrippedName);
572 
573     /* Check for existence of the path: */
574     if (!stat( pathbuf, &filestats)) {
575       if ((FullPathName=(char*)malloc( (j+fnamelen+2)*sizeof(char)))==NULL) {
576 	T1_errno=T1ERR_ALLOC_MEM;
577 	return(NULL);
578       }
579       strcpy( FullPathName, pathbuf);
580       if (t1lib_log_file!=NULL){
581 	sprintf( err_warn_msg_buf, "stat()'ing %s successful",
582 		 FullPathName);
583 	T1_PrintLog( "intT1_Env_GetCompletePath()", err_warn_msg_buf,
584 		     T1LOG_DEBUG);
585       }
586       return(FullPathName);
587     }
588     if (t1lib_log_file!=NULL){
589       sprintf( err_warn_msg_buf, "stat()'ing %s failed",
590 	       pathbuf);
591       T1_PrintLog( "intT1_Env_GetCompletePath()", err_warn_msg_buf,
592 		   T1LOG_DEBUG);
593     }
594     /* We didn't find the file --> try next path entry */
595     i++;
596   }
597   /* If we get here, no file was found at all, so return a NULL-pointer */
598   return(NULL);
599 }
600 
601 
602 
603 /* T1_SetFileSearchPath(): Set the search path to find files of the
604    specified type and return 0 if successful and -1 otherwise. An existing
605    path is overwritten rigorously, unless the database already contains fonts.
606    In the latter case the function returns with an error status.
607    Multiple path types may be specified as a bitmask!
608 */
T1_SetFileSearchPath(int type,char * pathname)609 int T1_SetFileSearchPath( int type, char *pathname)
610 {
611 
612   int i;
613   int pathlen;
614 
615 
616   if (pathname==NULL){
617     T1_errno=T1ERR_INVALID_PARAMETER;
618     return(-1);
619   }
620 
621   /* We do not allow to change the searchpath if the database already
622      contains one or more entries. */
623   if (T1_Get_no_fonts()>0){
624     sprintf( err_warn_msg_buf, "Path %s not set, database is not empty",
625 	     pathname);
626     T1_PrintLog( "T1_SetFileSearchPath()", err_warn_msg_buf,
627 		 T1LOG_STATISTIC);
628     T1_errno=T1ERR_OP_NOT_PERMITTED;
629     return(-1);
630   }
631 
632   pathlen=strlen(pathname)+1;
633   /* Throw away a possibly existing path */
634   if (type & T1_PFAB_PATH){
635     if (pfab_no==-1) {
636       T1_PFAB_ptr=NULL; /* realloc() will do a malloc() */
637     }
638     else {
639       /* throw away current paths */
640       i=0;
641       while (T1_PFAB_ptr[i]!=NULL) {
642 	free (T1_PFAB_ptr[i++]);
643       }
644     }
645     if ((T1_PFAB_ptr=(char**)realloc( T1_PFAB_ptr, 2*sizeof(char*)))==NULL) {
646       T1_errno=T1ERR_ALLOC_MEM;
647       return(-1);
648     }
649     if ((T1_PFAB_ptr[0]=(char*)malloc(pathlen*sizeof(char)))==NULL) {
650       T1_errno=T1ERR_ALLOC_MEM;
651       return(-1);
652     }
653     strcpy( T1_PFAB_ptr[0], pathname);
654     T1_PFAB_ptr[1]=NULL;
655     pfab_no=1;
656   }
657   if (type & T1_AFM_PATH){
658     if (afm_no==-1) {
659       T1_AFM_ptr=NULL; /* realloc() will do a malloc() */
660     }
661     else {
662       /* throw away current paths */
663       i=0;
664       while (T1_AFM_ptr[i]!=NULL) {
665 	free (T1_AFM_ptr[i++]);
666       }
667     }
668     if ((T1_AFM_ptr=(char**)realloc( T1_AFM_ptr, 2*sizeof(char*)))==NULL) {
669       T1_errno=T1ERR_ALLOC_MEM;
670       return(-1);
671     }
672     if ((T1_AFM_ptr[0]=(char*)malloc(pathlen*sizeof(char)))==NULL) {
673       T1_errno=T1ERR_ALLOC_MEM;
674       return(-1);
675     }
676     strcpy( T1_AFM_ptr[0], pathname);
677     T1_AFM_ptr[1]=NULL;
678     afm_no=1;
679   }
680   if (type & T1_ENC_PATH){
681     if (enc_no==-1) {
682       T1_ENC_ptr=NULL; /* realloc() will do a malloc() */
683     }
684     else {
685       /* throw away current paths */
686       i=0;
687       while (T1_ENC_ptr[i]!=NULL) {
688 	free (T1_ENC_ptr[i++]);
689       }
690     }
691     if ((T1_ENC_ptr=(char**)realloc( T1_ENC_ptr, 2*sizeof(char*)))==NULL) {
692       T1_errno=T1ERR_ALLOC_MEM;
693       return(-1);
694     }
695     if ((T1_ENC_ptr[0]=(char*)malloc(pathlen*sizeof(char)))==NULL) {
696       T1_errno=T1ERR_ALLOC_MEM;
697       return(-1);
698     }
699     strcpy( T1_ENC_ptr[0], pathname);
700     T1_ENC_ptr[1]=NULL;
701     enc_no=1;
702   }
703 
704   return(0);
705 
706 }
707 
708 
709 
710 /* T1_GetFileSearchPath(): Return the specified file search path
711    or NULL if an error occurred. Note: We do only one path at a
712    time, so that if a bitmask is specified, the first match wins.
713    The returned path is formatted using the actual PATH_SEP_CHAR. */
T1_GetFileSearchPath(int type)714 char *T1_GetFileSearchPath( int type)
715 {
716   static char *out_ptr;
717   int i;
718   int pathlen;
719   char **src_ptr=NULL;
720 
721 
722   if (out_ptr!=NULL)
723     free( out_ptr);
724   out_ptr=NULL;
725 
726   if (type & T1_PFAB_PATH) {
727     src_ptr=T1_PFAB_ptr;
728   }
729   else  if (type & T1_AFM_PATH) {
730     src_ptr=T1_AFM_ptr;
731   }
732   else if (type & T1_ENC_PATH) {
733     src_ptr=T1_ENC_ptr;
734   }
735   else if (type & T1_FDB_PATH) {
736     src_ptr=T1_FDB_ptr;
737   }
738 
739 
740   i=0;
741   pathlen=0;
742   while (src_ptr[i]!=NULL) {
743     pathlen +=strlen( src_ptr[i++]);
744     pathlen+=1; /* path separator */
745   }
746   if ((out_ptr=(char *)malloc(pathlen+1))==NULL) {
747     T1_errno=T1ERR_ALLOC_MEM;
748     return( NULL);
749   }
750   strcpy( out_ptr, src_ptr[0]);
751   i=1;
752   while (src_ptr[i]!=NULL) {
753     strcat( out_ptr, path_sep_string);
754     strcat( out_ptr, src_ptr[i++]);
755   }
756 
757   return( out_ptr);
758 
759 }
760 
761 
762 /* T1_AddToFileSearchPath(): Add the specified path element to
763    the specified search path. If the existing path is the default path,
764    it will not be replaced by the new path element. Since this function might
765    be called before initialization, we have to be aware that even the default
766    path could be missing. Multiple path types may be specified as a bitmask!
767    Return value is 0 if successful and -1 otherwise */
T1_AddToFileSearchPath(int pathtype,int mode,char * pathname)768 int T1_AddToFileSearchPath( int pathtype, int mode, char *pathname)
769 {
770   int i;
771   int pathlen;
772   char* newpath;
773   int nofonts;
774 
775 
776 
777   if (pathname==NULL)
778     return(-1);
779 
780   nofonts=T1_Get_no_fonts();
781 
782   pathlen=strlen(pathname);
783 
784   if (pathtype & T1_PFAB_PATH){
785     /* Allocate meory for string */
786     if ((newpath=(char*)malloc( (pathlen+1)*sizeof(char)))==NULL)  {
787       T1_errno=T1ERR_ALLOC_MEM;
788       return(-1);
789     }
790     /* Check for and handle the existing path configuration */
791     if (pfab_no==0) {   /* do not free the default path but establish it
792 			   as a regularly setup path, if database not empty! */
793       if (nofonts>0) {
794 	pfab_no++;
795       }
796       else {
797 	free( T1_AFM_ptr[0]);
798       }
799     }
800     if (pfab_no==-1) {  /* not initialized! */
801       pfab_no=0;
802       T1_PFAB_ptr=NULL; /* realloc() will do the malloc()! */
803     }
804     if ((T1_PFAB_ptr=(char**)realloc( T1_PFAB_ptr, (++pfab_no+1)*sizeof(char*)))==NULL) {
805       T1_errno=T1ERR_ALLOC_MEM;
806       return(-1);
807     }
808     /* Insert the new path element: */
809     if (mode & T1_PREPEND_PATH){ /* prepend */
810       i=pfab_no-2;
811       while (i>=0) {
812 	T1_PFAB_ptr[i+1]=T1_PFAB_ptr[i];
813 	i--;
814       }
815       T1_PFAB_ptr[0]=newpath;
816     }
817     else{ /* append */
818       T1_PFAB_ptr[pfab_no-1]=newpath;
819     }
820     T1_PFAB_ptr[pfab_no]=NULL;
821   }
822   if (pathtype & T1_AFM_PATH){
823     /* Allocate meory for string */
824     if ((newpath=(char*)malloc( (pathlen+1)*sizeof(char)))==NULL)  {
825       T1_errno=T1ERR_ALLOC_MEM;
826       return(-1);
827     }
828     /* Check for and handle the existing path configuration */
829     if (afm_no==0) {   /* do not free the default path but establish it
830 			  as a regularly setup path, if database not empty! */
831       if (nofonts>0) {
832 	afm_no++;
833       }
834       else {
835 	free( T1_AFM_ptr[0]);
836       }
837     }
838     if (afm_no==-1) {  /* not initialized! */
839       afm_no=0;
840       T1_AFM_ptr=NULL; /* realloc() will do the malloc()! */
841     }
842     if ((T1_AFM_ptr=(char**)realloc( T1_AFM_ptr, (++afm_no+1)*sizeof(char*)))==NULL) {
843       T1_errno=T1ERR_ALLOC_MEM;
844       return(-1);
845     }
846     /* Insert the new path element */
847     if (mode & T1_PREPEND_PATH){ /* prepend */
848       i=afm_no-2;
849       while (i>=0) {
850 	T1_AFM_ptr[i+1]=T1_AFM_ptr[i];
851 	i--;
852       }
853       T1_AFM_ptr[0]=newpath;
854     }
855     else{ /* append */
856       T1_AFM_ptr[afm_no-1]=newpath;
857     }
858     T1_AFM_ptr[afm_no]=NULL;
859   }
860   if (pathtype & T1_ENC_PATH){
861     /* Allocate meory for string */
862     if ((newpath=(char*)malloc( (pathlen+1)*sizeof(char)))==NULL)  {
863       T1_errno=T1ERR_ALLOC_MEM;
864       return(-1);
865     }
866     /* Check for and handle the existing path configuration */
867     if (enc_no==0) {    /* do not free the default path but establish it
868 			   as a regularly setup path, if database not empty! */
869       if (nofonts>0) {
870 	enc_no++;
871       }
872       else {
873 	free( T1_ENC_ptr[0]);
874       }
875     }
876     if (enc_no==-1) {  /* not initialized! */
877       enc_no=0;
878       T1_ENC_ptr=NULL; /* realloc() will do the malloc()! */
879     }
880     if ((T1_ENC_ptr=(char**)realloc( T1_ENC_ptr, (++enc_no+1)*sizeof(char*)))==NULL) {
881       T1_errno=T1ERR_ALLOC_MEM;
882       return(-1);
883     }
884     /* Insert the new path element: */
885     if (mode & T1_PREPEND_PATH){ /* prepend */
886       i=enc_no-2;
887       while (i>=0) {
888 	T1_ENC_ptr[i+1]=T1_ENC_ptr[i];
889 	i--;
890       }
891       T1_ENC_ptr[0]=newpath;
892     }
893     else{ /* append */
894       T1_ENC_ptr[enc_no-1]=newpath;
895     }
896     T1_ENC_ptr[enc_no]=NULL;
897   }
898   return(0);
899 
900 }
901 
902 
903 
904 /* T1_SetFontDataBase(): Set a new name for the font database. It replaces the default
905    name and any names specified previously with this function.
906    Return value: 0 if OK, and -1 if filename not valid or an allocation
907    error occurred */
T1_SetFontDataBase(char * filename)908 int T1_SetFontDataBase( char *filename)
909 {
910   int pathlen;
911   int i;
912   int result=0;
913 
914 
915   /* chekc filename */
916   if (filename==NULL) {
917     T1_errno=T1ERR_INVALID_PARAMETER;
918     return -1;
919   }
920 
921   /* this function must be called before any font is in the database, that is, usually,
922      before initialization! */
923   if ( pFontBase!=NULL && pFontBase->no_fonts>0) {
924     T1_errno=T1ERR_OP_NOT_PERMITTED;
925     return -1;
926   }
927 
928 
929   pathlen=strlen(filename)+1;
930   /* Throw away a possibly existing font database-statement */
931   if (fdb_no==-1) {
932     T1_FDB_ptr=NULL; /* realloc() will do a malloc() */
933   }
934   else {
935     /* throw away current paths */
936     i=0;
937     while (T1_FDB_ptr[i]!=NULL) {
938       free (T1_FDB_ptr[i++]);
939     }
940   }
941 
942   if ((T1_FDB_ptr=(char**)realloc( T1_FDB_ptr, 2*sizeof(char*)))==NULL) {
943     T1_errno=T1ERR_ALLOC_MEM;
944     return -1;
945   }
946 
947   if ((T1_FDB_ptr[0]=(char*)malloc(pathlen*sizeof(char)))==NULL) {
948     T1_errno=T1ERR_ALLOC_MEM;
949     return -1;
950   }
951   strcpy( T1_FDB_ptr[0], filename);
952   T1_FDB_ptr[1]=NULL;
953   fdb_no=1;
954 
955   /* Load database immediately if t1lib already is initailzed */
956   if (CheckForInit()==0) {
957     if ((result=intT1_scanFontDBase(T1_FDB_ptr[0]))==-1) {
958       T1_PrintLog( "T1_AddFontDataBase()", "Fatal error scanning Font Database File %s (T1_errno=%d)",
959 		   T1LOG_WARNING, T1_FDB_ptr[0], T1_errno);
960     }
961     if (result>-1)
962       pFontBase->no_fonts+=result;
963     result=pFontBase->no_fonts;
964   }
965   return result;
966 
967 }
968 
969 
970 /* T1_AddFontDataBase(): Add a new font database file to the list. If the
971    lib is already initialzed, then the new database is immediately loaded.
972    Otherwise it is simply appended to the list and loaded at the time of
973    initialization.
974    Returns: -1    an error occured
975              0    successfully inserted but not loaded because lib not initilized
976 	     n>0  the highest defined FontID
977 */
T1_AddFontDataBase(int mode,char * filename)978 int T1_AddFontDataBase( int mode, char *filename)
979 {
980   int i;
981   int pathlen;
982   int result=0;
983   char* newpath;
984 
985 
986   if (filename==NULL) {
987     T1_errno=T1ERR_INVALID_PARAMETER;
988     return(-1);
989   }
990 
991   pathlen=strlen(filename);
992 
993   /* Allocate memory for string */
994   if ((newpath=(char*)malloc( (pathlen+1)*sizeof(char)))==NULL)  {
995     T1_errno=T1ERR_ALLOC_MEM;
996     return(-1);
997   }
998   strcpy( newpath, filename);
999   /* Check for and handle the existing path configuration */
1000   if (fdb_no==0) {   /* defauls setup, free the path */
1001     free( T1_FDB_ptr[0]);
1002   }
1003   if (fdb_no==-1) {  /* not initialized! */
1004     fdb_no=0;
1005     T1_FDB_ptr=NULL; /* realloc() will do the malloc()! */
1006   }
1007 
1008   if ((T1_FDB_ptr=(char**)realloc( T1_FDB_ptr, (++fdb_no+1)*sizeof(char*)))==NULL) {
1009     T1_errno=T1ERR_ALLOC_MEM;
1010     return(-1);
1011   }
1012   /* Insert the new database. If t1lib is already initialzed, the database can only
1013      be appended. Otherwise. prepending is also possible.*/
1014   if ((mode & T1_PREPEND_PATH) && (CheckForInit()!=0) ) { /* prepend */
1015     i=fdb_no-2;
1016     while (i>=0) {
1017       T1_FDB_ptr[i+1]=T1_FDB_ptr[i];
1018       i--;
1019     }
1020     T1_FDB_ptr[0]=newpath;
1021     result=0;
1022   }
1023   else { /* append */
1024     T1_FDB_ptr[fdb_no-1]=newpath;
1025     if (CheckForInit()==0) {
1026       if ((result=intT1_scanFontDBase(T1_FDB_ptr[fdb_no-1]))==-1) {
1027 	T1_PrintLog( "T1_AddFontDataBase()", "Fatal error scanning Font Database File %s (T1_errno=%d)",
1028 		     T1LOG_WARNING, T1_FDB_ptr[fdb_no-1], T1_errno);
1029       }
1030       if (result>-1)
1031 	pFontBase->no_fonts+=result;
1032       result=pFontBase->no_fonts;
1033     }
1034   }
1035   T1_FDB_ptr[fdb_no]=NULL;
1036   return result;
1037 
1038 }
1039 
1040 
1041