1 /*--------------------------------------------------------------------------
2 ----- File: t1env.c
3 ----- Author: Rainer Menzner (Rainer.Menzner@web.de)
4 ----- Date: 2007-12-22
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-2007.
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 static int fdbxlfd_no=-1;
78
79 static char path_sep_char='\0';
80 static char path_sep_string[2];
81
82 static char pathbuf[2048];
83
84 /* Define some default search paths */
85 #ifndef VMS
86 static char T1_pfab[]=".";
87 static char T1_afm[]=".";
88 static char T1_enc[]=".";
89 #else
90 static char T1_pfab[]="sys$disk:[]";
91 static char T1_afm[]="sys$disk:[]";
92 static char T1_enc[]="sys$disk:[]";
93 #endif
94 char T1_fdb[]="FontDataBase";
95 char T1_fdbxlfd[]=""; /* By default, we do not search XLFD databases. */
96
97
98 /* keywords recognized in config file */
99 static const char enc_key[]="ENCODING";
100 static const char pfab_key[]="TYPE1";
101 static const char afm_key[]="AFM";
102 static const char fdb_key[]="FONTDATABASE";
103 static const char fdbxlfd_key[]="FONTDATABASEXLFD";
104
105
106 /* qstrncpy(): Copy bytes from srcP to to destP. srcP is count bytes long
107 and destP is the number of quoted characters shorter. That is, count
108 refers to the number of characters including the escapement chars in
109 srcP! */
qstrncpy(char * destP,const char * srcP,long nochars)110 static void qstrncpy( char *destP, const char *srcP, long nochars)
111 {
112 long i;
113 long j;
114
115 i=0; /* dest-index */
116 j=0; /* src-index */
117
118 while (j<nochars) {
119 if (srcP[j]=='\\') {
120 if (srcP[j+1]=='"') {
121 j++; /* escaped quotation character --> omit escape char. */
122 }
123 }
124 else { /* normal character */
125 destP[i++]=srcP[j++];
126 }
127 }
128 }
129
130
131
132
133 /* Setup the default paths for searching the distinct file types. If
134 paths have been setup explicitly, skip the step of setting up a default path. */
intT1_SetupDefaultSearchPaths(void)135 void intT1_SetupDefaultSearchPaths( void)
136 {
137
138 path_sep_char=PATH_SEP_CHAR;
139 sprintf( path_sep_string, "%c", path_sep_char);
140
141 /* We set the number of stored path elements 0 so that we can distiguish
142 between explicitly setup paths and default paths in intT1_ScanConfigFile(). */
143 if (pfab_no==-1) {
144 T1_PFAB_ptr=(char**) calloc( 2, sizeof(char*));
145 T1_PFAB_ptr[0]=(char*)malloc(strlen(T1_pfab)+1);
146 strcpy(T1_PFAB_ptr[0],T1_pfab);
147 pfab_no=0;
148 }
149
150 if (afm_no==-1) {
151 T1_AFM_ptr=(char**) calloc( 2, sizeof(char*));
152 T1_AFM_ptr[0]=(char*)malloc(strlen(T1_afm)+1);
153 strcpy(T1_AFM_ptr[0],T1_afm);
154 afm_no=0;
155 }
156
157 if (enc_no==-1) {
158 T1_ENC_ptr=(char**) calloc( 2, sizeof(char*));
159 T1_ENC_ptr[0]=(char*)malloc(strlen(T1_enc)+1);
160 strcpy(T1_ENC_ptr[0],T1_enc);
161 enc_no=0;
162 }
163
164 if (fdb_no==-1) {
165 T1_FDB_ptr=(char**) calloc( 2, sizeof(char*));
166 T1_FDB_ptr[0]=(char*)malloc(strlen(T1_fdb)+1);
167 strcpy(T1_FDB_ptr[0],T1_fdb);
168 fdb_no=0;
169 }
170
171 if (fdbxlfd_no==-1) {
172 /* The XLFD font data base defaults to be empty */
173 T1_FDBXLFD_ptr=(char**) calloc( 1, sizeof(char*));
174 fdbxlfd_no=0;
175 }
176 }
177
178
179 /* This function is called from T1_CloseLib(). We have to indicate the state
180 of a non-initialzed t1lib! */
intT1_FreeSearchPaths(void)181 void intT1_FreeSearchPaths( void)
182 {
183 int i;
184
185 i=0;
186 if (T1_PFAB_ptr!=NULL) {
187 while (T1_PFAB_ptr[i]!=NULL) {
188 free(T1_PFAB_ptr[i]);
189 T1_PFAB_ptr[i++]=NULL;
190 }
191 free( T1_PFAB_ptr);
192 T1_PFAB_ptr=NULL;
193 }
194 i=0;
195 if (T1_AFM_ptr!=NULL) {
196 while (T1_AFM_ptr[i]!=NULL) {
197 free(T1_AFM_ptr[i]);
198 T1_AFM_ptr[i++]=NULL;
199 }
200 free( T1_AFM_ptr);
201 T1_AFM_ptr=NULL;
202 }
203 i=0;
204 if (T1_ENC_ptr!=NULL) {
205 while (T1_ENC_ptr[i]!=NULL) {
206 free(T1_ENC_ptr[i]);
207 T1_ENC_ptr[i++]=NULL;
208 }
209 free( T1_ENC_ptr);
210 T1_ENC_ptr=NULL;
211 }
212 i=0;
213 if (T1_FDB_ptr!=NULL) {
214 while (T1_FDB_ptr[i]!=NULL) {
215 free(T1_FDB_ptr[i]);
216 T1_FDB_ptr[i++]=NULL;
217 }
218 free( T1_FDB_ptr);
219 T1_FDB_ptr=NULL;
220 }
221 i=0;
222 if (T1_FDBXLFD_ptr!=NULL) {
223 while (T1_FDBXLFD_ptr[i]!=NULL) {
224 free(T1_FDBXLFD_ptr[i]);
225 T1_FDBXLFD_ptr[i++]=NULL;
226 }
227 free( T1_FDBXLFD_ptr);
228 T1_FDBXLFD_ptr=NULL;
229 }
230 /* indicate t1lib non-initialized */
231 pfab_no=-1;
232 afm_no=-1;
233 enc_no=-1;
234 fdb_no=-1;
235 fdbxlfd_no=-1;
236
237 return;
238 }
239
240
241 /* ScanConfigFile(): Read a configuration file and scan and save the
242 environment strings used for searching pfa/pfb-, afm- and encoding
243 files as well as the name of the font database file. */
intT1_ScanConfigFile(void)244 int intT1_ScanConfigFile( void)
245 {
246
247 char *env_str;
248 char *linebuf;
249 char *usershome;
250 char *cnffilepath;
251 char *globalcnffilepath;
252 static int linecnt;
253 char local_path_sep_char;
254 int quoted=0;
255 int quotecnt=0;
256 FILE *cfg_fp;
257 int filesize, i, j, k;
258 int ignoreline=0;
259
260 char*** destP=NULL;
261 int *idestP=NULL;
262 char* curr_key=NULL;
263
264 /* First, get the string stored in the environment variable: */
265 env_str=getenv(ENV_CONF_STRING);
266 linecnt=1;
267
268 if (!env_str) {
269 /* environment variable not set, try to open default file
270 in user's home directory and afterwards global config file */
271 if ((usershome=getenv("HOME"))!=NULL) {
272 cnffilepath=(char *)malloc((strlen(usershome) +
273 strlen(T1_CONFIGFILENAME) + 2
274 ) * sizeof(char));
275 if (cnffilepath==NULL){
276 T1_errno=T1ERR_ALLOC_MEM;
277 return(-1);
278 }
279 strcpy( cnffilepath, usershome);
280 }
281 else {
282 cnffilepath=(char *)malloc((strlen(T1_CONFIGFILENAME) + 2
283 ) * sizeof(char));
284 }
285 strcat( cnffilepath, DIRECTORY_SEP);
286 strcat( cnffilepath, T1_CONFIGFILENAME);
287
288 globalcnffilepath=(char*)malloc((strlen(GLOBAL_CONFIG_DIR) +
289 strlen(GLOBAL_CONFIG_FILE) + 2
290 ) * sizeof(char));
291 if (globalcnffilepath==NULL){
292 T1_errno=T1ERR_ALLOC_MEM;
293 return(-1);
294 }
295 strcpy( globalcnffilepath, GLOBAL_CONFIG_DIR);
296 strcat( globalcnffilepath, DIRECTORY_SEP);
297 strcat( globalcnffilepath, GLOBAL_CONFIG_FILE);
298
299 if ((cfg_fp=fopen( cnffilepath, "rb"))==NULL){
300 sprintf( err_warn_msg_buf, "Could not open configfile %s",
301 cnffilepath);
302 T1_PrintLog( "ScanConfigFile()", err_warn_msg_buf, T1LOG_STATISTIC);
303 /* Try global config file */
304 if ((cfg_fp=fopen( globalcnffilepath, "rb"))==NULL){
305 sprintf( err_warn_msg_buf, "Could not open global configfile %s",
306 globalcnffilepath);
307 T1_PrintLog( "ScanConfigFile()", err_warn_msg_buf, T1LOG_WARNING);
308 }
309 else{
310 sprintf( err_warn_msg_buf, "Using %s as Configfile (global)",
311 globalcnffilepath);
312 T1_PrintLog( "ScanConfigFile()", err_warn_msg_buf, T1LOG_STATISTIC);
313 }
314 }
315 else{
316 sprintf( err_warn_msg_buf, "Using %s as Configfile (user's)",
317 cnffilepath);
318 T1_PrintLog( "ScanConfigFile()", err_warn_msg_buf, T1LOG_STATISTIC);
319 }
320 free( cnffilepath);
321 free( globalcnffilepath);
322 if (cfg_fp==NULL){
323 T1_PrintLog( "ScanConfigFile()",
324 "Neither user's nor global Configfile has been found",
325 T1LOG_WARNING);
326 return(0);
327 }
328 }
329 else {
330 /* open specified file for reading the configuration */
331 if ((cfg_fp=fopen(env_str,"rb"))==NULL){
332 T1_PrintLog( "ScanConfigFile()",
333 "Configfile as specified by Environment has not been found",
334 T1LOG_WARNING);
335 return(0); /* specified file could not be openend
336 => no config paths read */
337 }
338 else {
339 sprintf( err_warn_msg_buf, "Using %s as Configfile (environment)",
340 env_str);
341 T1_PrintLog( "ScanConfigFile()", err_warn_msg_buf, T1LOG_STATISTIC);
342 }
343 }
344
345
346 /* cfg_fp points now to a valid config file */
347 /* Get the file size */
348 fseek( cfg_fp, 0, SEEK_END);
349 filesize=ftell(cfg_fp);
350 /* Reset fileposition to start */
351 fseek( cfg_fp, 0, SEEK_SET);
352
353 if ((linebuf=(char *)calloc( filesize+1,
354 sizeof(char)))==NULL){
355 T1_errno=T1ERR_ALLOC_MEM;
356 return(-1);
357 }
358
359 fread((char *)linebuf, sizeof(char), filesize, cfg_fp);
360 fclose(cfg_fp);
361
362 i=0;
363
364 /* this might be overwritten on a per file basis */
365 local_path_sep_char=path_sep_char;
366
367 while(i<filesize) {
368 ignoreline=0;
369 j=i; /* Save index of beginning of line */
370 while ((linebuf[i]!='=') && (linebuf[i]!='\n') && (i<filesize)) {
371 i++;
372 }
373 if (i==filesize) {
374 free( linebuf);
375 return(i);
376 }
377
378 if (strncmp( enc_key, &linebuf[j], 8)==0) {
379 /* setup target */
380 destP=&T1_ENC_ptr;
381 idestP=&enc_no;
382 curr_key=(char*)enc_key;
383 }
384 else if (strncmp( pfab_key, &linebuf[j], 5)==0) {
385 /* setup target */
386 destP=&T1_PFAB_ptr;
387 idestP=&pfab_no;
388 curr_key=(char*)pfab_key;
389 }
390 else if (strncmp( afm_key, &linebuf[j], 3)==0) {
391 /* setup target */
392 destP=&T1_AFM_ptr;
393 idestP=&afm_no;
394 curr_key=(char*)afm_key;
395 }
396 else if (strncmp( fdbxlfd_key, &linebuf[j], 16)==0) {
397 /* The handling here is somewhat specific. XLFD font database
398 specifications may coexist with standard font database
399 specification. However, if the standard font database is
400 the default value, an existing XLFD specification clears
401 this default value. Let this precede the standard fdb because
402 otherwise, this code would never be reached. */
403 if (fdb_no==0) { /* default paths are currently setup, get rid of them */
404 free(T1_FDB_ptr[0]);
405 T1_FDB_ptr[0]=NULL;
406 }
407
408 /* setup target */
409 destP=&T1_FDBXLFD_ptr;
410 idestP=&fdbxlfd_no;
411 curr_key=(char*)fdbxlfd_key;
412 }
413 else if (strncmp( fdb_key, &linebuf[j], 12)==0) {
414 /* setup target */
415 destP=&T1_FDB_ptr;
416 idestP=&fdb_no;
417 curr_key=(char*)fdb_key;
418 }
419 else {
420 ignoreline=1;
421 T1_PrintLog( "ScanConfigFile()", "Ignoring line %d",
422 T1LOG_DEBUG, linecnt);
423 }
424
425 /* If appropriate, scan this line. */
426 if (ignoreline==0) {
427 /* Check for an explicitly assigned value */
428 if (*idestP==0) { /* default paths are currently setup, get rid of them */
429 if ((*destP)[0]!=NULL) {
430 free((*destP)[0]);
431 (*destP)[0]=NULL;
432 }
433 }
434 else { /* append to existing paths */
435 T1_PrintLog( "ScanConfigFile()",
436 "Appending to existing %s search path",
437 T1LOG_DEBUG, curr_key);
438 }
439 while ( (!isspace((int)linebuf[i])) && (i<filesize) ) {
440 k=++i; /* index to current path element */
441 (*idestP)++;
442 quotecnt=0;
443 if (linebuf[i]=='"') { /* We have a quoted string */
444 quoted=1;
445 k=++i;
446 while ( 1) {
447 if ( linebuf[i]=='"' ) { /* we find a quote-char */
448 if ( linebuf[i-1]!='\\' )
449 break; /* not escaped --> end of path specification */
450 else
451 quotecnt++;
452 } /* some other char */
453 if (linebuf[i]=='\n') { /* a newline in a quoted string? Perhabs, quotes do not match! */
454 T1_PrintLog( "ScanConfigFile()",
455 "Newline in quoted %s-string in line %d, column %d, of config file! Closing quote missing?",
456 T1LOG_WARNING, curr_key, linecnt, i-j+1);
457 j=i+1; /* resynchronize linecount */
458 linecnt++;
459 }
460 if (i<filesize) { /* filesize not exceeded? */
461 i++;
462 }
463 else { /* issue error msg because end of quotation is missing */
464 T1_PrintLog( "ScanConfigFile()", "Unterminated quoted string in config file",
465 T1LOG_ERROR);
466 return -1;
467 }
468 }
469 }
470 else {
471 quoted=0;
472 while ( (linebuf[i]!=local_path_sep_char) && (!isspace((int)linebuf[i])) && (i<filesize) )
473 i++;
474 }
475 if (((*destP)=(char**)realloc( (*destP), ((*idestP)+1)*sizeof(char*)))==NULL) {
476 T1_errno=T1ERR_ALLOC_MEM;
477 return(-1);
478 }
479 if (((*destP)[(*idestP)-1]=(char*)malloc((i-k-quotecnt+1)*sizeof(char)))==NULL) {
480 T1_errno=T1ERR_ALLOC_MEM;
481 return(-1);
482 }
483 if (quoted==0) {
484 strncpy( (*destP)[*idestP-1], &(linebuf[k]), i-k);
485 (*destP)[(*idestP)-1][i-k]='\0';
486 }
487 else {
488 qstrncpy( (*destP)[(*idestP)-1], &(linebuf[k]), i-k);
489 (*destP)[(*idestP)-1][i-k-quotecnt]='\0';
490 i++; /* step over closing quote */
491 }
492 (*destP)[(*idestP)]=NULL; /* indicate end of string list */
493 }
494 }
495
496 /* skip remaining of line or file */
497 while ((linebuf[i]!='\n')&&(i<filesize))
498 i++;
499 i++;
500 linecnt++;
501 }
502 /* file should now be read in */
503 free( linebuf);
504
505 return(i);
506
507 }
508
509
510
511 /* intT1_Env_GetCompletePath( ): Get a full path name from the file specified by
512 argument 1 in the environment specified by argument 2. Return the pointer
513 to the path string or NULL if no file was found.*/
intT1_Env_GetCompletePath(char * FileName,char ** env_ptr)514 char *intT1_Env_GetCompletePath( char *FileName,
515 char **env_ptr )
516 {
517 struct stat filestats; /* A structure where fileinfo is stored */
518 int fnamelen, i, j;
519 char *FullPathName;
520 char *StrippedName;
521
522
523 if (FileName==NULL)
524 return(NULL);
525 fnamelen=strlen(FileName);
526
527 /* We check whether absolute or relative pathname is given. If so,
528 stat() it and if appropriate, return that string immediately. */
529 if ( (FileName[0]==DIRECTORY_SEP_CHAR)
530 ||
531 ((fnamelen>1) && (FileName[0]=='.') &&
532 (FileName[1]==DIRECTORY_SEP_CHAR))
533 ||
534 ((fnamelen>2) && (FileName[0]=='.') &&
535 (FileName[1]=='.') && (FileName[2]==DIRECTORY_SEP_CHAR))
536 #if defined(MSDOS) | defined(_WIN32) | defined (__EMX__)
537 ||
538 ((isalpha(FileName[0])) && (FileName[1]==':'))
539 #endif
540 #ifdef VMS
541 || (strchr(FileName,':') != NULL)
542 #endif
543 )
544 {
545 /* Check for existence of the path: */
546 if (!stat( FileName, &filestats)) {
547 if (t1lib_log_file!=NULL) {
548 sprintf( err_warn_msg_buf, "stat()'ing complete path %s successful",
549 FileName);
550 T1_PrintLog( "intT1_Env_GetCompletePath()", err_warn_msg_buf,
551 T1LOG_DEBUG);
552 }
553 /* Return a copy of the string */
554 if ((FullPathName=(char *)malloc( fnamelen + 1))==NULL) {
555 T1_errno=T1ERR_ALLOC_MEM;
556 return(NULL);
557 }
558 strcpy( FullPathName, FileName);
559 return(FullPathName);
560 }
561 if (t1lib_log_file!=NULL){
562 sprintf( err_warn_msg_buf, "stat()'ing complete path %s failed",
563 FileName);
564 T1_PrintLog( "intT1_Env_GetCompletePath()", err_warn_msg_buf,
565 T1LOG_DEBUG);
566 }
567 /* Trying to locate absolute path spec. failed. We try to recover
568 by removing the path component and searching in the remaining search
569 path entries. This depends on the OS. */
570 i=fnamelen-1;
571 StrippedName=&(FileName[i]);
572 while ( FileName[i]!=DIRECTORY_SEP_CHAR
573 #if defined(VMS)
574 /* What exactly to do for VMS? */
575 #elif defined(MSDOS) | defined(_WIN32) | defined (__EMX__) | defined(_MSC_VER)
576 /* We take a drive specification into account. This means we
577 step back until the directory separator or a drive specifier
578 appears! */
579 && FileName[i]!=':'
580 #endif
581 ) {
582 i--;
583 }
584 i++;
585 StrippedName=&FileName[i];
586 if (t1lib_log_file!=NULL){
587 sprintf( err_warn_msg_buf, "path %s stripped to %s",
588 FileName, StrippedName);
589 T1_PrintLog( "intT1_Env_GetCompletePath()", err_warn_msg_buf,
590 T1LOG_DEBUG);
591 }
592 }
593 else{ /* We have a relative path name */
594 StrippedName=&FileName[0];
595 }
596
597 i=0;
598 while (env_ptr[i]!=NULL) {
599 /* Copy current path element: */
600 strcpy( pathbuf, env_ptr[i]);
601 /* cut a trailing directory separator */
602 j=strlen(pathbuf);
603 if (pathbuf[j-1]==DIRECTORY_SEP_CHAR)
604 pathbuf[--j]='\0';
605 /* Add the directory separator: */
606 #ifdef VMS
607 { char *p= strrchr(pathbuf, DIRECTORY_SEP_CHAR);
608 if (p && *(p+1) == '\0')
609 *p = '\0';
610 }
611 #endif
612 strcat( pathbuf, DIRECTORY_SEP);
613 /* And finally the filename.
614 The following is fix against a vulnerability given by passing in
615 large filenames, cf.:
616
617 http://www.securityfocus.com/bid/25079
618
619 or
620
621 http://packetstormsecurity.nl/0707-advisories/t1lib.txt
622
623 If current pathbuf + StrippedName + 1 byte for NULL is bigger than
624 pathbuf log a warning and try next pathbuf */
625 if ( strlen(pathbuf) + strlen(StrippedName) + 1 > sizeof(pathbuf) ) {
626 T1_PrintLog( "intT1_Env_GetCompletePath()", "Omitting suspicious long candidate path in order to prevent buffer overflow.",
627 T1LOG_WARNING);
628 i++;
629 continue;
630 }
631 strcat( pathbuf, StrippedName);
632
633 /* Check for existence of the path: */
634 if (!stat( pathbuf, &filestats)) {
635 if ((FullPathName=(char*)malloc( (j+fnamelen+2)*sizeof(char)))==NULL) {
636 T1_errno=T1ERR_ALLOC_MEM;
637 return(NULL);
638 }
639 strcpy( FullPathName, pathbuf);
640 if (t1lib_log_file!=NULL){
641 sprintf( err_warn_msg_buf, "stat()'ing %s successful",
642 FullPathName);
643 T1_PrintLog( "intT1_Env_GetCompletePath()", err_warn_msg_buf,
644 T1LOG_DEBUG);
645 }
646 return(FullPathName);
647 }
648 if (t1lib_log_file!=NULL){
649 sprintf( err_warn_msg_buf, "stat()'ing %s failed",
650 pathbuf);
651 T1_PrintLog( "intT1_Env_GetCompletePath()", err_warn_msg_buf,
652 T1LOG_DEBUG);
653 }
654 /* We didn't find the file --> try next path entry */
655 i++;
656 }
657 /* If we get here, no file was found at all, so return a NULL-pointer */
658 return(NULL);
659 }
660
661
662
663 /* T1_SetFileSearchPath(): Set the search path to find files of the
664 specified type and return 0 if successful and -1 otherwise. An existing
665 path is overwritten rigorously, unless the database already contains fonts.
666 In the latter case the function returns with an error status.
667 Multiple path types may be specified as a bitmask!
668 */
T1_SetFileSearchPath(int type,char * pathname)669 int T1_SetFileSearchPath( int type, char *pathname)
670 {
671
672 int i;
673 int pathlen;
674
675
676 if (pathname==NULL){
677 T1_errno=T1ERR_INVALID_PARAMETER;
678 return(-1);
679 }
680
681 /* We do not allow to change the searchpath if the database already
682 contains one or more entries. */
683 if (T1_GetNoFonts()>0){
684 sprintf( err_warn_msg_buf, "Path %s not set, database is not empty",
685 pathname);
686 T1_PrintLog( "T1_SetFileSearchPath()", err_warn_msg_buf,
687 T1LOG_STATISTIC);
688 T1_errno=T1ERR_OP_NOT_PERMITTED;
689 return(-1);
690 }
691
692 pathlen=strlen(pathname)+1;
693 /* Throw away a possibly existing path */
694 if (type & T1_PFAB_PATH){
695 if (pfab_no==-1) {
696 T1_PFAB_ptr=NULL; /* realloc() will do a malloc() */
697 }
698 else {
699 /* throw away current paths */
700 i=0;
701 while (T1_PFAB_ptr[i]!=NULL) {
702 free (T1_PFAB_ptr[i++]);
703 }
704 }
705 if ((T1_PFAB_ptr=(char**)realloc( T1_PFAB_ptr, 2*sizeof(char*)))==NULL) {
706 T1_errno=T1ERR_ALLOC_MEM;
707 return(-1);
708 }
709 if ((T1_PFAB_ptr[0]=(char*)malloc(pathlen*sizeof(char)))==NULL) {
710 T1_errno=T1ERR_ALLOC_MEM;
711 return(-1);
712 }
713 strcpy( T1_PFAB_ptr[0], pathname);
714 T1_PFAB_ptr[1]=NULL;
715 pfab_no=1;
716 }
717 if (type & T1_AFM_PATH){
718 if (afm_no==-1) {
719 T1_AFM_ptr=NULL; /* realloc() will do a malloc() */
720 }
721 else {
722 /* throw away current paths */
723 i=0;
724 while (T1_AFM_ptr[i]!=NULL) {
725 free (T1_AFM_ptr[i++]);
726 }
727 }
728 if ((T1_AFM_ptr=(char**)realloc( T1_AFM_ptr, 2*sizeof(char*)))==NULL) {
729 T1_errno=T1ERR_ALLOC_MEM;
730 return(-1);
731 }
732 if ((T1_AFM_ptr[0]=(char*)malloc(pathlen*sizeof(char)))==NULL) {
733 T1_errno=T1ERR_ALLOC_MEM;
734 return(-1);
735 }
736 strcpy( T1_AFM_ptr[0], pathname);
737 T1_AFM_ptr[1]=NULL;
738 afm_no=1;
739 }
740 if (type & T1_ENC_PATH){
741 if (enc_no==-1) {
742 T1_ENC_ptr=NULL; /* realloc() will do a malloc() */
743 }
744 else {
745 /* throw away current paths */
746 i=0;
747 while (T1_ENC_ptr[i]!=NULL) {
748 free (T1_ENC_ptr[i++]);
749 }
750 }
751 if ((T1_ENC_ptr=(char**)realloc( T1_ENC_ptr, 2*sizeof(char*)))==NULL) {
752 T1_errno=T1ERR_ALLOC_MEM;
753 return(-1);
754 }
755 if ((T1_ENC_ptr[0]=(char*)malloc(pathlen*sizeof(char)))==NULL) {
756 T1_errno=T1ERR_ALLOC_MEM;
757 return(-1);
758 }
759 strcpy( T1_ENC_ptr[0], pathname);
760 T1_ENC_ptr[1]=NULL;
761 enc_no=1;
762 }
763
764 return(0);
765
766 }
767
768
769
770 /* T1_GetFileSearchPath(): Return the specified file search path
771 or NULL if an error occurred. Note: We do only one path at a
772 time, so that if a bitmask is specified, the first match wins.
773 The returned path is formatted using the actual PATH_SEP_CHAR. */
T1_GetFileSearchPath(int type)774 char *T1_GetFileSearchPath( int type)
775 {
776 static char *out_ptr;
777 int i;
778 int pathlen;
779 char **src_ptr=NULL;
780
781
782 if (out_ptr!=NULL)
783 free( out_ptr);
784 out_ptr=NULL;
785
786 if (type & T1_PFAB_PATH) {
787 src_ptr=T1_PFAB_ptr;
788 }
789 else if (type & T1_AFM_PATH) {
790 src_ptr=T1_AFM_ptr;
791 }
792 else if (type & T1_ENC_PATH) {
793 src_ptr=T1_ENC_ptr;
794 }
795 else if (type & T1_FDB_PATH) {
796 src_ptr=T1_FDB_ptr;
797 }
798
799
800 i=0;
801 pathlen=0;
802 while (src_ptr[i]!=NULL) {
803 pathlen +=strlen( src_ptr[i++]);
804 pathlen+=1; /* path separator */
805 }
806 if ((out_ptr=(char *)malloc(pathlen+1))==NULL) {
807 T1_errno=T1ERR_ALLOC_MEM;
808 return( NULL);
809 }
810 strcpy( out_ptr, src_ptr[0]);
811 i=1;
812 while (src_ptr[i]!=NULL) {
813 strcat( out_ptr, path_sep_string);
814 strcat( out_ptr, src_ptr[i++]);
815 }
816
817 return( out_ptr);
818
819 }
820
821
822 /* T1_AddToFileSearchPath(): Add the specified path element to
823 the specified search path. If the existing path is the default path,
824 it will not be replaced by the new path element. Since this function might
825 be called before initialization, we have to be aware that even the default
826 path could be missing. Multiple path types may be specified as a bitmask!
827 Return value is 0 if successful and -1 otherwise */
T1_AddToFileSearchPath(int pathtype,int mode,char * pathname)828 int T1_AddToFileSearchPath( int pathtype, int mode, char *pathname)
829 {
830 int i;
831 int pathlen;
832 char* newpath = NULL;
833 int nofonts;
834
835
836 if (pathname==NULL)
837 return(-1);
838
839 nofonts=T1_GetNoFonts();
840
841 pathlen=strlen(pathname);
842
843 if (pathtype & T1_PFAB_PATH){
844 /* Allocate meory for string */
845 if ((newpath=(char*)malloc( (pathlen+1)*sizeof(char)))==NULL) {
846 T1_errno=T1ERR_ALLOC_MEM;
847 return(-1);
848 }
849 /* Check for and handle the existing path configuration */
850 if (pfab_no==0) { /* do not free the default path but establish it
851 as a regularly setup path, if database not empty! */
852 if (nofonts>0) {
853 pfab_no++;
854 }
855 else {
856 free( T1_AFM_ptr[0]);
857 }
858 }
859 if (pfab_no==-1) { /* not initialized! */
860 pfab_no=0;
861 T1_PFAB_ptr=NULL; /* realloc() will do the malloc()! */
862 }
863 if ((T1_PFAB_ptr=(char**)realloc( T1_PFAB_ptr, (++pfab_no+1)*sizeof(char*)))==NULL) {
864 T1_errno=T1ERR_ALLOC_MEM;
865 return(-1);
866 }
867 /* Insert the new path element: */
868 if (mode & T1_PREPEND_PATH){ /* prepend */
869 i=pfab_no-2;
870 while (i>=0) {
871 T1_PFAB_ptr[i+1]=T1_PFAB_ptr[i];
872 i--;
873 }
874 T1_PFAB_ptr[0]=newpath;
875 }
876 else{ /* append */
877 T1_PFAB_ptr[pfab_no-1]=newpath;
878 }
879 T1_PFAB_ptr[pfab_no]=NULL;
880 }
881 if (pathtype & T1_AFM_PATH){
882 /* Allocate meory for string */
883 if ((newpath=(char*)malloc( (pathlen+1)*sizeof(char)))==NULL) {
884 T1_errno=T1ERR_ALLOC_MEM;
885 return(-1);
886 }
887 /* Check for and handle the existing path configuration */
888 if (afm_no==0) { /* do not free the default path but establish it
889 as a regularly setup path, if database not empty! */
890 if (nofonts>0) {
891 afm_no++;
892 }
893 else {
894 free( T1_AFM_ptr[0]);
895 }
896 }
897 if (afm_no==-1) { /* not initialized! */
898 afm_no=0;
899 T1_AFM_ptr=NULL; /* realloc() will do the malloc()! */
900 }
901 if ((T1_AFM_ptr=(char**)realloc( T1_AFM_ptr, (++afm_no+1)*sizeof(char*)))==NULL) {
902 T1_errno=T1ERR_ALLOC_MEM;
903 return(-1);
904 }
905 /* Insert the new path element */
906 if (mode & T1_PREPEND_PATH){ /* prepend */
907 i=afm_no-2;
908 while (i>=0) {
909 T1_AFM_ptr[i+1]=T1_AFM_ptr[i];
910 i--;
911 }
912 T1_AFM_ptr[0]=newpath;
913 }
914 else{ /* append */
915 T1_AFM_ptr[afm_no-1]=newpath;
916 }
917 T1_AFM_ptr[afm_no]=NULL;
918 }
919 if (pathtype & T1_ENC_PATH){
920 /* Allocate meory for string */
921 if ((newpath=(char*)malloc( (pathlen+1)*sizeof(char)))==NULL) {
922 T1_errno=T1ERR_ALLOC_MEM;
923 return(-1);
924 }
925 /* Check for and handle the existing path configuration */
926 if (enc_no==0) { /* do not free the default path but establish it
927 as a regularly setup path, if database not empty! */
928 if (nofonts>0) {
929 enc_no++;
930 }
931 else {
932 free( T1_ENC_ptr[0]);
933 }
934 }
935 if (enc_no==-1) { /* not initialized! */
936 enc_no=0;
937 T1_ENC_ptr=NULL; /* realloc() will do the malloc()! */
938 }
939 if ((T1_ENC_ptr=(char**)realloc( T1_ENC_ptr, (++enc_no+1)*sizeof(char*)))==NULL) {
940 T1_errno=T1ERR_ALLOC_MEM;
941 return(-1);
942 }
943 /* Insert the new path element: */
944 if (mode & T1_PREPEND_PATH){ /* prepend */
945 i=enc_no-2;
946 while (i>=0) {
947 T1_ENC_ptr[i+1]=T1_ENC_ptr[i];
948 i--;
949 }
950 T1_ENC_ptr[0]=newpath;
951 }
952 else{ /* append */
953 T1_ENC_ptr[enc_no-1]=newpath;
954 }
955 T1_ENC_ptr[enc_no]=NULL;
956 }
957
958 /* Copy new path to where it belongs ... */
959 if (newpath)
960 strcpy(newpath, pathname);
961
962 return(0);
963
964 }
965
966
967
968 /* T1_SetFontDataBase(): Set a new name for the font database. It replaces the default
969 name and any names specified previously with this function.
970 Return value: 0 if OK, and -1 if filename not valid or an allocation
971 error occurred */
T1_SetFontDataBase(char * filename)972 int T1_SetFontDataBase( char *filename)
973 {
974 int pathlen;
975 int i;
976 int result=0;
977
978
979 /* chekc filename */
980 if (filename==NULL) {
981 T1_errno=T1ERR_INVALID_PARAMETER;
982 return -1;
983 }
984
985 /* this function must be called before any font is in the database, that is, usually,
986 before initialization! */
987 if ( pFontBase!=NULL && pFontBase->no_fonts>0) {
988 T1_errno=T1ERR_OP_NOT_PERMITTED;
989 return -1;
990 }
991
992
993 pathlen=strlen(filename)+1;
994 /* Throw away a possibly existing font database-statement */
995 if (fdb_no==-1) {
996 T1_FDB_ptr=NULL; /* realloc() will do a malloc() */
997 }
998 else {
999 /* throw away current paths */
1000 i=0;
1001 while (T1_FDB_ptr[i]!=NULL) {
1002 free (T1_FDB_ptr[i++]);
1003 }
1004 }
1005
1006 if ((T1_FDB_ptr=(char**)realloc( T1_FDB_ptr, 2*sizeof(char*)))==NULL) {
1007 T1_errno=T1ERR_ALLOC_MEM;
1008 return -1;
1009 }
1010
1011 if ((T1_FDB_ptr[0]=(char*)malloc(pathlen*sizeof(char)))==NULL) {
1012 T1_errno=T1ERR_ALLOC_MEM;
1013 return -1;
1014 }
1015 strcpy( T1_FDB_ptr[0], filename);
1016 T1_FDB_ptr[1]=NULL;
1017 fdb_no=1;
1018
1019 /* Load database immediately if t1lib already is initailzed */
1020 if (T1_CheckForInit()==0) {
1021 if ((result=intT1_scanFontDBase(T1_FDB_ptr[0]))==-1) {
1022 T1_PrintLog( "T1_AddFontDataBase()", "Fatal error scanning Font Database File %s (T1_errno=%d)",
1023 T1LOG_WARNING, T1_FDB_ptr[0], T1_errno);
1024 }
1025 if (result>-1)
1026 pFontBase->no_fonts+=result;
1027 result=pFontBase->no_fonts;
1028 }
1029 return result;
1030
1031 }
1032
1033
1034 /* T1_AddFontDataBase(): Add a new font database file to the list. If the
1035 lib is already initialzed, then the new database is immediately loaded.
1036 Otherwise it is simply appended to the list and loaded at the time of
1037 initialization.
1038 Returns: -1 an error occured
1039 0 successfully inserted but not loaded because lib not initilized
1040 n>0 the highest defined FontID
1041 */
T1_AddFontDataBase(int mode,char * filename)1042 int T1_AddFontDataBase( int mode, char *filename)
1043 {
1044 int i;
1045 int pathlen;
1046 int result=0;
1047 char* newpath;
1048
1049
1050 if (filename==NULL) {
1051 T1_errno=T1ERR_INVALID_PARAMETER;
1052 return(-1);
1053 }
1054
1055 pathlen=strlen(filename);
1056
1057 /* Allocate memory for string */
1058 if ((newpath=(char*)malloc( (pathlen+1)*sizeof(char)))==NULL) {
1059 T1_errno=T1ERR_ALLOC_MEM;
1060 return(-1);
1061 }
1062 strcpy( newpath, filename);
1063 /* Check for and handle the existing path configuration */
1064 if (fdb_no==0) { /* defauls setup, free the path */
1065 free( T1_FDB_ptr[0]);
1066 }
1067 if (fdb_no==-1) { /* not initialized! */
1068 fdb_no=0;
1069 T1_FDB_ptr=NULL; /* realloc() will do the malloc()! */
1070 }
1071
1072 if ((T1_FDB_ptr=(char**)realloc( T1_FDB_ptr, (++fdb_no+1)*sizeof(char*)))==NULL) {
1073 T1_errno=T1ERR_ALLOC_MEM;
1074 return(-1);
1075 }
1076 /* Insert the new database. If t1lib is already initialzed, the database can only
1077 be appended. Otherwise. prepending is also possible.*/
1078 if ((mode & T1_PREPEND_PATH) && (T1_CheckForInit()!=0) ) { /* prepend */
1079 i=fdb_no-2;
1080 while (i>=0) {
1081 T1_FDB_ptr[i+1]=T1_FDB_ptr[i];
1082 i--;
1083 }
1084 T1_FDB_ptr[0]=newpath;
1085 result=0;
1086 }
1087 else { /* append */
1088 T1_FDB_ptr[fdb_no-1]=newpath;
1089 if (T1_CheckForInit()==0) {
1090 if ((result=intT1_scanFontDBase(T1_FDB_ptr[fdb_no-1]))==-1) {
1091 T1_PrintLog( "T1_AddFontDataBase()", "Fatal error scanning Font Database File %s (T1_errno=%d)",
1092 T1LOG_WARNING, T1_FDB_ptr[fdb_no-1], T1_errno);
1093 }
1094 if (result>-1)
1095 pFontBase->no_fonts+=result;
1096 result=pFontBase->no_fonts;
1097 }
1098 }
1099 T1_FDB_ptr[fdb_no]=NULL;
1100 return result;
1101
1102 }
1103
1104
1105
1106 /* T1_SetFontDataBaseXLFD(): Set a new name for the XLFD font database. It
1107 replaces the default name (which is empty and any names specified
1108 previously with this function.
1109 Return value: 0 if OK, and -1 if filename not valid or an allocation
1110 error occurred */
T1_SetFontDataBaseXLFD(char * filename)1111 int T1_SetFontDataBaseXLFD( char *filename)
1112 {
1113 int pathlen;
1114 int i;
1115 int result=0;
1116
1117
1118 /* check filename */
1119 if (filename==NULL) {
1120 T1_errno=T1ERR_INVALID_PARAMETER;
1121 return -1;
1122 }
1123
1124 /* this function must be called before any font is in the database, that is, usually,
1125 before initialization! */
1126 if ( pFontBase!=NULL && pFontBase->no_fonts>0) {
1127 T1_errno=T1ERR_OP_NOT_PERMITTED;
1128 return -1;
1129 }
1130
1131
1132 pathlen=strlen(filename)+1;
1133 /* Throw away a possibly existing font database-statement */
1134 if (fdbxlfd_no==-1) {
1135 T1_FDBXLFD_ptr=NULL; /* realloc() will do a malloc() */
1136 }
1137 else {
1138 /* throw away current paths */
1139 i=0;
1140 while (T1_FDBXLFD_ptr[i]!=NULL) {
1141 free (T1_FDBXLFD_ptr[i++]);
1142 }
1143 }
1144
1145 if ((T1_FDBXLFD_ptr=(char**)realloc( T1_FDBXLFD_ptr, 2*sizeof(char*)))==NULL) {
1146 T1_errno=T1ERR_ALLOC_MEM;
1147 return -1;
1148 }
1149
1150 if ((T1_FDBXLFD_ptr[0]=(char*)malloc(pathlen*sizeof(char)))==NULL) {
1151 T1_errno=T1ERR_ALLOC_MEM;
1152 return -1;
1153 }
1154 strcpy( T1_FDBXLFD_ptr[0], filename);
1155 T1_FDBXLFD_ptr[1]=NULL;
1156 fdb_no=1;
1157
1158 /* Load XLFD database immediately if t1lib already is initailzed */
1159 if (T1_CheckForInit()==0) {
1160 if ((result=intT1_scanFontDBaseXLFD(T1_FDBXLFD_ptr[0]))==-1) {
1161 T1_PrintLog( "T1_AddFontDataBaseXLFD()", "Fatal error scanning XLFD Font Database File %s (T1_errno=%d)",
1162 T1LOG_WARNING, T1_FDBXLFD_ptr[0], T1_errno);
1163 }
1164 if (result>-1)
1165 pFontBase->no_fonts+=result;
1166 result=pFontBase->no_fonts;
1167 }
1168 return result;
1169
1170 }
1171
1172
1173 /* T1_AddFontDataBaseXLFD(): Add a new XLFD font database file to the list. If
1174 the lib is already initialzed, then the new database is immediately loaded.
1175 Otherwise it is simply appended to the list and loaded at the time of
1176 initialization.
1177 Returns: -1 an error occured
1178 0 successfully inserted but not loaded because lib not initilized
1179 n>0 the highest defined FontID
1180 */
T1_AddFontDataBaseXLFD(int mode,char * filename)1181 int T1_AddFontDataBaseXLFD( int mode, char *filename)
1182 {
1183 int i;
1184 int pathlen;
1185 int result=0;
1186 char* newpath;
1187
1188
1189 if (filename==NULL) {
1190 T1_errno=T1ERR_INVALID_PARAMETER;
1191 return(-1);
1192 }
1193
1194 pathlen=strlen(filename);
1195
1196 /* Allocate memory for string */
1197 if ((newpath=(char*)malloc( (pathlen+1)*sizeof(char)))==NULL) {
1198 T1_errno=T1ERR_ALLOC_MEM;
1199 return(-1);
1200 }
1201 strcpy( newpath, filename);
1202 /* Check for and handle the existing path configuration */
1203 if (fdb_no==0) { /* defauls setup, free the path */
1204 free( T1_FDB_ptr[0]);
1205 }
1206 if (fdbxlfd_no==-1) { /* not initialized! */
1207 fdbxlfd_no=0;
1208 T1_FDBXLFD_ptr=NULL; /* realloc() will do the malloc()! */
1209 }
1210
1211 if ((T1_FDBXLFD_ptr=(char**)realloc( T1_FDBXLFD_ptr, (++fdbxlfd_no+1)*sizeof(char*)))==NULL) {
1212 T1_errno=T1ERR_ALLOC_MEM;
1213 return(-1);
1214 }
1215 /* Insert the new database. If t1lib is already initialzed, the database can only
1216 be appended. Otherwise. prepending is also possible.*/
1217 if ((mode & T1_PREPEND_PATH) && (T1_CheckForInit()!=0) ) { /* prepend */
1218 i=fdbxlfd_no-2;
1219 while (i>=0) {
1220 T1_FDBXLFD_ptr[i+1]=T1_FDBXLFD_ptr[i];
1221 i--;
1222 }
1223 T1_FDBXLFD_ptr[0]=newpath;
1224 result=0;
1225 }
1226 else { /* append */
1227 T1_FDBXLFD_ptr[fdbxlfd_no-1]=newpath;
1228 if (T1_CheckForInit()==0) {
1229 if ((result=intT1_scanFontDBaseXLFD(T1_FDBXLFD_ptr[fdbxlfd_no-1]))==-1) {
1230 T1_PrintLog( "T1_AddFontDataBase()", "Fatal error scanning Font Database File %s (T1_errno=%d)",
1231 T1LOG_WARNING, T1_FDBXLFD_ptr[fdbxlfd_no-1], T1_errno);
1232 }
1233 if (result>-1)
1234 pFontBase->no_fonts+=result;
1235 result=pFontBase->no_fonts;
1236 }
1237 }
1238 T1_FDBXLFD_ptr[fdbxlfd_no]=NULL;
1239 return result;
1240
1241 }
1242
1243
1244