Files correlati : Ricompilazione Demo : [ ] Commento : Riportata la versione 3.1 patch 650 git-svn-id: svn://10.65.10.50/trunk@14148 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			1421 lines
		
	
	
		
			36 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1421 lines
		
	
	
		
			36 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /*---------------------------------------------------------------------------*
 | |
|  |              PDFlib - A library for generating PDF on the fly             |
 | |
|  +---------------------------------------------------------------------------+
 | |
|  | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
 | |
|  +---------------------------------------------------------------------------+
 | |
|  |                                                                           |
 | |
|  |    This software is subject to the PDFlib license. It is NOT in the       |
 | |
|  |    public domain. Extended versions and commercial licenses are           |
 | |
|  |    available, please check http://www.pdflib.com.                         |
 | |
|  |                                                                           |
 | |
|  *---------------------------------------------------------------------------*/
 | |
| 
 | |
| /* $Id: p_document.c,v 1.2 2006-07-11 13:10:33 alex Exp $
 | |
|  *
 | |
|  * PDFlib document related routines
 | |
|  *
 | |
|  */
 | |
| 
 | |
| 
 | |
| #undef MVS_TEST
 | |
| 
 | |
| #define P_DOCUMENT_C
 | |
| 
 | |
| #include "p_intern.h"
 | |
| #include "p_font.h"
 | |
| #include "p_image.h"
 | |
| #include "p_layer.h"
 | |
| #include "p_page.h"
 | |
| #include "p_tagged.h"
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| #if (defined(WIN32) || defined(OS2)) && !defined(WINCE)
 | |
| #include <fcntl.h>
 | |
| #include <io.h>
 | |
| #endif
 | |
| 
 | |
| 
 | |
| #define PDF_MAX_LANGCODE  8
 | |
| 
 | |
| /* Document open modes */
 | |
| 
 | |
| typedef enum
 | |
| {
 | |
|     open_auto,
 | |
|     open_none,
 | |
|     open_bookmarks,
 | |
|     open_thumbnails,
 | |
|     open_fullscreen
 | |
| 
 | |
| }
 | |
| pdf_openmode;
 | |
| 
 | |
| static const pdc_keyconn pdf_openmode_keylist[] =
 | |
| {
 | |
|     {"none",        open_none},
 | |
|     {"bookmarks",   open_bookmarks},
 | |
|     {"thumbnails",  open_thumbnails},
 | |
|     {"fullscreen",  open_fullscreen},
 | |
| 
 | |
|     {NULL, 0}
 | |
| };
 | |
| 
 | |
| static const pdc_keyconn pdf_openmode_pdfkeylist[] =
 | |
| {
 | |
|     {"UseNone",     open_auto},
 | |
|     {"UseNone",     open_none},
 | |
|     {"UseOutlines", open_bookmarks},
 | |
|     {"UseThumbs",   open_thumbnails},
 | |
|     {"FullScreen",  open_fullscreen},
 | |
| 
 | |
|     {NULL, 0}
 | |
| };
 | |
| 
 | |
| 
 | |
| /* Document page layout */
 | |
| 
 | |
| typedef enum
 | |
| {
 | |
|     layout_default,
 | |
|     layout_singlepage,
 | |
|     layout_onecolumn,
 | |
|     layout_twocolumnleft,
 | |
|     layout_twocolumnright
 | |
| }
 | |
| pdf_pagelayout;
 | |
| 
 | |
| static const pdc_keyconn pdf_pagelayout_pdfkeylist[] =
 | |
| {
 | |
|     {"Default",        layout_default},
 | |
|     {"SinglePage",     layout_singlepage},
 | |
|     {"OneColumn",      layout_onecolumn},
 | |
|     {"TwoColumnLeft",  layout_twocolumnleft},
 | |
|     {"TwoColumnRight", layout_twocolumnright},
 | |
|     {NULL, 0}
 | |
| };
 | |
| 
 | |
| 
 | |
| /* NonFullScreenPageMode */
 | |
| 
 | |
| static const pdc_keyconn pdf_nonfullscreen_keylist[] =
 | |
| {
 | |
|     {"none",        open_none},
 | |
|     {"bookmarks",   open_bookmarks},
 | |
|     {"thumbnails",  open_thumbnails},
 | |
| 
 | |
|     {NULL, 0}
 | |
| };
 | |
| 
 | |
| /* Direction */
 | |
| 
 | |
| typedef enum
 | |
| {
 | |
|     doc_l2r,
 | |
|     doc_r2l
 | |
| }
 | |
| pdf_textdirection;
 | |
| 
 | |
| static const pdc_keyconn pdf_textdirection_pdfkeylist[] =
 | |
| {
 | |
|     {"L2R",   doc_l2r},
 | |
|     {"R2L",   doc_r2l},
 | |
|     {NULL, 0}
 | |
| };
 | |
| 
 | |
| 
 | |
| /* compatibility */
 | |
| 
 | |
| static const pdc_keyconn pdf_compatibility_keylist[] =
 | |
| {
 | |
|     {"1.3", PDC_1_3},
 | |
|     {"1.4", PDC_1_4},
 | |
|     {"1.5", PDC_1_5},
 | |
|     {"1.6", PDC_1_6},
 | |
|     {NULL, 0}
 | |
| };
 | |
| 
 | |
| 
 | |
| static const pdc_keyconn pdf_pdfx_keylist[] =
 | |
| {
 | |
|     {NULL, 0}
 | |
| };
 | |
| 
 | |
| 
 | |
| /* configurable flush points */
 | |
| 
 | |
| static const pdc_keyconn pdf_flush_keylist[] =
 | |
| {
 | |
|     {"none",    pdf_flush_none},
 | |
|     {"page",    pdf_flush_page},
 | |
|     {"content", pdf_flush_content},
 | |
|     {"heavy",   pdf_flush_heavy},
 | |
|     {NULL, 0}
 | |
| };
 | |
| 
 | |
| static const pdc_keyconn pl_pwencoding_keylist[] =
 | |
| {
 | |
|     {"ebcdic",          pdc_ebcdic},
 | |
|     {"pdfdoc",          pdc_pdfdoc},
 | |
|     {"winansi",         pdc_winansi},
 | |
|     {"macroman",        pdc_macroman_apple},
 | |
|     {NULL, 0}
 | |
| };
 | |
| 
 | |
| #define PDF_MAXPW 0
 | |
| static const pdc_keyconn pdc_permissions_keylist[] =
 | |
| {
 | |
|     {NULL, 0}
 | |
| };
 | |
| 
 | |
| #define PDF_SECURITY_FLAG  PDC_OPT_UNSUPP
 | |
| 
 | |
| #define PDF_LINEARIZE_FLAG  PDC_OPT_UNSUPP
 | |
| 
 | |
| #define PDF_ICC_FLAG  PDC_OPT_UNSUPP
 | |
| 
 | |
| #define PDF_TAGGED_FLAG  PDC_OPT_UNSUPP
 | |
| 
 | |
| #define PDF_METADATA_FLAG  PDC_OPT_UNSUPP
 | |
| 
 | |
| #define PDF_DOCUMENT_OPTIONS1 \
 | |
| \
 | |
|     {"pdfx", pdc_keywordlist, PDF_ICC_FLAG, 1, 1, \
 | |
|       0.0, 0.0, pdf_pdfx_keylist}, \
 | |
| \
 | |
