• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <ctype.h>
2 #include "pdftopdf_processor.h"
3 #include <cups/ppd.h>
4 
5 #include <string.h>
6 
7 // TODO: -currently changes ppd.  (Copies)
8 //
emitJCLOptions(FILE * fp,ppd_file_t * ppd,int deviceCopies)9 static void emitJCLOptions(FILE *fp, ppd_file_t *ppd, int deviceCopies) // {{{
10 {
11   int section;
12   ppd_choice_t **choices;
13   int i;
14   char buf[1024];
15   ppd_attr_t *attr;
16   bool withJCL=false,
17     datawritten=false;
18 
19   if (!ppd) return;
20 
21   if ((attr = ppdFindAttr(ppd,"pdftopdfJCLBegin",NULL)) != NULL) {
22     withJCL=true;
23     const int n=strlen(attr->value);
24     for (i = 0;i < n;i++) {
25       if (attr->value[i] == '\r' || attr->value[i] == '\n') {
26         // skip new line
27         continue;
28       }
29       fputc(attr->value[i],fp);
30       datawritten=true;
31     }
32   }
33 
34   snprintf(buf,sizeof(buf),"%d",deviceCopies);
35   if (ppdFindOption(ppd,"Copies") != NULL) {
36     ppdMarkOption(ppd,"Copies",buf);
37   } else {
38     if ((attr = ppdFindAttr(ppd,"pdftopdfJCLCopies",buf)) != NULL) {
39       fputs(attr->value,fp);
40       datawritten=true;
41     } else if (withJCL) {
42       fprintf(fp,"Copies=%d;",deviceCopies);
43       datawritten=true;
44     }
45   }
46   for (section = (int)PPD_ORDER_ANY;
47        section <= (int)PPD_ORDER_PROLOG;section++) {
48     int n = ppdCollect(ppd,(ppd_section_t)section,&choices);
49     for (i = 0;i < n;i++) {
50       snprintf(buf,sizeof(buf),"pdftopdfJCL%s",
51 	       ((ppd_option_t *)(choices[i]->option))->keyword);
52       if ((attr = ppdFindAttr(ppd,buf,choices[i]->choice)) != NULL) {
53         fputs(attr->value,fp);
54         datawritten=true;
55       } else if (withJCL) {
56         fprintf(fp,"%s=%s;",
57 		((ppd_option_t *)(choices[i]->option))->keyword,
58 		choices[i]->choice);
59         datawritten=true;
60       }
61     }
62   }
63   if (datawritten) {
64     fputc('\n',fp);
65   }
66 }
67 // }}}
68 
69 /* Copied ppd_decode() from CUPS which is not exported to the API; needed in emitPreamble() */
70 // {{{ static int ppd_decode(char *string)
71 static int				/* O - Length of decoded string */
ppd_decode(char * string)72 ppd_decode(char *string)		/* I - String to decode */
73 {
74   char	*inptr,				/* Input pointer */
75     *outptr;			/* Output pointer */
76 
77   inptr  = string;
78   outptr = string;
79 
80   while (*inptr != '\0')
81     if (*inptr == '<' && isxdigit(inptr[1] & 255)) {
82       /*
83        * Convert hex to 8-bit values...
84        */
85 
86       inptr ++;
87       while (isxdigit(*inptr & 255)) {
88 	if (isalpha(*inptr))
89 	  *outptr = (tolower(*inptr) - 'a' + 10) << 4;
90 	else
91 	  *outptr = (*inptr - '0') << 4;
92 
93 	inptr ++;
94 
95         if (!isxdigit(*inptr & 255))
96 	  break;
97 
98 	if (isalpha(*inptr))
99 	  *outptr |= tolower(*inptr) - 'a' + 10;
100 	else
101 	  *outptr |= *inptr - '0';
102 
103 	inptr ++;
104 	outptr ++;
105       }
106 
107       while (*inptr != '>' && *inptr != '\0')
108 	inptr ++;
109       while (*inptr == '>')
110 	inptr ++;
111     } else
112       *outptr++ = *inptr++;
113 
114   *outptr = '\0';
115 
116   return ((int)(outptr - string));
117 }
118 // }}}
119 
emitPreamble(ppd_file_t * ppd,const ProcessingParameters & param)120 void emitPreamble(ppd_file_t *ppd,const ProcessingParameters &param) // {{{
121 {
122   if (ppd == 0) return;
123 
124   ppdEmit(ppd,stdout,PPD_ORDER_EXIT);
125 
126   if (param.emitJCL) {
127     /* pdftopdf only adds JCL to the job if the printer is a native PDF
128        printer and the PPD is for this mode, having the "*JCLToPDFInterpreter:"
129        keyword. We need to read this keyword manually from the PPD and replace
130        the content of ppd->jcl_ps by the value of this keyword, so that
131        ppdEmitJCL() actually adds JCL based on the presence on
132        "*JCLToPDFInterpreter:". */
133     ppd_attr_t *attr;
134     char buf[1024];
135     int devicecopies_done = 0;
136     char *old_jcl_ps = ppd->jcl_ps;
137     /* If there is a "Copies" option in the PPD file, assure that hardware
138        copies are implemented as described by this option */
139     if (ppdFindOption(ppd,"Copies") != NULL &&
140 	param.deviceCopies > 1) {
141       snprintf(buf,sizeof(buf),"%d",param.deviceCopies);
142       ppdMarkOption(ppd,"Copies",buf);
143       devicecopies_done = 1;
144     }
145     if ((attr=ppdFindAttr(ppd,"JCLToPDFInterpreter",NULL)) != NULL) {
146       if (param.deviceCopies > 1 && devicecopies_done == 0 && // HW copies
147 	  strncmp(ppd->jcl_begin, "\033%-12345X@", 10) == 0) { // PJL
148 	/* Add a PJL command to implement the hardware copies */
149         const size_t size=strlen(attr->value)+1+30;
150         ppd->jcl_ps=(char *)malloc(size*sizeof(char));
151         if (param.deviceCollate) {
152           snprintf(ppd->jcl_ps, size, "@PJL SET QTY=%d\n%s",
153                    param.deviceCopies, attr->value);
154         } else {
155           snprintf(ppd->jcl_ps, size, "@PJL SET COPIES=%d\n%s",
156                    param.deviceCopies, attr->value);
157         }
158       } else
159 	ppd->jcl_ps=strdup(attr->value);
160       ppd_decode(ppd->jcl_ps);
161     } else {
162       ppd->jcl_ps=NULL;
163     }
164     ppdEmitJCL(ppd,stdout,param.jobId,param.user,param.title);
165     emitJCLOptions(stdout,ppd,param.deviceCopies);
166     free(ppd->jcl_ps);
167     ppd->jcl_ps = old_jcl_ps; // cups uses pool allocator, not free()
168   }
169 }
170 // }}}
171 
emitPostamble(ppd_file_t * ppd,const ProcessingParameters & param)172 void emitPostamble(ppd_file_t *ppd,const ProcessingParameters &param) // {{{
173 {
174   if (param.emitJCL) {
175     ppdEmitJCLEnd(ppd,stdout);
176   }
177 }
178 // }}}
179 
180 // pass information to subsequent filters via PDF comments
emitComment(PDFTOPDF_Processor & proc,const ProcessingParameters & param)181 void emitComment(PDFTOPDF_Processor &proc,const ProcessingParameters &param) // {{{
182 {
183   std::vector<std::string> output;
184 
185   output.push_back("% This file was generated by pdftopdf");
186 
187   // This is not standard, but like PostScript.
188   if (param.deviceCopies>0) {
189     char buf[256];
190     snprintf(buf,sizeof(buf),"%d",param.deviceCopies);
191     output.push_back(std::string("%%PDFTOPDFNumCopies : ")+buf);
192 
193     if (param.deviceCollate) {
194       output.push_back("%%PDFTOPDFCollate : true");
195     } else {
196       output.push_back("%%PDFTOPDFCollate : false");
197     }
198   }
199 
200   proc.setComments(output);
201 }
202 // }}}
203