]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/attr.c
Import CUPS 1.4svn-r7585.
[thirdparty/cups.git] / cups / attr.c
1 /*
2 * "$Id: attr.c 7584 2008-05-16 22:55:53Z mike $"
3 *
4 * PPD model-specific attribute routines for the Common UNIX Printing System
5 * (CUPS).
6 *
7 * Copyright 2007-2008 by Apple Inc.
8 * Copyright 1997-2006 by Easy Software Products.
9 *
10 * These coded instructions, statements, and computer programs are the
11 * property of Apple Inc. and are protected by Federal copyright
12 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
13 * which should have been included with this file. If this file is
14 * file is missing or damaged, see the license at "http://www.cups.org/".
15 *
16 * Contents:
17 *
18 * ppdFindAttr() - Find the first matching attribute.
19 * ppdFindNextAttr() - Find the next matching attribute.
20 */
21
22 /*
23 * Include necessary headers...
24 */
25
26 #include "ppd-private.h"
27 #include "debug.h"
28 #include "string.h"
29 #include <stdlib.h>
30
31
32 /*
33 * 'ppdFindAttr()' - Find the first matching attribute.
34 *
35 * @since CUPS 1.1.19@
36 */
37
38 ppd_attr_t * /* O - Attribute or @code NULL@ if not found */
39 ppdFindAttr(ppd_file_t *ppd, /* I - PPD file data */
40 const char *name, /* I - Attribute name */
41 const char *spec) /* I - Specifier string or @code NULL@ */
42 {
43 ppd_attr_t key, /* Search key */
44 *attr; /* Current attribute */
45 int diff; /* Current difference */
46
47
48 DEBUG_printf(("ppdFindAttr(ppd=%p, name=\"%s\", spec=\"%s\")\n", ppd,
49 name ? name : "(null)", spec ? spec : "(null)"));
50
51 /*
52 * Range check input...
53 */
54
55 if (!ppd || !name || ppd->num_attrs == 0)
56 return (NULL);
57
58 /*
59 * Search for a matching attribute...
60 */
61
62 memset(&key, 0, sizeof(key));
63 strlcpy(key.name, name, sizeof(key.name));
64 if (spec)
65 strlcpy(key.spec, spec, sizeof(key.spec));
66
67 /*
68 * Return the first matching attribute, if any...
69 */
70
71 if ((attr = (ppd_attr_t *)cupsArrayFind(ppd->sorted_attrs, &key)) != NULL)
72 return (attr);
73 else if (spec)
74 return (NULL);
75
76 /*
77 * No match found, loop through the sorted attributes to see if we can
78 * find a "wildcard" match for the attribute...
79 */
80
81 for (attr = (ppd_attr_t *)cupsArrayFirst(ppd->sorted_attrs);
82 attr;
83 attr = (ppd_attr_t *)cupsArrayNext(ppd->sorted_attrs))
84 {
85 if ((diff = strcasecmp(attr->name, name)) == 0)
86 break;
87
88 if (diff > 0)
89 {
90 /*
91 * All remaining attributes are > than the one we are trying to find...
92 */
93
94 cupsArrayIndex(ppd->sorted_attrs, cupsArrayCount(ppd->sorted_attrs));
95
96 return (NULL);
97 }
98 }
99
100 return (attr);
101 }
102
103
104 /*
105 * 'ppdFindNextAttr()' - Find the next matching attribute.
106 *
107 * @since CUPS 1.1.19@
108 */
109
110 ppd_attr_t * /* O - Attribute or @code NULL@ if not found */
111 ppdFindNextAttr(ppd_file_t *ppd, /* I - PPD file data */
112 const char *name, /* I - Attribute name */
113 const char *spec) /* I - Specifier string or @code NULL@ */
114 {
115 ppd_attr_t *attr; /* Current attribute */
116
117
118 /*
119 * Range check input...
120 */
121
122 if (!ppd || !name || ppd->num_attrs == 0 ||
123 !cupsArrayCurrent(ppd->sorted_attrs))
124 return (NULL);
125
126 /*
127 * See if there are more attributes to return...
128 */
129
130 if ((attr = (ppd_attr_t *)cupsArrayNext(ppd->sorted_attrs)) == NULL)
131 return (NULL);
132
133 /*
134 * Check the next attribute to see if it is a match...
135 */
136
137 if (strcasecmp(attr->name, name) || (spec && strcasecmp(attr->spec, spec)))
138 {
139 /*
140 * Nope, reset the current pointer to the end of the array...
141 */
142
143 cupsArrayIndex(ppd->sorted_attrs, cupsArrayCount(ppd->sorted_attrs));
144
145 return (NULL);
146 }
147
148 /*
149 * Return the next attribute's value...
150 */
151
152 return (attr);
153 }
154
155
156 /*
157 * '_ppdGet1284Values()' - Get 1284 device ID keys and values.
158 *
159 * The returned dictionary is a CUPS option array that can be queried with
160 * cupsGetOption and freed with cupsFreeOptions.
161 */
162
163 int /* O - Number of key/value pairs */
164 _ppdGet1284Values(
165 const char *device_id, /* I - IEEE-1284 device ID string */
166 cups_option_t **values) /* O - Array of key/value pairs */
167 {
168 int num_values; /* Number of values */
169 char key[256], /* Key string */
170 value[256], /* Value string */
171 *ptr; /* Pointer into key/value */
172
173
174 /*
175 * Range check input...
176 */
177
178 if (values)
179 *values = NULL;
180
181 if (!device_id || !values)
182 return (0);
183
184 /*
185 * Parse the 1284 device ID value into keys and values. The format is
186 * repeating sequences of:
187 *
188 * [whitespace]key:value[whitespace];
189 */
190
191 num_values = 0;
192 while (*device_id)
193 {
194 while (isspace(*device_id & 255))
195 device_id ++;
196
197 if (!*device_id)
198 break;
199
200 for (ptr = key; *device_id && *device_id != ':'; device_id ++)
201 if (ptr < (key + sizeof(key) - 1))
202 *ptr++ = *device_id;
203
204 if (!*device_id)
205 break;
206
207 while (ptr > key && isspace(ptr[-1] & 255))
208 ptr --;
209
210 *ptr = '\0';
211 device_id ++;
212
213 while (isspace(*device_id & 255))
214 device_id ++;
215
216 if (!*device_id)
217 break;
218
219 for (ptr = value; *device_id && *device_id != ';'; device_id ++)
220 if (ptr < (value + sizeof(value) - 1))
221 *ptr++ = *device_id;
222
223 if (!*device_id)
224 break;
225
226 while (ptr > value && isspace(ptr[-1] & 255))
227 ptr --;
228
229 *ptr = '\0';
230 device_id ++;
231
232 num_values = cupsAddOption(key, value, num_values, values);
233 }
234
235 return (num_values);
236 }
237
238
239 /*
240 * '_ppdNormalizeMakeAndModel()' - Normalize a product/make-and-model string.
241 *
242 * This function tries to undo the mistakes made by many printer manufacturers
243 * to produce a clean make-and-model string we can use.
244 */
245
246 char * /* O - Normalized make-and-model string or NULL on error */
247 _ppdNormalizeMakeAndModel(
248 const char *make_and_model, /* I - Original make-and-model string */
249 char *buffer, /* I - String buffer */
250 size_t bufsize) /* I - Size of string buffer */
251 {
252 char *bufptr; /* Pointer into buffer */
253
254
255 if (!make_and_model || !buffer || bufsize < 1)
256 {
257 if (buffer)
258 *buffer = '\0';
259
260 return (NULL);
261 }
262
263 /*
264 * Skip leading whitespace...
265 */
266
267 while (isspace(*make_and_model & 255))
268 make_and_model ++;
269
270 /*
271 * Remove parenthesis and add manufacturers as needed...
272 */
273
274 if (make_and_model[0] == '(')
275 {
276 strlcpy(buffer, make_and_model + 1, bufsize);
277
278 if ((bufptr = strrchr(buffer, ')')) != NULL)
279 *bufptr = '\0';
280 }
281 else if (!strncasecmp(make_and_model, "XPrint", 6))
282 {
283 /*
284 * Xerox XPrint...
285 */
286
287 snprintf(buffer, bufsize, "Xerox %s", make_and_model);
288 }
289 else if (!strncasecmp(make_and_model, "Eastman", 7))
290 {
291 /*
292 * Kodak...
293 */
294
295 snprintf(buffer, bufsize, "Kodak %s", make_and_model + 7);
296 }
297 else if (!strncasecmp(make_and_model, "laserwriter", 11))
298 {
299 /*
300 * Apple LaserWriter...
301 */
302
303 snprintf(buffer, bufsize, "Apple LaserWriter%s", make_and_model + 11);
304 }
305 else if (!strncasecmp(make_and_model, "colorpoint", 10))
306 {
307 /*
308 * Seiko...
309 */
310
311 snprintf(buffer, bufsize, "Seiko %s", make_and_model);
312 }
313 else if (!strncasecmp(make_and_model, "fiery", 5))
314 {
315 /*
316 * EFI...
317 */
318
319 snprintf(buffer, bufsize, "EFI %s", make_and_model);
320 }
321 else if (!strncasecmp(make_and_model, "ps ", 3) ||
322 !strncasecmp(make_and_model, "colorpass", 9))
323 {
324 /*
325 * Canon...
326 */
327
328 snprintf(buffer, bufsize, "Canon %s", make_and_model);
329 }
330 else if (!strncasecmp(make_and_model, "primera", 7))
331 {
332 /*
333 * Fargo...
334 */
335
336 snprintf(buffer, bufsize, "Fargo %s", make_and_model);
337 }
338 else if (!strncasecmp(make_and_model, "designjet", 9) ||
339 !strncasecmp(make_and_model, "deskjet", 7))
340 {
341 /*
342 * HP...
343 */
344
345 snprintf(buffer, bufsize, "HP %s", make_and_model);
346 }
347 else
348 strlcpy(buffer, make_and_model, bufsize);
349
350 /*
351 * Clean up the make...
352 */
353
354 if (!strncasecmp(buffer, "agfa", 4))
355 {
356 /*
357 * Replace with AGFA (all uppercase)...
358 */
359
360 buffer[0] = 'A';
361 buffer[1] = 'G';
362 buffer[2] = 'F';
363 buffer[3] = 'A';
364 }
365 else if (!strncasecmp(buffer, "Hewlett-Packard hp ", 19))
366 {
367 /*
368 * Just put "HP" on the front...
369 */
370
371 buffer[0] = 'H';
372 buffer[1] = 'P';
373 _cups_strcpy(buffer + 2, buffer + 18);
374 }
375 else if (!strncasecmp(buffer, "Hewlett-Packard ", 16))
376 {
377 /*
378 * Just put "HP" on the front...
379 */
380
381 buffer[0] = 'H';
382 buffer[1] = 'P';
383 _cups_strcpy(buffer + 2, buffer + 15);
384 }
385 else if (!strncasecmp(buffer, "Lexmark International", 21))
386 {
387 /*
388 * Strip "International"...
389 */
390
391 _cups_strcpy(buffer + 8, buffer + 21);
392 }
393 else if (!strncasecmp(buffer, "herk", 4))
394 {
395 /*
396 * Replace with LHAG...
397 */
398
399 buffer[0] = 'L';
400 buffer[1] = 'H';
401 buffer[2] = 'A';
402 buffer[3] = 'G';
403 }
404 else if (!strncasecmp(buffer, "linotype", 8))
405 {
406 /*
407 * Replace with LHAG...
408 */
409
410 buffer[0] = 'L';
411 buffer[1] = 'H';
412 buffer[2] = 'A';
413 buffer[3] = 'G';
414 _cups_strcpy(buffer + 4, buffer + 8);
415 }
416
417 /*
418 * Remove trailing whitespace and return...
419 */
420
421 for (bufptr = buffer + strlen(buffer) - 1;
422 bufptr >= buffer && isspace(*bufptr & 255);
423 bufptr --);
424
425 bufptr[1] = '\0';
426
427 return (buffer[0] ? buffer : NULL);
428 }
429
430
431 /*
432 * End of "$Id: attr.c 7584 2008-05-16 22:55:53Z mike $".
433 */