|     {"compatibility", pdc_keywordlist, PDC_OPT_IGNOREIF1, 1, 1, \
 | |
|       0.0, 0.0, pdf_compatibility_keylist}, \
 | |
| \
 | |
|     {"flush", pdc_keywordlist, PDC_OPT_NONE, 1, 1, \
 | |
|       0.0, 0.0, pdf_flush_keylist}, \
 | |
| \
 | |
|     {"passwordencoding", pdc_keywordlist, PDF_SECURITY_FLAG, 1, 1, \
 | |
|       0.0, 0.0, pl_pwencoding_keylist}, \
 | |
| \
 | |
|     {"masterpassword", pdc_stringlist,  PDF_SECURITY_FLAG, 1, 1, \
 | |
|       0.0, PDF_MAXPW, NULL}, \
 | |
| \
 | |
|     {"userpassword", pdc_stringlist,  PDF_SECURITY_FLAG, 1, 1, \
 | |
|       0.0, PDF_MAXPW, NULL}, \
 | |
| \
 | |
|     {"permissions", pdc_keywordlist, \
 | |
|       PDF_SECURITY_FLAG | PDC_OPT_BUILDOR | PDC_OPT_DUPORIGVAL, 1, 9,\
 | |
|       0.0, 0.0, pdc_permissions_keylist}, \
 | |
| \
 | |
|     {"tagged", pdc_booleanlist, PDF_TAGGED_FLAG, 1, 1, \
 | |
|       0.0, 0.0, NULL}, \
 | |
| \
 | |
|     {"lang", pdc_stringlist,  PDF_TAGGED_FLAG, 1, 1, \
 | |
|       0.0, PDF_MAX_LANGCODE, NULL}, \
 | |
| \
 | |
|     {"search", pdc_stringlist,  PDC_OPT_NONE, 1, 1, \
 | |
|       0.0, PDF_MAXSTRINGSIZE, NULL}, \
 | |
| \
 | |
|     {"groups", pdc_stringlist,  PDC_OPT_NONE, 1, PDC_USHRT_MAX, \
 | |
|       0.0, PDF_MAX_NAMESTRING, NULL}, \
 | |
| \
 | |
|     {"linearize", pdc_booleanlist, PDF_LINEARIZE_FLAG, 1, 1, \
 | |
|       0.0, 0.0, NULL}, \
 | |
| \
 | |
|     {"inmemory", pdc_booleanlist, PDF_LINEARIZE_FLAG, 1, 1,\
 | |
|       0.0, 0.0, NULL}, \
 | |
| \
 | |
|     {"tempdirname", pdc_stringlist,  PDF_LINEARIZE_FLAG, 1, 1, \
 | |
|       4.0, 400.0, NULL}, \
 | |
| 
 | |
| 
 | |
| #if defined(MVS) || defined(MVS_TEST)
 | |
| #define PDF_DOCUMENT_OPTIONS10 \
 | |
| \
 | |
|     {"recordsize", pdc_integerlist, PDF_LINEARIZE_FLAG, 1, 1, \
 | |
|       0.0, 32768.0, NULL}, \
 | |
| \
 | |
|     {"tempfilenames", pdc_stringlist,  PDF_LINEARIZE_FLAG, 2, 2, \
 | |
|       4.0, 400.0, NULL}, \
 | |
| 
 | |
| #endif
 | |
| 
 | |
| 
 | |
| #define PDF_DOCUMENT_OPTIONS2 \
 | |
| \
 | |
|     {"hypertextencoding", pdc_stringlist,  PDC_OPT_NONE, 1, 1, \
 | |
|       0.0, PDF_MAX_NAMESTRING, NULL}, \
 | |
| \
 | |
|     {"moddate", pdc_booleanlist, PDC_OPT_NONE, 1, 1,\
 | |
|       0.0, 0.0, NULL}, \
 | |
| \
 | |
|     {"destination", pdc_stringlist, PDC_OPT_NONE, 1, 1, \
 | |
|       0.0, PDF_MAXSTRINGSIZE, NULL}, \
 | |
| \
 | |
|     {"destname", pdc_stringlist, PDC_OPT_IGNOREIF1, 1, 1, \
 | |
|       0.0, PDF_MAXSTRINGSIZE, NULL}, \
 | |
| \
 | |
|     {"action", pdc_stringlist, PDC_OPT_NONE, 1, 1, \
 | |
|       0.0, PDF_MAXSTRINGSIZE, NULL}, \
 | |
| \
 | |
|     {"labels", pdc_stringlist,  PDC_OPT_NONE, 1, PDC_USHRT_MAX, \
 | |
|       0.0, PDC_USHRT_MAX, NULL}, \
 | |
| \
 | |
|     {"openmode", pdc_keywordlist, PDC_OPT_NONE, 1, 1, \
 | |
|       0.0, 0.0, pdf_openmode_keylist}, \
 | |
| \
 | |
|     {"pagelayout", pdc_keywordlist, PDC_OPT_NONE, 1, 1, \
 | |
|       0.0, 0.0, pdf_pagelayout_pdfkeylist}, \
 | |
| \
 | |
|     {"uri", pdc_stringlist, PDC_OPT_NONE, 1, 1, \
 | |
|       0.0, PDF_MAXSTRINGSIZE, NULL}, \
 | |
| \
 | |
|     {"viewerpreferences", pdc_stringlist, PDC_OPT_NONE, 1, 1, \
 | |
|       0.0, PDC_USHRT_MAX, NULL}, \
 | |
| \
 | |
|     {"metadata", pdc_stringlist, PDF_METADATA_FLAG, 1, 1, \
 | |
|       0.0, PDF_MAXSTRINGSIZE, NULL}, \
 | |
| 
 | |
| 
 | |
| /* document struct */
 | |
| 
 | |
| struct pdf_document_s
 | |
| {
 | |
|     int compatibility;               /* PDF version number * 10 */
 | |
|     pdf_flush_state flush;           /* flush points for callback output */
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
|     pdc_bool moddate;                /* modified date will be created */
 | |
|     char lang[PDF_MAX_LANGCODE + 1]; /* default natural language */
 | |
|     char *action;                    /* document actions */
 | |
|     pdf_dest *dest;                  /* destination as open action */
 | |
|     char *uri;                       /* document's base url */
 | |
|     char *viewerpreferences;         /* option list with viewer preferences */
 | |
|     pdc_bool writevpdict;            /* viewer preferences dictionary
 | |
|                                       * must be written */
 | |
|     pdf_openmode openmode;           /* document open mode */
 | |
|     pdf_pagelayout pagelayout;       /* page layout within document */
 | |
| 
 | |
|     char *searchindexname;           /* file name for search index */
 | |
|     char *searchindextype;           /* type for search index */
 | |
| 
 | |
| 
 | |
| 
 | |
|     char *filename;                  /* file name of document */
 | |
|     size_t (*writeproc)(PDF *p, void *data, size_t size);
 | |
|                                      /* output procedure */
 | |
|     FILE *fp;                        /* file id - deprecated */
 | |
|     int len;                         /* length of custom */
 | |
| };
 | |
| 
 | |
| static pdf_document *
 | |
| pdf_init_get_document(PDF *p)
 | |
