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