• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // PPD file import methods for the CUPS PPD Compiler.
3 //
4 // Copyright 2007-2011 by Apple Inc.
5 // Copyright 2002-2006 by Easy Software Products.
6 //
7 // Licensed under Apache License v2.0.  See the file "LICENSE" for more information.
8 //
9 
10 //
11 // Include necessary headers...
12 //
13 
14 #include "ppdc-private.h"
15 #include <cups/ppd.h>
16 
17 
18 //
19 // 'ppdcSource::import_ppd()' - Import a PPD file.
20 //
21 
22 int					// O - 1 on success, 0 on failure
import_ppd(const char * f)23 ppdcSource::import_ppd(const char *f)	// I - Filename
24 {
25   int		i, j, k;		// Looping vars
26   cups_file_t	*fp;			// File
27   char		line[256],		// Comment line
28 		*ptr;			// Pointer into line
29   int		cost;			// Cost for filter
30   ppd_file_t	*ppd;			// PPD file data
31   ppd_group_t	*group;			// PPD group
32   ppd_option_t	*option;		// PPD option
33   ppd_choice_t	*choice;		// PPD choice
34   ppd_attr_t	*attr;			// PPD attribute
35   ppd_const_t	*constraint;		// PPD UI constraint
36   ppd_const_t	*constraint2;		// Temp PPD UI constraint
37   ppd_size_t	*size;			// PPD page size
38   ppdcDriver	*driver;		// Driver
39   ppdcFilter	*filter;		// Current filter
40   ppdcFont	*font;			// Font
41   ppdcGroup	*cgroup;		// UI group
42   ppdcOption	*coption;		// UI option
43   ppdcChoice	*cchoice;		// UI choice
44   ppdcConstraint *cconstraint;		// UI constraint
45   ppdcMediaSize	*csize;			// Media size
46 
47 
48   // Try opening the PPD file...
49   if ((ppd = ppdOpenFile(f)) == NULL)
50     return (0);
51 
52   // All PPD files need a PCFileName attribute...
53   if (!ppd->pcfilename)
54   {
55     ppdClose(ppd);
56     return (0);
57   }
58 
59   // See if the driver has already been imported...
60   if ((driver = find_driver(ppd->pcfilename)) == NULL)
61   {
62     // Create a new PPD file...
63     if ((fp = cupsFileOpen(f, "r")) == NULL)
64     {
65       ppdClose(ppd);
66       return (0);
67     }
68 
69     driver       = new ppdcDriver();
70     driver->type = PPDC_DRIVER_PS;
71 
72     drivers->add(driver);
73 
74     // Read the initial comments from the PPD file and use them as the
75     // copyright/license text...
76     cupsFileGets(fp, line, sizeof(line));
77 					// Skip *PPD-Adobe-M.m
78 
79     while (cupsFileGets(fp, line, sizeof(line)))
80       if (strncmp(line, "*%", 2))
81         break;
82       else if (strncmp(line, "*%%%% ", 6))
83       {
84         for (ptr = line + 2; isspace(*ptr); ptr ++);
85 
86         driver->add_copyright(ptr);
87       }
88 
89     cupsFileClose(fp);
90 
91     // Then add the stuff from the PPD file...
92     if (ppd->modelname && ppd->manufacturer &&
93         !_cups_strncasecmp(ppd->modelname, ppd->manufacturer,
94                      strlen(ppd->manufacturer)))
95     {
96       ptr = ppd->modelname + strlen(ppd->manufacturer);
97 
98       while (isspace(*ptr))
99         ptr ++;
100     }
101     else
102       ptr = ppd->modelname;
103 
104     if (ppd->nickname)
105       driver->add_attr(new ppdcAttr("NickName", NULL, NULL, ppd->nickname));
106 
107     if (ppd->shortnickname)
108       driver->add_attr(new ppdcAttr("ShortNickName", NULL, NULL,
109                                     ppd->shortnickname));
110 
111     driver->manufacturer        = new ppdcString(ppd->manufacturer);
112     driver->model_name          = new ppdcString(ptr);
113     driver->pc_file_name        = new ppdcString(ppd->pcfilename);
114     attr = ppdFindAttr(ppd, "FileVersion", NULL);
115     driver->version             = new ppdcString(attr ? attr->value : NULL);
116     driver->model_number        = ppd->model_number;
117     driver->manual_copies       = ppd->manual_copies;
118     driver->color_device        = ppd->color_device;
119     driver->throughput          = ppd->throughput;
120     driver->variable_paper_size = ppd->variable_sizes;
121     driver->max_width           = ppd->custom_max[0];
122     driver->max_length          = ppd->custom_max[1];
123     driver->min_width           = ppd->custom_min[0];
124     driver->min_length          = ppd->custom_min[1];
125     driver->left_margin         = ppd->custom_margins[0];
126     driver->bottom_margin       = ppd->custom_margins[1];
127     driver->right_margin        = ppd->custom_margins[2];
128     driver->top_margin          = ppd->custom_margins[3];
129 
130     for (i = 0; i < ppd->num_filters; i ++)
131     {
132       strlcpy(line, ppd->filters[i], sizeof(line));
133 
134       for (ptr = line; *ptr; ptr ++)
135         if (isspace(*ptr & 255))
136 	  break;
137       *ptr++ = '\0';
138 
139       cost = strtol(ptr, &ptr, 10);
140 
141       while (isspace(*ptr & 255))
142         ptr ++;
143 
144       filter = new ppdcFilter(line, ptr, cost);
145       driver->add_filter(filter);
146     }
147 
148     attr = ppdFindAttr(ppd, "DefaultFont", NULL);
149     driver->default_font  = new ppdcString(attr ? attr->value : NULL);
150 
151     // Collect media sizes...
152     ppd_option_t	*region_option,		// PageRegion option
153 			*size_option;		// PageSize option
154     ppd_choice_t	*region_choice,		// PageRegion choice
155 			*size_choice;		// PageSize choice
156 
157     region_option = ppdFindOption(ppd, "PageRegion");
158     size_option   = ppdFindOption(ppd, "PageSize");
159 
160     for (i = ppd->num_sizes, size = ppd->sizes; i > 0; i --, size ++)
161     {
162       // Don't do custom size here...
163       if (!_cups_strcasecmp(size->name, "Custom"))
164         continue;
165 
166       // Get the code for the PageSize and PageRegion options...
167       region_choice = ppdFindChoice(region_option, size->name);
168       size_choice   = ppdFindChoice(size_option, size->name);
169 
170       // Create a new media size record and add it to the driver...
171       csize = new ppdcMediaSize(size->name, size_choice->text, size->width,
172                                 size->length, size->left, size->bottom,
173 				size->width - size->right,
174 				size->length - size->top,
175 				size_choice->code, region_choice->code);
176 
177        driver->add_size(csize);
178 
179        if (!_cups_strcasecmp(size_option->defchoice, size->name))
180          driver->set_default_size(csize);
181     }
182 
183     // Now all of the options...
184     for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
185     {
186       cgroup = new ppdcGroup(group->name, group->text);
187       driver->add_group(cgroup);
188 
189       for (j = group->num_options, option = group->options; j > 0; j --, option ++)
190       {
191         if (!strcmp(option->keyword, "PageSize") || !strcmp(option->keyword, "PageRegion"))
192           continue;
193 
194         coption = new ppdcOption((ppdcOptType)option->ui, option->keyword,
195 	                         option->text, (ppdcOptSection)option->section,
196 				 option->order);
197         cgroup->add_option(coption);
198 
199         for (k = option->num_choices, choice = option->choices; k > 0; k --, choice ++)
200         {
201 	  if (!strcmp(choice->choice, "Custom"))
202 	    continue;
203 
204           cchoice = new ppdcChoice(choice->choice, choice->text, choice->code);
205           coption->add_choice(cchoice);
206 
207           if (!_cups_strcasecmp(option->defchoice, choice->choice))
208             coption->set_defchoice(cchoice);
209         }
210       }
211     }
212 
213     // Now the constraints...
214     for (i = ppd->num_consts, constraint = ppd->consts;
215          i > 0;
216 	 i --, constraint ++)
217     {
218       // Look for mirrored constraints...
219       for (j = i - 1, constraint2 = constraint + 1;
220            j > 0;
221 	   j --, constraint2 ++)
222 	if (!strcmp(constraint->option1, constraint2->option2) &&
223 	    !strcmp(constraint->choice1, constraint2->choice2) &&
224 	    !strcmp(constraint->option2, constraint2->option1) &&
225 	    !strcmp(constraint->choice2, constraint2->choice1))
226           break;
227 
228       if (j)
229         continue;
230 
231       cconstraint = new ppdcConstraint(constraint->option2, constraint->choice2,
232                                        constraint->option1, constraint->choice1);
233       driver->add_constraint(cconstraint);
234     }
235 
236     for (i = 0; i < ppd->num_attrs; i ++)
237     {
238       attr = ppd->attrs[i];
239 
240       if (!strcmp(attr->name, "Font"))
241       {
242         // Font...
243 	char		encoding[256],	// Encoding string
244 			version[256],	// Version string
245 			charset[256],	// Charset string
246 			status[256];	// Status string
247 	ppdcFontStatus	fstatus;	// Status enumeration
248 
249 
250         if (sscanf(attr->value, "%s%*[^\"]\"%[^\"]\"%s%s", encoding, version,
251 	           charset, status) != 4)
252 	{
253 	  _cupsLangPrintf(stderr, _("ppdc: Bad font attribute: %s"),
254 	                  attr->value);
255 	  continue;
256 	}
257 
258         if (!strcmp(status, "ROM"))
259 	  fstatus = PPDC_FONT_ROM;
260 	else
261 	  fstatus = PPDC_FONT_DISK;
262 
263         font = new ppdcFont(attr->spec, encoding, version, charset, fstatus);
264 
265 	driver->add_font(font);
266       }
267       else if (!strcmp(attr->name, "CustomPageSize"))
268       {
269         driver->set_custom_size_code(attr->value);
270       }
271       else if ((strncmp(attr->name, "Default", 7) ||
272         	!strcmp(attr->name, "DefaultColorSpace")) &&
273 	       strcmp(attr->name, "ColorDevice") &&
274 	       strcmp(attr->name, "Manufacturer") &&
275 	       strcmp(attr->name, "ModelName") &&
276 	       strcmp(attr->name, "MaxMediaHeight") &&
277 	       strcmp(attr->name, "MaxMediaWidth") &&
278 	       strcmp(attr->name, "NickName") &&
279 	       strcmp(attr->name, "ParamCustomPageSize") &&
280 	       strcmp(attr->name, "ShortNickName") &&
281 	       strcmp(attr->name, "Throughput") &&
282 	       strcmp(attr->name, "PCFileName") &&
283 	       strcmp(attr->name, "FileVersion") &&
284 	       strcmp(attr->name, "FormatVersion") &&
285 	       strcmp(attr->name, "HWMargins") &&
286 	       strcmp(attr->name, "VariablePaperSize") &&
287 	       strcmp(attr->name, "LanguageEncoding") &&
288 	       strcmp(attr->name, "LanguageVersion") &&
289 	       strcmp(attr->name, "cupsFilter") &&
290 	       strcmp(attr->name, "cupsFlipDuplex") &&
291 	       strcmp(attr->name, "cupsLanguages") &&
292 	       strcmp(attr->name, "cupsManualCopies") &&
293 	       strcmp(attr->name, "cupsModelNumber") &&
294 	       strcmp(attr->name, "cupsVersion"))
295       {
296         if ((ptr = strchr(attr->name, '.')) != NULL &&
297 	    ((ptr - attr->name) == 2 || (ptr - attr->name) == 5))
298 	{
299 	  // Might be a localization attribute; test further...
300 	  if (isalpha(attr->name[0] & 255) &&
301 	      isalpha(attr->name[1] & 255) &&
302 	      (attr->name[2] == '.' ||
303 	       (attr->name[2] == '_' && isalpha(attr->name[3] & 255) &&
304 	        isalpha(attr->name[4] & 255))))
305             continue;
306 	}
307 
308         // Attribute...
309         driver->add_attr(new ppdcAttr(attr->name, attr->spec, attr->text,
310 	                              attr->value));
311       }
312       else if (!strncmp(attr->name, "Default", 7) &&
313                !ppdFindOption(ppd, attr->name + 7) &&
314 	       strcmp(attr->name, "DefaultFont") &&
315 	       strcmp(attr->name, "DefaultImageableArea") &&
316 	       strcmp(attr->name, "DefaultPaperDimension") &&
317 	       strcmp(attr->name, "DefaultFont"))
318       {
319         // Default attribute...
320         driver->add_attr(new ppdcAttr(attr->name, attr->spec, attr->text,
321 	                              attr->value));
322       }
323     }
324   }
325 
326   return (1);
327 }
328