1/*---------------------------------------------------------------------------*
2 |              PDFlib - A library for generating PDF on the fly             |
3 +---------------------------------------------------------------------------+
4 | Copyright (c) 1997-2004 Thomas Merz and PDFlib GmbH. All rights reserved. |
5 +---------------------------------------------------------------------------+
6 |                                                                           |
7 |    This software is subject to the PDFlib license. It is NOT in the       |
8 |    public domain. Extended versions and commercial licenses are           |
9 |    available, please check http://www.pdflib.com.                         |
10 |                                                                           |
11 *---------------------------------------------------------------------------*/
12
13/* $Id: p_params.c 14574 2005-10-29 16:27:43Z bonefish $
14 *
15 * PDFlib parameter handling
16 *
17 */
18
19#define P_PARAMS_C
20
21#include "p_intern.h"
22#include "p_font.h"
23#include "p_image.h"
24
25/*
26 * PDF_get_parameter() and PDF_set_parameter() deal with strings,
27 * PDF_get_value() and PDF_set_value() deal with numerical values.
28 */
29
30typedef struct
31{
32    char *	name;		/* parameter name */
33    pdc_bool	mod_zero;	/* PDF_get_() modifier argument must be 0 */
34    int		get_scope;	/* bit mask of legal states for PDF_get_() */
35    int		set_scope;	/* bit mask of legal states for PDF_set_() */
36} pdf_parm_descr;
37
38static pdf_parm_descr parms[] =
39{
40#define pdf_gen_parm_descr	1
41#include "p_params.h"
42#undef	pdf_gen_parm_descr
43
44    { "", 0, 0, 0 }
45};
46
47enum
48{
49#define pdf_gen_parm_enum	1
50#include "p_params.h"
51#undef	pdf_gen_parm_enum
52
53    PDF_PARAMETER_LIMIT
54};
55
56static int
57get_index(const char *key)
58{
59    int i;
60
61    for (i = 0; i < PDF_PARAMETER_LIMIT; ++i)
62	if (strcmp(key, parms[i].name) == 0)
63	    return i;
64
65    return -1;
66}
67
68static pdc_bool
69pdf_bool_value(PDF *p, const char *key, const char *value)
70{
71    if (!strcmp(value, "true"))
72	return pdc_true;
73
74    if (!strcmp(value, "false"))
75	return pdc_false;
76
77    pdc_error(p->pdc, PDC_E_ILLARG_BOOL, key, value, 0, 0);
78
79    return pdc_false;		/* compilers love it */
80}
81
82PDFLIB_API void PDFLIB_CALL
83PDF_set_parameter(PDF *p, const char *key, const char *value)
84{
85    static const char fn[] = "PDF_set_parameter";
86    pdc_usebox usebox = use_none;
87    pdc_text_format textformat = pdc_auto;
88    int i, k;
89
90    if (key == NULL || !*key)
91	pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "key", 0, 0, 0);
92
93    i = get_index(key);
94
95    if (!pdf_enter_api(p, fn, (pdf_state) pdf_state_all,
96	"(p[%p], \"%s\", \"%s\")\n", (void *) p, key, value))
97	return;
98
99    if (i == -1)
100	pdc_error(p->pdc, PDC_E_PAR_UNKNOWNKEY, key, 0, 0, 0);
101
102    if ((p->state_stack[p->state_sp] & parms[i].set_scope) == 0)
103	pdc_error(p->pdc, PDF_E_DOC_SCOPE_SET, key, pdf_current_scope(p), 0, 0);
104
105    if (value == NULL)
106	pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "value", 0, 0, 0);
107
108    switch (i)
109    {
110        case PDF_PARAMETER_PDIUSEBOX:
111        case PDF_PARAMETER_VIEWAREA:
112        case PDF_PARAMETER_VIEWCLIP:
113        case PDF_PARAMETER_PRINTAREA:
114        case PDF_PARAMETER_PRINTCLIP:
115            k = pdc_get_keycode(value, pdf_usebox_keylist);
116            if (k == PDC_KEY_NOTFOUND)
117                pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0);
118            usebox = (pdc_usebox) k;
119            break;
120
121        case PDF_PARAMETER_TEXTFORMAT:
122        case PDF_PARAMETER_HYPERTEXTFORMAT:
123            k = pdc_get_keycode(value, pdf_textformat_keylist);
124            if (k == PDC_KEY_NOTFOUND)
125                pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0);
126            textformat = (pdc_text_format) k;
127            break;
128    }
129
130    switch (i)
131    {
132        case PDF_PARAMETER_SEARCHPATH:
133        case PDF_PARAMETER_FONTAFM:
134	case PDF_PARAMETER_FONTPFM:
135        case PDF_PARAMETER_FONTOUTLINE:
136        case PDF_PARAMETER_HOSTFONT:
137        case PDF_PARAMETER_ENCODING:
138        case PDF_PARAMETER_ICCPROFILE:
139        case PDF_PARAMETER_STANDARDOUTPUTINTENT:
140	{
141            pdf_add_resource(p, key, value);
142            break;
143        }
144
145	case PDF_PARAMETER_FLUSH:
146	    if (p->binding != NULL && strcmp(p->binding, "C++"))
147		break;
148
149	    if (!strcmp(value, "none"))
150		p->flush = pdf_flush_none;
151	    else if (!strcmp(value, "page"))
152                p->flush = (pdf_flush_state) (p->flush | pdf_flush_page);
153	    else if (!strcmp(value, "content"))
154                p->flush = (pdf_flush_state) (p->flush | pdf_flush_content);
155	    else if (!strcmp(value, "heavy"))
156                p->flush = (pdf_flush_state) (p->flush | pdf_flush_heavy);
157	    else
158		pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0);
159
160	    break;
161
162	case PDF_PARAMETER_DEBUG:
163	{
164	    const unsigned char *c;
165
166	    for (c = (const unsigned char *) value; *c; c++) {
167		p->debug[(int) *c] = 1;
168
169		if (*c == 't') {
170		    pdc_set_trace(p->pdc, "PDFlib " PDFLIB_VERSIONSTRING);
171		}
172	    }
173	    break;
174	}
175
176	case PDF_PARAMETER_NODEBUG:
177	{
178	    const unsigned char *c;
179
180	    for (c = (const unsigned char *) value; *c; c++) {
181		if (*c == 't')
182		    pdc_set_trace(p->pdc, NULL);
183
184		p->debug[(int) *c] = 0;
185	    }
186	    break;
187	}
188
189        case PDF_PARAMETER_BINDING:
190            if (!p->binding)
191                p->binding = pdc_strdup(p->pdc, value);
192            break;
193
194        case PDF_PARAMETER_HASTOBEPOS:
195            p->hastobepos = pdf_bool_value(p, key, value);
196            break;
197
198	case PDF_PARAMETER_UNDERLINE:
199	    p->underline = pdf_bool_value(p, key, value);
200	    break;
201
202	case PDF_PARAMETER_OVERLINE:
203	    p->overline = pdf_bool_value(p, key, value);
204	    break;
205
206	case PDF_PARAMETER_STRIKEOUT:
207	    p->strikeout = pdf_bool_value(p, key, value);
208	    break;
209
210        case PDF_PARAMETER_KERNING:
211            pdc_warning(p->pdc, PDF_E_UNSUPP_KERNING, 0, 0, 0, 0);
212            break;
213
214        case PDF_PARAMETER_AUTOSUBSETTING:
215            pdc_warning(p->pdc, PDF_E_UNSUPP_SUBSET, 0, 0, 0, 0);
216            break;
217
218        case PDF_PARAMETER_AUTOCIDFONT:
219            pdc_warning(p->pdc, PDF_E_UNSUPP_UNICODE, 0, 0, 0, 0);
220            break;
221
222        case PDF_PARAMETER_UNICODEMAP:
223            pdc_warning(p->pdc, PDF_E_UNSUPP_UNICODE, 0, 0, 0, 0);
224            break;
225
226	case PDF_PARAMETER_MASTERPASSWORD:
227	    pdc_warning(p->pdc, PDF_E_UNSUPP_CRYPT, 0, 0, 0, 0);
228	    break;
229
230	case PDF_PARAMETER_USERPASSWORD:
231            pdc_warning(p->pdc, PDF_E_UNSUPP_CRYPT, 0, 0, 0, 0);
232	    break;
233
234	case PDF_PARAMETER_PERMISSIONS:
235            pdc_warning(p->pdc, PDF_E_UNSUPP_CRYPT, 0, 0, 0, 0);
236	    break;
237
238	case PDF_PARAMETER_COMPATIBILITY:
239
240	    if (!strcmp(value, "1.3"))
241		p->compatibility = PDC_1_3;
242	    else if (!strcmp(value, "1.4"))
243		p->compatibility = PDC_1_4;
244	    else if (!strcmp(value, "1.5"))
245		p->compatibility = PDC_1_5;
246	    else
247		pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0);
248	    break;
249
250	case PDF_PARAMETER_PDFX:
251	    pdc_warning(p->pdc, PDF_E_UNSUPP_PDFX, 0, 0, 0, 0);
252
253	    break;
254
255
256        case PDF_PARAMETER_RESOURCEFILE:
257            if (p->resourcefilename)
258            {
259                pdc_free(p->pdc, p->resourcefilename);
260                p->resourcefilename = NULL;
261            }
262            p->resourcefilename = pdc_strdup(p->pdc, value);
263            p->resfilepending = pdc_true;
264            break;
265
266	case PDF_PARAMETER_PREFIX:
267            if (p->prefix)
268            {
269                pdc_free(p->pdc, p->prefix);
270                p->prefix = NULL;
271            }
272            /* because of downward compatibility */
273            p->prefix = pdc_strdup(p->pdc, &value[value[0] == '/' ? 1 : 0]);
274	    break;
275
276	case PDF_PARAMETER_WARNING:
277	    pdc_set_warnings(p->pdc, pdf_bool_value(p, key, value));
278	    break;
279
280        case PDF_PARAMETER_OPENWARNING:
281            p->debug['o'] = (char) pdf_bool_value(p, key, value);
282            break;
283
284        case PDF_PARAMETER_FONTWARNING:
285            p->debug['F'] = (char) pdf_bool_value(p, key, value);
286            break;
287
288        case PDF_PARAMETER_ICCWARNING:
289            p->debug['I'] = (char) pdf_bool_value(p, key, value);
290            break;
291
292	case PDF_PARAMETER_IMAGEWARNING:
293	    p->debug['i'] = (char) pdf_bool_value(p, key, value);
294	    break;
295
296        case PDF_PARAMETER_PDIWARNING:
297            p->debug['p'] = (char) pdf_bool_value(p, key, value);
298            break;
299
300        case PDF_PARAMETER_HONORICCPROFILE:
301            p->debug['e'] = (char) pdf_bool_value(p, key, value);
302            break;
303
304        case PDF_PARAMETER_GLYPHWARNING:
305            p->debug['g'] = (char) pdf_bool_value(p, key, value);
306            break;
307
308        case PDF_PARAMETER_RENDERINGINTENT:
309            k = pdc_get_keycode(value, gs_renderingintents);
310            if (k == PDC_KEY_NOTFOUND)
311                pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0);
312            p->rendintent = (pdf_renderingintent) k;
313            break;
314
315        case PDF_PARAMETER_PRESERVEOLDPANTONENAMES:
316            p->preserveoldpantonenames = pdf_bool_value(p, key, value);
317            break;
318
319        case PDF_PARAMETER_SPOTCOLORLOOKUP:
320            p->spotcolorlookup = pdf_bool_value(p, key, value);
321            break;
322
323	case PDF_PARAMETER_INHERITGSTATE:
324	    p->inheritgs = pdf_bool_value(p, key, value);
325	    break;
326
327	case PDF_PARAMETER_PDISTRICT:
328	    p->pdi_strict = pdf_bool_value(p, key, value);
329	    break;
330
331	case PDF_PARAMETER_PDIUSEBOX:
332            p->pdi_usebox = usebox;
333            break;
334
335	case PDF_PARAMETER_PASSTHROUGH:
336	    p->debug['P'] = (char) !pdf_bool_value(p, key, value);
337	    break;
338
339	case PDF_PARAMETER_HIDETOOLBAR:
340	    if (pdf_bool_value(p, key, value))
341		p->ViewerPreferences.flags |= HideToolbar;
342	    break;
343
344	case PDF_PARAMETER_HIDEMENUBAR:
345	    if (pdf_bool_value(p, key, value))
346		p->ViewerPreferences.flags |= HideMenubar;
347	    break;
348
349	case PDF_PARAMETER_HIDEWINDOWUI:
350	    if (pdf_bool_value(p, key, value))
351		p->ViewerPreferences.flags |= HideWindowUI;
352	    break;
353
354	case PDF_PARAMETER_FITWINDOW:
355	    if (pdf_bool_value(p, key, value))
356		p->ViewerPreferences.flags |= FitWindow;
357	    break;
358
359	case PDF_PARAMETER_CENTERWINDOW:
360	    if (pdf_bool_value(p, key, value))
361		p->ViewerPreferences.flags |= CenterWindow;
362	    break;
363
364	case PDF_PARAMETER_DISPLAYDOCTITLE:
365	    if (pdf_bool_value(p, key, value))
366		p->ViewerPreferences.flags |= DisplayDocTitle;
367	    break;
368
369	case PDF_PARAMETER_NONFULLSCREENPAGEMODE:
370	    if (!strcmp(value, "useoutlines")) {
371		p->ViewerPreferences.flags |= NonFullScreenPageModeOutlines;
372		p->ViewerPreferences.flags &= ~NonFullScreenPageModeThumbs;
373	    } else if (!strcmp(value, "usethumbs")) {
374		p->ViewerPreferences.flags &= ~NonFullScreenPageModeOutlines;
375		p->ViewerPreferences.flags |= NonFullScreenPageModeThumbs;
376	    } else if (!strcmp(value, "usenone")) {
377		p->ViewerPreferences.flags &= ~NonFullScreenPageModeOutlines;
378		p->ViewerPreferences.flags &= ~NonFullScreenPageModeThumbs;
379	    } else {
380		pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0);
381	    }
382
383	    break;
384
385	case PDF_PARAMETER_DIRECTION:
386	    if (!strcmp(value, "r2l")) {
387		p->ViewerPreferences.flags |= DirectionR2L;
388	    } else if (!strcmp(value, "l2r")) {
389		p->ViewerPreferences.flags &= ~DirectionR2L;
390	    } else {
391		pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0);
392	    }
393	    break;
394
395	case PDF_PARAMETER_VIEWAREA:
396            p->ViewerPreferences.ViewArea = usebox;
397	    break;
398
399	case PDF_PARAMETER_VIEWCLIP:
400            p->ViewerPreferences.ViewClip = usebox;
401            break;
402
403	case PDF_PARAMETER_PRINTAREA:
404            p->ViewerPreferences.PrintArea = usebox;
405            break;
406
407	case PDF_PARAMETER_PRINTCLIP:
408            p->ViewerPreferences.PrintClip = usebox;
409            break;
410
411        case PDF_PARAMETER_TOPDOWN:
412            if (pdf_bool_value(p, key, value))
413                p->ydirection = (float) -1.0;
414            else
415                p->ydirection = (float) 1.0;
416            break;
417
418        case PDF_PARAMETER_USERCOORDINATES:
419            p->usercoordinates = pdf_bool_value(p, key, value);
420            break;
421
422	case PDF_PARAMETER_OPENACTION:
423	    pdf_cleanup_destination(p, &p->open_action);
424
425	    pdf_parse_destination_optlist(p,
426                value, &p->open_action, 1, pdf_openaction);
427	    break;
428
429	case PDF_PARAMETER_OPENMODE:
430	    if (!strcmp(value, "none")) {
431		p->open_mode = open_none;
432	    } else if (!strcmp(value, "bookmarks")) {
433		p->open_mode = open_bookmarks;
434	    } else if (!strcmp(value, "thumbnails")) {
435		p->open_mode = open_thumbnails;
436	    } else if (!strcmp(value, "fullscreen")) {
437		p->open_mode = open_fullscreen;
438	    } else {
439		pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0);
440	    }
441	    break;
442
443	case PDF_PARAMETER_BOOKMARKDEST:
444	    pdf_cleanup_destination(p, &p->bookmark_dest);
445
446	    pdf_parse_destination_optlist(p,
447                value, &p->bookmark_dest, 0, pdf_bookmark);
448	    break;
449
450	case PDF_PARAMETER_FILLRULE:
451	    if (!strcmp(value, "winding")) {
452		p->fillrule = pdf_fill_winding;
453	    } else if (!strcmp(value, "evenodd")) {
454		p->fillrule = pdf_fill_evenodd;
455	    } else {
456		pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0);
457	    }
458	    break;
459
460        case PDF_PARAMETER_TEXTFORMAT:
461            p->textformat = textformat;
462            break;
463
464        case PDF_PARAMETER_HYPERTEXTFORMAT:
465            p->hypertextformat = textformat;
466            break;
467
468        case PDF_PARAMETER_HYPERTEXTENCODING:
469        {
470            pdc_encoding enc;
471
472            if (!*value)
473            {
474                enc = pdc_unicode;
475            }
476            else
477            {
478                enc = pdf_find_encoding(p, (const char *) value);
479                if (enc == pdc_invalidenc)
480                    enc = pdf_insert_encoding(p, (const char *) value);
481                if (enc < 0 && enc != pdc_unicode)
482                    pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0);
483            }
484            p->hypertextencoding = enc;
485            break;
486        }
487
488	/* deprecated */
489	case PDF_PARAMETER_NATIVEUNICODE:
490	    (void) pdf_bool_value(p, key, value);
491	    break;
492
493	case PDF_PARAMETER_TRANSITION:
494	    pdf_set_transition(p, value);
495	    break;
496
497	case PDF_PARAMETER_BASE:
498	    if (p->base) {
499		pdc_free(p->pdc, p->base);
500		p->base = NULL;
501	    }
502
503	    p->base = pdc_strdup(p->pdc, value);
504	    break;
505
506	case PDF_PARAMETER_LAUNCHLINK_PARAMETERS:
507	    if (p->launchlink_parameters) {
508		pdc_free(p->pdc, p->launchlink_parameters);
509		p->launchlink_parameters = NULL;
510	    }
511	    p->launchlink_parameters = pdc_strdup(p->pdc, value);
512	    break;
513
514	case PDF_PARAMETER_LAUNCHLINK_OPERATION:
515	    if (p->launchlink_operation) {
516		pdc_free(p->pdc, p->launchlink_operation);
517		p->launchlink_operation = NULL;
518	    }
519	    p->launchlink_operation = pdc_strdup(p->pdc, value);
520	    break;
521
522	case PDF_PARAMETER_LAUNCHLINK_DEFAULTDIR:
523	    if (p->launchlink_defaultdir) {
524		pdc_free(p->pdc, p->launchlink_defaultdir);
525		p->launchlink_defaultdir = NULL;
526	    }
527	    p->launchlink_defaultdir = pdc_strdup(p->pdc, value);
528	    break;
529
530	case PDF_PARAMETER_TRACE:
531	    if (pdf_bool_value(p, key, value)) {
532		p->debug['t'] = 1;
533		pdc_set_trace(p->pdc, "PDFlib " PDFLIB_VERSIONSTRING);
534	    } else {
535		pdc_set_trace(p->pdc, NULL);
536		p->debug['t'] = 0;
537	    }
538	    break;
539
540	case PDF_PARAMETER_TRACEFILE:
541	    pdc_set_tracefile(p->pdc, value);
542	    break;
543
544	case PDF_PARAMETER_TRACEMSG:
545	    /* do nothing -- client-supplied string will show up in the trace */
546	    break;
547
548	case PDF_PARAMETER_SERIAL:
549	case PDF_PARAMETER_LICENSE:
550	    break;
551
552	case PDF_PARAMETER_LICENSEFILE:
553	    break;
554
555	default:
556	    pdc_error(p->pdc, PDC_E_PAR_UNKNOWNKEY, key, 0, 0, 0);
557	    break;
558    } /* switch */
559} /* PDF_set_parameter */
560
561static float
562pdf_value(PDF *p, const char *key, float value, int minver)
563{
564    if (p->compatibility < minver)
565	pdc_error(p->pdc, PDC_E_PAR_VERSION,
566	    key, pdc_errprintf(p->pdc, "%d.%d", minver/10, minver%10), 0, 0);
567
568    return value;
569}
570
571static float
572pdf_pos_value(PDF *p, const char *key, float value, int minver)
573{
574    if (p->compatibility < minver)
575	pdc_error(p->pdc, PDC_E_PAR_VERSION,
576	    key, pdc_errprintf(p->pdc, "%d.%d", minver/10, minver%10), 0, 0);
577
578    if (value <= (float) 0)
579	pdc_error(p->pdc, PDC_E_PAR_ILLVALUE,
580	    pdc_errprintf(p->pdc, "%f", value), key, 0, 0);
581
582    return value;
583}
584
585PDFLIB_API void PDFLIB_CALL
586PDF_set_value(PDF *p, const char *key, float value)
587{
588    static const char fn[] = "PDF_set_value";
589    int i;
590    int ivalue = (int) value;
591
592    if (key == NULL || !*key)
593	pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "key", 0, 0, 0);
594
595    i = get_index(key);
596
597    if (!pdf_enter_api(p, fn, (pdf_state) pdf_state_all,
598	"(p[%p], \"%s\", %g)\n", (void *) p, key, value))
599	return;
600
601    if (i == -1)
602	pdc_error(p->pdc, PDC_E_PAR_UNKNOWNKEY, key, 0, 0, 0);
603
604    if ((p->state_stack[p->state_sp] & parms[i].set_scope) == 0)
605	pdc_error(p->pdc, PDF_E_DOC_SCOPE_SET, key, pdf_current_scope(p), 0, 0);
606
607    switch (i)
608    {
609	case PDF_PARAMETER_COMPRESS:
610	    if (ivalue < 0 || ivalue > 9)
611		pdc_error(p->pdc, PDC_E_PAR_ILLVALUE,
612		    pdc_errprintf(p->pdc, "%f", value), key, 0, 0);
613
614	    if (pdc_get_compresslevel(p->out) != ivalue)
615	    {
616		/*
617		 * We must restart the compression engine and start a new
618		 * contents section if we're in the middle of a page.
619		 */
620		if (PDF_GET_STATE(p) == pdf_state_page) {
621		    pdf_end_contents_section(p);
622		    pdc_set_compresslevel(p->out, ivalue);
623		    pdf_begin_contents_section(p);
624		} else
625		    pdc_set_compresslevel(p->out, ivalue);
626	    }
627
628	    break;
629
630	case PDF_PARAMETER_FLOATDIGITS:
631	    if (3 <= ivalue && ivalue <= 6)
632		pdc_set_floatdigits(p->pdc, ivalue);
633	    else
634		pdc_error(p->pdc, PDC_E_PAR_ILLVALUE,
635		    pdc_errprintf(p->pdc, "%d", ivalue), key, 0, 0);
636	    break;
637
638	case PDF_PARAMETER_PAGEWIDTH:
639            if (p->ydirection == -1)
640                pdc_error(p->pdc, PDF_E_PAGE_ILLCHGSIZE, 0, 0, 0, 0);
641	    if (p->compatibility >= PDC_1_3 &&
642		(value < PDF_ACRO4_MINPAGE || value > PDF_ACRO4_MAXPAGE))
643		    pdc_warning(p->pdc, PDF_E_PAGE_SIZE_ACRO4, 0, 0, 0, 0);
644
645	    p->width = pdf_pos_value(p, key, value, PDC_1_3);
646	    break;
647
648	case PDF_PARAMETER_PAGEHEIGHT:
649            if (p->ydirection == -1)
650                pdc_error(p->pdc, PDF_E_PAGE_ILLCHGSIZE, 0, 0, 0, 0);
651	    if (p->compatibility >= PDC_1_3 &&
652		(value < PDF_ACRO4_MINPAGE || value > PDF_ACRO4_MAXPAGE))
653		    pdc_warning(p->pdc, PDF_E_PAGE_SIZE_ACRO4, 0, 0, 0, 0);
654
655	    p->height = pdf_pos_value(p, key, value, PDC_1_3);
656	    break;
657
658	case PDF_PARAMETER_CROPBOX_LLX:
659	    p->CropBox.llx = pdf_value(p, key, value, PDC_1_3);
660	    break;
661
662	case PDF_PARAMETER_CROPBOX_LLY:
663	    p->CropBox.lly = pdf_value(p, key, value, PDC_1_3);
664	    break;
665
666	case PDF_PARAMETER_CROPBOX_URX:
667	    p->CropBox.urx = pdf_value(p, key, value, PDC_1_3);
668	    break;
669
670	case PDF_PARAMETER_CROPBOX_URY:
671	    p->CropBox.ury = pdf_value(p, key, value, PDC_1_3);
672	    break;
673
674	case PDF_PARAMETER_BLEEDBOX_LLX:
675	    p->BleedBox.llx = pdf_value(p, key, value, PDC_1_3);
676	    break;
677
678	case PDF_PARAMETER_BLEEDBOX_LLY:
679	    p->BleedBox.lly = pdf_value(p, key, value, PDC_1_3);
680	    break;
681
682	case PDF_PARAMETER_BLEEDBOX_URX:
683	    p->BleedBox.urx = pdf_value(p, key, value, PDC_1_3);
684	    break;
685
686	case PDF_PARAMETER_BLEEDBOX_URY:
687	    p->BleedBox.ury = pdf_value(p, key, value, PDC_1_3);
688	    break;
689
690	case PDF_PARAMETER_TRIMBOX_LLX:
691	    p->TrimBox.llx = pdf_value(p, key, value, PDC_1_3);
692	    break;
693
694	case PDF_PARAMETER_TRIMBOX_LLY:
695	    p->TrimBox.lly = pdf_value(p, key, value, PDC_1_3);
696	    break;
697
698	case PDF_PARAMETER_TRIMBOX_URX:
699	    p->TrimBox.urx = pdf_value(p, key, value, PDC_1_3);
700	    break;
701
702	case PDF_PARAMETER_TRIMBOX_URY:
703	    p->TrimBox.ury = pdf_value(p, key, value, PDC_1_3);
704	    break;
705
706	case PDF_PARAMETER_ARTBOX_LLX:
707	    p->ArtBox.llx = pdf_value(p, key, value, PDC_1_3);
708	    break;
709
710	case PDF_PARAMETER_ARTBOX_LLY:
711	    p->ArtBox.lly = pdf_value(p, key, value, PDC_1_3);
712	    break;
713
714	case PDF_PARAMETER_ARTBOX_URX:
715	    p->ArtBox.urx = pdf_value(p, key, value, PDC_1_3);
716	    break;
717
718	case PDF_PARAMETER_ARTBOX_URY:
719	    p->ArtBox.ury = pdf_value(p, key, value, PDC_1_3);
720	    break;
721
722	case PDF_PARAMETER_LEADING:
723	    pdf_set_leading(p, value);
724	    break;
725
726	case PDF_PARAMETER_TEXTRISE:
727	    pdf_set_text_rise(p, value);
728	    break;
729
730	case PDF_PARAMETER_HORIZSCALING:
731	    pdf_set_horiz_scaling(p, value);
732	    break;
733
734	case PDF_PARAMETER_TEXTRENDERING:
735	    pdf_set_text_rendering(p, (int) value);
736	    break;
737
738	case PDF_PARAMETER_CHARSPACING:
739	    pdf_set_char_spacing(p, value);
740	    break;
741
742	case PDF_PARAMETER_WORDSPACING:
743	    pdf_set_word_spacing(p, value);
744	    break;
745
746	case PDF_PARAMETER_DURATION:
747	    pdf_set_duration(p, value);
748	    break;
749
750	case PDF_PARAMETER_DEFAULTGRAY:
751	    break;
752
753	case PDF_PARAMETER_DEFAULTRGB:
754	    break;
755
756	case PDF_PARAMETER_DEFAULTCMYK:
757	    break;
758
759        case PDF_PARAMETER_SETCOLOR_ICCPROFILEGRAY:
760            break;
761
762        case PDF_PARAMETER_SETCOLOR_ICCPROFILERGB:
763            break;
764
765        case PDF_PARAMETER_SETCOLOR_ICCPROFILECMYK:
766            break;
767
768        case PDF_PARAMETER_SUBSETLIMIT:
769            pdc_warning(p->pdc, PDF_E_UNSUPP_SUBSET, 0, 0, 0, 0);
770            break;
771
772        case PDF_PARAMETER_SUBSETMINSIZE:
773            pdc_warning(p->pdc, PDF_E_UNSUPP_SUBSET, 0, 0, 0, 0);
774            break;
775
776	default:
777	    pdc_error(p->pdc, PDC_E_PAR_UNKNOWNKEY, key, 0, 0, 0);
778	    break;
779    } /* switch */
780} /* PDF_set_value */
781
782PDFLIB_API float PDFLIB_CALL
783PDF_get_value(PDF *p, const char *key, float mod)
784{
785    static const char fn[] = "PDF_get_value";
786    int i = -1;
787    int imod = (int) mod;
788    float result = (float) 0;
789
790    /* some parameters can be retrieved with p == 0.
791    */
792    if (key != NULL && (i = get_index(key)) != -1)
793    {
794	switch (i)
795	{
796	    case PDF_PARAMETER_MAJOR:
797		result = PDFLIB_MAJORVERSION;
798		return result;
799
800	    case PDF_PARAMETER_MINOR:
801		result = PDFLIB_MINORVERSION;
802		return result;
803
804	    case PDF_PARAMETER_REVISION:
805		result = PDFLIB_REVISION;
806		return result;
807	} /* switch */
808    }
809
810    if (!pdf_enter_api(p, fn, (pdf_state) pdf_state_all,
811	"(p[%p], \"%s\", %g)", (void *) p, key, mod))
812	return (float) 0;
813
814    if (i == -1)
815        pdc_error(p->pdc, PDC_E_PAR_UNKNOWNKEY, key, 0, 0, 0);
816
817    if ((p->state_stack[p->state_sp] & parms[i].get_scope) == 0)
818	pdc_error(p->pdc, PDF_E_DOC_SCOPE_GET, key, pdf_current_scope(p), 0, 0);
819
820    if (key == NULL || !*key)
821	pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "key", 0, 0, 0);
822
823    if (parms[i].mod_zero && mod != (float) 0)
824	pdc_error(p->pdc, PDC_E_PAR_ILLVALUE,
825	    pdc_errprintf(p->pdc, "%f", mod), key, 0, 0);
826
827    switch (i)
828    {
829        case PDF_PARAMETER_IMAGEWIDTH:
830        case PDF_PARAMETER_IMAGEHEIGHT:
831        case PDF_PARAMETER_RESX:
832        case PDF_PARAMETER_RESY:
833            PDF_INPUT_HANDLE(p, imod)
834            pdf_check_handle(p, imod, pdc_imagehandle);
835            break;
836
837        case PDF_PARAMETER_FONTMAXCODE:
838        case PDF_PARAMETER_CAPHEIGHT:
839        case PDF_PARAMETER_ASCENDER:
840        case PDF_PARAMETER_DESCENDER:
841            PDF_INPUT_HANDLE(p, imod)
842            pdf_check_handle(p, imod, pdc_fonthandle);
843            break;
844    }
845
846    switch (i)
847    {
848        case PDF_PARAMETER_PAGEWIDTH:
849            result = p->width;
850            break;
851
852        case PDF_PARAMETER_PAGEHEIGHT:
853            result = p->height;
854            break;
855
856        case PDF_PARAMETER_IMAGEWIDTH:
857            result = (float) (p->images[imod].width);
858            break;
859
860        case PDF_PARAMETER_IMAGEHEIGHT:
861            result = (float) fabs((double) (p->images[imod].height));
862            break;
863
864        case PDF_PARAMETER_RESX:
865            result = (float) (p->images[imod].dpi_x);
866            break;
867
868        case PDF_PARAMETER_RESY:
869            result = (float) (p->images[imod].dpi_y);
870            break;
871
872        case PDF_PARAMETER_IMAGE_ICCPROFILE:
873            break;
874
875        case PDF_PARAMETER_ICCCOMPONENTS:
876            break;
877
878        case PDF_PARAMETER_CURRENTX:
879	    result = (float) (p->gstate[p->sl].x);
880	    break;
881
882	case PDF_PARAMETER_CURRENTY:
883	    result = (float) (p->gstate[p->sl].y);
884	    break;
885
886	case PDF_PARAMETER_TEXTX:
887	    result = (float) (p->tstate[p->sl].m.e);
888	    break;
889
890	case PDF_PARAMETER_TEXTY:
891	    result = (float) (p->tstate[p->sl].m.f);
892	    break;
893
894	case PDF_PARAMETER_WORDSPACING:
895	    result = (float) (p->tstate[p->sl].w);
896	    break;
897
898	case PDF_PARAMETER_CHARSPACING:
899	    result = (float) (p->tstate[p->sl].c);
900	    break;
901
902	case PDF_PARAMETER_HORIZSCALING:
903            result = pdf_get_horiz_scaling(p);
904	    break;
905
906	case PDF_PARAMETER_TEXTRISE:
907	    result = (float) (p->tstate[p->sl].rise);
908	    break;
909
910	case PDF_PARAMETER_LEADING:
911	    result = (float) (p->tstate[p->sl].l);
912	    break;
913
914	case PDF_PARAMETER_TEXTRENDERING:
915	    result = (float) (p->tstate[p->sl].mode);
916	    break;
917
918	case PDF_PARAMETER_FONT:
919	    result = (float) (pdf_get_font(p));
920            if (p->hastobepos) result += 1; \
921	    break;
922
923        case PDF_PARAMETER_MONOSPACE:
924            result = (float) pdf_get_monospace(p);
925            break;
926
927        case PDF_PARAMETER_FONTSIZE:
928            result = (float) (pdf_get_fontsize(p));
929            break;
930
931        case PDF_PARAMETER_FONTMAXCODE:
932            result = (float) (p->fonts[imod].numOfCodes - 1);
933            break;
934
935	case PDF_PARAMETER_CAPHEIGHT:
936	    result = (float) (p->fonts[imod].capHeight / (float) 1000);
937	    break;
938
939	case PDF_PARAMETER_ASCENDER:
940	    result = (float) (p->fonts[imod].ascender / (float) 1000);
941	    break;
942
943	case PDF_PARAMETER_DESCENDER:
944	    result = (float) (p->fonts[imod].descender / (float) 1000);
945	    break;
946
947        case PDF_PARAMETER_SUBSETLIMIT:
948            break;
949
950	default:
951	    pdc_error(p->pdc, PDC_E_PAR_UNKNOWNKEY, key, 0, 0, 0);
952	    break;
953    } /* switch */
954
955    pdc_trace(p->pdc, "[%g]\n", result);
956    return result;
957} /* PDF_get_value */
958
959PDFLIB_API const char * PDFLIB_CALL
960PDF_get_parameter(PDF *p, const char *key, float mod)
961{
962    static const char fn[] = "PDF_get_parameter";
963    int i = -1;
964    const char *result = "";
965
966    /* some parameters can be retrieved with p == 0.
967    */
968    if (key != NULL && (i = get_index(key)) != -1)
969    {
970	switch (i)
971	{
972	    case PDF_PARAMETER_VERSION:
973		result = PDFLIB_VERSIONSTRING;
974		return result;
975
976	    case PDF_PARAMETER_PDI:
977		result = "false";
978		return result;
979	} /* switch */
980    }
981
982    if (!pdf_enter_api(p, fn, (pdf_state) pdf_state_all,
983	"(p[%p], \"%s\", %g);", (void *) p, key, mod))
984        return "";
985
986    if (key == NULL || !*key)
987	pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "key", 0, 0, 0);
988
989    if (i == -1)
990        pdc_error(p->pdc, PDC_E_PAR_UNKNOWNKEY, key, 0, 0, 0);
991
992    if ((p->state_stack[p->state_sp] & parms[i].get_scope) == 0)
993	pdc_error(p->pdc, PDF_E_DOC_SCOPE_GET, key, pdf_current_scope(p), 0, 0);
994
995    if (parms[i].mod_zero && mod != (float) 0)
996	pdc_error(p->pdc, PDC_E_PAR_ILLPARAM,
997	    pdc_errprintf(p->pdc, "%f", mod), key, 0, 0);
998
999    switch (i)
1000    {
1001	case PDF_PARAMETER_FONTNAME:
1002	    result = pdf_get_fontname(p);
1003	    break;
1004
1005        case PDF_PARAMETER_FONTSTYLE:
1006            result = pdf_get_fontstyle(p);
1007            break;
1008
1009        case PDF_PARAMETER_FONTENCODING:
1010            result = pdf_get_fontencoding(p);
1011            break;
1012
1013	case PDF_PARAMETER_UNDERLINE:
1014            result = PDC_BOOLSTR(p->underline);
1015	    break;
1016
1017	case PDF_PARAMETER_OVERLINE:
1018            result = PDC_BOOLSTR(p->overline);
1019	    break;
1020
1021	case PDF_PARAMETER_STRIKEOUT:
1022            result = PDC_BOOLSTR(p->strikeout);
1023	    break;
1024
1025	case PDF_PARAMETER_INHERITGSTATE:
1026            result = PDC_BOOLSTR(p->inheritgs);
1027	    break;
1028
1029	case PDF_PARAMETER_SCOPE:
1030	    switch (p->state_stack[p->state_sp]) {
1031		case pdf_state_object:	result = "object";	break;
1032		case pdf_state_document:result = "document";	break;
1033		case pdf_state_page:	result = "page";	break;
1034		case pdf_state_pattern:	result = "pattern";	break;
1035		case pdf_state_template:result = "template";	break;
1036		case pdf_state_path:	result = "path";	break;
1037		default:		result = "(unknown)";	break;
1038	    }
1039	    break;
1040
1041        case PDF_PARAMETER_TEXTFORMAT:
1042            result = pdc_get_keyword(p->textformat, pdf_textformat_keylist);
1043            break;
1044
1045        case PDF_PARAMETER_HYPERTEXTFORMAT:
1046            result = pdc_get_keyword(p->hypertextformat,pdf_textformat_keylist);
1047            break;
1048
1049        case PDF_PARAMETER_HYPERTEXTENCODING:
1050            result = pdf_get_encoding_name(p, p->hypertextencoding);
1051            break;
1052
1053	default:
1054	    pdc_error(p->pdc, PDC_E_PAR_UNKNOWNKEY, key, 0, 0, 0);
1055	    break;
1056    } /* switch */
1057
1058    pdc_trace(p->pdc, "[%s]\n", result);
1059    return result;
1060} /* PDF_get_parameter */
1061