Blame ppdc/ppdc-import.cxx

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