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.
313 lines
6.3 KiB
313 lines
6.3 KiB
/*
|
|
* PPD model-specific attribute routines for CUPS.
|
|
*
|
|
* Copyright 2007-2015 by Apple Inc.
|
|
* Copyright 1997-2006 by Easy Software Products.
|
|
*
|
|
* Licensed under Apache License v2.0. See the file "LICENSE" for more
|
|
* information.
|
|
*/
|
|
|
|
/*
|
|
* Include necessary headers...
|
|
*/
|
|
|
|
#include "cups-private.h"
|
|
#include "ppd-private.h"
|
|
#include "debug-internal.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);
|
|
}
|