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