home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / print / print-ps.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-10-06  |  18.6 KB  |  735 lines

  1. /*
  2.  * "$Id: print-ps.c,v 1.23 2000/10/04 01:47:59 mitch Exp $"
  3.  *
  4.  *   Print plug-in Adobe PostScript driver for the GIMP.
  5.  *
  6.  *   Copyright 1997-2000 Michael Sweet (mike@easysw.com) and
  7.  *    Robert Krawitz (rlk@alum.mit.edu)
  8.  *
  9.  *   This program is free software; you can redistribute it and/or modify it
  10.  *   under the terms of the GNU General Public License as published by the Free
  11.  *   Software Foundation; either version 2 of the License, or (at your option)
  12.  *   any later version.
  13.  *
  14.  *   This program is distributed in the hope that it will be useful, but
  15.  *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  16.  *   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  17.  *   for more details.
  18.  *
  19.  *   You should have received a copy of the GNU General Public License
  20.  *   along with this program; if not, write to the Free Software
  21.  *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  22.  */
  23.  
  24. /*
  25.  * This file must include only standard C header files.  The core code must
  26.  * compile on generic platforms that don't support glib, gimp, gtk, etc.
  27.  */
  28.  
  29. #include "print.h"
  30. #include <time.h>
  31. #include <string.h>
  32. #include <limits.h>
  33.  
  34. /*#define DEBUG*/
  35.  
  36.  
  37. /*
  38.  * Local variables...
  39.  */
  40.  
  41. static FILE    *ps_ppd = NULL;
  42. static const char    *ps_ppd_file = NULL;
  43.  
  44.  
  45. /*
  46.  * Local functions...
  47.  */
  48.  
  49. static void    ps_hex(FILE *, unsigned short *, int);
  50. static void    ps_ascii85(FILE *, unsigned short *, int, int);
  51. static char    *ppd_find(const char *, const char *, const char *, int *);
  52.  
  53.  
  54. /*
  55.  * 'ps_parameters()' - Return the parameter values for the given parameter.
  56.  */
  57.  
  58. char **                    /* O - Parameter values */
  59. ps_parameters(const printer_t *printer,    /* I - Printer model */
  60.               char *ppd_file,        /* I - PPD file (not used) */
  61.               char *name,        /* I - Name of parameter */
  62.               int  *count)        /* O - Number of values */
  63. {
  64.   int        i;
  65.   char        line[1024],
  66.         lname[255],
  67.         loption[255];
  68.   char        **valptrs;
  69.  
  70.   if (count == NULL)
  71.     return (NULL);
  72.  
  73.   *count = 0;
  74.  
  75.   if (ppd_file == NULL || name == NULL)
  76.     return (NULL);
  77.  
  78.   if (ps_ppd_file == NULL || strcmp(ps_ppd_file, ppd_file) != 0)
  79.   {
  80.     if (ps_ppd != NULL)
  81.       fclose(ps_ppd);
  82.  
  83.     ps_ppd = fopen(ppd_file, "r");
  84.  
  85.     if (ps_ppd == NULL)
  86.       ps_ppd_file = NULL;
  87.     else
  88.       ps_ppd_file = ppd_file;
  89.   }
  90.  
  91.   if (ps_ppd == NULL)
  92.     {
  93.       if (strcmp(name, "PageSize") == 0)
  94.     {
  95.       const papersize_t *papersizes = get_papersizes();
  96.       valptrs = malloc(sizeof(char *) * known_papersizes());
  97.       *count = 0;
  98.       for (i = 0; i < known_papersizes(); i++)
  99.         {
  100.           if (strlen(papersizes[i].name) > 0)
  101.         {
  102.           valptrs[*count] = malloc(strlen(papersizes[i].name) + 1);
  103.           strcpy(valptrs[*count], papersizes[i].name);
  104.           (*count)++;
  105.         }
  106.         }
  107.       return (valptrs);
  108.     }
  109.       else
  110.     return (NULL);
  111.     }
  112.  
  113.   rewind(ps_ppd);
  114.   *count = 0;
  115.  
  116.   valptrs = malloc(100 * sizeof(char *));
  117.  
  118.   while (fgets(line, sizeof(line), ps_ppd) != NULL)
  119.   {
  120.     if (line[0] != '*')
  121.       continue;
  122.  
  123.     if (sscanf(line, "*%s %[^/:]", lname, loption) != 2)
  124.       continue;
  125.  
  126.     if (strcasecmp(lname, name) == 0)
  127.     {
  128.       valptrs[(*count)] = malloc(strlen(loption) + 1);
  129.       strcpy(valptrs[(*count)], loption);
  130.       (*count) ++;
  131.     }
  132.   }
  133.  
  134.   if (*count == 0)
  135.   {
  136.     free(valptrs);
  137.     return (NULL);
  138.   }
  139.   else
  140.     return (valptrs);
  141. }
  142.  
  143.  
  144. /*
  145.  * 'ps_media_size()' - Return the size of the page.
  146.  */
  147.  
  148. void
  149. ps_media_size(const printer_t *printer,    /* I - Printer model */
  150.           const vars_t *v,        /* I */
  151.               int  *width,        /* O - Width in points */
  152.               int  *length)        /* O - Length in points */
  153. {
  154.   char    *dimensions;            /* Dimensions of media size */
  155.  
  156.  
  157. #ifdef DEBUG
  158.   printf("ps_media_size(%d, \'%s\', \'%s\', %08x, %08x)\n", model, ppd_file,
  159.          media_size, width, length);
  160. #endif /* DEBUG */
  161.  
  162.   if ((dimensions = ppd_find(v->ppd_file, "PaperDimension", v->media_size,
  163.                  NULL))
  164.       != NULL)
  165.     sscanf(dimensions, "%d%d", width, length);
  166.   else
  167.     default_media_size(printer, v, width, length);
  168. }
  169.  
  170.  
  171. /*
  172.  * 'ps_imageable_area()' - Return the imageable area of the page.
  173.  */
  174.  
  175. void
  176. ps_imageable_area(const printer_t *printer,    /* I - Printer model */
  177.           const vars_t *v,      /* I */
  178.                   int  *left,        /* O - Left position in points */
  179.                   int  *right,        /* O - Right position in points */
  180.                   int  *bottom,        /* O - Bottom position in points */
  181.                   int  *top)        /* O - Top position in points */
  182. {
  183.   char    *area;                /* Imageable area of media */
  184.   float    fleft,                /* Floating point versions */
  185.     fright,
  186.     fbottom,
  187.     ftop;
  188.  
  189.  
  190.   if ((area = ppd_find(v->ppd_file, "ImageableArea", v->media_size, NULL))
  191.       != NULL)
  192.   {
  193. #ifdef DEBUG
  194.     printf("area = \'%s\'\n", area);
  195. #endif /* DEBUG */
  196.     if (sscanf(area, "%f%f%f%f", &fleft, &fbottom, &fright, &ftop) == 4)
  197.     {
  198.       *left   = (int)fleft;
  199.       *right  = (int)fright;
  200.       *bottom = (int)fbottom;
  201.       *top    = (int)ftop;
  202.     }
  203.     else
  204.       *left = *right = *bottom = *top = 0;
  205.   }
  206.   else
  207.   {
  208.     default_media_size(printer, v, right, top);
  209.     *left   = 18;
  210.     *right  -= 18;
  211.     *top    -= 36;
  212.     *bottom = 36;
  213.   }
  214. }
  215.  
  216. void
  217. ps_limit(const printer_t *printer,    /* I - Printer model */
  218.         const vars_t *v,          /* I */
  219.         int  *width,        /* O - Left position in points */
  220.         int  *length)        /* O - Top position in points */
  221. {
  222.   *width =    INT_MAX;
  223.     *length =    INT_MAX;
  224. }
  225.  
  226. const char *
  227. ps_default_resolution(const printer_t *printer)
  228. {
  229.   return "default";
  230. }
  231.  
  232. /*
  233.  * 'ps_print()' - Print an image to a PostScript printer.
  234.  */
  235.  
  236. void
  237. ps_print(const printer_t *printer,        /* I - Model (Level 1 or 2) */
  238.          int       copies,        /* I - Number of copies */
  239.          FILE      *prn,        /* I - File to print to */
  240.          Image     image,        /* I - Image to print */
  241.      const vars_t    *v)
  242. {
  243.   unsigned char *cmap = v->cmap;
  244.   int        model = printer->model;
  245.   const char    *ppd_file = v->ppd_file;
  246.   const char    *resolution = v->resolution;
  247.   const char    *media_size = v->media_size;
  248.   const char    *media_type = v->media_type;
  249.   const char    *media_source = v->media_source;
  250.   int         output_type = v->output_type;
  251.   int        orientation = v->orientation;
  252.   double     scaling = v->scaling;
  253.   int        top = v->top;
  254.   int        left = v->left;
  255.   int        i, j;        /* Looping vars */
  256.   int        y;        /* Looping vars */
  257.   unsigned char    *in;        /* Input pixels from image */
  258.   unsigned short    *out;        /* Output pixels for printer */
  259.   int        page_left,    /* Left margin of page */
  260.         page_right,    /* Right margin of page */
  261.         page_top,    /* Top of page */
  262.         page_bottom,    /* Bottom of page */
  263.         page_width,    /* Width of page */
  264.         page_height,    /* Height of page */
  265.         out_width,    /* Width of image on page */
  266.         out_height,    /* Height of image on page */
  267.         out_bpp,    /* Output bytes per pixel */
  268.         out_length,    /* Output length (Level 2 output) */
  269.         out_offset;    /* Output offset (Level 2 output) */
  270.   time_t    curtime;    /* Current time of day */
  271.   convert_t    colorfunc;    /* Color conversion function... */
  272.   char        *command;    /* PostScript command */
  273.   int        order,        /* Order of command */
  274.         num_commands;    /* Number of commands */
  275.   struct            /* PostScript commands... */
  276.   {
  277.     char    *command;
  278.     int        order;
  279.   }        commands[4];
  280.   int           image_height,
  281.                 image_width,
  282.                 image_bpp;
  283.   vars_t    nv;
  284.  
  285.   memcpy(&nv, v, sizeof(vars_t));
  286.  /*
  287.   * Setup a read-only pixel region for the entire image...
  288.   */
  289.  
  290.   Image_init(image);
  291.   image_height = Image_height(image);
  292.   image_width = Image_width(image);
  293.   image_bpp = Image_bpp(image);
  294.  
  295.  /*
  296.   * Choose the correct color conversion function...
  297.   */
  298.  
  299.   colorfunc = choose_colorfunc(output_type, image_bpp, cmap, &out_bpp, &nv);
  300.  
  301.  /*
  302.   * Compute the output size...
  303.   */
  304.  
  305.   ps_imageable_area(printer, &nv, &page_left, &page_right,
  306.                     &page_bottom, &page_top);
  307.   compute_page_parameters(page_right, page_left, page_top, page_bottom,
  308.               scaling, image_width, image_height, image,
  309.               &orientation, &page_width, &page_height,
  310.               &out_width, &out_height, &left, &top);
  311.  
  312.   /*
  313.    * Recompute the image height and width.  If the image has been
  314.    * rotated, these will change from previously.
  315.    */
  316.   image_height = Image_height(image);
  317.   image_width = Image_width(image);
  318.  
  319.  /*
  320.   * Let the user know what we're doing...
  321.   */
  322.  
  323.   Image_progress_init(image);
  324.  
  325.  /*
  326.   * Output a standard PostScript header with DSC comments...
  327.   */
  328.  
  329.   curtime = time(NULL);
  330.  
  331.   if (left < 0)
  332.     left = (page_width - out_width) / 2 + page_left;
  333.   else
  334.     left += page_left;
  335.  
  336.   if (top < 0)
  337.     top  = (page_height + out_height) / 2 + page_bottom;
  338.   else
  339.     top = page_height - top + page_bottom;
  340.  
  341. #ifdef DEBUG
  342.   printf("out_width = %d, out_height = %d\n", out_width, out_height);
  343.   printf("page_left = %d, page_right = %d, page_bottom = %d, page_top = %d\n",
  344.          page_left, page_right, page_bottom, page_top);
  345.   printf("left = %d, top = %d\n", left, top);
  346. #endif /* DEBUG */
  347.  
  348. #ifdef __EMX__
  349.   _fsetmode(prn, "t");
  350. #endif
  351.   fputs("%!PS-Adobe-3.0\n", prn);
  352.   fprintf(prn, "%%%%Creator: %s\n", Image_get_appname(image));
  353.   fprintf(prn, "%%%%CreationDate: %s", ctime(&curtime));
  354.   fputs("%%Copyright: 1997-2000 by Michael Sweet (mike@easysw.com) and Robert Krawitz (rlk@alum.mit.edu)\n", prn);
  355.   fprintf(prn, "%%%%BoundingBox: %d %d %d %d\n",
  356.           left, top - out_height, left + out_width, top);
  357.   fputs("%%DocumentData: Clean7Bit\n", prn);
  358.   fprintf(prn, "%%%%LanguageLevel: %d\n", model + 1);
  359.   fputs("%%Pages: 1\n", prn);
  360.   fputs("%%Orientation: Portrait\n", prn);
  361.   fputs("%%EndComments\n", prn);
  362.  
  363.  /*
  364.   * Find any printer-specific commands...
  365.   */
  366.  
  367.   num_commands = 0;
  368.  
  369.   if ((command = ppd_find(ppd_file, "PageSize", media_size, &order)) != NULL)
  370.   {
  371.     commands[num_commands].command = malloc(strlen(command) + 1);
  372.     strcpy(commands[num_commands].command, command);
  373.     commands[num_commands].order   = order;
  374.     num_commands ++;
  375.   }
  376.  
  377.   if ((command = ppd_find(ppd_file, "InputSlot", media_source, &order)) != NULL)
  378.   {
  379.     commands[num_commands].command = malloc(strlen(command) + 1);
  380.     strcpy(commands[num_commands].command, command);
  381.     commands[num_commands].order   = order;
  382.     num_commands ++;
  383.   }
  384.  
  385.   if ((command = ppd_find(ppd_file, "MediaType", media_type, &order)) != NULL)
  386.   {
  387.     commands[num_commands].command = malloc(strlen(command) + 1);
  388.     strcpy(commands[num_commands].command, command);
  389.     commands[num_commands].order   = order;
  390.     num_commands ++;
  391.   }
  392.  
  393.   if ((command = ppd_find(ppd_file, "Resolution", resolution, &order)) != NULL)
  394.   {
  395.     commands[num_commands].command = malloc(strlen(command) + 1);
  396.     strcpy(commands[num_commands].command, command);
  397.     commands[num_commands].order   = order;
  398.     num_commands ++;
  399.   }
  400.  
  401.  /*
  402.   * Sort the commands using the OrderDependency value...
  403.   */
  404.  
  405.   for (i = 0; i < (num_commands - 1); i ++)
  406.     for (j = i + 1; j < num_commands; j ++)
  407.       if (commands[j].order < commands[i].order)
  408.       {
  409.         order               = commands[i].order;
  410.         command             = commands[i].command;
  411.         commands[i].command = commands[j].command;
  412.         commands[i].order   = commands[j].order;
  413.         commands[j].command = command;
  414.         commands[j].order   = order;
  415.       }
  416.  
  417.  /*
  418.   * Send the commands...
  419.   */
  420.  
  421.   if (num_commands > 0)
  422.   {
  423.     fputs("%%BeginProlog\n", prn);
  424.  
  425.     for (i = 0; i < num_commands; i ++)
  426.     {
  427.       fputs(commands[i].command, prn);
  428.       fputs("\n", prn);
  429.       free(commands[i].command);
  430.     }
  431.  
  432.     fputs("%%EndProlog\n", prn);
  433.   }
  434.  
  435.  /*
  436.   * Output the page...
  437.   */
  438.  
  439.   fputs("%%Page: 1\n", prn);
  440.   fputs("gsave\n", prn);
  441.  
  442.   fprintf(prn, "%d %d translate\n", left, top);
  443.   fprintf(prn, "%.3f %.3f scale\n",
  444.           (double)out_width / ((double)image_width),
  445.           (double)out_height / ((double)image_height));
  446.  
  447.   in  = malloc(image_width * image_bpp);
  448.   out = malloc((image_width * out_bpp + 3) * 2);
  449.  
  450.   compute_lut(256, &nv);
  451.  
  452.   if (model == 0)
  453.   {
  454.     fprintf(prn, "/picture %d string def\n", image_width * out_bpp);
  455.  
  456.     fprintf(prn, "%d %d 8\n", image_width, image_height);
  457.  
  458.     fputs("[ 1 0 0 -1 0 1 ]\n", prn);
  459.  
  460.     if (output_type == OUTPUT_GRAY)
  461.       fputs("{currentfile picture readhexstring pop} image\n", prn);
  462.     else
  463.       fputs("{currentfile picture readhexstring pop} false 3 colorimage\n", prn);
  464.  
  465.     for (y = 0; y < image_height; y ++)
  466.     {
  467.       if ((y & 15) == 0)
  468.     Image_note_progress(image, y, image_height);
  469.  
  470.       Image_get_row(image, in, y);
  471.       (*colorfunc)(in, out, image_width, image_bpp, cmap, &nv);
  472.  
  473.       ps_hex(prn, out, image_width * out_bpp);
  474.     }
  475.   }
  476.   else
  477.   {
  478.     if (output_type == OUTPUT_GRAY)
  479.       fputs("/DeviceGray setcolorspace\n", prn);
  480.     else
  481.       fputs("/DeviceRGB setcolorspace\n", prn);
  482.  
  483.     fputs("<<\n", prn);
  484.     fputs("\t/ImageType 1\n", prn);
  485.  
  486.     fprintf(prn, "\t/Width %d\n", image_width);
  487.     fprintf(prn, "\t/Height %d\n", image_height);
  488.     fputs("\t/BitsPerComponent 8\n", prn);
  489.  
  490.     if (output_type == OUTPUT_GRAY)
  491.       fputs("\t/Decode [ 0 1 ]\n", prn);
  492.     else
  493.       fputs("\t/Decode [ 0 1 0 1 0 1 ]\n", prn);
  494.  
  495.     fputs("\t/DataSource currentfile /ASCII85Decode filter\n", prn);
  496.  
  497.     if ((image_width * 72 / out_width) < 100)
  498.       fputs("\t/Interpolate true\n", prn);
  499.  
  500.     fputs("\t/ImageMatrix [ 1 0 0 -1 0 1 ]\n", prn);
  501.  
  502.     fputs(">>\n", prn);
  503.     fputs("image\n", prn);
  504.  
  505.     for (y = 0, out_offset = 0; y < image_height; y ++)
  506.     {
  507.       if ((y & 15) == 0)
  508.     Image_note_progress(image, y, image_height);
  509.  
  510.       Image_get_row(image, in, y);
  511.       (*colorfunc)(in, out + out_offset, image_width, image_bpp, cmap, &nv);
  512.  
  513.       out_length = out_offset + image_width * out_bpp;
  514.  
  515.       if (y < (image_height - 1))
  516.       {
  517.         ps_ascii85(prn, out, out_length & ~3, 0);
  518.         out_offset = out_length & 3;
  519.       }
  520.       else
  521.       {
  522.         ps_ascii85(prn, out, out_length, 1);
  523.         out_offset = 0;
  524.       }
  525.  
  526.       if (out_offset > 0)
  527.         memcpy(out, out + out_length - out_offset, out_offset);
  528.     }
  529.   }
  530.   Image_progress_conclude(image);
  531.  
  532.   free_lut(&nv);
  533.   free(in);
  534.   free(out);
  535.  
  536.   fputs("grestore\n", prn);
  537.   fputs("showpage\n", prn);
  538.   fputs("%%EndPage\n", prn);
  539.   fputs("%%EOF\n", prn);
  540. }
  541.  
  542.  
  543. /*
  544.  * 'ps_hex()' - Print binary data as a series of hexadecimal numbers.
  545.  */
  546.  
  547. static void
  548. ps_hex(FILE   *prn,    /* I - File to print to */
  549.        unsigned short *data,    /* I - Data to print */
  550.        int    length)    /* I - Number of bytes to print */
  551. {
  552.   int        col;    /* Current column */
  553.   static char    *hex = "0123456789ABCDEF";
  554.  
  555.  
  556.   col = 0;
  557.   while (length > 0)
  558.   {
  559.     unsigned char pixel = (*data & 0xff00) >> 8;
  560.    /*
  561.     * Put the hex chars out to the file; note that we don't use fprintf()
  562.     * for speed reasons...
  563.     */
  564.  
  565.     putc(hex[pixel >> 4], prn);
  566.     putc(hex[pixel & 15], prn);
  567.  
  568.     data ++;
  569.     length --;
  570.  
  571.     col = (col + 1) & 31;
  572.     if (col == 0)
  573.       putc('\n', prn);
  574.   }
  575.  
  576.   if (col > 0)
  577.     putc('\n', prn);
  578. }
  579.  
  580.  
  581. /*
  582.  * 'ps_ascii85()' - Print binary data as a series of base-85 numbers.
  583.  */
  584.  
  585. static void
  586. ps_ascii85(FILE   *prn,        /* I - File to print to */
  587.        unsigned short *data,    /* I - Data to print */
  588.        int    length,    /* I - Number of bytes to print */
  589.        int    last_line)    /* I - Last line of raster data? */
  590. {
  591.   int        i;        /* Looping var */
  592.   unsigned    b;        /* Binary data word */
  593.   unsigned char    c[5];        /* ASCII85 encoded chars */
  594.  
  595.  
  596.   while (length > 3)
  597.   {
  598.     unsigned char d0 = (data[0] & 0xff00) >> 8;
  599.     unsigned char d1 = (data[1] & 0xff00) >> 8;
  600.     unsigned char d2 = (data[2] & 0xff00) >> 8;
  601.     unsigned char d3 = (data[3] & 0xff00) >> 8;
  602.     b = (((((d0 << 8) | d1) << 8) | d2) << 8) | d3;
  603.  
  604.     if (b == 0)
  605.       putc('z', prn);
  606.     else
  607.     {
  608.       c[4] = (b % 85) + '!';
  609.       b /= 85;
  610.       c[3] = (b % 85) + '!';
  611.       b /= 85;
  612.       c[2] = (b % 85) + '!';
  613.       b /= 85;
  614.       c[1] = (b % 85) + '!';
  615.       b /= 85;
  616.       c[0] = b + '!';
  617.  
  618.       fwrite(c, 5, 1, prn);
  619.     }
  620.  
  621.     data += 4;
  622.     length -= 4;
  623.   }
  624.  
  625.   if (last_line)
  626.   {
  627.     if (length > 0)
  628.     {
  629.       for (b = 0, i = length; i > 0; b = (b << 8) | data[0], data ++, i --);
  630.  
  631.       c[4] = (b % 85) + '!';
  632.       b /= 85;
  633.       c[3] = (b % 85) + '!';
  634.       b /= 85;
  635.       c[2] = (b % 85) + '!';
  636.       b /= 85;
  637.       c[1] = (b % 85) + '!';
  638.       b /= 85;
  639.       c[0] = b + '!';
  640.  
  641.       fwrite(c, length + 1, 1, prn);
  642.     }
  643.  
  644.     fputs("~>\n", prn);
  645.   }
  646. }
  647.  
  648.  
  649. /*
  650.  * 'ppd_find()' - Find a control string with the specified name & parameters.
  651.  */
  652.  
  653. static char *            /* O - Control string */
  654. ppd_find(const char *ppd_file,    /* I - Name of PPD file */
  655.          const char *name,        /* I - Name of parameter */
  656.          const char *option,        /* I - Value of parameter */
  657.          int  *order)        /* O - Order of the control string */
  658. {
  659.   char        line[1024],    /* Line from file */
  660.         lname[255],    /* Name from line */
  661.         loption[255],    /* Value from line */
  662.         *opt;        /* Current control string pointer */
  663.   static char    *value = NULL;    /* Current control string value */
  664.  
  665.  
  666.   if (ppd_file == NULL || name == NULL || option == NULL)
  667.     return (NULL);
  668.   if (!value)
  669.     value = malloc(32768);
  670.  
  671.   if (ps_ppd_file == NULL || strcmp(ps_ppd_file, ppd_file) != 0)
  672.   {
  673.     if (ps_ppd != NULL)
  674.       fclose(ps_ppd);
  675.  
  676.     ps_ppd = fopen(ppd_file, "r");
  677.  
  678.     if (ps_ppd == NULL)
  679.       ps_ppd_file = NULL;
  680.     else
  681.       ps_ppd_file = ppd_file;
  682.   }
  683.  
  684.   if (ps_ppd == NULL)
  685.     return (NULL);
  686.  
  687.   if (order != NULL)
  688.     *order = 1000;
  689.  
  690.   rewind(ps_ppd);
  691.   while (fgets(line, sizeof(line), ps_ppd) != NULL)
  692.   {
  693.     if (line[0] != '*')
  694.       continue;
  695.  
  696.     if (strncasecmp(line, "*OrderDependency:", 17) == 0 && order != NULL)
  697.     {
  698.       sscanf(line, "%*s%d", order);
  699.       continue;
  700.     }
  701.     else if (sscanf(line, "*%s %[^/:]", lname, loption) != 2)
  702.       continue;
  703.  
  704.     if (strcasecmp(lname, name) == 0 &&
  705.         strcasecmp(loption, option) == 0)
  706.     {
  707.       opt = strchr(line, ':') + 1;
  708.       while (*opt == ' ' || *opt == '\t')
  709.         opt ++;
  710.       if (*opt != '\"')
  711.         continue;
  712.  
  713.       strcpy(value, opt + 1);
  714.       if ((opt = strchr(value, '\"')) == NULL)
  715.       {
  716.         while (fgets(line, sizeof(line), ps_ppd) != NULL)
  717.         {
  718.           strcat(value, line);
  719.           if (strchr(line, '\"') != NULL)
  720.           {
  721.             strcpy(strchr(value, '\"'), "\n");
  722.             break;
  723.           }
  724.         }
  725.       }
  726.       else
  727.         *opt = '\0';
  728.  
  729.       return (value);
  730.     }
  731.   }
  732.  
  733.   return (NULL);
  734. }
  735.