| {
 | |
|     static const char fn[] = "pdf_init_get_document";
 | |
| 
 | |
|     if (p->document == NULL)
 | |
|     {
 | |
|         pdf_document *doc = (pdf_document *)
 | |
|                                 pdc_malloc(p->pdc, sizeof(pdf_document), fn);
 | |
| 
 | |
|         doc->compatibility = PDC_1_5;
 | |
|         doc->flush = pdf_flush_page;
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
|         doc->moddate = pdc_false;
 | |
|         doc->lang[0] = 0;
 | |
|         doc->action = NULL;
 | |
|         doc->dest = NULL;
 | |
|         doc->uri = NULL;
 | |
|         doc->viewerpreferences = NULL;
 | |
|         doc->writevpdict = pdc_false;
 | |
|         doc->openmode = open_auto;
 | |
|         doc->pagelayout = layout_default;
 | |
| 
 | |
|         doc->searchindexname = NULL;
 | |
|         doc->searchindextype = NULL;
 | |
| 
 | |
| 
 | |
| 
 | |
|         doc->fp = NULL;
 | |
|         doc->filename = NULL;
 | |
|         doc->writeproc = NULL;
 | |
|         doc->len = 0;
 | |
| 
 | |
|         p->document = doc;
 | |
|     }
 | |
| 
 | |
|     return p->document;
 | |
| }
 | |
| 
 | |
| static void
 | |
| pdf_cleanup_document_internal(PDF *p)
 | |
