1 /*
2 * (c) Copyright 2001 Uwe Steinmann.
3 * All rights reserved.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
19 */
20
21 /* $Id$ */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 #include <stdio.h>
27 #include <errno.h>
28 #include <stdlib.h>
29 #include <stdarg.h>
30 #include <string.h>
31 #include "ps_intern.h"
32 #include "ps_memory.h"
33 #include "ps_fontenc.h"
34 #include "ps_inputenc.h"
35 #include "ps_error.h"
36
37 /* ps_write() {{{
38 * Output data using the current writeprocedure
39 */
40 void
ps_write(PSDoc * p,const void * data,size_t size)41 ps_write(PSDoc *p, const void *data, size_t size) {
42 (void) p->writeproc(p, (void *) data, size);
43 }
44 /* }}} */
45
46 /* ps_putc() {{{
47 * Output char
48 */
49 void
ps_putc(PSDoc * p,char c)50 ps_putc(PSDoc *p, char c)
51 {
52 ps_write(p, (void *) &c, (size_t) 1);
53 }
54 /* }}} */
55
56 /* ps_puts() {{{
57 * Output string
58 */
59 void
ps_puts(PSDoc * p,const char * s)60 ps_puts(PSDoc *p, const char *s)
61 {
62 ps_write(p, (void *) s, strlen(s));
63 }
64 /* }}} */
65
66 /* ps_printf() {{{
67 * Output formated string
68 */
69 void
ps_printf(PSDoc * p,const char * fmt,...)70 ps_printf(PSDoc *p, const char *fmt, ...)
71 {
72 char buf[LINEBUFLEN]; /* formatting buffer */
73 va_list ap;
74
75 va_start(ap, fmt);
76
77 setlocale(LC_NUMERIC, "C");
78 (void) vsnprintf(buf, LINEBUFLEN, fmt, ap);
79 setlocale(LC_NUMERIC, "");
80 ps_puts(p, buf);
81
82 va_end(ap);
83 }
84 /* }}} */
85
86 /* ps_ght_malloc() {{{
87 *
88 * malloc routine which is passed to the hash table functions.
89 */
ps_ght_malloc(size_t size,void * data)90 void* ps_ght_malloc(size_t size, void *data) {
91 PSDoc *psdoc = data;
92 return(psdoc->malloc(psdoc, size, _("Allocate memory for hash table of char metrics")));
93 }
94 /* }}} */
95
96 /* ps_ght_free() {{{
97 *
98 * free routine which is passed to the hash table functions.
99 */
ps_ght_free(void * ptr,void * data)100 void ps_ght_free(void *ptr, void *data) {
101 PSDoc *psdoc = data;
102 psdoc->free(psdoc, ptr);
103 }
104 /* }}} */
105
106 /* ps_enter_scope() {{{
107 */
ps_enter_scope(PSDoc * psdoc,int scope)108 void ps_enter_scope(PSDoc *psdoc, int scope) {
109 if(psdoc->scopecount == (MAX_SCOPES-1)) {
110 ps_error(psdoc, PS_RuntimeError, _("Maximum number of scopes reached."));
111 } else {
112 psdoc->scopecount++;
113 psdoc->scopes[psdoc->scopecount] = scope;
114 }
115 }
116 /* }}} */
117
118 /* ps_leave_scope() {{{
119 */
ps_leave_scope(PSDoc * psdoc,int scope)120 void ps_leave_scope(PSDoc *psdoc, int scope) {
121 if(scope != psdoc->scopes[psdoc->scopecount])
122 ps_error(psdoc, PS_RuntimeError, _("Trying to leave scope %d but you are in %d."), scope, psdoc->scopes[psdoc->scopecount]);
123 else
124 psdoc->scopecount--;
125 }
126 /* }}} */
127
128 /* ps_current_scope() {{{
129 */
ps_current_scope(PSDoc * psdoc)130 int ps_current_scope(PSDoc *psdoc) {
131 return(psdoc->scopes[psdoc->scopecount]);
132 }
133 /* }}} */
134
135 /* ps_check_scope() {{{
136 */
ps_check_scope(PSDoc * psdoc,int scope)137 ps_bool ps_check_scope(PSDoc *psdoc, int scope) {
138 return(scope & psdoc->scopes[psdoc->scopecount]);
139 }
140 /* }}} */
141
142 /* ps_get_resources() {{{
143 * Returns an array of pointers to all resources of a category.
144 */
ps_get_resources(PSDoc * psdoc,const char * category,int * count)145 PS_RESOURCE **ps_get_resources(PSDoc *psdoc, const char *category, int *count) {
146 PS_CATEGORY *cat;
147 PS_RESOURCE *res;
148 PS_RESOURCE **ress = NULL;
149 int i;
150
151 *count = 0;
152 for(cat = dlst_first(psdoc->categories); cat != NULL; cat = dlst_next(cat)) {
153 if (!strcmp(cat->name, category)) {
154 ress = psdoc->malloc(psdoc, cat->resources->count * sizeof(PS_RESOURCE *), _("Allocate Memory for list of resources."));
155 *count = cat->resources->count;
156 for(i=0, res = dlst_first(cat->resources); res != NULL; res = dlst_next(res), i++) {
157 ress[i] = res;
158 }
159 }
160 }
161 return(ress);
162 }
163 /* }}} */
164
165 /* ps_find_resource() {{{
166 */
ps_find_resource(PSDoc * psdoc,const char * category,const char * resource)167 char *ps_find_resource(PSDoc *psdoc, const char *category, const char *resource) {
168 PS_CATEGORY *cat;
169 PS_RESOURCE *res;
170
171 for(cat = dlst_first(psdoc->categories); cat != NULL; cat = dlst_next(cat)) {
172 if (!strcmp(cat->name, category)) {
173 for(res = dlst_first(cat->resources); res != NULL; res = dlst_next(res)) {
174 if (!strcmp(res->name, resource))
175 return(res->value);
176 }
177 }
178 }
179 return(NULL);
180 }
181 /* }}} */
182
183 /* ps_add_resource() {{{
184 */
ps_add_resource(PSDoc * psdoc,const char * category,const char * resource,const char * filename,const char * prefix)185 PS_RESOURCE * ps_add_resource(PSDoc *psdoc, const char *category, const char *resource, const char *filename, const char *prefix) {
186 PS_CATEGORY *cat;
187 PS_RESOURCE *res;
188
189 /* Right and LeftMarginKerning are set in PS_set_paramter. They manipulate
190 * the ADOBEINFO struct of the affected char directly.
191 */
192 if (strcmp("SearchPath", category) &&
193 strcmp("FontAFM", category) &&
194 strcmp("FontEncoding", category) &&
195 strcmp("FontProtusion", category) &&
196 strcmp("FontOutline", category)) {
197 return(NULL);
198 }
199
200 /* Search for the category */
201 for(cat = dlst_first(psdoc->categories); cat != NULL; cat = dlst_next(cat)) {
202 if(!strcmp(cat->name, category))
203 break;
204 }
205
206 /* Create a new category if it does not exist */
207 if(cat == NULL) {
208 if(NULL == (cat = (PS_CATEGORY *) dlst_newnode(psdoc->categories, sizeof(PS_CATEGORY)))) {
209 return(NULL);
210 }
211 cat->name = ps_strdup(psdoc, category);
212 cat->resources = dlst_init(psdoc->malloc, psdoc->realloc, psdoc->free);
213 dlst_insertafter(psdoc->categories, cat, PS_DLST_HEAD(psdoc->categories));
214 }
215
216 /* Check if resource already available */
217 if(resource) {
218 for(res = dlst_first(cat->resources); res != NULL; res = dlst_next(res)) {
219 if(!strcmp(res->name, resource))
220 break;
221 }
222 } else {
223 res = NULL;
224 }
225 if(res) {
226 psdoc->free(psdoc, res->name);
227 res->name = ps_strdup(psdoc, resource);
228 psdoc->free(psdoc, res->value);
229 res->value = ps_strdup(psdoc, filename);
230 } else {
231 if(NULL == (res = (PS_RESOURCE *) dlst_newnode(cat->resources, sizeof(PS_RESOURCE)))) {
232 return(NULL);
233 }
234 if(resource)
235 res->name = ps_strdup(psdoc, resource);
236 else
237 res->name = NULL;
238 res->value = ps_strdup(psdoc, filename);
239 dlst_insertafter(cat->resources, res, PS_DLST_HEAD(cat->resources));
240 }
241
242 return(res);
243 }
244 /* }}} */
245
246 /* ps_del_resources() {{{
247 */
ps_del_resources(PSDoc * psdoc)248 void ps_del_resources(PSDoc *psdoc) {
249 PS_CATEGORY *cat, *nextcat;
250 PS_RESOURCE *res, *nextres;
251 if(NULL == psdoc->categories)
252 return;
253 cat = dlst_first(psdoc->categories);
254 while(cat != NULL) {
255 nextcat = dlst_next(cat);
256 psdoc->free(psdoc, cat->name);
257 res = dlst_first(cat->resources);
258 while(res != NULL) {
259 nextres = dlst_next(res);
260 if(res->name)
261 psdoc->free(psdoc, res->name);
262 if(res->value)
263 psdoc->free(psdoc, res->value);
264 res = nextres;
265 }
266 dlst_kill(cat->resources, dlst_freenode);
267 cat = nextcat;
268 }
269 dlst_kill(psdoc->categories, dlst_freenode);
270 psdoc->categories = NULL;
271 }
272 /* }}} */
273
274 /* ps_del_parameters() {{{
275 */
ps_del_parameters(PSDoc * psdoc)276 void ps_del_parameters(PSDoc *psdoc) {
277 PS_PARAMETER *param, *nextparam;
278 if(NULL == psdoc->parameters)
279 return;
280 param = dlst_first(psdoc->parameters);
281 while(param != NULL) {
282 nextparam = dlst_next(param);
283 psdoc->free(psdoc, param->name);
284 psdoc->free(psdoc, param->value);
285 param = nextparam;
286 }
287 dlst_kill(psdoc->parameters, dlst_freenode);
288 psdoc->parameters = NULL;
289 }
290 /* }}} */
291
292 /* ps_del_values() {{{
293 */
ps_del_values(PSDoc * psdoc)294 void ps_del_values(PSDoc *psdoc) {
295 PS_VALUE *param, *nextparam;
296 if(NULL == psdoc->values)
297 return;
298 param = dlst_first(psdoc->values);
299 while(param != NULL) {
300 nextparam = dlst_next(param);
301 psdoc->free(psdoc, param->name);
302 param = nextparam;
303 }
304 dlst_kill(psdoc->values, dlst_freenode);
305 psdoc->values = NULL;
306 }
307 /* }}} */
308
309 /* ps_del_bookmarks() {{{
310 */
ps_del_bookmarks(PSDoc * psdoc,DLIST * bookmarks)311 void ps_del_bookmarks(PSDoc *psdoc, DLIST *bookmarks) {
312 PS_BOOKMARK *bm, *nextbm;
313 if(NULL == bookmarks)
314 return;
315 bm = dlst_first(bookmarks);
316 while(bm != NULL) {
317 nextbm = dlst_next(bm);
318 psdoc->free(psdoc, bm->text);
319 ps_del_bookmarks(psdoc, bm->children);
320 bm = nextbm;
321 }
322 dlst_kill(bookmarks, dlst_freenode);
323 }
324 /* }}} */
325
326 /* ps_add_word_spacing() {{{
327 */
ps_add_word_spacing(PSDoc * psdoc,PSFont * psfont,float value)328 void ps_add_word_spacing(PSDoc *psdoc, PSFont *psfont, float value) {
329 psfont->wordspace += value * 1000.0 / psfont->size;
330 }
331 /* }}} */
332
333 /* ps_set_word_spacing() {{{
334 */
ps_set_word_spacing(PSDoc * psdoc,PSFont * psfont,float value)335 void ps_set_word_spacing(PSDoc *psdoc, PSFont *psfont, float value) {
336 ADOBEINFO *ai;
337
338 if(value != 0.0) {
339 psfont->wordspace = value * 1000.0 / psfont->size;
340 } else {
341 ai = gfindadobe(psfont->metrics->gadobechars, "space");
342 if(ai)
343 psfont->wordspace = ai->width;
344 else
345 psfont->wordspace = 500.0;
346 }
347 }
348 /* }}} */
349
350 /* ps_get_word_spacing() {{{
351 */
ps_get_word_spacing(PSDoc * psdoc,PSFont * psfont)352 float ps_get_word_spacing(PSDoc *psdoc, PSFont *psfont) {
353 float ws;
354 ws = ((float) psfont->wordspace) * psfont->size / 1000.0;
355 return(ws);
356 }
357 /* }}} */
358
359 /* ps_check_for_lig() {{{
360 * Checks if the characters in text form a ligature with the character
361 * in ai. If that is the case the number of characters consumed in text
362 * will be returned in offset and the name of the ligature will be returned
363 * in newadobename.
364 * Ligatures can be broken off by a ligdischar. In such a case 1 will be
365 * returned
366 * and offset is set to 1 in order to skip the ligdischar. newadobename is set
367 * to the name of the passed character.
368 */
ps_check_for_lig(PSDoc * psdoc,ADOBEFONTMETRIC * metrics,ADOBEINFO * ai,const char * text,char ligdischar,char ** newadobename,int * offset)369 int ps_check_for_lig(PSDoc *psdoc, ADOBEFONTMETRIC *metrics, ADOBEINFO *ai, const char *text, char ligdischar, char **newadobename, int *offset) {
370 ADOBEINFO *nextai;
371 LIG *ligs;
372 if((NULL == ai) || (NULL == ai->ligs))
373 return 0;
374 if(NULL == text || text[0] == '\0')
375 return 0;
376
377 ligs = ai->ligs;
378 /* ligdischar breaks ligatures. The idea is, that every char followed
379 * by a ligdischar
380 * forms a ligature which is the char itself. Setting offset to
381 * 1 will skip the ligdischar */
382 if(ligs && text[0] == ligdischar) {
383 *offset += 1;
384 *newadobename = ai->adobename;
385 return 1;
386 }
387 if(ligs) {
388 int _offset = 0;
389 char *nextadobename;
390 nextai = gfindadobe(metrics->gadobechars, psdoc->inputenc->vec[(unsigned char) (text[0])]);
391 if(NULL == nextai)
392 return 0;
393
394 /* check if nextai and the following char form a ligature
395 * If that is the case then there is a change that we have a 3 char
396 * ligature. First check if current char and ligature of 2nd and 3th
397 * char for a ligature.
398 */
399 if(ps_check_for_lig(psdoc, metrics, nextai, &text[1], ligdischar, &nextadobename, &_offset)) {
400 while(ligs) {
401 if(0 == strcmp(ligs->succ, nextadobename)) {
402 *offset += 1+_offset;
403 *newadobename = ligs->sub;
404 return 1;
405 }
406 ligs = ligs->next;
407 }
408 }
409
410 /* If we haven't found a three char ligature at this point then check
411 * for a 2 char ligatur.
412 */
413 ligs = ai->ligs;
414 while(ligs) {
415 // printf("Ligature for %s is %s\n", ai->adobename, ligs->succ);
416 if(!strcmp(ligs->succ, nextai->adobename)) {
417 ADOBEINFO *ligai;
418 *offset += 1;
419 /* check if the ligature made of the first two chars form a ligature
420 * which the third char
421 */
422 ligai = gfindadobe(metrics->gadobechars, ligs->sub);
423 if(ligai) {
424 if(ps_check_for_lig(psdoc, metrics, ligai, &text[1], ligdischar, &nextadobename, offset)) {
425 *newadobename = nextadobename;
426 return 1;
427
428 }
429 }
430 *newadobename = ligs->sub;
431 // printf("Found %s followed by %s replaced with %s\n", ai->adobename, nextai->adobename, ligs->sub);
432 return 1;
433 }
434 ligs = ligs->next;
435 }
436 }
437 return 0;
438 }
439 /* }}} */
440
441 /* ps_build_enc_hash() {{{
442 * Builds the hash table of an encoding vector.
443 * The glyhname is the the key, the position in the vector is the data.
444 * The position of the glyph in the vector starts at 1 because 0 is reserved
445 * by the hash table to indicate the end of the list.
446 * If a glyphname exists more than once, only the first one will be
447 * stored in the hash table. This would be the case for "" as glyphname,
448 * but empty strings are not stored at all.
449 */
ps_build_enc_hash(PSDoc * psdoc,ENCODING * enc)450 ght_hash_table_t *ps_build_enc_hash(PSDoc *psdoc, ENCODING *enc) {
451 int i;
452 ght_hash_table_t *hashvec;
453 hashvec = ght_create(512);
454 if(hashvec) {
455 ght_set_alloc(hashvec, ps_ght_malloc, ps_ght_free, psdoc);
456 for(i=0; i<256; i++) {
457 if(strlen(enc->vec[i]) > 0)
458 ght_insert(hashvec, (char *) i+1, strlen(enc->vec[i])+1, enc->vec[i]);
459 }
460 }
461 return(hashvec);
462 }
463 /* }}} */
464
465 /* ps_build_enc_from_font() {{{
466 * Builds the hash table with a font encoding from the font itself.
467 * This will only include those glyphs which have a number > 0.
468 */
ps_build_enc_from_font(PSDoc * psdoc,ADOBEFONTMETRIC * metrics)469 ght_hash_table_t *ps_build_enc_from_font(PSDoc *psdoc, ADOBEFONTMETRIC *metrics) {
470 ght_hash_table_t *hashvec;
471
472 hashvec = ght_create(512);
473 if(hashvec) {
474 ght_iterator_t iterator;
475 char *p_key;
476 ADOBEINFO *p_e;
477
478 ght_set_alloc(hashvec, ps_ght_malloc, ps_ght_free, psdoc);
479 for(p_e = ght_first(metrics->gadobechars, &iterator, (void **) &p_key); p_e; p_e = ght_next(metrics->gadobechars, &iterator, (void **) &p_key)) {
480 /* Do not add glyphs with a number <= 0 */
481 if(p_e->adobenum > 0) {
482 if(0 > ght_insert(hashvec, (char *) p_e->adobenum+1, strlen(p_e->adobename)+1, p_e->adobename))
483 ps_error(psdoc, PS_Warning, _("Could not insert entry %d->%s into font encoding hash table."), p_e->adobenum, p_e->adobename);
484 }
485 }
486 }
487 return(hashvec);
488 }
489 /* }}} */
490
491 /* ps_build_enc_vector() {{{
492 * Builds the encoding vector from the hash table
493 */
ps_build_enc_vector(PSDoc * psdoc,ght_hash_table_t * hashvec)494 ENCODING *ps_build_enc_vector(PSDoc *psdoc, ght_hash_table_t *hashvec) {
495 if(hashvec) {
496 ght_iterator_t iterator;
497 char *glyphname;
498 int i;
499 ENCODING *enc;
500
501 enc = (ENCODING *) psdoc->malloc(psdoc, sizeof(ENCODING), _("Allocate memory for new encoding vector.")) ;
502 if(NULL == enc) {
503 ps_error(psdoc, PS_MemoryError, _("Could not allocate memory for encoding vector."));
504 return NULL;
505 }
506 memset(enc, 0, sizeof(ENCODING));
507
508 for(i = (int) ght_first(hashvec, &iterator, (void **) &glyphname); i; i = (int) ght_next(hashvec, &iterator, (void **) &glyphname)) {
509 // printf("got %s = %d\n", glyphname, i-1);
510 enc->vec[i-1] = ps_strdup(psdoc, glyphname);
511 }
512
513 return(enc);
514 } else {
515 return NULL;
516 }
517 }
518 /* }}} */
519
520 /* ps_list_fontenc() {{{
521 *
522 */
ps_list_fontenc(PSDoc * psdoc,ght_hash_table_t * hashvec)523 void ps_list_fontenc(PSDoc *psdoc, ght_hash_table_t *hashvec) {
524 if(hashvec) {
525 ght_iterator_t iterator;
526 char *glyphname;
527 int i;
528
529 fprintf(stderr, "---- Font encoding vector -----\n");
530 fprintf(stderr, "Has %d entries.\n", ght_size(hashvec));
531 for(i = (int) ght_first(hashvec, &iterator, (void **) &glyphname); i; i = (int) ght_next(hashvec, &iterator, (void **) &glyphname)) {
532 fprintf(stderr, "%s = %d\n", glyphname, i-1);
533 }
534 }
535 }
536 /* }}} */
537
538 /* ps_free_enc_vector() {{{
539 * Frees all memory allocated for an encoding vector including the vector
540 * itself.
541 */
ps_free_enc_vector(PSDoc * psdoc,ENCODING * enc)542 void ps_free_enc_vector(PSDoc *psdoc, ENCODING *enc) {
543 int i;
544 if(!enc)
545 return;
546 if(enc->name)
547 psdoc->free(psdoc, enc->name);
548 for(i=0; i<256; i++) {
549 if(enc->vec[i])
550 psdoc->free(psdoc, enc->vec[i]);
551 }
552 psdoc->free(psdoc, enc);
553 }
554 /* }}} */
555
556 /* ps_fontenc_code() {{{
557 * Returns the index in the fontencoding vector
558 */
ps_fontenc_code(PSDoc * psdoc,ght_hash_table_t * fontenc,char * adobename)559 unsigned char ps_fontenc_code(PSDoc *psdoc, ght_hash_table_t *fontenc, char *adobename) {
560 if(fontenc) {
561 int code;
562 code = (int) ght_get(fontenc, strlen(adobename)+1, (void *) adobename);
563 if(code)
564 return((unsigned char) code -1);
565 else {
566 ps_error(psdoc, PS_Warning, _("The font encoding vector does not contain the glyph '%s'. Using '?' instead."), adobename);
567 return '?';
568 }
569 } else {
570 return '?';
571 }
572 }
573 /* }}} */
574
575 /* ps_fontenc_has_glpyh() {{{
576 * checks of a glyph is in the fontencoding vector
577 */
ps_fontenc_has_glyph(PSDoc * psdoc,ght_hash_table_t * fontenc,char * adobename)578 int ps_fontenc_has_glyph(PSDoc *psdoc, ght_hash_table_t *fontenc, char *adobename) {
579 if(fontenc) {
580 int code;
581 code = (int) ght_get(fontenc, strlen(adobename)+1, (void *) adobename);
582 if(code)
583 return ps_true;
584 else {
585 return ps_false;
586 }
587 } else {
588 return ps_false;
589 }
590 }
591 /* }}} */
592
593 /* ps_inputenc_name() {{{
594 * Returns the adobe name for a char in the input encoding vector
595 */
ps_inputenc_name(PSDoc * psdoc,unsigned char c)596 char *ps_inputenc_name(PSDoc *psdoc, unsigned char c) {
597 if(psdoc->inputenc) {
598 return(psdoc->inputenc->vec[c]);
599 } else {
600 return NULL;
601 }
602 }
603 /* }}} */
604
605 /* ps_get_bool_parameter() {{{
606 */
ps_get_bool_parameter(PSDoc * psdoc,const char * name,int deflt)607 int ps_get_bool_parameter(PSDoc *psdoc, const char *name, int deflt) {
608 const char *onoffstr;
609 onoffstr = PS_get_parameter(psdoc, name, 0);
610 if(NULL == onoffstr) {
611 return(deflt);
612 } else {
613 if(!strcmp(onoffstr, "true"))
614 return(1);
615 else
616 return(0);
617 }
618 }
619 /* }}} */
620
621 /* ps_open_file_in_path() {{{
622 */
ps_open_file_in_path(PSDoc * psdoc,const char * filename)623 FILE *ps_open_file_in_path(PSDoc *psdoc, const char *filename) {
624 FILE *fp;
625 PS_RESOURCE **pathres;
626 int count;
627 int i;
628 char buffer[255];
629
630 if(fp = fopen(filename, "rb"))
631 return fp;
632
633 if(NULL != (pathres = ps_get_resources(psdoc, "SearchPath", &count))) {
634 for(i=count-1; i>=0; i--) {
635 #ifdef HAVE_SNPRINTF
636 snprintf(buffer, 255, "%s/%s", pathres[i]->value, filename);
637 #else
638 sprintf(buffer, "%s/%s", pathres[i]->value, filename);
639 #endif
640 // fprintf(stderr, "Searching for %s\n", buffer);
641 if(fp = fopen(buffer, "rb")) {
642 // fprintf(stderr, "found %s in %s\n", filename, pathres[i]->value);
643 break;
644 }
645 }
646 psdoc->free(psdoc, pathres);
647 if(fp)
648 return(fp);
649 }
650
651 #ifdef PACKAGE_DATA_DIR
652 #ifdef HAVE_SNPRINTF
653 snprintf(buffer, 255, "%s/%s", PACKAGE_DATA_DIR, filename);
654 #else
655 sprintf(buffer, "%s/%s", PACKAGE_DATA_DIR, filename);
656 #endif
657 if(fp = fopen(buffer, "rb"))
658 return fp;
659 #endif
660
661 return NULL;
662 }
663 /* }}} */
664
665 int pow85[5] = {1, 85, 85*85, 85*85*85, 85*85*85*85};
666
667 /* ps_ascii85_encode() {{{
668 */
ps_ascii85_encode(PSDoc * psdoc,char * data,size_t len)669 void ps_ascii85_encode(PSDoc *psdoc, char *data, size_t len) {
670 unsigned long buffer;
671 unsigned char c;
672 int i, count, cc;
673
674 buffer = 0;
675 count = 0;
676 cc = 0;
677 while(count <= len-4) {
678 // buffer = ((long) data[count] << 24) + ((long) data[count+1] << 16) + ((long) data[count+2] << 8) + (long) data[count+3];
679 buffer |= ((unsigned char) data[count] << 24);
680 buffer |= ((unsigned char) data[count+1] << 16);
681 buffer |= ((unsigned char) data[count+2] << 8);
682 buffer |= ((unsigned char) data[count+3]);
683
684 if(buffer == 0) {
685 ps_putc(psdoc, 'z');
686 cc++;
687 } else {
688 for(i=4; i>=0; i--) {
689 c = (unsigned int) buffer / pow85[i];
690 ps_putc(psdoc, c+'!');
691 buffer = (unsigned int) buffer % pow85[i];
692 }
693 cc += 4;
694 }
695 count += 4;
696 if(cc > 55) {
697 ps_putc(psdoc, '\n');
698 cc = 0;
699 }
700 }
701 if(len-count) {
702 buffer = 0;
703 for(i=0; i<len-count; i++)
704 buffer = (buffer << 8) + (long) data[count+i];
705 buffer = buffer << ((4-len+count)*8);
706 for(i=4; i>=4-len+count; i--) {
707 c = (unsigned int) buffer / pow85[i];
708 ps_putc(psdoc, c+'!');
709 buffer = (unsigned int) buffer % pow85[i];
710 }
711 }
712 ps_putc(psdoc, '~');
713 ps_putc(psdoc, '>');
714 }
715 /* }}} */
716
717 /* ps_asciihex_encode() {{{
718 */
ps_asciihex_encode(PSDoc * psdoc,char * data,size_t len)719 void ps_asciihex_encode(PSDoc *psdoc, char *data, size_t len) {
720 int i, cc=0;
721 unsigned char *dataptr;
722
723 dataptr = data;
724 for(i=0; i<len; i++) {
725 ps_printf(psdoc, "%02x", *dataptr);
726 dataptr ++;
727 cc++;
728 if(cc > 35 && i < (len-1)) {
729 ps_printf(psdoc, "\n");
730 cc = 0;
731 }
732 }
733 ps_putc(psdoc, '\n');
734 ps_putc(psdoc, '>');
735 }
736 /* }}} */
737
738 /* ps_parse_optlist() {{{
739 */
ps_parse_optlist(PSDoc * psdoc,const char * optstr)740 ght_hash_table_t *ps_parse_optlist(PSDoc *psdoc, const char *optstr) {
741 int i, isname;
742 char name[100], value[100], delim;
743 const char *optstrptr;
744 ght_hash_table_t *opthash;
745
746 if(optstr == NULL || optstr[0] == '\0')
747 return(NULL);
748
749 opthash = ght_create(30);
750 if(opthash) {
751 ght_set_alloc(opthash, ps_ght_malloc, ps_ght_free, psdoc);
752
753 isname = 1;
754 optstrptr = optstr;
755 name[0] = '\0';
756 value[0] = '\0';
757
758 /* Skip leading spaces */
759 while(*optstrptr == ' ')
760 optstrptr++;
761
762 while(*optstrptr != '\0') {
763 if(isname) {
764 i = 0;
765 while(*optstrptr != '\0' && *optstrptr != ' ') {
766 name[i] = *optstrptr;
767 i++;
768 optstrptr++;
769 }
770 name[i] = '\0';
771 isname = 0;
772 optstrptr++;
773 } else {
774 if(*optstrptr == '{') {
775 delim = '}';
776 optstrptr++;
777 } else {
778 delim = ' ';
779 }
780 i = 0;
781 while(*optstrptr != '\0' && *optstrptr != delim) {
782 value[i] = *optstrptr;
783 i++;
784 optstrptr++;
785 }
786 value[i] = '\0';
787 isname = 1;
788 optstrptr++;
789
790 /* Value and Name is read, insert it into hash */
791 if(name[0]) {
792 ght_insert(opthash, (char *) ps_strdup(psdoc, value), strlen(name)+1, name);
793 name[0] = '\0';
794 value[0] = '\0';
795 }
796 }
797 while(*optstrptr != '\0' && *optstrptr == ' ')
798 optstrptr++;
799 }
800 }
801 return(opthash);
802 }
803 /* }}} */
804
805 /* ps_free_optlist() {{{
806 */
ps_free_optlist(PSDoc * psdoc,ght_hash_table_t * opthash)807 void ps_free_optlist(PSDoc *psdoc, ght_hash_table_t *opthash) {
808 ght_iterator_t iterator;
809 char *strval, *key;
810
811 // fprintf(stderr, "Freeing optlist\n");
812 for(strval = ght_first(opthash, &iterator, (void **) &key); strval; strval = ght_next(opthash, &iterator, (void **) &key)) {
813 // fprintf(stderr, "Freeing %s\n", strval);
814 psdoc->free(psdoc, strval);
815 }
816 ght_finalize(opthash);
817 }
818 /* }}} */
819
820 /* get_optlist_element_as_float() {{{
821 * Retrieves an element from the hash and converts its value into float
822 * Modifies *value only if the conversion was successful.
823 * Returns -1 if the parameter is not available and -2 if it is available
824 * but the value cannot be retrieved.
825 */
get_optlist_element_as_float(PSDoc * psdoc,ght_hash_table_t * opthash,const char * name,float * value)826 int get_optlist_element_as_float(PSDoc *psdoc, ght_hash_table_t *opthash, const char *name, float *value) {
827 float tmp;
828 char *strval;
829 char *endval;
830
831 if(NULL == opthash) {
832 return(-1);
833 }
834 if(NULL == (strval = ght_get(opthash, strlen(name)+1, (void *) name))) {
835 return(-1);
836 }
837 tmp = (float) strtod(strval, &endval);
838 if(endval == strval) {
839 return(-2);
840 }
841 *value = tmp;
842 return(0);
843 }
844 /* }}} */
845
846 /* get_optlist_element_as_int() {{{
847 * Retrieves an element from the hash and converts its value into integer
848 * Modifies *value only if the conversion was successful.
849 * Returns -1 if the parameter is not available and -2 if it is available
850 * but the value cannot be retrieved.
851 */
get_optlist_element_as_int(PSDoc * psdoc,ght_hash_table_t * opthash,const char * name,int * value)852 int get_optlist_element_as_int(PSDoc *psdoc, ght_hash_table_t *opthash, const char *name, int *value) {
853 long tmp;
854 char *strval;
855 char *endval;
856
857 if(NULL == opthash) {
858 return(-1);
859 }
860 if(NULL == (strval = ght_get(opthash, strlen(name)+1, (void *) name))) {
861 return(-1);
862 }
863 tmp = strtol(strval, &endval, 10);
864 if(endval == strval) {
865 return(-2);
866 }
867 *value = tmp;
868 return(0);
869 }
870 /* }}} */
871
872 /* get_optlist_element_as_bool() {{{
873 * Retrieves an element from the hash and converts its value into boolean
874 * Returns -1 if the parameter is not available and -2 if it is available
875 * but the value cannot be retrieved.
876 */
get_optlist_element_as_bool(PSDoc * psdoc,ght_hash_table_t * opthash,const char * name,ps_bool * value)877 int get_optlist_element_as_bool(PSDoc *psdoc, ght_hash_table_t *opthash, const char *name, ps_bool *value) {
878 char *strval;
879
880 if(NULL == opthash) {
881 return(-1);
882 }
883 if(NULL == (strval = ght_get(opthash, strlen(name)+1, (void *) name))) {
884 return(-1);
885 }
886 if(strcmp(strval, "false") == 0) {
887 *value = ps_false;
888 } else if(strcmp(strval, "true") == 0) {
889 *value = ps_true;
890 } else {
891 return(-2);
892 }
893 return(0);
894 }
895 /* }}} */
896
897 /* get_optlist_element_as_string() {{{
898 * Retrieves an element from the hash and converts its value into string
899 * Returns -1 if the parameter is not available
900 */
get_optlist_element_as_string(PSDoc * psdoc,ght_hash_table_t * opthash,const char * name,char ** value)901 int get_optlist_element_as_string(PSDoc *psdoc, ght_hash_table_t *opthash, const char *name, char **value) {
902 char *strval;
903
904 if(NULL == opthash) {
905 return(-1);
906 }
907 if(NULL == (strval = ght_get(opthash, strlen(name)+1, (void *) name))) {
908 return(-1);
909 }
910
911 *value = strval;
912
913 return(0);
914 }
915 /* }}} */
916
917 /*
918 * Local variables:
919 * tab-width: 4
920 * c-basic-offset: 4
921 * End:
922 * vim600: sw=2 ts=2 fdm=marker
923 * vim<600: sw=2 ts=2
924 */
925