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