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