Exemplo n.º 1
0
static void
ppd_defaults(ppd_file_t  *ppd,		/* I - PPD file */
             ppd_group_t *g)		/* I - Group to default */
{
  int		i;			/* Looping var */
  ppd_option_t	*o;			/* Current option */
  ppd_group_t	*sg;			/* Current sub-group */


  for (i = g->num_options, o = g->options; i > 0; i --, o ++)
    if (_cups_strcasecmp(o->keyword, "PageRegion") != 0)
      ppdMarkOption(ppd, o->keyword, o->defchoice);

  for (i = g->num_subgroups, sg = g->subgroups; i > 0; i --, sg ++)
    ppd_defaults(ppd, sg);
}
Exemplo n.º 2
0
static void
ppd_handle_media(ppd_file_t *ppd)	/* I - PPD file */
{
  ppd_choice_t	*manual_feed,		/* ManualFeed choice, if any */
		*input_slot;		/* InputSlot choice, if any */
  ppd_size_t	*size;			/* Current media size */
  ppd_attr_t	*rpr;			/* RequiresPageRegion value */


 /*
  * This function determines what page size code to use, if any, for the
  * current media size, InputSlot, and ManualFeed selections.
  *
  * We use the PageSize code if:
  *
  * 1. A custom media size is selected.
  * 2. ManualFeed and InputSlot are not selected (or do not exist).
  * 3. ManualFeed is selected but is False and InputSlot is not selected or
  *    the selection has no code - the latter check done to support "auto" or
  *    "printer default" InputSlot options.
  *
  * We use the PageRegion code if:
  *
  * 4. RequiresPageRegion does not exist and the PPD contains cupsFilter
  *    keywords, indicating this is a CUPS-based driver.
  * 5. RequiresPageRegion exists for the selected InputSlot (or "All" for any
  *    InputSlot or ManualFeed selection) and is True.
  *
  * If none of the 5 conditions are true, no page size code is used and we
  * unmark any existing PageSize or PageRegion choices.
  */

  if ((size = ppdPageSize(ppd, NULL)) == NULL)
    return;

  manual_feed = ppdFindMarkedChoice(ppd, "ManualFeed");
  input_slot  = ppdFindMarkedChoice(ppd, "InputSlot");

  if (input_slot != NULL)
    rpr = ppdFindAttr(ppd, "RequiresPageRegion", input_slot->choice);
  else
    rpr = NULL;

  if (!rpr)
    rpr = ppdFindAttr(ppd, "RequiresPageRegion", "All");

  if (!_cups_strcasecmp(size->name, "Custom") ||
      (!manual_feed && !input_slot) ||
      (manual_feed && !_cups_strcasecmp(manual_feed->choice, "False") &&
       (!input_slot || (input_slot->code && !input_slot->code[0]))) ||
      (!rpr && ppd->num_filters > 0))
  {
   /*
    * Use PageSize code...
    */

    ppdMarkOption(ppd, "PageSize", size->name);
  }
  else if (rpr && rpr->value && !_cups_strcasecmp(rpr->value, "True"))
  {
   /*
    * Use PageRegion code...
    */

    ppdMarkOption(ppd, "PageRegion", size->name);
  }
  else
  {
   /*
    * Do not use PageSize or PageRegion code...
    */

    ppd_choice_t	*page;		/* PageSize/Region choice, if any */

    if ((page = ppdFindMarkedChoice(ppd, "PageSize")) != NULL)
    {
     /*
      * Unmark PageSize...
      */

      page->marked = 0;
      cupsArrayRemove(ppd->marked, page);
    }

    if ((page = ppdFindMarkedChoice(ppd, "PageRegion")) != NULL)
    {
     /*
      * Unmark PageRegion...
      */

      page->marked = 0;
      cupsArrayRemove(ppd->marked, page);
    }
  }
}
Exemplo n.º 3
0
int					/* O - Exit status */
main(int  argc,				/* I - Number of command-line arguments */
     char *argv[])			/* I - Command-line arguments */
{
  int		i;			/* Looping var */
  ppd_file_t	*ppd;			/* PPD file loaded from disk */
  char		line[256],		/* Input buffer */
		*ptr,			/* Pointer into buffer */
		*optr,			/* Pointer to first option name */
		*cptr;			/* Pointer to first choice */
  int		num_options;		/* Number of options */
  cups_option_t	*options;		/* Options */
  char		*option,		/* Current option */
		*choice;		/* Current choice */


  if (argc != 2)
  {
    puts("Usage: testconflicts filename.ppd");
    return (1);
  }

  if ((ppd = ppdOpenFile(argv[1])) == NULL)
  {
    ppd_status_t	err;		/* Last error in file */
    int			linenum;	/* Line number in file */

    err = ppdLastError(&linenum);

    printf("Unable to open PPD file \"%s\": %s on line %d\n", argv[1],
           ppdErrorString(err), linenum);
    return (1);
  }

  ppdMarkDefaults(ppd);

  option = NULL;
  choice = NULL;

  for (;;)
  {
    num_options = 0;
    options     = NULL;

    if (!cupsResolveConflicts(ppd, option, choice, &num_options, &options))
      puts("Unable to resolve conflicts!");
    else if ((!option && num_options > 0) || (option && num_options > 1))
    {
      fputs("Resolved conflicts with the following options:\n   ", stdout);
      for (i = 0; i < num_options; i ++)
        if (!option || _cups_strcasecmp(option, options[i].name))
	  printf(" %s=%s", options[i].name, options[i].value);
      putchar('\n');

      cupsFreeOptions(num_options, options);
    }

    if (option)
    {
      free(option);
      option = NULL;
    }

    if (choice)
    {
      free(choice);
      choice = NULL;
    }

    printf("\nNew Option(s): ");
    fflush(stdout);
    if (!fgets(line, sizeof(line), stdin) || line[0] == '\n')
      break;

    for (ptr = line; isspace(*ptr & 255); ptr ++);
    for (optr = ptr; *ptr && *ptr != '='; ptr ++);
    if (!*ptr)
      break;
    for (*ptr++ = '\0', cptr = ptr; *ptr && !isspace(*ptr & 255); ptr ++);
    if (!*ptr)
      break;
    *ptr++ = '\0';

    option      = strdup(optr);
    choice      = strdup(cptr);
    num_options = cupsParseOptions(ptr, 0, &options);

    ppdMarkOption(ppd, option, choice);
    if (cupsMarkOptions(ppd, num_options, options))
      puts("Options Conflict!");
    cupsFreeOptions(num_options, options);
  }

  if (option)
    free(option);
  if (choice)
    free(choice);

  return (0);
}
Exemplo n.º 4
0
int					/* O - Exit status */
imagetops_main(int  argc,				/* I - Number of command-line arguments */
     char *argv[])			/* I - Command-line arguments */
{
  cups_image_t	*img;			/* Image to print */
  float		xprint,			/* Printable area */
		yprint,
		xinches,		/* Total size in inches */
		yinches;
  float		xsize,			/* Total size in points */
		ysize,
		xsize2,
		ysize2;
  float		aspect;			/* Aspect ratio */
  int		xpages,			/* # x pages */
		ypages,			/* # y pages */
		xpage,			/* Current x page */
		ypage,			/* Current y page */
		page;			/* Current page number */
  int		xc0, yc0,			/* Corners of the page in image coords */
		xc1, yc1;
  cups_ib_t	*row;			/* Current row */
  int		y;			/* Current Y coordinate in image */
  int		colorspace;		/* Output colorspace */
  int		out_offset,		/* Offset into output buffer */
		out_length;		/* Length of output buffer */
  ppd_file_t	*ppd;			/* PPD file */
  ppd_choice_t	*choice;		/* PPD option choice */
  int		num_options;		/* Number of print options */
  cups_option_t	*options;		/* Print options */
  const char	*val;			/* Option value */
  int		slowcollate;		/* Collate copies the slow way */
  float		g;			/* Gamma correction value */
  float		b;			/* Brightness factor */
  float		zoom;			/* Zoom facter */
  int		xppi, yppi;		/* Pixels-per-inch */
  int		hue, sat;		/* Hue and saturation adjustment */
  int		realcopies,		/* Real copies being printed */
		emit_jcl;		/* Emit JCL? */
  float		left, top;		/* Left and top of image */
  char		filename[1024];		/* Name of file to print */
  time_t	curtime;		/* Current time */
  struct tm	*curtm;			/* Current date */
  char		curdate[255];		/* Current date string */
  int psFileMode = 0; //0:CREATE New ; 1: Append
  int outColorDevice = 1; //0 : monochrome print , 1:color print
  int count = 0,numFiles=1;
  int defout,outfd;
 /*
  * Make sure status messages are not buffered...
  */

	int ii=0;
	for(;ii<argc;ii++)
		LOGI("imagetops : argv:%s",argv[ii]);

  fflush(stdout);

  Copies = 1;	
  
  setbuf(stderr, NULL);

 /*
  * Ignore broken pipe signals...
  */

  signal(SIGPIPE, SIG_IGN);

 	
 /*
  * Process command-line options and write the prolog...
  */

  zoom = 0.0;
  xppi = 0;
  yppi = 0;
  hue  = 0;
  sat  = 100;
  g    = 1.0;
  b    = 1.0;

  Copies = atoi(argv[4]);

  options     = NULL;
  num_options = cupsParseOptions(argv[5], 0, &options);

  ppdFilePath = argv[6];
  ContentType= argv[7];
  psFilePath = argv[8];
  outColorDevice = atoi(argv[9]);
  numFiles = argc - 10;
  LOGI("imagetops : numFiles=%d",numFiles);
  
  
  ppd = SetCommonOptions(num_options, options, 0);
  
  if ((val = cupsGetOption("multiple-document-handling", num_options, options)) != NULL)
  {
   /*
    * This IPP attribute is unnecessarily complicated...
    *
    *   single-document, separate-documents-collated-copies, and
    *   single-document-new-sheet all require collated copies.
    *
    *   separate-documents-uncollated-copies allows for uncollated copies.
    */

    Collate = _cups_strcasecmp(val, "separate-documents-uncollated-copies") != 0;
  }

  if ((val = cupsGetOption("Collate", num_options, options)) != NULL &&
      _cups_strcasecmp(val, "True") == 0)
    Collate = 1;

  if ((val = cupsGetOption("gamma", num_options, options)) != NULL)
  {
   /*
    * Get gamma value from 1 to 10000...
    */

    g = atoi(val) * 0.001f;

    if (g < 0.001f)
      g = 0.001f;
    else if (g > 10.0f)
      g = 10.0f;
  }

  if ((val = cupsGetOption("brightness", num_options, options)) != NULL)
  {
   /*
    * Get brightness value from 10 to 1000.
    */

    b = atoi(val) * 0.01f;

    if (b < 0.1f)
      b = 0.1f;
    else if (b > 10.0f)
      b = 10.0f;
  }

  if ((val = cupsGetOption("scaling", num_options, options)) != NULL)
		zoom = atoi(val) * 0.01;
  else if ((val = cupsGetOption("fitplot", num_options, options)) != NULL &&
           !_cups_strcasecmp(val, "true"))
		zoom = 1.0;
  else if ((val = cupsGetOption("fit-to-page", num_options, options)) != NULL &&
           !_cups_strcasecmp(val, "true"))
    zoom = 1.0;

  if ((val = cupsGetOption("ppi", num_options, options)) != NULL)
    if (sscanf(val, "%dx%d", &xppi, &yppi) < 2)
      yppi = xppi;

  if ((val = cupsGetOption("position", num_options, options)) != NULL)
  {
    if (_cups_strcasecmp(val, "center") == 0)
    {
      XPosition = 0;
      YPosition = 0;
    }
    else if (_cups_strcasecmp(val, "top") == 0)
    {
      XPosition = 0;
      YPosition = 1;
    }
    else if (_cups_strcasecmp(val, "left") == 0)
    {
      XPosition = -1;
      YPosition = 0;
    }
    else if (_cups_strcasecmp(val, "right") == 0)
    {
      XPosition = 1;
      YPosition = 0;
    }
    else if (_cups_strcasecmp(val, "top-left") == 0)
    {
      XPosition = -1;
      YPosition = 1;
    }
    else if (_cups_strcasecmp(val, "top-right") == 0)
    {
      XPosition = 1;
      YPosition = 1;
    }
    else if (_cups_strcasecmp(val, "bottom") == 0)
    {
      XPosition = 0;
      YPosition = -1;
    }
    else if (_cups_strcasecmp(val, "bottom-left") == 0)
    {
      XPosition = -1;
      YPosition = -1;
    }
    else if (_cups_strcasecmp(val, "bottom-right") == 0)
    {
      XPosition = 1;
      YPosition = -1;
    }
  }

  if ((val = cupsGetOption("saturation", num_options, options)) != NULL)
    sat = atoi(val);

  if ((val = cupsGetOption("hue", num_options, options)) != NULL)
    hue = atoi(val);

  if ((choice = ppdFindMarkedChoice(ppd, "MirrorPrint")) != NULL)
  {
    val = choice->choice;
    choice->marked = 0;
  }
  else
    val = cupsGetOption("mirror", num_options, options);

  if (val && (!_cups_strcasecmp(val, "true") || !_cups_strcasecmp(val, "on") ||
              !_cups_strcasecmp(val, "yes")))
    Flip = 1;

  if ((val = cupsGetOption("emit-jcl", num_options, options)) != NULL &&
      (!_cups_strcasecmp(val, "false") || !_cups_strcasecmp(val, "off") ||
       !_cups_strcasecmp(val, "no") || !strcmp(val, "0")))
    emit_jcl = 0;
  else
    emit_jcl = 1;

  LOGI("imagetops/Copies=%d , Collate=%d, gamma=%f, brightness=%f, zoom=%f",Copies,Collate,g,b,zoom);
  LOGI("imagetops/xppi=%d,yppi=%d,XPosition=%d,YPosition=%d,sat=%d,hue=%d,flip=%d,emit_jcl=%d",xppi,yppi,XPosition,YPosition,sat,hue,Flip,emit_jcl);
 /*
  * Open the input image to print...
  */
  
	if(outColorDevice == 1) //added @ grv
		colorspace = CUPS_IMAGE_RGB_CMYK;
	else
		colorspace = CUPS_IMAGE_WHITE;

	LOGI("imagetops/ colorspace = %d",colorspace);
		
	for(count=0;count<numFiles;count++){
		Copies = atoi(argv[4]);
		//do everything for both image files
		strlcpy(filename, argv[(10 + count)], sizeof(filename)); 
		LOGI("imagetops : count=%d , filename=%s",count,filename);
		img = cupsImageOpen(filename, colorspace, CUPS_IMAGE_WHITE, sat, hue, NULL);
		if (img == NULL)
		{
			LOGI("imagetops:error:The print file could not be opened.");
			_cupsLangPrintFilter(stderr, "ERROR",
							 _("The print file could not be opened."));
			ppdClose(ppd);
			return (1);
		}
		colorspace = cupsImageGetColorSpace(img);
		LOGI("imagetops: cupsImageGetColorSpace finished : colorspace :%d",colorspace);
		/*
		* Scale as necessary...
		*/
			
		if (zoom == 0.0 && xppi == 0)
		{
			xppi = cupsImageGetXPPI(img);
			yppi = cupsImageGetYPPI(img);
		}
		LOGI("imagetops:xppi=%d",xppi);
		LOGI("imagetops:yppi=%d",yppi);
		if (yppi == 0)
			yppi = xppi;

		fprintf(stderr, "DEBUG: Before scaling: xppi=%d, yppi=%d, zoom=%.2f\n",
			  xppi, yppi, zoom);
		if (xppi > 0)
		{
			/*
			* Scale the image as neccesary to match the desired pixels-per-inch.
			*/

			if (Orientation & 1)
			{
				xprint = (PageTop - PageBottom) / 72.0;
				yprint = (PageRight - PageLeft) / 72.0;
			}
			else
			{
				xprint = (PageRight - PageLeft) / 72.0;
				yprint = (PageTop - PageBottom) / 72.0;
			}

			fprintf(stderr, "DEBUG: Before scaling: xprint=%.1f, yprint=%.1f\n",
				xprint, yprint);

			xinches = (float)cupsImageGetWidth(img) / (float)xppi;
			yinches = (float)cupsImageGetHeight(img) / (float)yppi;

			fprintf(stderr, "DEBUG: Image size is %.1f x %.1f inches...\n",
				xinches, yinches);

			if ((val = cupsGetOption("natural-scaling", num_options, options)) != NULL)
			{
				xinches = xinches * atoi(val) / 100;
				yinches = yinches * atoi(val) / 100;
			}

			if (cupsGetOption("orientation-requested", num_options, options) == NULL &&
				cupsGetOption("landscape", num_options, options) == NULL)
			{
				/*
				* Rotate the image if it will fit landscape but not portrait...
				*/

				fputs("DEBUG: Auto orientation...\n", stderr);
				LOGI("imagetops.c : Auto orientation...");
				if ((xinches > xprint || yinches > yprint) && xinches <= yprint && yinches <= xprint)
				{
					/*
					* Rotate the image as needed...
					*/

					fputs("DEBUG: Using landscape orientation...\n", stderr);
					LOGI("imagetops.c : Auto orientation : Using landscape orientation");
					Orientation = (Orientation + 1) & 3;
					xsize       = yprint;
					yprint      = xprint;
					xprint      = xsize;
				}
			}
		}else{
			/*
			* Scale percentage of page size...
			*/

			xprint = (PageRight - PageLeft) / 72.0;
			yprint = (PageTop - PageBottom) / 72.0;
			aspect = (float)cupsImageGetYPPI(img) / (float)cupsImageGetXPPI(img);

			fprintf(stderr, "DEBUG: Before scaling: xprint=%.1f, yprint=%.1f\n",
            xprint, yprint);

			fprintf(stderr, "DEBUG: cupsImageGetXPPI(img) = %d, cupsImageGetYPPI(img) = %d, aspect = %f\n",
            cupsImageGetXPPI(img), cupsImageGetYPPI(img), aspect);

			xsize = xprint * zoom;
			ysize = xsize * cupsImageGetHeight(img) / cupsImageGetWidth(img) / aspect;

			if (ysize > (yprint * zoom))
			{
				ysize = yprint * zoom;
				xsize = ysize * cupsImageGetWidth(img) * aspect / cupsImageGetHeight(img);
			}

			xsize2 = yprint * zoom;
			ysize2 = xsize2 * cupsImageGetHeight(img) / cupsImageGetWidth(img) / aspect;

			if (ysize2 > (xprint * zoom))
			{
				ysize2 = xprint * zoom;
				xsize2 = ysize2 * cupsImageGetWidth(img) * aspect / cupsImageGetHeight(img);
			}

			fprintf(stderr, "DEBUG: Portrait size is %.2f x %.2f inches\n", xsize, ysize);
			fprintf(stderr, "DEBUG: Landscape size is %.2f x %.2f inches\n", xsize2, ysize2);

			if (cupsGetOption("orientation-requested", num_options, options) == NULL &&	cupsGetOption("landscape", num_options, options) == NULL)
			{
				/*
				* Choose the rotation with the largest area, but prefer
				* portrait if they are equal...
				*/

				fputs("DEBUG: Auto orientation...\n", stderr);

				if ((xsize * ysize) < (xsize2 * xsize2))
				{
					/*
					* Do landscape orientation...
					*/

					fputs("DEBUG: Using landscape orientation...\n", stderr);

					Orientation = 1;
					xinches     = xsize2;
					yinches     = ysize2;
					xprint      = (PageTop - PageBottom) / 72.0;
					yprint      = (PageRight - PageLeft) / 72.0;
				}
				else
				{
					/*
					* Do portrait orientation...
					*/

					fputs("DEBUG: Using portrait orientation...\n", stderr);

					Orientation = 0;
					xinches     = xsize;
					yinches     = ysize;
				}
			}
			else if (Orientation & 1)
			{
				fputs("DEBUG: Using landscape orientation...\n", stderr);

				xinches     = xsize2;
				yinches     = ysize2;
				xprint      = (PageTop - PageBottom) / 72.0;
				yprint      = (PageRight - PageLeft) / 72.0;
			}
			else
			{
				fputs("DEBUG: Using portrait orientation...\n", stderr);

				xinches     = xsize;
				yinches     = ysize;
				xprint      = (PageRight - PageLeft) / 72.0;
				yprint      = (PageTop - PageBottom) / 72.0;
			}
		}
		
		/*
		* Compute the number of pages to print and the size of the image on each
		* page...
		*/

		xpages = ceil(xinches / xprint);
		ypages = ceil(yinches / yprint);

		xprint = xinches / xpages;
		yprint = yinches / ypages;

		fprintf(stderr, "DEBUG: xpages = %dx%.2fin, ypages = %dx%.2fin\n",xpages, xprint, ypages, yprint);
		
		 
		/*
		* Update the page size for custom sizes...
		*/

		if ((choice = ppdFindMarkedChoice(ppd, "PageSize")) != NULL && _cups_strcasecmp(choice->choice, "Custom") == 0)
		{
			float	width,		/* New width in points */
			length;		/* New length in points */
			char	s[255];		/* New custom page size... */


			/*
			* Use the correct width and length for the current orientation...
			*/

			if (Orientation & 1)
			{
				width  = yprint * 72.0;
				length = xprint * 72.0;
			}
			else
			{
				width  = xprint * 72.0;
				length = yprint * 72.0;
			}

			/*
			* Add margins to page size...
			*/

			width  += ppd->custom_margins[0] + ppd->custom_margins[2];
			length += ppd->custom_margins[1] + ppd->custom_margins[3];

			/*
			* Enforce minimums...
			*/

			if (width < ppd->custom_min[0])
				width = ppd->custom_min[0];

			if (length < ppd->custom_min[1])
				length = ppd->custom_min[1];

			fprintf(stderr, "DEBUG: Updated custom page size to %.2f x %.2f inches...\n",width / 72.0, length / 72.0);

			/*
			* Set the new custom size...
			*/

			sprintf(s, "Custom.%.0fx%.0f", width, length);
			ppdMarkOption(ppd, "PageSize", s);

			/*
			* Update page variables...
			*/

			PageWidth  = width;
			PageLength = length;
			PageLeft   = ppd->custom_margins[0];
			PageRight  = width - ppd->custom_margins[2];
			PageBottom = ppd->custom_margins[1];
			PageTop    = length - ppd->custom_margins[3];
		}

		/*
		* See if we need to collate, and if so how we need to do it...
		*/

		if (xpages == 1 && ypages == 1)
			Collate = 0;

		slowcollate = Collate && ppdFindOption(ppd, "Collate") == NULL;

		if (Copies > 1 && !slowcollate)
		{
			realcopies = Copies;
			Copies     = 1;
		}
		else
			realcopies = 1;

		/*
		* Write any "exit server" options that have been selected...
		*/

		//Changes to create ps file -- start
		
		if(count == 0){//single side print
			defout = dup(1);
			outfd = open(psFilePath,O_RDWR | O_CREAT,S_IRWXU |S_IRWXG | S_IRWXO);
			dup2(outfd,1);
		}
		//Changes to create ps file -- end
		ppdEmit(ppd, stdout, PPD_ORDER_EXIT);
		/*
		* Write any JCL commands that are needed to print PostScript code...
		*/

		if (emit_jcl)
			ppdEmitJCL(ppd, stdout, atoi(argv[1]), argv[2], argv[3]);

		/*
		* Start sending the document with any commands needed...
		*/
		  
		curtime = time(NULL);
		curtm   = localtime(&curtime);
		//////////////////
		if(count == 0){
			puts("%!PS-Adobe-3.0");
			printf("%%%%BoundingBox: %.0f %.0f %.0f %.0f\n", PageLeft, PageBottom,PageRight, PageTop);
			printf("%%%%LanguageLevel: %d\n", LanguageLevel);
		
			printf("%%%%Pages: %d\n", xpages * ypages * Copies * numFiles);
			puts("%%DocumentData: Clean7Bit");
			puts("%%DocumentNeededResources: font Helvetica-Bold");
			puts("%%Creator: imagetops/" CUPS_SVERSION);
			strftime(curdate, sizeof(curdate), "%c", curtm);
			printf("%%%%CreationDate: %s\n", curdate);
			WriteTextComment("Title", argv[3]);
			WriteTextComment("For", argv[2]);
			if (Orientation & 1)
				puts("%%Orientation: Landscape");
			else
				puts("%%Orientation: Portrait");
			puts("%%EndComments");
			puts("%%BeginProlog");

			if (ppd != NULL && ppd->patches != NULL)
				puts(ppd->patches);

			ppdEmit(ppd, stdout, PPD_ORDER_DOCUMENT);
			ppdEmit(ppd, stdout, PPD_ORDER_ANY);
			ppdEmit(ppd, stdout, PPD_ORDER_PROLOG);

			if (g != 1.0 || b != 1.0)
				printf("{ neg 1 add dup 0 lt { pop 1 } { %.3f exp neg 1 add } "
					"ifelse %.3f mul } bind settransfer\n", g, b);

			WriteCommon();
			switch (Orientation)
			{
				case 0 :
					WriteLabelProlog(cupsGetOption("page-label", num_options, options),
						PageBottom, PageTop, PageWidth);
				break;

				case 1 :
					WriteLabelProlog(cupsGetOption("page-label", num_options, options),
						 PageLeft, PageRight, PageLength);
				break;

				case 2 :
					WriteLabelProlog(cupsGetOption("page-label", num_options, options),
						 PageLength - PageTop, PageLength - PageBottom, PageWidth);
				break;

				case 3 :
					WriteLabelProlog(cupsGetOption("page-label", num_options, options),
						 PageWidth - PageRight, PageWidth - PageLeft,PageLength);
				break;
			}

			if (realcopies > 1)
			{
				if (ppd == NULL || ppd->language_level == 1)
					printf("/#copies %d def\n", realcopies);
				else
					printf("<</NumCopies %d>>setpagedevice\n", realcopies);
			}

			puts("%%EndProlog");
		}
		/*
		* Output the pages...
		*/

		row = malloc(cupsImageGetWidth(img) * abs(colorspace) + 3);

		fprintf(stderr, "DEBUG: XPosition=%d, YPosition=%d, Orientation=%d\n",XPosition, YPosition, Orientation);
		fprintf(stderr, "DEBUG: xprint=%.0f, yprint=%.0f\n", xprint, yprint);
		fprintf(stderr, "DEBUG: PageLeft=%.0f, PageRight=%.0f, PageWidth=%.0f\n",PageLeft, PageRight, PageWidth);
		fprintf(stderr, "DEBUG: PageBottom=%.0f, PageTop=%.0f, PageLength=%.0f\n",PageBottom, PageTop, PageLength);

		switch (Orientation)
		{
			default :
				switch (XPosition)
				{
					case -1 :
						left = PageLeft;
					break;
					default :
						left = (PageRight + PageLeft - xprint * 72) / 2;
					break;
					case 1 :
						left = PageRight - xprint * 72;
					break;
				}

				switch (YPosition)
				{
					case -1 :
						top = PageBottom + yprint * 72;
					break;
					default :
						top = (PageTop + PageBottom + yprint * 72) / 2;
					break;
					case 1 :
						top = PageTop;
					break;
				}
			break;

			case 1 :
				switch (XPosition)
				{
					case -1 :
						left = PageBottom;
					break;
					default :
						left = (PageTop + PageBottom - xprint * 72) / 2;
					break;
					case 1 :
						left = PageTop - xprint * 72;
					break;
				}

				switch (YPosition)
				{
					case -1 :
						top = PageLeft + yprint * 72;
					break;
					default :
						top = (PageRight + PageLeft + yprint * 72) / 2;
					break;
					case 1 :
						top = PageRight;
					break;
				}
			break;

			case 2 :
				switch (XPosition)
				{
					case 1 :
						left = PageLeft;
					break;
					default :
						left = (PageRight + PageLeft - xprint * 72) / 2;
					break;
					case -1 :
						left = PageRight - xprint * 72;
					break;
				}

				switch (YPosition)
				{
					case 1 :
						top = PageBottom + yprint * 72;
					break;
					default :
						top = (PageTop + PageBottom + yprint * 72) / 2;
					break;
					case -1 :
						top = PageTop;
					break;
				}
			break;

			case 3 :
				switch (XPosition)
				{
					case 1 :
						left = PageBottom;
					break;
					default :
						left = (PageTop + PageBottom - xprint * 72) / 2;
					break;
					case -1 :
						left = PageTop - xprint * 72;
					break;
				}

				switch (YPosition)
				{
					case 1 :
						top = PageLeft + yprint * 72;
					break;
					default :
						top = (PageRight + PageLeft + yprint * 72) / 2;
					break;
					case -1 :
						top = PageRight;
					break;
				}
			break;
		}

		fprintf(stderr, "DEBUG: left=%.2f, top=%.2f\n", left, top);
		
		for (page = 1; Copies > 0; Copies --)
			for (xpage = 0; xpage < xpages; xpage ++)
				for (ypage = 0; ypage < ypages; ypage ++, page ++)
				{
					if (ppd && ppd->num_filters == 0)
						fprintf(stderr, "PAGE: %d %d\n", page, realcopies);

					_cupsLangPrintFilter(stderr, "INFO", _("Printing page %d."), page);

					printf("%%%%Page: %d %d\n", (page * (count+1)), (page*(count+1)));
					//TEST_TODO
					if(count>=1){
						puts("%%BeginPageSetup");
						if (Orientation & 1)
							puts("%%PageOrientation: Landscape");
						else
							puts("%%PageOrientation: Portrait");
						puts("%%EndPageSetup");
					}
					ppdEmit(ppd, stdout, PPD_ORDER_PAGE);

					puts("gsave");

					if (Flip)
						printf("%.0f 0 translate -1 1 scale\n", PageWidth);

					switch (Orientation)
					{
						case 1 : /* Landscape */
							printf("%.0f 0 translate 90 rotate\n", PageWidth);
						break;
						case 2 : /* Reverse Portrait */
							printf("%.0f %.0f translate 180 rotate\n", PageWidth, PageLength);
						break;
						case 3 : /* Reverse Landscape */
							printf("0 %.0f translate -90 rotate\n", PageLength);
						break;
					}

					puts("gsave");

					xc0 = cupsImageGetWidth(img) * xpage / xpages;
					xc1 = cupsImageGetWidth(img) * (xpage + 1) / xpages - 1;
					yc0 = cupsImageGetHeight(img) * ypage / ypages;
					yc1 = cupsImageGetHeight(img) * (ypage + 1) / ypages - 1;

					printf("%.1f %.1f translate\n", left, top);

					printf("%.3f %.3f scale\n\n",xprint * 72.0 / (xc1 - xc0 + 1),yprint * 72.0 / (yc1 - yc0 + 1));

					if (LanguageLevel == 1)
					{
						printf("/picture %d string def\n", (xc1 - xc0 + 1) * abs(colorspace));
						printf("%d %d 8[1 0 0 -1 0 1]", (xc1 - xc0 + 1), (yc1 - yc0 + 1));

						if (colorspace == CUPS_IMAGE_WHITE)
							puts("{currentfile picture readhexstring pop} image");
						else
							printf("{currentfile picture readhexstring pop} false %d colorimage\n",abs(colorspace));

						for (y = yc0; y <= yc1; y ++)
						{
							cupsImageGetRow(img, xc0, y, xc1 - xc0 + 1, row);
							ps_hex(row, (xc1 - xc0 + 1) * abs(colorspace), y == yc1);
						}
					}
					else
					{
						switch (colorspace)
						{
							case CUPS_IMAGE_WHITE :
								puts("/DeviceGray setcolorspace");
							break;
							case CUPS_IMAGE_RGB :
								puts("/DeviceRGB setcolorspace");
							break;
							case CUPS_IMAGE_CMYK :
								puts("/DeviceCMYK setcolorspace");
							break;
						}

						printf("<<"
							"/ImageType 1"
							"/Width %d"
							"/Height %d"
							"/BitsPerComponent 8",
							xc1 - xc0 + 1, yc1 - yc0 + 1);

						switch (colorspace)
						{
							case CUPS_IMAGE_WHITE :
								fputs("/Decode[0 1]", stdout);
							break;
							case CUPS_IMAGE_RGB :
								fputs("/Decode[0 1 0 1 0 1]", stdout);
							break;
							case CUPS_IMAGE_CMYK :
								fputs("/Decode[0 1 0 1 0 1 0 1]", stdout);
							break;
						}

						fputs("\n/DataSource currentfile/ASCII85Decode filter", stdout);

						if (((xc1 - xc0 + 1) / xprint) < 100.0)
							fputs("/Interpolate true", stdout);

						puts("/ImageMatrix[1 0 0 -1 0 1]>>image");

						for (y = yc0, out_offset = 0; y <= yc1; y ++)
						{
							cupsImageGetRow(img, xc0, y, xc1 - xc0 + 1, row + out_offset);

							out_length = (xc1 - xc0 + 1) * abs(colorspace) + out_offset;
							out_offset = out_length & 3;

							ps_ascii85(row, out_length, y == yc1);

							if (out_offset > 0)
								memcpy(row, row + out_length - out_offset, out_offset);
						}
					}

					if(count==1){
						puts("grestore");
						WriteLabels(0);
						puts("grestore");
					}
					puts("showpage");
					puts("%%PageTrailer");
				}
		
	} //end of big for loop
  
   
   	puts("%%EOF");
 
	/*
	* End the job with the appropriate JCL command or CTRL-D otherwise.
	*/

	if (emit_jcl)
	{
		if (ppd && ppd->jcl_end)
			ppdEmitJCLEnd(ppd, stdout);
		else
		putchar(0x04);
	}

	fflush(stdout);
	dup2(defout,1);
	close(outfd);
	close(defout);

	/*
	* Close files...
	*/
	LOGI("imagetops:Close files");
	cupsImageClose(img);
	ppdClose(ppd);

  return (0);
}
Exemplo n.º 5
0
int					/* O - Exit status */
main(int  argc,				/* I - Number of command-line arguments */
     char *argv[])			/* I - Command-line arguments */
{
  int		i;			/* Looping var */
  ppd_file_t	*ppd;			/* PPD file loaded from disk */
  int		status;			/* Status of tests (0 = success, 1 = fail) */
  int		conflicts;		/* Number of conflicts */
  char		*s;			/* String */
  char		buffer[8192];		/* String buffer */
  const char	*text,			/* Localized text */
		*val;			/* Option value */
  int		num_options;		/* Number of options */
  cups_option_t	*options;		/* Options */
  ppd_size_t	minsize,		/* Minimum size */
		maxsize,		/* Maximum size */
		*size;			/* Current size */
  ppd_attr_t	*attr;			/* Current attribute */
  _ppd_cache_t	*pc;			/* PPD cache */


  status = 0;

  if (argc == 1)
  {
   /*
    * Setup directories for locale stuff...
    */

    if (access("locale", 0))
    {
      mkdir("locale", 0777);
      mkdir("locale/fr", 0777);
      symlink("../../../locale/cups_fr.po", "locale/fr/cups_fr.po");
      mkdir("locale/zh_TW", 0777);
      symlink("../../../locale/cups_zh_TW.po", "locale/zh_TW/cups_zh_TW.po");
    }

    putenv("LOCALEDIR=locale");
    putenv("SOFTWARE=CUPS");

   /*
    * Do tests with test.ppd...
    */

    fputs("ppdOpenFile(test.ppd): ", stdout);

    if ((ppd = _ppdOpenFile("test.ppd", _PPD_LOCALIZATION_ALL)) != NULL)
      puts("PASS");
    else
    {
      ppd_status_t	err;		/* Last error in file */
      int		line;		/* Line number in file */


      status ++;
      err = ppdLastError(&line);

      printf("FAIL (%s on line %d)\n", ppdErrorString(err), line);
    }

    fputs("ppdFindAttr(wildcard): ", stdout);
    if ((attr = ppdFindAttr(ppd, "cupsTest", NULL)) == NULL)
    {
      status ++;
      puts("FAIL (not found)");
    }
    else if (strcmp(attr->name, "cupsTest") || strcmp(attr->spec, "Foo"))
    {
      status ++;
      printf("FAIL (got \"%s %s\")\n", attr->name, attr->spec);
    }
    else
      puts("PASS");

    fputs("ppdFindNextAttr(wildcard): ", stdout);
    if ((attr = ppdFindNextAttr(ppd, "cupsTest", NULL)) == NULL)
    {
      status ++;
      puts("FAIL (not found)");
    }
    else if (strcmp(attr->name, "cupsTest") || strcmp(attr->spec, "Bar"))
    {
      status ++;
      printf("FAIL (got \"%s %s\")\n", attr->name, attr->spec);
    }
    else
      puts("PASS");

    fputs("ppdFindAttr(Foo): ", stdout);
    if ((attr = ppdFindAttr(ppd, "cupsTest", "Foo")) == NULL)
    {
      status ++;
      puts("FAIL (not found)");
    }
    else if (strcmp(attr->name, "cupsTest") || strcmp(attr->spec, "Foo"))
    {
      status ++;
      printf("FAIL (got \"%s %s\")\n", attr->name, attr->spec);
    }
    else
      puts("PASS");

    fputs("ppdFindNextAttr(Foo): ", stdout);
    if ((attr = ppdFindNextAttr(ppd, "cupsTest", "Foo")) != NULL)
    {
      status ++;
      printf("FAIL (got \"%s %s\")\n", attr->name, attr->spec);
    }
    else
      puts("PASS");

    fputs("ppdMarkDefaults: ", stdout);
    ppdMarkDefaults(ppd);

    if ((conflicts = ppdConflicts(ppd)) == 0)
      puts("PASS");
    else
    {
      status ++;
      printf("FAIL (%d conflicts)\n", conflicts);
    }

    fputs("ppdEmitString (defaults): ", stdout);
    if ((s = ppdEmitString(ppd, PPD_ORDER_ANY, 0.0)) != NULL &&
	!strcmp(s, default_code))
      puts("PASS");
    else
    {
      status ++;
      printf("FAIL (%d bytes instead of %d)\n", s ? (int)strlen(s) : 0,
	     (int)strlen(default_code));

      if (s)
	puts(s);
    }

    if (s)
      free(s);

    fputs("ppdEmitString (custom size and string): ", stdout);
    ppdMarkOption(ppd, "PageSize", "Custom.400x500");
    ppdMarkOption(ppd, "StringOption", "{String1=\"value 1\" String2=value(2)}");

    if ((s = ppdEmitString(ppd, PPD_ORDER_ANY, 0.0)) != NULL &&
	!strcmp(s, custom_code))
      puts("PASS");
    else
    {
      status ++;
      printf("FAIL (%d bytes instead of %d)\n", s ? (int)strlen(s) : 0,
	     (int)strlen(custom_code));

      if (s)
	puts(s);
    }

    if (s)
      free(s);

   /*
    * Test constraints...
    */

    fputs("cupsGetConflicts(InputSlot=Envelope): ", stdout);
    ppdMarkOption(ppd, "PageSize", "Letter");

    num_options = cupsGetConflicts(ppd, "InputSlot", "Envelope", &options);
    if (num_options != 2 ||
        (val = cupsGetOption("PageRegion", num_options, options)) == NULL ||
	_cups_strcasecmp(val, "Letter") ||
	(val = cupsGetOption("PageSize", num_options, options)) == NULL ||
	_cups_strcasecmp(val, "Letter"))
    {
      printf("FAIL (%d options:", num_options);
      for (i = 0; i < num_options; i ++)
        printf(" %s=%s", options[i].name, options[i].value);
      puts(")");
      status ++;
    }
    else
      puts("PASS");

    fputs("ppdConflicts(): ", stdout);
    ppdMarkOption(ppd, "InputSlot", "Envelope");

    if ((conflicts = ppdConflicts(ppd)) == 2)
      puts("PASS (2)");
    else
    {
      printf("FAIL (%d)\n", conflicts);
      status ++;
    }

    fputs("cupsResolveConflicts(InputSlot=Envelope): ", stdout);
    num_options = 0;
    options     = NULL;
    if (!cupsResolveConflicts(ppd, "InputSlot", "Envelope", &num_options,
                             &options))
    {
      puts("FAIL (Unable to resolve)");
      status ++;
    }
    else if (num_options != 2 ||
             !cupsGetOption("PageSize", num_options, options))
    {
      printf("FAIL (%d options:", num_options);
      for (i = 0; i < num_options; i ++)
        printf(" %s=%s", options[i].name, options[i].value);
      puts(")");
      status ++;
    }
    else
      puts("PASS (Resolved by changing PageSize)");

    cupsFreeOptions(num_options, options);

    fputs("cupsResolveConflicts(No option/choice): ", stdout);
    num_options = 0;
    options     = NULL;
    if (cupsResolveConflicts(ppd, NULL, NULL, &num_options, &options) &&
        num_options == 1 && !_cups_strcasecmp(options[0].name, "InputSlot") &&
	!_cups_strcasecmp(options[0].value, "Tray"))
      puts("PASS (Resolved by changing InputSlot)");
    else if (num_options > 0)
    {
      printf("FAIL (%d options:", num_options);
      for (i = 0; i < num_options; i ++)
        printf(" %s=%s", options[i].name, options[i].value);
      puts(")");
      status ++;
    }
    else
    {
      puts("FAIL (Unable to resolve)");
      status ++;
    }
    cupsFreeOptions(num_options, options);

    fputs("ppdInstallableConflict(): ", stdout);
    if (ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble") &&
        !ppdInstallableConflict(ppd, "Duplex", "None"))
      puts("PASS");
    else if (!ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble"))
    {
      puts("FAIL (Duplex=DuplexNoTumble did not conflict)");
      status ++;
    }
    else
    {
      puts("FAIL (Duplex=None conflicted)");
      status ++;
    }

   /*
    * ppdPageSizeLimits
    */

    fputs("ppdPageSizeLimits: ", stdout);
    if (ppdPageSizeLimits(ppd, &minsize, &maxsize))
    {
      if (minsize.width != 36 || minsize.length != 36 ||
          maxsize.width != 1080 || maxsize.length != 86400)
      {
        printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, "
	       "expected min=36x36, max=1080x86400)\n", minsize.width,
	       minsize.length, maxsize.width, maxsize.length);
        status ++;
      }
      else
        puts("PASS");
    }
    else
    {
      puts("FAIL (returned 0)");
      status ++;
    }

   /*
    * cupsMarkOptions with PWG and IPP size names.
    */

    fputs("cupsMarkOptions(media=iso-a4): ", stdout);
    num_options = cupsAddOption("media", "iso-a4", 0, &options);
    cupsMarkOptions(ppd, num_options, options);
    cupsFreeOptions(num_options, options);

    size = ppdPageSize(ppd, NULL);
    if (!size || strcmp(size->name, "A4"))
    {
      printf("FAIL (%s)\n", size ? size->name : "unknown");
      status ++;
    }
    else
      puts("PASS");

    fputs("cupsMarkOptions(media=na_letter_8.5x11in): ", stdout);
    num_options = cupsAddOption("media", "na_letter_8.5x11in", 0, &options);
    cupsMarkOptions(ppd, num_options, options);
    cupsFreeOptions(num_options, options);

    size = ppdPageSize(ppd, NULL);
    if (!size || strcmp(size->name, "Letter"))
    {
      printf("FAIL (%s)\n", size ? size->name : "unknown");
      status ++;
    }
    else
      puts("PASS");

    fputs("cupsMarkOptions(media=oe_letter-fullbleed_8.5x11in): ", stdout);
    num_options = cupsAddOption("media", "oe_letter-fullbleed_8.5x11in", 0,
                                &options);
    cupsMarkOptions(ppd, num_options, options);
    cupsFreeOptions(num_options, options);

    size = ppdPageSize(ppd, NULL);
    if (!size || strcmp(size->name, "Letter.Fullbleed"))
    {
      printf("FAIL (%s)\n", size ? size->name : "unknown");
      status ++;
    }
    else
      puts("PASS");

    fputs("cupsMarkOptions(media=A4): ", stdout);
    num_options = cupsAddOption("media", "A4", 0, &options);
    cupsMarkOptions(ppd, num_options, options);
    cupsFreeOptions(num_options, options);

    size = ppdPageSize(ppd, NULL);
    if (!size || strcmp(size->name, "A4"))
    {
      printf("FAIL (%s)\n", size ? size->name : "unknown");
      status ++;
    }
    else
      puts("PASS");

   /*
    * Custom sizes...
    */

    fputs("cupsMarkOptions(media=Custom.8x10in): ", stdout);
    num_options = cupsAddOption("media", "Custom.8x10in", 0, &options);
    cupsMarkOptions(ppd, num_options, options);
    cupsFreeOptions(num_options, options);

    size = ppdPageSize(ppd, NULL);
    if (!size || strcmp(size->name, "Custom") ||
        size->width != 576 || size->length != 720)
    {
      printf("FAIL (%s - %gx%g)\n", size ? size->name : "unknown",
             size ? size->width : 0.0, size ? size->length : 0.0);
      status ++;
    }
    else
      puts("PASS");

   /*
    * Test localization...
    */

    fputs("ppdLocalizeIPPReason(text): ", stdout);
    if (ppdLocalizeIPPReason(ppd, "foo", NULL, buffer, sizeof(buffer)) &&
        !strcmp(buffer, "Foo Reason"))
      puts("PASS");
    else
    {
      status ++;
      printf("FAIL (\"%s\" instead of \"Foo Reason\")\n", buffer);
    }

    fputs("ppdLocalizeIPPReason(http): ", stdout);
    if (ppdLocalizeIPPReason(ppd, "foo", "http", buffer, sizeof(buffer)) &&
        !strcmp(buffer, "http://foo/bar.html"))
      puts("PASS");
    else
    {
      status ++;
      printf("FAIL (\"%s\" instead of \"http://foo/bar.html\")\n", buffer);
    }

    fputs("ppdLocalizeIPPReason(help): ", stdout);
    if (ppdLocalizeIPPReason(ppd, "foo", "help", buffer, sizeof(buffer)) &&
        !strcmp(buffer, "help:anchor='foo'%20bookID=Vendor%20Help"))
      puts("PASS");
    else
    {
      status ++;
      printf("FAIL (\"%s\" instead of \"help:anchor='foo'%%20bookID=Vendor%%20Help\")\n", buffer);
    }

    fputs("ppdLocalizeIPPReason(file): ", stdout);
    if (ppdLocalizeIPPReason(ppd, "foo", "file", buffer, sizeof(buffer)) &&
        !strcmp(buffer, "/help/foo/bar.html"))
      puts("PASS");
    else
    {
      status ++;
      printf("FAIL (\"%s\" instead of \"/help/foo/bar.html\")\n", buffer);
    }

    putenv("LANG=fr");
    putenv("LC_ALL=fr");
    putenv("LC_CTYPE=fr");
    putenv("LC_MESSAGES=fr");

    fputs("ppdLocalizeIPPReason(fr text): ", stdout);
    if (ppdLocalizeIPPReason(ppd, "foo", NULL, buffer, sizeof(buffer)) &&
        !strcmp(buffer, "La Long Foo Reason"))
      puts("PASS");
    else
    {
      status ++;
      printf("FAIL (\"%s\" instead of \"La Long Foo Reason\")\n", buffer);
    }

    putenv("LANG=zh_TW");
    putenv("LC_ALL=zh_TW");
    putenv("LC_CTYPE=zh_TW");
    putenv("LC_MESSAGES=zh_TW");

    fputs("ppdLocalizeIPPReason(zh_TW text): ", stdout);
    if (ppdLocalizeIPPReason(ppd, "foo", NULL, buffer, sizeof(buffer)) &&
        !strcmp(buffer, "Number 1 Foo Reason"))
      puts("PASS");
    else
    {
      status ++;
      printf("FAIL (\"%s\" instead of \"Number 1 Foo Reason\")\n", buffer);
    }

   /*
    * cupsMarkerName localization...
    */

    putenv("LANG=en");
    putenv("LC_ALL=en");
    putenv("LC_CTYPE=en");
    putenv("LC_MESSAGES=en");

    fputs("ppdLocalizeMarkerName(bogus): ", stdout);

    if ((text = ppdLocalizeMarkerName(ppd, "bogus")) != NULL)
    {
      status ++;
      printf("FAIL (\"%s\" instead of NULL)\n", text);
    }
    else
      puts("PASS");

    fputs("ppdLocalizeMarkerName(cyan): ", stdout);

    if ((text = ppdLocalizeMarkerName(ppd, "cyan")) != NULL &&
        !strcmp(text, "Cyan Toner"))
      puts("PASS");
    else
    {
      status ++;
      printf("FAIL (\"%s\" instead of \"Cyan Toner\")\n",
             text ? text : "(null)");
    }

    putenv("LANG=fr");
    putenv("LC_ALL=fr");
    putenv("LC_CTYPE=fr");
    putenv("LC_MESSAGES=fr");

    fputs("ppdLocalizeMarkerName(fr cyan): ", stdout);
    if ((text = ppdLocalizeMarkerName(ppd, "cyan")) != NULL &&
        !strcmp(text, "La Toner Cyan"))
      puts("PASS");
    else
    {
      status ++;
      printf("FAIL (\"%s\" instead of \"La Toner Cyan\")\n",
             text ? text : "(null)");
    }

    putenv("LANG=zh_TW");
    putenv("LC_ALL=zh_TW");
    putenv("LC_CTYPE=zh_TW");
    putenv("LC_MESSAGES=zh_TW");

    fputs("ppdLocalizeMarkerName(zh_TW cyan): ", stdout);
    if ((text = ppdLocalizeMarkerName(ppd, "cyan")) != NULL &&
        !strcmp(text, "Number 1 Cyan Toner"))
      puts("PASS");
    else
    {
      status ++;
      printf("FAIL (\"%s\" instead of \"Number 1 Cyan Toner\")\n",
             text ? text : "(null)");
    }

    ppdClose(ppd);

   /*
    * Test new constraints...
    */

    fputs("ppdOpenFile(test2.ppd): ", stdout);

    if ((ppd = ppdOpenFile("test2.ppd")) != NULL)
      puts("PASS");
    else
    {
      ppd_status_t	err;		/* Last error in file */
      int		line;		/* Line number in file */


      status ++;
      err = ppdLastError(&line);

      printf("FAIL (%s on line %d)\n", ppdErrorString(err), line);
    }

    fputs("ppdMarkDefaults: ", stdout);
    ppdMarkDefaults(ppd);

    if ((conflicts = ppdConflicts(ppd)) == 0)
      puts("PASS");
    else
    {
      status ++;
      printf("FAIL (%d conflicts)\n", conflicts);
    }

    fputs("ppdEmitString (defaults): ", stdout);
    if ((s = ppdEmitString(ppd, PPD_ORDER_ANY, 0.0)) != NULL &&
	!strcmp(s, default2_code))
      puts("PASS");
    else
    {
      status ++;
      printf("FAIL (%d bytes instead of %d)\n", s ? (int)strlen(s) : 0,
	     (int)strlen(default2_code));

      if (s)
	puts(s);
    }

    if (s)
      free(s);

    fputs("ppdConflicts(): ", stdout);
    ppdMarkOption(ppd, "PageSize", "Env10");
    ppdMarkOption(ppd, "InputSlot", "Envelope");
    ppdMarkOption(ppd, "Quality", "Photo");

    if ((conflicts = ppdConflicts(ppd)) == 1)
      puts("PASS (1)");
    else
    {
      printf("FAIL (%d)\n", conflicts);
      status ++;
    }

    fputs("cupsResolveConflicts(Quality=Photo): ", stdout);
    num_options = 0;
    options     = NULL;
    if (cupsResolveConflicts(ppd, "Quality", "Photo", &num_options,
                             &options))
    {
      printf("FAIL (%d options:", num_options);
      for (i = 0; i < num_options; i ++)
        printf(" %s=%s", options[i].name, options[i].value);
      puts(")");
      status ++;
    }
    else
      puts("PASS (Unable to resolve)");
    cupsFreeOptions(num_options, options);

    fputs("cupsResolveConflicts(No option/choice): ", stdout);
    num_options = 0;
    options     = NULL;
    if (cupsResolveConflicts(ppd, NULL, NULL, &num_options, &options) &&
        num_options == 1 && !_cups_strcasecmp(options->name, "Quality") &&
	!_cups_strcasecmp(options->value, "Normal"))
      puts("PASS");
    else if (num_options > 0)
    {
      printf("FAIL (%d options:", num_options);
      for (i = 0; i < num_options; i ++)
        printf(" %s=%s", options[i].name, options[i].value);
      puts(")");
      status ++;
    }
    else
    {
      puts("FAIL (Unable to resolve!)");
      status ++;
    }
    cupsFreeOptions(num_options, options);

    fputs("cupsResolveConflicts(loop test): ", stdout);
    ppdMarkOption(ppd, "PageSize", "A4");
    ppdMarkOption(ppd, "InputSlot", "Tray");
    ppdMarkOption(ppd, "Quality", "Photo");
    num_options = 0;
    options     = NULL;
    if (!cupsResolveConflicts(ppd, NULL, NULL, &num_options, &options))
      puts("PASS");
    else if (num_options > 0)
    {
      printf("FAIL (%d options:", num_options);
      for (i = 0; i < num_options; i ++)
        printf(" %s=%s", options[i].name, options[i].value);
      puts(")");
    }
    else
      puts("FAIL (No conflicts!)");

    fputs("ppdInstallableConflict(): ", stdout);
    if (ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble") &&
        !ppdInstallableConflict(ppd, "Duplex", "None"))
      puts("PASS");
    else if (!ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble"))
    {
      puts("FAIL (Duplex=DuplexNoTumble did not conflict)");
      status ++;
    }
    else
    {
      puts("FAIL (Duplex=None conflicted)");
      status ++;
    }

   /*
    * ppdPageSizeLimits
    */

    ppdMarkDefaults(ppd);

    fputs("ppdPageSizeLimits(default): ", stdout);
    if (ppdPageSizeLimits(ppd, &minsize, &maxsize))
    {
      if (minsize.width != 36 || minsize.length != 36 ||
          maxsize.width != 1080 || maxsize.length != 86400)
      {
        printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, "
	       "expected min=36x36, max=1080x86400)\n", minsize.width,
	       minsize.length, maxsize.width, maxsize.length);
        status ++;
      }
      else
        puts("PASS");
    }
    else
    {
      puts("FAIL (returned 0)");
      status ++;
    }

    ppdMarkOption(ppd, "InputSlot", "Manual");

    fputs("ppdPageSizeLimits(InputSlot=Manual): ", stdout);
    if (ppdPageSizeLimits(ppd, &minsize, &maxsize))
    {
      if (minsize.width != 100 || minsize.length != 100 ||
          maxsize.width != 1000 || maxsize.length != 1000)
      {
        printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, "
	       "expected min=100x100, max=1000x1000)\n", minsize.width,
	       minsize.length, maxsize.width, maxsize.length);
        status ++;
      }
      else
        puts("PASS");
    }
    else
    {
      puts("FAIL (returned 0)");
      status ++;
    }

    ppdMarkOption(ppd, "Quality", "Photo");

    fputs("ppdPageSizeLimits(Quality=Photo): ", stdout);
    if (ppdPageSizeLimits(ppd, &minsize, &maxsize))
    {
      if (minsize.width != 200 || minsize.length != 200 ||
          maxsize.width != 1000 || maxsize.length != 1000)
      {
        printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, "
	       "expected min=200x200, max=1000x1000)\n", minsize.width,
	       minsize.length, maxsize.width, maxsize.length);
        status ++;
      }
      else
        puts("PASS");
    }
    else
    {
      puts("FAIL (returned 0)");
      status ++;
    }

    ppdMarkOption(ppd, "InputSlot", "Tray");

    fputs("ppdPageSizeLimits(Quality=Photo): ", stdout);
    if (ppdPageSizeLimits(ppd, &minsize, &maxsize))
    {
      if (minsize.width != 300 || minsize.length != 300 ||
          maxsize.width != 1080 || maxsize.length != 86400)
      {
        printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, "
	       "expected min=300x300, max=1080x86400)\n", minsize.width,
	       minsize.length, maxsize.width, maxsize.length);
        status ++;
      }
      else
        puts("PASS");
    }
    else
    {
      puts("FAIL (returned 0)");
      status ++;
    }
  }
  else
  {
    const char	*filename;		/* PPD filename */
    struct stat	fileinfo;		/* File information */


    if (!strncmp(argv[1], "-d", 2))
    {
      const char *printer;		/* Printer name */

      if (argv[1][2])
	printer = argv[1] + 2;
      else if (argv[2])
	printer = argv[2];
      else
      {
        puts("Usage: ./testppd -d printer");
	return (1);
      }

      filename = cupsGetPPD(printer);

      if (!filename)
      {
        printf("%s: %s\n", printer, cupsLastErrorString());
        return (1);
      }
    }
    else
      filename = argv[1];

    if (lstat(filename, &fileinfo))
    {
      printf("%s: %s\n", filename, strerror(errno));
      return (1);
    }

    if (S_ISLNK(fileinfo.st_mode))
    {
      char	realfile[1024];		/* Real file path */
      ssize_t	realsize;		/* Size of real file path */


      if ((realsize = readlink(filename, realfile, sizeof(realfile) - 1)) < 0)
        strlcpy(realfile, "Unknown", sizeof(realfile));
      else
        realfile[realsize] = '\0';

      if (stat(realfile, &fileinfo))
	printf("%s: symlink to \"%s\", %s\n", filename, realfile,
	       strerror(errno));
      else
	printf("%s: symlink to \"%s\", %ld bytes\n", filename, realfile,
	       (long)fileinfo.st_size);
    }
    else
      printf("%s: regular file, %ld bytes\n", filename, (long)fileinfo.st_size);

    if ((ppd = ppdOpenFile(filename)) == NULL)
    {
      ppd_status_t	err;		/* Last error in file */
      int		line;		/* Line number in file */


      status ++;
      err = ppdLastError(&line);

      printf("%s: %s on line %d\n", argv[1], ppdErrorString(err), line);
    }
    else
    {
      int		j, k;		/* Looping vars */
      ppd_group_t	*group;		/* Option group */
      ppd_option_t	*option;	/* Option */
      ppd_coption_t	*coption;	/* Custom option */
      ppd_cparam_t	*cparam;	/* Custom parameter */
      ppd_const_t	*c;		/* UIConstraints */
      char		lang[255],	/* LANG environment variable */
			lc_all[255],	/* LC_ALL environment variable */
			lc_ctype[255],	/* LC_CTYPE environment variable */
			lc_messages[255];/* LC_MESSAGES environment variable */


      if (argc > 2)
      {
        snprintf(lang, sizeof(lang), "LANG=%s", argv[2]);
	putenv(lang);
        snprintf(lc_all, sizeof(lc_all), "LC_ALL=%s", argv[2]);
	putenv(lc_all);
        snprintf(lc_ctype, sizeof(lc_ctype), "LC_CTYPE=%s", argv[2]);
	putenv(lc_ctype);
        snprintf(lc_messages, sizeof(lc_messages), "LC_MESSAGES=%s", argv[2]);
	putenv(lc_messages);
      }

      ppdLocalize(ppd);
      ppdMarkDefaults(ppd);

      if (argc > 3)
      {
        text = ppdLocalizeIPPReason(ppd, argv[3], NULL, buffer, sizeof(buffer));
	printf("ppdLocalizeIPPReason(%s)=%s\n", argv[3],
	       text ? text : "(null)");
	return (text == NULL);
      }

      for (i = ppd->num_groups, group = ppd->groups;
	   i > 0;
	   i --, group ++)
      {
	printf("%s (%s):\n", group->name, group->text);

	for (j = group->num_options, option = group->options;
	     j > 0;
	     j --, option ++)
	{
	  printf("    %s (%s):\n", option->keyword, option->text);

	  for (k = 0; k < option->num_choices; k ++)
	    printf("        - %s%s (%s)\n",
	           option->choices[k].marked ? "*" : "",
		   option->choices[k].choice, option->choices[k].text);

          if ((coption = ppdFindCustomOption(ppd, option->keyword)) != NULL)
	  {
	    for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
	         cparam;
		 cparam = (ppd_cparam_t *)cupsArrayNext(coption->params))
            {
	      switch (cparam->type)
	      {
	        case PPD_CUSTOM_CURVE :
		    printf("              %s(%s): PPD_CUSTOM_CURVE (%g to %g)\n",
		           cparam->name, cparam->text,
			   cparam->minimum.custom_curve,
			   cparam->maximum.custom_curve);
		    break;

	        case PPD_CUSTOM_INT :
		    printf("              %s(%s): PPD_CUSTOM_INT (%d to %d)\n",
		           cparam->name, cparam->text,
			   cparam->minimum.custom_int,
			   cparam->maximum.custom_int);
		    break;

	        case PPD_CUSTOM_INVCURVE :
		    printf("              %s(%s): PPD_CUSTOM_INVCURVE (%g to %g)\n",
		           cparam->name, cparam->text,
			   cparam->minimum.custom_invcurve,
			   cparam->maximum.custom_invcurve);
		    break;

	        case PPD_CUSTOM_PASSCODE :
		    printf("              %s(%s): PPD_CUSTOM_PASSCODE (%d to %d)\n",
		           cparam->name, cparam->text,
			   cparam->minimum.custom_passcode,
			   cparam->maximum.custom_passcode);
		    break;

	        case PPD_CUSTOM_PASSWORD :
		    printf("              %s(%s): PPD_CUSTOM_PASSWORD (%d to %d)\n",
		           cparam->name, cparam->text,
			   cparam->minimum.custom_password,
			   cparam->maximum.custom_password);
		    break;

	        case PPD_CUSTOM_POINTS :
		    printf("              %s(%s): PPD_CUSTOM_POINTS (%g to %g)\n",
		           cparam->name, cparam->text,
			   cparam->minimum.custom_points,
			   cparam->maximum.custom_points);
		    break;

	        case PPD_CUSTOM_REAL :
		    printf("              %s(%s): PPD_CUSTOM_REAL (%g to %g)\n",
		           cparam->name, cparam->text,
			   cparam->minimum.custom_real,
			   cparam->maximum.custom_real);
		    break;

	        case PPD_CUSTOM_STRING :
		    printf("              %s(%s): PPD_CUSTOM_STRING (%d to %d)\n",
		           cparam->name, cparam->text,
			   cparam->minimum.custom_string,
			   cparam->maximum.custom_string);
		    break;
	      }
	    }
	  }
	}
      }

      puts("\nSizes:");
      for (i = ppd->num_sizes, size = ppd->sizes; i > 0; i --, size ++)
        printf("    %s = %gx%g, [%g %g %g %g]\n", size->name, size->width,
	       size->length, size->left, size->bottom, size->right, size->top);

      puts("\nConstraints:");

      for (i = ppd->num_consts, c = ppd->consts; i > 0; i --, c ++)
        printf("    *UIConstraints: *%s %s *%s %s\n", c->option1, c->choice1,
	       c->option2, c->choice2);
      if (ppd->num_consts == 0)
        puts("    NO CONSTRAINTS");

      puts("\nFilters:");

      for (i = 0; i < ppd->num_filters; i ++)
        printf("    %s\n", ppd->filters[i]);

      if (ppd->num_filters == 0)
        puts("    NO FILTERS");

      puts("\nAttributes:");

      for (attr = (ppd_attr_t *)cupsArrayFirst(ppd->sorted_attrs);
           attr;
	   attr = (ppd_attr_t *)cupsArrayNext(ppd->sorted_attrs))
        printf("    *%s %s/%s: \"%s\"\n", attr->name, attr->spec,
	       attr->text, attr->value ? attr->value : "");

      puts("\nPPD Cache:");
      if ((pc = _ppdCacheCreateWithPPD(ppd)) == NULL)
        printf("    Unable to create: %s\n", cupsLastErrorString());
      else
      {
        _ppdCacheWriteFile(pc, "t.cache", NULL);
        puts("    Wrote t.cache.");
      }
    }

    if (!strncmp(argv[1], "-d", 2))
      unlink(filename);
  }

#ifdef __APPLE__
  if (getenv("MallocStackLogging") && getenv("MallocStackLoggingNoCompact"))
  {
    char	command[1024];		/* malloc_history command */

    snprintf(command, sizeof(command), "malloc_history %d -all_by_size",
	     getpid());
    fflush(stdout);
    system(command);
  }
#endif /* __APPLE__ */

  ppdClose(ppd);

  return (status);
}