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