mirror of https://gitee.com/openkylin/cups.git
328 lines
10 KiB
C++
328 lines
10 KiB
C++
|
//
|
||
|
// PPD file import methods for the CUPS PPD Compiler.
|
||
|
//
|
||
|
// Copyright 2007-2011 by Apple Inc.
|
||
|
// Copyright 2002-2006 by Easy Software Products.
|
||
|
//
|
||
|
// Licensed under Apache License v2.0. See the file "LICENSE" for more information.
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// Include necessary headers...
|
||
|
//
|
||
|
|
||
|
#include "ppdc-private.h"
|
||
|
#include <cups/ppd.h>
|
||
|
|
||
|
|
||
|
//
|
||
|
// 'ppdcSource::import_ppd()' - Import a PPD file.
|
||
|
//
|
||
|
|
||
|
int // O - 1 on success, 0 on failure
|
||
|
ppdcSource::import_ppd(const char *f) // I - Filename
|
||
|
{
|
||
|
int i, j, k; // Looping vars
|
||
|
cups_file_t *fp; // File
|
||
|
char line[256], // Comment line
|
||
|
*ptr; // Pointer into line
|
||
|
int cost; // Cost for filter
|
||
|
ppd_file_t *ppd; // PPD file data
|
||
|
ppd_group_t *group; // PPD group
|
||
|
ppd_option_t *option; // PPD option
|
||
|
ppd_choice_t *choice; // PPD choice
|
||
|
ppd_attr_t *attr; // PPD attribute
|
||
|
ppd_const_t *constraint; // PPD UI constraint
|
||
|
ppd_const_t *constraint2; // Temp PPD UI constraint
|
||
|
ppd_size_t *size; // PPD page size
|
||
|
ppdcDriver *driver; // Driver
|
||
|
ppdcFilter *filter; // Current filter
|
||
|
ppdcFont *font; // Font
|
||
|
ppdcGroup *cgroup; // UI group
|
||
|
ppdcOption *coption; // UI option
|
||
|
ppdcChoice *cchoice; // UI choice
|
||
|
ppdcConstraint *cconstraint; // UI constraint
|
||
|
ppdcMediaSize *csize; // Media size
|
||
|
|
||
|
|
||
|
// Try opening the PPD file...
|
||
|
if ((ppd = ppdOpenFile(f)) == NULL)
|
||
|
return (0);
|
||
|
|
||
|
// All PPD files need a PCFileName attribute...
|
||
|
if (!ppd->pcfilename)
|
||
|
{
|
||
|
ppdClose(ppd);
|
||
|
return (0);
|
||
|
}
|
||
|
|
||
|
// See if the driver has already been imported...
|
||
|
if ((driver = find_driver(ppd->pcfilename)) == NULL)
|
||
|
{
|
||
|
// Create a new PPD file...
|
||
|
if ((fp = cupsFileOpen(f, "r")) == NULL)
|
||
|
{
|
||
|
ppdClose(ppd);
|
||
|
return (0);
|
||
|
}
|
||
|
|
||
|
driver = new ppdcDriver();
|
||
|
driver->type = PPDC_DRIVER_PS;
|
||
|
|
||
|
drivers->add(driver);
|
||
|
|
||
|
// Read the initial comments from the PPD file and use them as the
|
||
|
// copyright/license text...
|
||
|
cupsFileGets(fp, line, sizeof(line));
|
||
|
// Skip *PPD-Adobe-M.m
|
||
|
|
||
|
while (cupsFileGets(fp, line, sizeof(line)))
|
||
|
if (strncmp(line, "*%", 2))
|
||
|
break;
|
||
|
else if (strncmp(line, "*%%%% ", 6))
|
||
|
{
|
||
|
for (ptr = line + 2; isspace(*ptr); ptr ++);
|
||
|
|
||
|
driver->add_copyright(ptr);
|
||
|
}
|
||
|
|
||
|
cupsFileClose(fp);
|
||
|
|
||
|
// Then add the stuff from the PPD file...
|
||
|
if (ppd->modelname && ppd->manufacturer &&
|
||
|
!_cups_strncasecmp(ppd->modelname, ppd->manufacturer,
|
||
|
strlen(ppd->manufacturer)))
|
||
|
{
|
||
|
ptr = ppd->modelname + strlen(ppd->manufacturer);
|
||
|
|
||
|
while (isspace(*ptr))
|
||
|
ptr ++;
|
||
|
}
|
||
|
else
|
||
|
ptr = ppd->modelname;
|
||
|
|
||
|
if (ppd->nickname)
|
||
|
driver->add_attr(new ppdcAttr("NickName", NULL, NULL, ppd->nickname));
|
||
|
|
||
|
if (ppd->shortnickname)
|
||
|
driver->add_attr(new ppdcAttr("ShortNickName", NULL, NULL,
|
||
|
ppd->shortnickname));
|
||
|
|
||
|
driver->manufacturer = new ppdcString(ppd->manufacturer);
|
||
|
driver->model_name = new ppdcString(ptr);
|
||
|
driver->pc_file_name = new ppdcString(ppd->pcfilename);
|
||
|
attr = ppdFindAttr(ppd, "FileVersion", NULL);
|
||
|
driver->version = new ppdcString(attr ? attr->value : NULL);
|
||
|
driver->model_number = ppd->model_number;
|
||
|
driver->manual_copies = ppd->manual_copies;
|
||
|
driver->color_device = ppd->color_device;
|
||
|
driver->throughput = ppd->throughput;
|
||
|
driver->variable_paper_size = ppd->variable_sizes;
|
||
|
driver->max_width = ppd->custom_max[0];
|
||
|
driver->max_length = ppd->custom_max[1];
|
||
|
driver->min_width = ppd->custom_min[0];
|
||
|
driver->min_length = ppd->custom_min[1];
|
||
|
driver->left_margin = ppd->custom_margins[0];
|
||
|
driver->bottom_margin = ppd->custom_margins[1];
|
||
|
driver->right_margin = ppd->custom_margins[2];
|
||
|
driver->top_margin = ppd->custom_margins[3];
|
||
|
|
||
|
for (i = 0; i < ppd->num_filters; i ++)
|
||
|
{
|
||
|
strlcpy(line, ppd->filters[i], sizeof(line));
|
||
|
|
||
|
for (ptr = line; *ptr; ptr ++)
|
||
|
if (isspace(*ptr & 255))
|
||
|
break;
|
||
|
*ptr++ = '\0';
|
||
|
|
||
|
cost = strtol(ptr, &ptr, 10);
|
||
|
|
||
|
while (isspace(*ptr & 255))
|
||
|
ptr ++;
|
||
|
|
||
|
filter = new ppdcFilter(line, ptr, cost);
|
||
|
driver->add_filter(filter);
|
||
|
}
|
||
|
|
||
|
attr = ppdFindAttr(ppd, "DefaultFont", NULL);
|
||
|
driver->default_font = new ppdcString(attr ? attr->value : NULL);
|
||
|
|
||
|
// Collect media sizes...
|
||
|
ppd_option_t *region_option, // PageRegion option
|
||
|
*size_option; // PageSize option
|
||
|
ppd_choice_t *region_choice, // PageRegion choice
|
||
|
*size_choice; // PageSize choice
|
||
|
|
||
|
region_option = ppdFindOption(ppd, "PageRegion");
|
||
|
size_option = ppdFindOption(ppd, "PageSize");
|
||
|
|
||
|
for (i = ppd->num_sizes, size = ppd->sizes; i > 0; i --, size ++)
|
||
|
{
|
||
|
// Don't do custom size here...
|
||
|
if (!_cups_strcasecmp(size->name, "Custom"))
|
||
|
continue;
|
||
|
|
||
|
// Get the code for the PageSize and PageRegion options...
|
||
|
region_choice = ppdFindChoice(region_option, size->name);
|
||
|
size_choice = ppdFindChoice(size_option, size->name);
|
||
|
|
||
|
// Create a new media size record and add it to the driver...
|
||
|
csize = new ppdcMediaSize(size->name, size_choice->text, size->width,
|
||
|
size->length, size->left, size->bottom,
|
||
|
size->width - size->right,
|
||
|
size->length - size->top,
|
||
|
size_choice->code, region_choice->code);
|
||
|
|
||
|
driver->add_size(csize);
|
||
|
|
||
|
if (!_cups_strcasecmp(size_option->defchoice, size->name))
|
||
|
driver->set_default_size(csize);
|
||
|
}
|
||
|
|
||
|
// Now all of the options...
|
||
|
for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
|
||
|
{
|
||
|
cgroup = new ppdcGroup(group->name, group->text);
|
||
|
driver->add_group(cgroup);
|
||
|
|
||
|
for (j = group->num_options, option = group->options; j > 0; j --, option ++)
|
||
|
{
|
||
|
if (!strcmp(option->keyword, "PageSize") || !strcmp(option->keyword, "PageRegion"))
|
||
|
continue;
|
||
|
|
||
|
coption = new ppdcOption((ppdcOptType)option->ui, option->keyword,
|
||
|
option->text, (ppdcOptSection)option->section,
|
||
|
option->order);
|
||
|
cgroup->add_option(coption);
|
||
|
|
||
|
for (k = option->num_choices, choice = option->choices; k > 0; k --, choice ++)
|
||
|
{
|
||
|
if (!strcmp(choice->choice, "Custom"))
|
||
|
continue;
|
||
|
|
||
|
cchoice = new ppdcChoice(choice->choice, choice->text, choice->code);
|
||
|
coption->add_choice(cchoice);
|
||
|
|
||
|
if (!_cups_strcasecmp(option->defchoice, choice->choice))
|
||
|
coption->set_defchoice(cchoice);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Now the constraints...
|
||
|
for (i = ppd->num_consts, constraint = ppd->consts;
|
||
|
i > 0;
|
||
|
i --, constraint ++)
|
||
|
{
|
||
|
// Look for mirrored constraints...
|
||
|
for (j = i - 1, constraint2 = constraint + 1;
|
||
|
j > 0;
|
||
|
j --, constraint2 ++)
|
||
|
if (!strcmp(constraint->option1, constraint2->option2) &&
|
||
|
!strcmp(constraint->choice1, constraint2->choice2) &&
|
||
|
!strcmp(constraint->option2, constraint2->option1) &&
|
||
|
!strcmp(constraint->choice2, constraint2->choice1))
|
||
|
break;
|
||
|
|
||
|
if (j)
|
||
|
continue;
|
||
|
|
||
|
cconstraint = new ppdcConstraint(constraint->option2, constraint->choice2,
|
||
|
constraint->option1, constraint->choice1);
|
||
|
driver->add_constraint(cconstraint);
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < ppd->num_attrs; i ++)
|
||
|
{
|
||
|
attr = ppd->attrs[i];
|
||
|
|
||
|
if (!strcmp(attr->name, "Font"))
|
||
|
{
|
||
|
// Font...
|
||
|
char encoding[256], // Encoding string
|
||
|
version[256], // Version string
|
||
|
charset[256], // Charset string
|
||
|
status[256]; // Status string
|
||
|
ppdcFontStatus fstatus; // Status enumeration
|
||
|
|
||
|
|
||
|
if (sscanf(attr->value, "%s%*[^\"]\"%[^\"]\"%s%s", encoding, version,
|
||
|
charset, status) != 4)
|
||
|
{
|
||
|
_cupsLangPrintf(stderr, _("ppdc: Bad font attribute: %s"),
|
||
|
attr->value);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (!strcmp(status, "ROM"))
|
||
|
fstatus = PPDC_FONT_ROM;
|
||
|
else
|
||
|
fstatus = PPDC_FONT_DISK;
|
||
|
|
||
|
font = new ppdcFont(attr->spec, encoding, version, charset, fstatus);
|
||
|
|
||
|
driver->add_font(font);
|
||
|
}
|
||
|
else if (!strcmp(attr->name, "CustomPageSize"))
|
||
|
{
|
||
|
driver->set_custom_size_code(attr->value);
|
||
|
}
|
||
|
else if ((strncmp(attr->name, "Default", 7) ||
|
||
|
!strcmp(attr->name, "DefaultColorSpace")) &&
|
||
|
strcmp(attr->name, "ColorDevice") &&
|
||
|
strcmp(attr->name, "Manufacturer") &&
|
||
|
strcmp(attr->name, "ModelName") &&
|
||
|
strcmp(attr->name, "MaxMediaHeight") &&
|
||
|
strcmp(attr->name, "MaxMediaWidth") &&
|
||
|
strcmp(attr->name, "NickName") &&
|
||
|
strcmp(attr->name, "ParamCustomPageSize") &&
|
||
|
strcmp(attr->name, "ShortNickName") &&
|
||
|
strcmp(attr->name, "Throughput") &&
|
||
|
strcmp(attr->name, "PCFileName") &&
|
||
|
strcmp(attr->name, "FileVersion") &&
|
||
|
strcmp(attr->name, "FormatVersion") &&
|
||
|
strcmp(attr->name, "HWMargins") &&
|
||
|
strcmp(attr->name, "VariablePaperSize") &&
|
||
|
strcmp(attr->name, "LanguageEncoding") &&
|
||
|
strcmp(attr->name, "LanguageVersion") &&
|
||
|
strcmp(attr->name, "cupsFilter") &&
|
||
|
strcmp(attr->name, "cupsFlipDuplex") &&
|
||
|
strcmp(attr->name, "cupsLanguages") &&
|
||
|
strcmp(attr->name, "cupsManualCopies") &&
|
||
|
strcmp(attr->name, "cupsModelNumber") &&
|
||
|
strcmp(attr->name, "cupsVersion"))
|
||
|
{
|
||
|
if ((ptr = strchr(attr->name, '.')) != NULL &&
|
||
|
((ptr - attr->name) == 2 || (ptr - attr->name) == 5))
|
||
|
{
|
||
|
// Might be a localization attribute; test further...
|
||
|
if (isalpha(attr->name[0] & 255) &&
|
||
|
isalpha(attr->name[1] & 255) &&
|
||
|
(attr->name[2] == '.' ||
|
||
|
(attr->name[2] == '_' && isalpha(attr->name[3] & 255) &&
|
||
|
isalpha(attr->name[4] & 255))))
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// Attribute...
|
||
|
driver->add_attr(new ppdcAttr(attr->name, attr->spec, attr->text,
|
||
|
attr->value));
|
||
|
}
|
||
|
else if (!strncmp(attr->name, "Default", 7) &&
|
||
|
!ppdFindOption(ppd, attr->name + 7) &&
|
||
|
strcmp(attr->name, "DefaultFont") &&
|
||
|
strcmp(attr->name, "DefaultImageableArea") &&
|
||
|
strcmp(attr->name, "DefaultPaperDimension") &&
|
||
|
strcmp(attr->name, "DefaultFont"))
|
||
|
{
|
||
|
// Default attribute...
|
||
|
driver->add_attr(new ppdcAttr(attr->name, attr->spec, attr->text,
|
||
|
attr->value));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return (1);
|
||
|
}
|