| {
 | |
|     pdf_document *doc = (pdf_document *) p->document;
 | |
| 
 | |
|     if (doc)
 | |
|     {
 | |
|         pdf_cleanup_destination(p, doc->dest);
 | |
|         doc->dest = NULL;
 | |
| 
 | |
|         if (doc->action)
 | |
|         {
 | |
|             pdc_free(p->pdc, doc->action);
 | |
|             doc->action = NULL;
 | |
|         }
 | |
| 
 | |
|         if (doc->uri)
 | |
|         {
 | |
|             pdc_free(p->pdc, doc->uri);
 | |
|             doc->uri = NULL;
 | |
|         }
 | |
| 
 | |
|         if (doc->viewerpreferences)
 | |
|         {
 | |
|             pdc_free(p->pdc, doc->viewerpreferences);
 | |
|             doc->viewerpreferences = NULL;
 | |
|         }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
|         if (doc->searchindexname)
 | |
|         {
 | |
|             pdc_free(p->pdc, doc->searchindexname);
 | |
|             doc->searchindexname = NULL;
 | |
|         }
 | |
| 
 | |
|         if (doc->searchindextype)
 | |
|         {
 | |
|             pdc_free(p->pdc, doc->searchindextype);
 | |
|             doc->searchindextype = NULL;
 | |
|         }
 | |
| 
 | |
|         if (doc->filename)
 | |
|         {
 | |
|             pdc_free(p->pdc, doc->filename);
 | |
|             doc->filename = NULL;
 | |
|         }
 | |
| 
 | |
|         pdc_free(p->pdc, doc);
 | |
|         p->document = NULL;
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| void
 | |
| pdf_fix_openmode(PDF *p)
 | |
| {
 | |
|     pdf_document *doc = pdf_init_get_document(p);
 | |
| 
 | |
|     if (doc->openmode == open_auto)
 | |
|         doc->openmode = open_bookmarks;
 | |
| }
 | |
| 
 | |
| 
 | |
| static const pdc_defopt pdf_viewerpreferences_options[] =
 | |
| {
 | |
|     {"centerwindow", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
 | |
|       0.0, 0, NULL},
 | |
| 
 | |
|     {"direction", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
 | |
|       0.0, 0.0, pdf_textdirection_pdfkeylist},
 | |
| 
 | |
|     {"displaydoctitle", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
 | |
|       0.0, 0, NULL},
 | |
| 
 | |
|     {"fitwindow", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
 | |
|       0.0, 0, NULL},
 | |
| 
 | |
|     {"hidemenubar", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
 | |
|       0.0, 0, NULL},
 | |
| 
 | |
|     {"hidetoolbar", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
 | |
|       0.0, 0, NULL},
 | |
| 
 | |
|     {"hidewindowui", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
 | |
|       0.0, 0, NULL},
 | |
| 
 | |
|     {"nonfullscreenpagemode", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
 | |
|       0.0, 0.0, pdf_nonfullscreen_keylist},
 | |
| 
 | |
|     {"viewarea", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
 | |
|       0.0, 0.0, pdf_usebox_keylist},
 | |
| 
 | |
|     {"viewclip", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
 | |
|       0.0, 0.0, pdf_usebox_keylist},
 | |
| 
 | |
|     {"printarea", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
 | |
|       0.0, 0.0, pdf_usebox_keylist},
 | |
| 
 | |
|     {"printclip", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
 | |
|       0.0, 0.0, pdf_usebox_keylist},
 | |
| 
 | |
|     PDC_OPT_TERMINATE
 | |
| };
 | |
| 
 | |
| static int
 | |
| pdf_parse_and_write_viewerpreferences(PDF *p, const char *optlist,
 | |
|                                       pdc_bool output)
 | |
| {
 | |
|     pdc_resopt *resopts = NULL;
 | |
|     pdc_bool writevpdict = pdc_false;
 | |
|     pdc_bool flag;
 | |
|     int inum;
 | |
| 
 | |
|     /* parsing option list */
 | |
|     resopts = pdc_parse_optionlist(p->pdc, optlist,
 | |
|                   pdf_viewerpreferences_options, NULL, pdc_true);
 | |
| 
 | |
| 
 | |
|     if (pdc_get_optvalues("hidetoolbar", resopts, &flag, NULL) && flag)
 | |
|     {
 | |
|         writevpdict = pdc_true;
 | |
|         if (output) pdc_printf(p->out, "/HideToolbar true\n");
 | |
|     }
 | |
| 
 | |
|     if (pdc_get_optvalues("hidemenubar", resopts, &flag, NULL) && flag)
 | |
|     {
 | |
|         writevpdict = pdc_true;
 | |
|         if (output) pdc_printf(p->out, "/HideMenubar true\n");
 | |
|     }
 | |
| 
 | |
|     if (pdc_get_optvalues("hidewindowui", resopts, &flag, NULL) && flag)
 | |
|     {
 | |
|         writevpdict = pdc_true;
 | |
|         if (output) pdc_printf(p->out, "/HideWindowUI true\n");
 | |
|     }
 | |
| 
 | |
|     if (pdc_get_optvalues("fitwindow", resopts, &flag, NULL) && flag)
 | |
|     {
 | |
|         writevpdict = pdc_true;
 | |
|         if (output) pdc_printf(p->out, "/FitWindow true\n");
 | |
|     }
 | |
| 
 | |
|     if (pdc_get_optvalues("centerwindow", resopts, &flag, NULL) && flag)
 | |
|     {
 | |
|         writevpdict = pdc_true;
 | |
|         if (output) pdc_printf(p->out, "/CenterWindow true\n");
 | |
|     }
 | |
| 
 | |
|     if (pdc_get_optvalues("displaydoctitle", resopts, &flag, NULL) && flag)
 | |
|     {
 | |
|         writevpdict = pdc_true;
 | |
|         if (output) pdc_printf(p->out, "/DisplayDocTitle true\n");
 | |
|     }
 | |
| 
 | |
|     if (pdc_get_optvalues("nonfullscreenpagemode", resopts, &inum, NULL) &&
 | |
|         inum != (int) open_none)
 | |
|     {
 | |
|         writevpdict = pdc_true;
 | |
|         if (output) pdc_printf(p->out, "/NonFullScreenPageMode/%s\n",
 | |
|                    pdc_get_keyword(inum, pdf_openmode_pdfkeylist));
 | |
|     }
 | |
| 
 | |
| 
 | |
|     if (pdc_get_optvalues("direction", resopts, &inum, NULL) &&
 | |
|         inum != (int) doc_l2r)
 | |
|     {
 | |
|         writevpdict = pdc_true;
 | |
|         if (output) pdc_printf(p->out, "/Direction/%s\n",
 | |
|                    pdc_get_keyword(inum, pdf_textdirection_pdfkeylist));
 | |
|     }
 | |
| 
 | |
|     if (pdc_get_optvalues("viewarea", resopts, &inum, NULL) &&
 | |
|         inum != (int) use_crop)
 | |
|     {
 | |
|         writevpdict = pdc_true;
 | |
|         if (output) pdc_printf(p->out, "/ViewArea%s\n",
 | |
|                    pdc_get_keyword(inum, pdf_usebox_pdfkeylist));
 | |
|     }
 | |
| 
 | |
|     if (pdc_get_optvalues("viewclip", resopts, &inum, NULL) &&
 | |
|         inum != (int) use_crop)
 | |
|     {
 | |
|         writevpdict = pdc_true;
 | |
|         if (output) pdc_printf(p->out, "/ViewClip%s\n",
 | |
|                    pdc_get_keyword(inum, pdf_usebox_pdfkeylist));
 | |
|     }
 | |
| 
 | |
|     if (pdc_get_optvalues("printarea", resopts, &inum, NULL) &&
 | |
|         inum != (int) use_crop)
 | |
|     {
 | |
|         writevpdict = pdc_true;
 | |
|         if (output) pdc_printf(p->out, "/PrintArea%s\n",
 | |
|                    pdc_get_keyword(inum, pdf_usebox_pdfkeylist));
 | |
|     }
 | |
| 
 | |
|     if (pdc_get_optvalues("printclip", resopts, &inum, NULL) &&
 | |
|         inum != (int) use_crop)
 | |
|     {
 | |
|         writevpdict = pdc_true;
 | |
|         if (output) pdc_printf(p->out, "/PrintClip%s\n",
 | |
|                    pdc_get_keyword(inum, pdf_usebox_pdfkeylist));
 | |
|     }
 | |
| 
 | |
|     pdc_cleanup_optionlist(p->pdc, resopts);
 | |
| 
 | |
|     return writevpdict;
 | |
| }
 | |
| 
 | |
| static const pdc_defopt pdf_search_options[] =
 | |
| {
 | |
|     {"filename", pdc_stringlist, PDC_OPT_REQUIRED, 1, 1,
 | |
|       1.0, PDF_FILENAMELEN, NULL},
 | |
| 
 | |
|     {"indextype", pdc_stringlist, PDC_OPT_NONE, 1, 1,
 | |
|       0.0, PDF_MAX_NAMESTRING, NULL},
 | |
| 
 | |
|     PDC_OPT_TERMINATE
 | |
| };
 | |
| 
 | |
| static void
 | |
| pdf_parse_search_optlist(PDF *p, const char *optlist)
 | |
| {
 | |
|     pdf_document *doc = p->document;
 | |
|     pdc_resopt *resopts = NULL;
 | |
| 
 | |
|     /* parsing option list */
 | |
|     resopts = pdc_parse_optionlist(p->pdc, optlist,
 | |
|                               pdf_search_options, NULL, pdc_true);
 | |
| 
 | |
|     if (pdc_get_optvalues("filename", resopts, NULL, NULL))
 | |
|         doc->searchindexname =
 | |
|             (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
 | |
| 
 | |
|     if (pdc_get_optvalues("indextype", resopts, NULL, NULL))
 | |
|         doc->searchindextype =
 | |
|             (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
 | |
|     else
 | |
|         doc->searchindextype = pdc_strdup(p->pdc, "PDX");
 | |
| 
 | |
|     pdc_cleanup_optionlist(p->pdc, resopts);
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| static void
 | |
| pdf_get_document_common_options(PDF *p, pdc_resopt *resopts, int fcode)
 | |
| {
 | |
|     pdf_document *doc = p->document;
 | |
|     pdc_encoding hypertextencoding;
 | |
|     int codepage;
 | |
|     char **strlist;
 | |
|     int i, inum;
 | |
| 
 | |
|     pdc_get_optvalues("moddate", resopts, &doc->moddate, NULL);
 | |
| 
 | |
|     hypertextencoding =
 | |
|         pdf_get_hypertextencoding_opt(p, resopts, &codepage, pdc_true);
 | |
| 
 | |
|     if (pdc_get_optvalues("destination", resopts, NULL, &strlist))
 | |
|     {
 | |
|         if (doc->dest)
 | |
|             pdc_free(p->pdc, doc->dest);
 | |
|         doc->dest = pdf_parse_destination_optlist(p, strlist[0], 1,
 | |
|                                                   pdf_openaction, pdc_true);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         pdf_dest *dest = pdf_get_option_destname(p, resopts, hypertextencoding);
 | |
|         if (dest)
 | |
|         {
 | |
|             if (doc->dest)
 | |
|                 pdc_free(p->pdc, doc->dest);
 | |
|             doc->dest = dest;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (pdc_get_optvalues("action", resopts, NULL, NULL))
 | |
|     {
 | |
|         if (doc->action)
 | |
|             pdc_free(p->pdc, doc->action);
 | |
|         doc->action = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
 | |
|         pdf_parse_and_write_actionlist(p, event_document, NULL, doc->action);
 | |
|     }
 | |
| 
 | |
|     inum = pdc_get_optvalues("labels", resopts, NULL, &strlist);
 | |
|     for (i = 0; i < inum; i++)
 | |
| 	pdf_set_pagelabel(p, strlist[i], fcode);
 | |
| 
 | |
|     if (pdc_get_optvalues("openmode", resopts, &inum, NULL))
 | |
|         doc->openmode = (pdf_openmode) inum;
 | |
| 
 | |
| 
 | |
|     if (pdc_get_optvalues("pagelayout", resopts, &inum, NULL))
 | |
|         doc->pagelayout = (pdf_pagelayout) inum;
 | |
| 
 | |
|     if (pdc_get_optvalues("uri", resopts, NULL, NULL))
 | |
|     {
 | |
|         if (doc->uri)
 | |
|             pdc_free(p->pdc, doc->uri);
 | |
|         doc->uri = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
 | |
|     }
 | |
| 
 | |
|     if (pdc_get_optvalues("viewerpreferences", resopts, NULL, NULL))
 | |
|     {
 | |
|         if (doc->viewerpreferences)
 | |
|             pdc_free(p->pdc, doc->viewerpreferences);
 | |
|         doc->viewerpreferences =
 | |
|             (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
 | |
|         doc->writevpdict |=
 | |
|             pdf_parse_and_write_viewerpreferences(p, doc->viewerpreferences,
 | |
|                                                   pdc_false);
 | |
|     }
 | |
| 
 | |
|     if (pdc_get_optvalues("search", resopts, NULL, &strlist))
 | |
|         pdf_parse_search_optlist(p, strlist[0]);
 | |
| 
 | |
| }
 | |
| 
 | |
| static const pdc_defopt pdf_begin_document_options[] =
 | |
| {
 | |
|     PDF_DOCUMENT_OPTIONS1
 | |
| #if defined(MVS) || defined(MVS_TEST)
 | |
|     PDF_DOCUMENT_OPTIONS10
 | |
| #endif
 | |
|     PDF_DOCUMENT_OPTIONS2
 | |
|     PDC_OPT_TERMINATE
 | |
| };
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * The external callback interface requires a PDF* as the first argument,
 | |
|  * while the internal interface uses pdc_output* and doesn't know about PDF*.
 | |
|  * We use a wrapper to bridge the gap, and store the PDF* within the
 | |
|  * pdc_output structure opaquely.
 | |
|  */
 | |
| 
 | |
| static size_t
 | |
| writeproc_wrapper(pdc_output *out, void *data, size_t size)
 | |
| {
 | |
|     size_t ret;
 | |
| 
 | |
|     PDF *p = (PDF *) pdc_get_opaque(out);
 | |
| 
 | |
|     ret = (p->writeproc)(p, data, size);
 | |
|     pdc_trace_protocol(p->pdc, 1, trc_api,
 | |
|                        "/* writeproc(data[%p], %d)[%d] */\n", data, size, ret);
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| 
 | |
| /* ---------------------------- begin document -------------------------- */
 | |
| 
 | |
| static int
 | |
| pdf_begin_document_internal(PDF *p, const char *optlist, pdc_bool callback)
 | |
| {
 | |
|     pdf_document *doc = p->document;
 | |
|     pdc_resopt *resopts = NULL;
 | |
|     char **groups = NULL;
 | |
|     int n_groups = 0;
 | |
|     pdc_outctl oc;
 | |
| 
 | |
|     /* parsing option list */
 | |
|     if (optlist && *optlist)
 | |
|     {
 | |
|         int inum;
 | |
|         resopts = pdc_parse_optionlist(p->pdc, optlist,
 | |
|                                    pdf_begin_document_options, NULL, pdc_true);
 | |
| 
 | |
|         pdc_get_optvalues("compatibility", resopts, &doc->compatibility, NULL);
 | |
| 
 | |
|         if (pdc_get_optvalues("flush", resopts, &inum, NULL))
 | |
|             doc->flush = (pdf_flush_state) inum;
 | |
| 
 | |
|         pdc_get_optvalues("lang", resopts, doc->lang, NULL);
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 	n_groups = pdc_get_optvalues("groups", resopts, NULL, &groups);
 | |
|     }
 | |
| 
 | |
|     /* copy for easy access */
 | |
|     p->compatibility = doc->compatibility;
 | |
|     p->flush = doc->flush;
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
|     /*
 | |
|      * None of these functions must call pdc_alloc_id() or generate
 | |
|      * any output since the output machinery is not yet initialized!
 | |
|      */
 | |
| 
 | |
|     pdf_init_pages(p, (const char **) groups, n_groups);
 | |
| 
 | |
|     /* common options */
 | |
|     pdf_get_document_common_options(p, resopts, PDF_FC_BEGIN_DOCUMENT);
 | |
| 
 | |
|     /* deprecated */
 | |
|     p->bookmark_dest = pdf_init_destination(p);
 | |
| 
 | |
|     pdf_init_images(p);
 | |
|     pdf_init_xobjects(p);
 | |
|     pdf_init_fonts(p);
 | |
|     pdf_init_outlines(p);
 | |
|     pdf_init_annot_params(p);
 | |
|     pdf_init_colorspaces(p);
 | |
|     pdf_init_pattern(p);
 | |
|     pdf_init_shadings(p);
 | |
|     pdf_init_extgstates(p);
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
|     /* create document digest */
 | |
|     pdc_init_digest(p->out);
 | |
| 
 | |
|     if (doc->fp)
 | |
|         pdc_update_digest(p->out, (pdc_byte *) doc->fp, doc->len);
 | |
|     else if (doc->writeproc)
 | |
|         pdc_update_digest(p->out, (pdc_byte *) &doc->writeproc, doc->len);
 | |
|     else if (doc->filename && !p->ptfrun)
 | |
|         pdc_update_digest(p->out, (pdc_byte *) doc->filename, doc->len);
 | |
|     pdf_feed_digest_info(p);
 | |
| 
 | |
|     if (!p->ptfrun)
 | |
|     {
 | |
|         pdc_update_digest(p->out, (pdc_byte *) &p, sizeof(PDF*));
 | |
|         pdc_update_digest(p->out, (pdc_byte *) p, sizeof(PDF));
 | |
|     }
 | |
| 
 | |
| 
 | |
|     pdc_finish_digest(p->out, !p->ptfrun);
 | |
| 
 | |
|     /* preparing output struct */
 | |
|     pdc_init_outctl(&oc);
 | |
|     if (doc->fp)
 | |
|         oc.fp = doc->fp;
 | |
|     else if (doc->writeproc)
 | |
|     {
 | |
|         oc.writeproc = writeproc_wrapper;
 | |
|         p->writeproc = doc->writeproc;
 | |
|     }
 | |
|     else if (doc->filename)
 | |
|         oc.filename = doc->filename;
 | |
|     else
 | |
|         oc.filename = "";
 | |
| 
 | |
| 
 | |
| 
 | |
|     if (!pdc_init_output((void *) p, p->out, doc->compatibility, &oc))
 | |
|     {
 | |
|         if (oc.filename && *oc.filename)
 | |
|         {
 | |
|             pdc_set_fopen_errmsg(p->pdc,
 | |
|                 pdc_get_fopen_errnum(p->pdc, PDC_E_IO_WROPEN), "PDF ",
 | |
|                 pdc_errprintf(p->pdc, "%.*s", PDC_ET_MAXSTRLEN, oc.filename));
 | |
| 
 | |
|             if (p->debug[(int) 'o'])
 | |
|                 pdc_warning(p->pdc, -1, 0, 0, 0, 0);
 | |
|         }
 | |
|         return -1;
 | |
|     }
 | |
| 
 | |
|     /* Write the constant /ProcSet array once at the beginning */
 | |
|     p->procset_id = pdc_begin_obj(p->out, PDC_NEW_ID);
 | |
|     pdc_puts(p->out, "[/PDF/ImageB/ImageC/ImageI/Text]\n");
 | |
|     pdc_end_obj(p->out);
 | |
| 
 | |
|     pdf_init_pages2(p);
 | |
| 
 | |
|     return 1;
 | |
| }
 | |
| 
 | |
| #if defined(_MSC_VER) && defined(_MANAGED)
 | |
| #pragma unmanaged
 | |
| #endif
 | |
| int
 | |
| pdf__begin_document(PDF *p, const char *filename, int len, const char *optlist)
 | |
| {
 | |
|     pdf_document *doc;
 | |
|     int retval;
 | |
| 
 | |
| 
 | |
|     doc = pdf_init_get_document(p);
 | |
| 
 | |
|     /* file ID or filename */
 | |
|     if (len == -1)
 | |
|     {
 | |
|         FILE *fp = (FILE *) filename;
 | |
| 
 | |
|         /*
 | |
|          * It is the callers responsibility to open the file in binary mode,
 | |
|          * but it doesn't hurt to make sure it really is.
 | |
|          * The Intel version of the Metrowerks compiler doesn't have setmode().
 | |
|          */
 | |
| #if !defined(__MWERKS__) && (defined(WIN32) || defined(OS2))
 | |
| #if defined WINCE
 | |
|         _setmode(fileno(fp), _O_BINARY);
 | |
| #else
 | |
|         setmode(fileno(fp), O_BINARY);
 | |
| #endif
 | |
| #endif
 | |
| 
 | |
|         doc->fp = fp;
 | |
|         doc->len = sizeof(FILE);
 | |
|     }
 | |
|     else if (filename && (*filename || len > 0))
 | |
|     {
 | |
|         filename = pdf_convert_filename(p, filename, len, "filename", pdc_true);
 | |
|         doc->filename = pdc_strdup(p->pdc, filename);
 | |
|         doc->len = (int) strlen(doc->filename);
 | |
|     }
 | |
| 
 | |
|     retval = pdf_begin_document_internal(p, optlist, pdc_false);
 | |
| 
 | |
|     if (retval > -1)
 | |
|         PDF_SET_STATE(p, pdf_state_document);
 | |
| 
 | |
|     return retval;
 | |
| }
 | |
| #if defined(_MSC_VER) && defined(_MANAGED)
 | |
| #pragma managed
 | |
| #endif
 | |
| 
 | |
| void
 | |
| pdf__begin_document_callback(PDF *p,
 | |
|     size_t (*i_writeproc)(PDF *p, void *data, size_t size), const char *optlist)
 | |
| {
 | |
|     size_t (*writeproc)(PDF *, void *, size_t) = i_writeproc;
 | |
|     pdf_document *doc;
 | |
| 
 | |
|     if (writeproc == NULL)
 | |
|         pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "writeproc", 0, 0, 0);
 | |
| 
 | |
|     doc = pdf_init_get_document(p);
 | |
| 
 | |
|     /* initializing and opening the document */
 | |
|     doc->writeproc = writeproc;
 | |
|     doc->len = sizeof(writeproc);
 | |
| 
 | |
|     (void) pdf_begin_document_internal(p, optlist, pdc_true);
 | |
| 
 | |
|     PDF_SET_STATE(p, pdf_state_document);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* -----------------------------  name tree  ----------------------------- */
 | |
| 
 | |
| struct pdf_name_s
 | |
| {
 | |
|     pdc_id              obj_id;         /* id of this name object */
 | |
|     char *              name;           /* name string */
 | |
|     pdf_nametree_type   type;           /* name tree type */
 | |
| };
 | |
| 
 | |
| static void
 | |
| pdf_cleanup_names(PDF *p)
 | |
| {
 | |
|     int i;
 | |
| 
 | |
|     if (p->names == NULL)
 | |
|         return;
 | |
| 
 | |
|     for (i = 0; i < p->names_number; i++)
 | |
|     {
 | |
|         pdc_free(p->pdc, p->names[i].name);
 | |
|     }
 | |
| 
 | |
|     pdc_free(p->pdc, p->names);
 | |
|     p->names_number = 0;
 | |
|     p->names = NULL;
 | |
| }
 | |
| 
 | |
| void
 | |
| pdf_insert_name(PDF *p, const char *name, pdf_nametree_type type, pdc_id obj_id)
 | |
| {
 | |
|     static const char fn[] = "pdf_insert_name";
 | |
|     int i;
 | |
| 
 | |
|     if (p->names == NULL || p->names_number == p->names_capacity)
 | |
|     {
 | |
|         if (p->names == NULL)
 | |
|         {
 | |
|             p->names_number = 0;
 | |
|             p->names_capacity = NAMES_CHUNKSIZE;
 | |
|             p->names = (pdf_name *) pdc_malloc(p->pdc,
 | |
|                 sizeof(pdf_name) * p->names_capacity, fn);
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             p->names_capacity *= 2;
 | |
|             p->names = (pdf_name *) pdc_realloc(p->pdc, p->names,
 | |
|                 sizeof(pdf_name) * p->names_capacity, fn);
 | |
|         }
 | |
|         for (i = p->names_number; i < p->names_capacity; i++)
 | |
|         {
 | |
|             p->names[i].obj_id = PDC_BAD_ID;
 | |
|             p->names[i].name = NULL;
 | |
|             p->names[i].type = names_undef;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /* check identity */
 | |
|     for (i = 0; i < p->names_number; i++)
 | |
|     {
 | |
|         if (p->names[i].type == type && !strcmp(p->names[i].name, name))
 | |
|         {
 | |
|             pdc_free(p->pdc, p->names[i].name);
 | |
|             p->names[i].name = (char *) name;
 | |
|             return;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     p->names[i].obj_id = obj_id;
 | |
|     p->names[i].name = (char *) name;
 | |
|     p->names[i].type = type;
 | |
|     p->names_number++;
 | |
| }
 | |
| 
 | |
| static pdc_id
 | |
| pdf_write_names(PDF *p, pdf_nametree_type type)
 | |
| {
 | |
|     pdc_id ret = PDC_BAD_ID;
 | |
|     int i, ibeg = -1, iend = 0;
 | |
| 
 | |
|     for (i = 0; i < p->names_number; i++)
 | |
|     {
 | |
|         if (p->names[i].type == type)
 | |
|         {
 | |
|             if (ibeg == -1)
 | |
|                 ibeg = i;
 | |
|             iend = i;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (ibeg > -1)
 | |
|     {
 | |
|         ret = pdc_begin_obj(p->out, PDC_NEW_ID);    /* Names object */
 | |
| 
 | |
|         pdc_begin_dict(p->out);                     /* Node dict */
 | |
| 
 | |
|         pdc_puts(p->out, "/Limits");
 | |
|         pdc_begin_array(p->out);
 | |
|         pdf_put_hypertext(p, p->names[ibeg].name);
 | |
|         pdf_put_hypertext(p, p->names[iend].name);
 | |
|         pdc_end_array(p->out);
 | |
| 
 | |
|         pdc_puts(p->out, "/Names");
 | |
|         pdc_begin_array(p->out);
 | |
| 
 | |
|         for (i = ibeg; i <= iend; i++)
 | |
|         {
 | |
|             if (p->names[i].type == type)
 | |
|             {
 | |
|                 pdf_put_hypertext(p, p->names[i].name);
 | |
|                 pdc_objref(p->out, "", p->names[i].obj_id);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         pdc_end_array(p->out);
 | |
| 
 | |
|         pdc_end_dict(p->out);                       /* Node dict */
 | |
| 
 | |
|         pdc_end_obj(p->out);                        /* Names object */
 | |
| 
 | |
|     }
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| static int
 | |
| name_compare( const void*  a, const void*  b)
 | |
| {
 | |
|     pdf_name *p1 = (pdf_name *) a;
 | |
|     pdf_name *p2 = (pdf_name *) b;
 | |
| 
 | |
|     return strcmp(p1->name, p2->name);
 | |
| }
 | |
| 
 | |
| /* ---------------------------- write document -------------------------- */
 | |
| 
 | |
| static pdc_id
 | |
| pdf_write_pages_and_catalog(PDF *p)
 | |
| {
 | |
|     pdf_document *doc = p->document;
 | |
|     pdc_bool openact = pdc_false;
 | |
|     pdc_id act_idlist[PDF_MAX_EVENTS];
 | |
|     pdc_id root_id = PDC_BAD_ID;
 | |
|     pdc_id names_dests_id = PDC_BAD_ID;
 | |
|     pdc_id names_javascript_id = PDC_BAD_ID;
 | |
|     pdc_id names_ap_id = PDC_BAD_ID;
 | |
| 
 | |
|     pdc_id pages_id = pdf_write_pages_tree(p);
 | |
|     pdc_id labels_id = pdf_write_pagelabels(p);
 | |
| 
 | |
| 
 | |
| 
 | |
|     /* name tree dictionaries */
 | |
|     if (p->names_number)
 | |
|     {
 | |
| 
 | |
|         qsort(p->names, (size_t) p->names_number, sizeof(pdf_name),
 | |
|               name_compare);
 | |
| 
 | |
| 
 | |
|         names_dests_id = pdf_write_names(p, names_dests);
 | |
|         names_javascript_id = pdf_write_names(p, names_javascript);
 | |
|         names_ap_id = pdf_write_names(p, names_ap);
 | |
|     }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
|     /* write action objects */
 | |
|     if (doc->action)
 | |
|         pdf_parse_and_write_actionlist(p, event_document, act_idlist,
 | |
|                                        (const char *) doc->action);
 | |
| 
 | |
|     root_id = pdc_begin_obj(p->out, PDC_NEW_ID);        /* Catalog object */
 | |
| 
 | |
|     pdc_begin_dict(p->out);
 | |
|     pdc_puts(p->out, "/Type/Catalog\n");
 | |
| 
 | |
|     pdc_objref(p->out, "/Pages", pages_id);		/* Pages object */
 | |
| 
 | |
|     if (labels_id != PDC_BAD_ID)
 | |
|     {
 | |
|         pdc_objref(p->out, "/PageLabels", labels_id);
 | |
|     }
 | |
| 
 | |
|     if (p->names_number)
 | |
|     {
 | |
|         pdc_printf(p->out, "/Names");
 | |
|         pdc_begin_dict(p->out);                         /* Names */
 | |
| 
 | |
|         if (names_dests_id != PDC_BAD_ID)
 | |
|             pdc_objref(p->out, "/Dests", names_dests_id);
 | |
|         if (names_javascript_id != PDC_BAD_ID)
 | |
|             pdc_objref(p->out, "/JavaScript", names_javascript_id);
 | |
|         if (names_ap_id != PDC_BAD_ID)
 | |
|             pdc_objref(p->out, "/AP", names_ap_id);
 | |
| 
 | |
|         pdc_end_dict(p->out);                           /* Names */
 | |
|     }
 | |
| 
 | |
|     if (doc->writevpdict)
 | |
|     {
 | |
|         pdc_printf(p->out, "/ViewerPreferences\n");
 | |
|         pdc_begin_dict(p->out);                         /* ViewerPreferences */
 | |
|         pdf_parse_and_write_viewerpreferences(p,
 | |
|                        doc->viewerpreferences, pdc_true);
 | |
|         pdc_end_dict(p->out);                           /* ViewerPreferences */
 | |
|     }
 | |
| 
 | |
|     if (doc->pagelayout != layout_default)
 | |
|         pdc_printf(p->out, "/PageLayout/%s\n",
 | |
|                 pdc_get_keyword(doc->pagelayout, pdf_pagelayout_pdfkeylist));
 | |
| 
 | |
|     if (doc->openmode != open_auto && doc->openmode != open_none)
 | |
|         pdc_printf(p->out, "/PageMode/%s\n",
 | |
|                 pdc_get_keyword(doc->openmode, pdf_openmode_pdfkeylist));
 | |
| 
 | |
|     pdf_write_outline_root(p);  /* /Outlines */
 | |
| 
 | |
|     if (doc->action)  /* /AA */
 | |
|         openact = pdf_write_action_entries(p, event_document, act_idlist);
 | |
| 
 | |
|     if (doc->dest && !openact)
 | |
|     {
 | |
|         pdc_puts(p->out, "/OpenAction");
 | |
|         pdf_write_destination(p, doc->dest);
 | |
|     }
 | |
| 
 | |
|     if (doc->uri)
 | |
|     {
 | |
|         pdc_puts(p->out, "/URI");
 | |
|         pdc_begin_dict(p->out);
 | |
|         pdc_printf(p->out, "/Base");
 | |
|         pdf_put_hypertext(p, doc->uri);
 | |
|         pdc_end_dict(p->out);
 | |
|     }
 | |
| 
 | |
| 
 | |
|     if (doc->lang[0])
 | |
|     {
 | |
|         pdc_puts(p->out, "/Lang");
 | |
|         pdf_put_hypertext(p, doc->lang);
 | |
|         pdc_puts(p->out, "\n");
 | |
|     }
 | |
| 
 | |
|     /* /StructTreeRoot /MarkInfo */
 | |
| 
 | |
|     /* /OCProperties */
 | |
| 
 | |
| 
 | |
|     /* /Search */
 | |
|     if (doc->searchindexname != NULL)
 | |
|     {
 | |
|         pdc_puts(p->out, "/Search");
 | |
|         pdc_begin_dict(p->out);                         /* Search */
 | |
|         pdc_puts(p->out, "/Indexes");
 | |
|         pdc_begin_array(p->out);
 | |
|         pdc_begin_dict(p->out);                         /* Indexes */
 | |
|         pdc_puts(p->out, "/Name");
 | |
|         pdc_printf(p->out, "/%s", doc->searchindextype);
 | |
|         pdc_puts(p->out, "/Index");
 | |
|         pdc_begin_dict(p->out);                         /* Index */
 | |
|         pdc_puts(p->out, "/Type/Filespec");
 | |
|         pdc_puts(p->out, "/F");
 | |
|         pdf_put_pdffilename(p, doc->searchindexname);
 | |
|         pdc_end_dict(p->out);                           /* Index */
 | |
|         pdc_end_dict(p->out);                           /* Indexes */
 | |
|         pdc_end_array(p->out);
 | |
|         pdc_end_dict(p->out);                           /* Search */
 | |
|     }
 | |
| 
 | |
| 
 | |
|     /* not supported: /Threads /PieceInfo /Perms /Legal */
 | |
| 
 | |
|     pdc_end_dict(p->out);                               /* Catalog */
 | |
|     pdc_end_obj(p->out);
 | |
| 
 | |
|     return root_id;
 | |
| }
 | |
| 
 | |
| static void
 | |
| pdf_write_document(PDF *p)
 | |
| {
 | |
|     if (PDF_GET_STATE(p) != pdf_state_error)
 | |
|     {
 | |
|         pdf_document *doc = p->document;
 | |
|         pdc_id info_id;
 | |
|         pdc_id root_id;
 | |
| 
 | |
|         if (pdf_last_page(p) == 0)
 | |
|             pdc_error(p->pdc, PDF_E_DOC_EMPTY, 0, 0, 0, 0);
 | |
| 
 | |
| 
 | |
|         /* Write all pending document information up to xref table + trailer */
 | |
|         info_id = pdf_write_info(p, doc->moddate);
 | |
|         pdf_write_doc_fonts(p);                 /* font objects */
 | |
|         pdf_write_doc_colorspaces(p);           /* color space resources */
 | |
|         pdf_write_doc_extgstates(p);            /* ExtGState resources */
 | |
|         root_id = pdf_write_pages_and_catalog(p);
 | |
|         pdf_write_outlines(p);
 | |
|         pdc_write_xref(p->out);
 | |
|         pdc_write_trailer(p->out, info_id, root_id, 0, -1, -1, -1);
 | |
|     }
 | |
| 
 | |
|     pdc_close_output(p->out);
 | |
| }
 | |
| 
 | |
| /* ------------------------------ end document ---------------------------- */
 | |
| 
 | |
| void
 | |
| pdf_cleanup_document(PDF *p)
 | |
| {
 | |
|     if (PDF_GET_STATE(p) != pdf_state_object)
 | |
|     {
 | |
|         /* Don't call pdc_cleanup_output() here because we may still need
 | |
|          * the buffer contents for pdf__get_buffer() after pdf__end_document().
 | |
|          */
 | |
| 
 | |
|         pdf_cleanup_actions(p);
 | |
|         pdf_cleanup_destination(p, p->bookmark_dest); /* deprecated */
 | |
|         pdf_cleanup_pages(p);
 | |
|         pdf_cleanup_document_internal(p);
 | |
|         pdf_cleanup_info(p);
 | |
|         pdf_cleanup_fonts(p);
 | |
|         pdf_cleanup_outlines(p);
 | |
|         pdf_cleanup_annot_params(p);
 | |
|         pdf_cleanup_names(p);
 | |
|         pdf_cleanup_colorspaces(p);
 | |
|         pdf_cleanup_pattern(p);
 | |
|         pdf_cleanup_shadings(p);
 | |
|         pdf_cleanup_images(p);
 | |
|         pdf_cleanup_xobjects(p);
 | |
|         pdf_cleanup_extgstates(p);
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
|         pdf_cleanup_stringlists(p);
 | |
| 
 | |
|         PDF_SET_STATE(p, pdf_state_object);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static const pdc_defopt pdf_end_document_options[] =
 | |
| {
 | |
|     PDF_DOCUMENT_OPTIONS2
 | |
|     PDC_OPT_TERMINATE
 | |
| };
 | |
| 
 | |
| void
 | |
| pdf__end_document(PDF *p, const char *optlist)
 | |
| {
 | |
|     pdf_document *doc;
 | |
| 
 | |
|     /* check if there are any suspended pages left.
 | |
|     */
 | |
|     pdf_check_suspended_pages(p);
 | |
| 
 | |
|     /* get document pointer */
 | |
|     doc = pdf_init_get_document(p);
 | |
| 
 | |
|     if (optlist && *optlist)
 | |
|     {
 | |
|         pdc_resopt *resopts = NULL;
 | |
| 
 | |
|         /* parsing option list */
 | |
|         resopts = pdc_parse_optionlist(p->pdc, optlist,
 | |
|                                   pdf_end_document_options, NULL, pdc_true);
 | |
| 
 | |
|         /* get options */
 | |
|         pdf_get_document_common_options(p, resopts, PDF_FC_END_DOCUMENT);
 | |
|     }
 | |
| 
 | |
|     pdf_write_document(p);
 | |
| 
 | |
| 
 | |
|     pdf_cleanup_document(p);
 | |
| }
 | |
| 
 | |
| const char *
 | |
| pdf__get_buffer(PDF *p, long *size)
 | |
| {
 | |
|     const char *ret;
 | |
|     pdc_off_t llsize;
 | |
| 
 | |
| 
 | |
|     ret = pdc_get_stream_contents(p->out, &llsize);
 | |
| 
 | |
|     if (llsize > LONG_MAX)
 | |
| 	pdc_error(p->pdc, PDF_E_DOC_GETBUF_2GB, 0, 0, 0, 0);
 | |
| 
 | |
|     *size = (long) llsize;
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*****************************************************************************/
 | |
| /**               deprecated historical document functions                  **/
 | |
| /*****************************************************************************/
 | |
| 
 | |
| void
 | |
| pdf_set_flush(PDF *p, const char *flush)
 | |
| {
 | |
|     if (p->binding != NULL && strcmp(p->binding, "C++"))
 | |
|         return;
 | |
| 
 | |
|     if (flush != NULL && *flush)
 | |
|     {
 | |
|         int i = pdc_get_keycode_ci(flush, pdf_flush_keylist);
 | |
|         if (i != PDC_KEY_NOTFOUND)
 | |
|         {
 | |
|             pdf_document *doc = pdf_init_get_document(p);
 | |
| 
 | |
|             doc->flush = (pdf_flush_state) i;
 | |
|             p->flush = doc->flush;
 | |
|             return;
 | |
|         }
 | |
|         pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, flush, "flush",
 | |
|                   0, 0);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| pdf_set_uri(PDF *p, const char *uri)
 | |
| {
 | |
|     pdf_document *doc = pdf_init_get_document(p);
 | |
| 
 | |
|     if (doc->uri)
 | |
|         pdc_free(p->pdc, doc->uri);
 | |
|     doc->uri = pdc_strdup(p->pdc, uri);
 | |
| }
 | |
| 
 | |
| 
 | |
| void
 | |
| pdf_set_compatibility(PDF *p, const char *compatibility)
 | |
| {
 | |
| 
 | |
|     if (compatibility != NULL && *compatibility)
 | |
|     {
 | |
|         int i = pdc_get_keycode_ci(compatibility, pdf_compatibility_keylist);
 | |
|         if (i != PDC_KEY_NOTFOUND)
 | |
|         {
 | |
|             pdf_document *doc = pdf_init_get_document(p);
 | |
| 
 | |
|             doc->compatibility = p->compatibility = i;
 | |
|             return;
 | |
|         }
 | |
|         pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, compatibility, "compatibility",
 | |
|                   0, 0);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| pdf_set_openaction(PDF *p, const char *openaction)
 | |
| {
 | |
|     pdf_document *doc = pdf_init_get_document(p);
 | |
| 
 | |
|     if (openaction != NULL && *openaction)
 | |
|     {
 | |
|         pdf_cleanup_destination(p, doc->dest);
 | |
|         doc->dest = pdf_parse_destination_optlist(p, openaction, 1,
 | |
|                                                   pdf_openaction, pdc_true);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| pdf_set_openmode(PDF *p, const char *openmode)
 | |
| {
 | |
|     int i;
 | |
| 
 | |
|     if (openmode == NULL || !*openmode)
 | |
|         openmode = "none";
 | |
| 
 | |
|     i = pdc_get_keycode_ci(openmode, pdf_openmode_keylist);
 | |
|     if (i != PDC_KEY_NOTFOUND)
 | |
|     {
 | |
|         pdf_document *doc = pdf_init_get_document(p);
 | |
| 
 | |
|         doc->openmode = (pdf_openmode) i;
 | |
|     }
 | |
|     else
 | |
|         pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, openmode, "openmode", 0, 0);
 | |
| }
 | |
| 
 | |
| void
 | |
| pdf_set_viewerpreference(PDF *p, const char *viewerpreference)
 | |
| {
 | |
|     static const char fn[] = "pdf_set_viewerpreference";
 | |
|     pdf_document *doc = pdf_init_get_document(p);
 | |
|     char *optlist;
 | |
|     size_t nb1 = 0, nb2 = 0;
 | |
| 
 | |
|     if (doc->viewerpreferences)
 | |
|         nb1 = strlen(doc->viewerpreferences) * sizeof(char *);
 | |
|     nb2 = strlen(viewerpreference) * sizeof(char *);
 | |
| 
 | |
|     optlist = (char *) pdc_malloc(p->pdc, nb1 + nb2 + 2, fn);
 | |
|     optlist[0] = 0;
 | |
|     if (doc->viewerpreferences)
 | |
|     {
 | |
|         strcat(optlist, doc->viewerpreferences);
 | |
|         strcat(optlist, " ");
 | |
|     }
 | |
|     strcat(optlist, viewerpreference);
 | |
| 
 | |
|     if (doc->viewerpreferences)
 | |
|         pdc_free(p->pdc, doc->viewerpreferences);
 | |
|     doc->viewerpreferences = optlist;
 | |
|     doc->writevpdict |=
 | |
|         pdf_parse_and_write_viewerpreferences(p, optlist, pdc_false);
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 |