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