//
// "$Id: ppdc-import.cxx 343 2007-07-13 19:52:48Z mike $"
//
//   PPD file import methods for the CUPS PPD Compiler.
//
//   Copyright 2007 by Apple Inc.
//   Copyright 2002-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
//   file is missing or damaged, see the license at "http://www.cups.org/".
//
// Contents:
//
//   ppdcSource::import_ppd() - Import a PPD file.
//   ppd_gets()               - Get a line from a PPD file.
//

//
// Include necessary headers...
//

#include "ppdc.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
  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
  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
      {
        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 &&
        !strncasecmp(ppd->modelname, ppd->manufacturer,
                     strlen(ppd->manufacturer)))
    {
      ptr = ppd->modelname + strlen(ppd->manufacturer);

      while (isspace(*ptr))
        ptr ++;
    }
    else
      ptr = ppd->modelname;

    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;

    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 (!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 (!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 ++)
        {
          cchoice = new ppdcChoice(choice->choice, choice->text, choice->code);
          coption->add_choice(cchoice);

          if (!strcasecmp(option->defchoice, choice->choice))
            coption->set_defchoice(cchoice);
        }
      }
    }

    // Now the constraints...
    for (i = ppd->num_consts, constraint = ppd->consts;
         i > 0;
	 i --, constraint ++)
    {
      for (j = i - 1, constraint2 = constraint;
           j > 0;
	   j --, constraint2 ++)
	if (constraint != constraint2 &&
	    !strcmp(constraint->option1, constraint2->option2) &&
	    (constraint->choice1 == constraint2->choice2 ||
	     (constraint->choice1 && constraint2->choice2 &&
	      !strcmp(constraint->choice1, constraint2->choice2))) &&
	    !strcmp(constraint->option2, constraint2->option1) &&
	    (constraint->choice2 == constraint2->choice1 ||
	     (constraint->choice2 && constraint2->choice1 &&
	      !strcmp(constraint->choice2, constraint2->choice1))))
          break;

      if (j)
        continue;

      cconstraint = new ppdcConstraint(constraint->option1, constraint->choice1,
                                       constraint->option2, constraint->choice2);
      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)
	{
	  fprintf(stderr, "Bad font attribute: %s\n", 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 ((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, "ShortNickName") &&
	       strcmp(attr->name, "Throughput") &&
	       strcmp(attr->name, "PCFileName") &&
	       strcmp(attr->name, "FileVersion") &&
	       strcmp(attr->name, "FormatVersion") &&
	       strcmp(attr->name, "VariablePaperSize") &&
	       strcmp(attr->name, "LanguageEncoding") &&
	       strcmp(attr->name, "LanguageVersion"))
      {
        // 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);
}


//
// End of "$Id: ppdc-import.cxx 343 2007-07-13 19:52:48Z mike $".
//
