You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
314 lines
6.5 KiB
314 lines
6.5 KiB
/* |
|
* PPD model-specific attribute routines for CUPS. |
|
* |
|
* Copyright 2007-2015 by Apple Inc. |
|
* Copyright 1997-2006 by Easy Software Products. |
|
* |
|
* These coded instructions, statements, and computer programs are the |
|
* property of Apple Inc. and are protected by Federal copyright |
|
* law. Distribution and use rights are outlined in the file "LICENSE.txt" |
|
* which should have been included with this file. If this file is |
|
* missing or damaged, see the license at "http://www.cups.org/". |
|
*/ |
|
|
|
/* |
|
* Include necessary headers... |
|
*/ |
|
|
|
#include "cups-private.h" |
|
#include "ppd-private.h" |
|
|
|
|
|
/* |
|
* 'ppdFindAttr()' - Find the first matching attribute. |
|
* |
|
* @since CUPS 1.1.19/macOS 10.3@ |
|
*/ |
|
|
|
ppd_attr_t * /* O - Attribute or @code NULL@ if not found */ |
|
ppdFindAttr(ppd_file_t *ppd, /* I - PPD file data */ |
|
const char *name, /* I - Attribute name */ |
|
const char *spec) /* I - Specifier string or @code NULL@ */ |
|
{ |
|
ppd_attr_t key, /* Search key */ |
|
*attr; /* Current attribute */ |
|
|
|
|
|
DEBUG_printf(("2ppdFindAttr(ppd=%p, name=\"%s\", spec=\"%s\")", ppd, name, |
|
spec)); |
|
|
|
/* |
|
* Range check input... |
|
*/ |
|
|
|
if (!ppd || !name || ppd->num_attrs == 0) |
|
return (NULL); |
|
|
|
/* |
|
* Search for a matching attribute... |
|
*/ |
|
|
|
memset(&key, 0, sizeof(key)); |
|
strlcpy(key.name, name, sizeof(key.name)); |
|
|
|
/* |
|
* Return the first matching attribute, if any... |
|
*/ |
|
|
|
if ((attr = (ppd_attr_t *)cupsArrayFind(ppd->sorted_attrs, &key)) != NULL) |
|
{ |
|
if (spec) |
|
{ |
|
/* |
|
* Loop until we find the first matching attribute for "spec"... |
|
*/ |
|
|
|
while (attr && _cups_strcasecmp(spec, attr->spec)) |
|
{ |
|
if ((attr = (ppd_attr_t *)cupsArrayNext(ppd->sorted_attrs)) != NULL && |
|
_cups_strcasecmp(attr->name, name)) |
|
attr = NULL; |
|
} |
|
} |
|
} |
|
|
|
return (attr); |
|
} |
|
|
|
|
|
/* |
|
* 'ppdFindNextAttr()' - Find the next matching attribute. |
|
* |
|
* @since CUPS 1.1.19/macOS 10.3@ |
|
*/ |
|
|
|
ppd_attr_t * /* O - Attribute or @code NULL@ if not found */ |
|
ppdFindNextAttr(ppd_file_t *ppd, /* I - PPD file data */ |
|
const char *name, /* I - Attribute name */ |
|
const char *spec) /* I - Specifier string or @code NULL@ */ |
|
{ |
|
ppd_attr_t *attr; /* Current attribute */ |
|
|
|
|
|
/* |
|
* Range check input... |
|
*/ |
|
|
|
if (!ppd || !name || ppd->num_attrs == 0) |
|
return (NULL); |
|
|
|
/* |
|
* See if there are more attributes to return... |
|
*/ |
|
|
|
while ((attr = (ppd_attr_t *)cupsArrayNext(ppd->sorted_attrs)) != NULL) |
|
{ |
|
/* |
|
* Check the next attribute to see if it is a match... |
|
*/ |
|
|
|
if (_cups_strcasecmp(attr->name, name)) |
|
{ |
|
/* |
|
* Nope, reset the current pointer to the end of the array... |
|
*/ |
|
|
|
cupsArrayIndex(ppd->sorted_attrs, cupsArrayCount(ppd->sorted_attrs)); |
|
|
|
return (NULL); |
|
} |
|
|
|
if (!spec || !_cups_strcasecmp(attr->spec, spec)) |
|
break; |
|
} |
|
|
|
/* |
|
* Return the next attribute's value... |
|
*/ |
|
|
|
return (attr); |
|
} |
|
|
|
|
|
/* |
|
* '_ppdNormalizeMakeAndModel()' - Normalize a product/make-and-model string. |
|
* |
|
* This function tries to undo the mistakes made by many printer manufacturers |
|
* to produce a clean make-and-model string we can use. |
|
*/ |
|
|
|
char * /* O - Normalized make-and-model string or NULL on error */ |
|
_ppdNormalizeMakeAndModel( |
|
const char *make_and_model, /* I - Original make-and-model string */ |
|
char *buffer, /* I - String buffer */ |
|
size_t bufsize) /* I - Size of string buffer */ |
|
{ |
|
char *bufptr; /* Pointer into buffer */ |
|
|
|
|
|
if (!make_and_model || !buffer || bufsize < 1) |
|
{ |
|
if (buffer) |
|
*buffer = '\0'; |
|
|
|
return (NULL); |
|
} |
|
|
|
/* |
|
* Skip leading whitespace... |
|
*/ |
|
|
|
while (_cups_isspace(*make_and_model)) |
|
make_and_model ++; |
|
|
|
/* |
|
* Remove parenthesis and add manufacturers as needed... |
|
*/ |
|
|
|
if (make_and_model[0] == '(') |
|
{ |
|
strlcpy(buffer, make_and_model + 1, bufsize); |
|
|
|
if ((bufptr = strrchr(buffer, ')')) != NULL) |
|
*bufptr = '\0'; |
|
} |
|
else if (!_cups_strncasecmp(make_and_model, "XPrint", 6)) |
|
{ |
|
/* |
|
* Xerox XPrint... |
|
*/ |
|
|
|
snprintf(buffer, bufsize, "Xerox %s", make_and_model); |
|
} |
|
else if (!_cups_strncasecmp(make_and_model, "Eastman", 7)) |
|
{ |
|
/* |
|
* Kodak... |
|
*/ |
|
|
|
snprintf(buffer, bufsize, "Kodak %s", make_and_model + 7); |
|
} |
|
else if (!_cups_strncasecmp(make_and_model, "laserwriter", 11)) |
|
{ |
|
/* |
|
* Apple LaserWriter... |
|
*/ |
|
|
|
snprintf(buffer, bufsize, "Apple LaserWriter%s", make_and_model + 11); |
|
} |
|
else if (!_cups_strncasecmp(make_and_model, "colorpoint", 10)) |
|
{ |
|
/* |
|
* Seiko... |
|
*/ |
|
|
|
snprintf(buffer, bufsize, "Seiko %s", make_and_model); |
|
} |
|
else if (!_cups_strncasecmp(make_and_model, "fiery", 5)) |
|
{ |
|
/* |
|
* EFI... |
|
*/ |
|
|
|
snprintf(buffer, bufsize, "EFI %s", make_and_model); |
|
} |
|
else if (!_cups_strncasecmp(make_and_model, "ps ", 3) || |
|
!_cups_strncasecmp(make_and_model, "colorpass", 9)) |
|
{ |
|
/* |
|
* Canon... |
|
*/ |
|
|
|
snprintf(buffer, bufsize, "Canon %s", make_and_model); |
|
} |
|
else if (!_cups_strncasecmp(make_and_model, "designjet", 9) || |
|
!_cups_strncasecmp(make_and_model, "deskjet", 7)) |
|
{ |
|
/* |
|
* HP... |
|
*/ |
|
|
|
snprintf(buffer, bufsize, "HP %s", make_and_model); |
|
} |
|
else |
|
strlcpy(buffer, make_and_model, bufsize); |
|
|
|
/* |
|
* Clean up the make... |
|
*/ |
|
|
|
if (!_cups_strncasecmp(buffer, "agfa", 4)) |
|
{ |
|
/* |
|
* Replace with AGFA (all uppercase)... |
|
*/ |
|
|
|
buffer[0] = 'A'; |
|
buffer[1] = 'G'; |
|
buffer[2] = 'F'; |
|
buffer[3] = 'A'; |
|
} |
|
else if (!_cups_strncasecmp(buffer, "Hewlett-Packard hp ", 19)) |
|
{ |
|
/* |
|
* Just put "HP" on the front... |
|
*/ |
|
|
|
buffer[0] = 'H'; |
|
buffer[1] = 'P'; |
|
_cups_strcpy(buffer + 2, buffer + 18); |
|
} |
|
else if (!_cups_strncasecmp(buffer, "Hewlett-Packard ", 16)) |
|
{ |
|
/* |
|
* Just put "HP" on the front... |
|
*/ |
|
|
|
buffer[0] = 'H'; |
|
buffer[1] = 'P'; |
|
_cups_strcpy(buffer + 2, buffer + 15); |
|
} |
|
else if (!_cups_strncasecmp(buffer, "Lexmark International", 21)) |
|
{ |
|
/* |
|
* Strip "International"... |
|
*/ |
|
|
|
_cups_strcpy(buffer + 8, buffer + 21); |
|
} |
|
else if (!_cups_strncasecmp(buffer, "herk", 4)) |
|
{ |
|
/* |
|
* Replace with LHAG... |
|
*/ |
|
|
|
buffer[0] = 'L'; |
|
buffer[1] = 'H'; |
|
buffer[2] = 'A'; |
|
buffer[3] = 'G'; |
|
} |
|
else if (!_cups_strncasecmp(buffer, "linotype", 8)) |
|
{ |
|
/* |
|
* Replace with LHAG... |
|
*/ |
|
|
|
buffer[0] = 'L'; |
|
buffer[1] = 'H'; |
|
buffer[2] = 'A'; |
|
buffer[3] = 'G'; |
|
_cups_strcpy(buffer + 4, buffer + 8); |
|
} |
|
|
|
/* |
|
* Remove trailing whitespace and return... |
|
*/ |
|
|
|
for (bufptr = buffer + strlen(buffer) - 1; |
|
bufptr >= buffer && _cups_isspace(*bufptr); |
|
bufptr --); |
|
|
|
bufptr[1] = '\0'; |
|
|
|
return (buffer[0] ? buffer : NULL); |
|
}
|
|
|