]>
Commit | Line | Data |
---|---|---|
ef416fc2 | 1 | /* |
a906a731 | 2 | * PPD model-specific attribute routines for CUPS. |
ef416fc2 | 3 | * |
a906a731 MS |
4 | * Copyright 2007-2015 by Apple Inc. |
5 | * Copyright 1997-2006 by Easy Software Products. | |
ef416fc2 | 6 | * |
a906a731 MS |
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 | |
57b7b66b | 11 | * missing or damaged, see the license at "http://www.cups.org/". |
ef416fc2 | 12 | */ |
13 | ||
14 | /* | |
15 | * Include necessary headers... | |
16 | */ | |
17 | ||
71e16022 | 18 | #include "cups-private.h" |
5eb9da71 | 19 | #include "ppd-private.h" |
ef416fc2 | 20 | |
21 | ||
ef416fc2 | 22 | /* |
5a738aea | 23 | * 'ppdFindAttr()' - Find the first matching attribute. |
ef416fc2 | 24 | * |
8072030b | 25 | * @since CUPS 1.1.19/macOS 10.3@ |
ef416fc2 | 26 | */ |
27 | ||
5a738aea | 28 | ppd_attr_t * /* O - Attribute or @code NULL@ if not found */ |
d09495fa | 29 | ppdFindAttr(ppd_file_t *ppd, /* I - PPD file data */ |
30 | const char *name, /* I - Attribute name */ | |
5a738aea | 31 | const char *spec) /* I - Specifier string or @code NULL@ */ |
ef416fc2 | 32 | { |
d09495fa | 33 | ppd_attr_t key, /* Search key */ |
34 | *attr; /* Current attribute */ | |
d09495fa | 35 | |
ef416fc2 | 36 | |
e07d4801 MS |
37 | DEBUG_printf(("2ppdFindAttr(ppd=%p, name=\"%s\", spec=\"%s\")", ppd, name, |
38 | spec)); | |
ef416fc2 | 39 | |
40 | /* | |
41 | * Range check input... | |
42 | */ | |
43 | ||
bd7854cb | 44 | if (!ppd || !name || ppd->num_attrs == 0) |
ef416fc2 | 45 | return (NULL); |
46 | ||
47 | /* | |
bd7854cb | 48 | * Search for a matching attribute... |
ef416fc2 | 49 | */ |
50 | ||
51 | memset(&key, 0, sizeof(key)); | |
bd7854cb | 52 | strlcpy(key.name, name, sizeof(key.name)); |
ef416fc2 | 53 | |
54 | /* | |
bd7854cb | 55 | * Return the first matching attribute, if any... |
ef416fc2 | 56 | */ |
57 | ||
d09495fa | 58 | if ((attr = (ppd_attr_t *)cupsArrayFind(ppd->sorted_attrs, &key)) != NULL) |
d09495fa | 59 | { |
6e8b116d | 60 | if (spec) |
d09495fa | 61 | { |
62 | /* | |
6e8b116d | 63 | * Loop until we find the first matching attribute for "spec"... |
d09495fa | 64 | */ |
65 | ||
88f9aafc | 66 | while (attr && _cups_strcasecmp(spec, attr->spec)) |
6e8b116d MS |
67 | { |
68 | if ((attr = (ppd_attr_t *)cupsArrayNext(ppd->sorted_attrs)) != NULL && | |
88f9aafc | 69 | _cups_strcasecmp(attr->name, name)) |
6e8b116d MS |
70 | attr = NULL; |
71 | } | |
d09495fa | 72 | } |
73 | } | |
74 | ||
75 | return (attr); | |
ef416fc2 | 76 | } |
77 | ||
78 | ||
79 | /* | |
5a738aea | 80 | * 'ppdFindNextAttr()' - Find the next matching attribute. |
ef416fc2 | 81 | * |
8072030b | 82 | * @since CUPS 1.1.19/macOS 10.3@ |
ef416fc2 | 83 | */ |
84 | ||
5a738aea | 85 | ppd_attr_t * /* O - Attribute or @code NULL@ if not found */ |
ef416fc2 | 86 | ppdFindNextAttr(ppd_file_t *ppd, /* I - PPD file data */ |
87 | const char *name, /* I - Attribute name */ | |
5a738aea | 88 | const char *spec) /* I - Specifier string or @code NULL@ */ |
ef416fc2 | 89 | { |
bd7854cb | 90 | ppd_attr_t *attr; /* Current attribute */ |
ef416fc2 | 91 | |
92 | ||
93 | /* | |
94 | * Range check input... | |
95 | */ | |
96 | ||
6e8b116d | 97 | if (!ppd || !name || ppd->num_attrs == 0) |
ef416fc2 | 98 | return (NULL); |
99 | ||
100 | /* | |
101 | * See if there are more attributes to return... | |
102 | */ | |
103 | ||
6e8b116d | 104 | while ((attr = (ppd_attr_t *)cupsArrayNext(ppd->sorted_attrs)) != NULL) |
ef416fc2 | 105 | { |
106 | /* | |
6e8b116d | 107 | * Check the next attribute to see if it is a match... |
ef416fc2 | 108 | */ |
109 | ||
88f9aafc | 110 | if (_cups_strcasecmp(attr->name, name)) |
6e8b116d MS |
111 | { |
112 | /* | |
113 | * Nope, reset the current pointer to the end of the array... | |
114 | */ | |
bd7854cb | 115 | |
6e8b116d MS |
116 | cupsArrayIndex(ppd->sorted_attrs, cupsArrayCount(ppd->sorted_attrs)); |
117 | ||
118 | return (NULL); | |
119 | } | |
120 | ||
88f9aafc | 121 | if (!spec || !_cups_strcasecmp(attr->spec, spec)) |
6e8b116d | 122 | break; |
ef416fc2 | 123 | } |
6e8b116d | 124 | |
ef416fc2 | 125 | /* |
126 | * Return the next attribute's value... | |
127 | */ | |
128 | ||
bd7854cb | 129 | return (attr); |
ef416fc2 | 130 | } |
131 | ||
132 | ||
5eb9da71 MS |
133 | /* |
134 | * '_ppdNormalizeMakeAndModel()' - Normalize a product/make-and-model string. | |
135 | * | |
136 | * This function tries to undo the mistakes made by many printer manufacturers | |
137 | * to produce a clean make-and-model string we can use. | |
138 | */ | |
139 | ||
140 | char * /* O - Normalized make-and-model string or NULL on error */ | |
141 | _ppdNormalizeMakeAndModel( | |
142 | const char *make_and_model, /* I - Original make-and-model string */ | |
143 | char *buffer, /* I - String buffer */ | |
144 | size_t bufsize) /* I - Size of string buffer */ | |
145 | { | |
146 | char *bufptr; /* Pointer into buffer */ | |
147 | ||
148 | ||
149 | if (!make_and_model || !buffer || bufsize < 1) | |
150 | { | |
151 | if (buffer) | |
152 | *buffer = '\0'; | |
153 | ||
154 | return (NULL); | |
155 | } | |
156 | ||
157 | /* | |
158 | * Skip leading whitespace... | |
159 | */ | |
160 | ||
7cf5915e | 161 | while (_cups_isspace(*make_and_model)) |
5eb9da71 MS |
162 | make_and_model ++; |
163 | ||
164 | /* | |
165 | * Remove parenthesis and add manufacturers as needed... | |
166 | */ | |
167 | ||
168 | if (make_and_model[0] == '(') | |
169 | { | |
170 | strlcpy(buffer, make_and_model + 1, bufsize); | |
171 | ||
172 | if ((bufptr = strrchr(buffer, ')')) != NULL) | |
173 | *bufptr = '\0'; | |
174 | } | |
88f9aafc | 175 | else if (!_cups_strncasecmp(make_and_model, "XPrint", 6)) |
5eb9da71 MS |
176 | { |
177 | /* | |
178 | * Xerox XPrint... | |
179 | */ | |
180 | ||
181 | snprintf(buffer, bufsize, "Xerox %s", make_and_model); | |
182 | } | |
88f9aafc | 183 | else if (!_cups_strncasecmp(make_and_model, "Eastman", 7)) |
5eb9da71 MS |
184 | { |
185 | /* | |
186 | * Kodak... | |
187 | */ | |
188 | ||
189 | snprintf(buffer, bufsize, "Kodak %s", make_and_model + 7); | |
190 | } | |
88f9aafc | 191 | else if (!_cups_strncasecmp(make_and_model, "laserwriter", 11)) |
5eb9da71 MS |
192 | { |
193 | /* | |
194 | * Apple LaserWriter... | |
195 | */ | |
196 | ||
197 | snprintf(buffer, bufsize, "Apple LaserWriter%s", make_and_model + 11); | |
198 | } | |
88f9aafc | 199 | else if (!_cups_strncasecmp(make_and_model, "colorpoint", 10)) |
5eb9da71 MS |
200 | { |
201 | /* | |
202 | * Seiko... | |
203 | */ | |
204 | ||
205 | snprintf(buffer, bufsize, "Seiko %s", make_and_model); | |
206 | } | |
88f9aafc | 207 | else if (!_cups_strncasecmp(make_and_model, "fiery", 5)) |
5eb9da71 MS |
208 | { |
209 | /* | |
210 | * EFI... | |
211 | */ | |
212 | ||
213 | snprintf(buffer, bufsize, "EFI %s", make_and_model); | |
214 | } | |
88f9aafc MS |
215 | else if (!_cups_strncasecmp(make_and_model, "ps ", 3) || |
216 | !_cups_strncasecmp(make_and_model, "colorpass", 9)) | |
5eb9da71 MS |
217 | { |
218 | /* | |
219 | * Canon... | |
220 | */ | |
221 | ||
222 | snprintf(buffer, bufsize, "Canon %s", make_and_model); | |
223 | } | |
88f9aafc MS |
224 | else if (!_cups_strncasecmp(make_and_model, "designjet", 9) || |
225 | !_cups_strncasecmp(make_and_model, "deskjet", 7)) | |
5eb9da71 MS |
226 | { |
227 | /* | |
228 | * HP... | |
229 | */ | |
230 | ||
231 | snprintf(buffer, bufsize, "HP %s", make_and_model); | |
232 | } | |
233 | else | |
234 | strlcpy(buffer, make_and_model, bufsize); | |
235 | ||
236 | /* | |
237 | * Clean up the make... | |
238 | */ | |
239 | ||
88f9aafc | 240 | if (!_cups_strncasecmp(buffer, "agfa", 4)) |
5eb9da71 MS |
241 | { |
242 | /* | |
243 | * Replace with AGFA (all uppercase)... | |
244 | */ | |
245 | ||
246 | buffer[0] = 'A'; | |
247 | buffer[1] = 'G'; | |
248 | buffer[2] = 'F'; | |
249 | buffer[3] = 'A'; | |
250 | } | |
88f9aafc | 251 | else if (!_cups_strncasecmp(buffer, "Hewlett-Packard hp ", 19)) |
5eb9da71 MS |
252 | { |
253 | /* | |
254 | * Just put "HP" on the front... | |
255 | */ | |
256 | ||
257 | buffer[0] = 'H'; | |
258 | buffer[1] = 'P'; | |
259 | _cups_strcpy(buffer + 2, buffer + 18); | |
260 | } | |
88f9aafc | 261 | else if (!_cups_strncasecmp(buffer, "Hewlett-Packard ", 16)) |
5eb9da71 MS |
262 | { |
263 | /* | |
264 | * Just put "HP" on the front... | |
265 | */ | |
266 | ||
267 | buffer[0] = 'H'; | |
268 | buffer[1] = 'P'; | |
269 | _cups_strcpy(buffer + 2, buffer + 15); | |
270 | } | |
88f9aafc | 271 | else if (!_cups_strncasecmp(buffer, "Lexmark International", 21)) |
5eb9da71 MS |
272 | { |
273 | /* | |
274 | * Strip "International"... | |
275 | */ | |
276 | ||
277 | _cups_strcpy(buffer + 8, buffer + 21); | |
278 | } | |
88f9aafc | 279 | else if (!_cups_strncasecmp(buffer, "herk", 4)) |
5eb9da71 MS |
280 | { |
281 | /* | |
282 | * Replace with LHAG... | |
283 | */ | |
284 | ||
285 | buffer[0] = 'L'; | |
286 | buffer[1] = 'H'; | |
287 | buffer[2] = 'A'; | |
288 | buffer[3] = 'G'; | |
289 | } | |
88f9aafc | 290 | else if (!_cups_strncasecmp(buffer, "linotype", 8)) |
5eb9da71 MS |
291 | { |
292 | /* | |
293 | * Replace with LHAG... | |
294 | */ | |
295 | ||
296 | buffer[0] = 'L'; | |
297 | buffer[1] = 'H'; | |
298 | buffer[2] = 'A'; | |
299 | buffer[3] = 'G'; | |
300 | _cups_strcpy(buffer + 4, buffer + 8); | |
301 | } | |
302 | ||
303 | /* | |
304 | * Remove trailing whitespace and return... | |
305 | */ | |
306 | ||
307 | for (bufptr = buffer + strlen(buffer) - 1; | |
7cf5915e | 308 | bufptr >= buffer && _cups_isspace(*bufptr); |
5eb9da71 MS |
309 | bufptr --); |
310 | ||
311 | bufptr[1] = '\0'; | |
312 | ||
313 | return (buffer[0] ? buffer : NULL); | |
314 | } |