]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Merge changes from 1.1 tree.
authormike <mike@7a7537e8-13f0-0310-91df-b6672ffda945>
Sun, 13 May 2001 18:38:42 +0000 (18:38 +0000)
committermike <mike@7a7537e8-13f0-0310-91df-b6672ffda945>
Sun, 13 May 2001 18:38:42 +0000 (18:38 +0000)
git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/branches/branch-1.2@1719 7a7537e8-13f0-0310-91df-b6672ffda945

136 files changed:
CHANGES.txt
INSTALL.txt
Makedefs.in
Makefile
README.txt
backend/ipp.c
backend/socket.c
berkeley/lpc.c
berkeley/lpq.c
berkeley/lpr.c
berkeley/lprm.c
cgi-bin/admin.c
cgi-bin/classes.c
cgi-bin/jobs.c
cgi-bin/printers.c
conf/mime.types
config.h.in
configure.in
cups.list
cups.sh.in
cups.spec
cups/cups.h
cups/encode.c
cups/http.c
cups/http.h
cups/ipp.c
cups/ipp.h
cups/options.c
cups/ppd.c
cups/string.h
cups/util.c
doc/cmp.pdf
doc/idd.pdf
doc/ipp.pdf
doc/overview.pdf
doc/sam.html
doc/sam.pdf
doc/sdd.pdf
doc/spm.pdf
doc/sps.pdf
doc/ssr.pdf
doc/stp.pdf
doc/sum.html
doc/sum.pdf
doc/sum.shtml
doc/svd.pdf
filter/common.c
filter/common.h
filter/image-bmp.c
filter/image-tiff.c
filter/imagetops.c
filter/imagetoraster.c
filter/pstops.c
filter/rastertoepson.c
filter/rastertohp.c
filter/textcommon.c
filter/textcommon.h
filter/texttops.c
pdftops/CompactFontInfo.h
pdftops/Dict.cxx
pdftops/Dict.h
pdftops/Error.cxx
pdftops/Error.h
pdftops/FontEncoding.cxx
pdftops/FontEncoding.h
pdftops/FontFile.cxx
pdftops/FontFile.h
pdftops/FontInfo.h
pdftops/FormWidget.cxx
pdftops/Gfx.cxx
pdftops/Gfx.h
pdftops/GfxFont.cxx
pdftops/GfxFont.h
pdftops/GfxState.cxx
pdftops/GfxState.h
pdftops/ImageOutputDev.cxx [deleted file]
pdftops/ImageOutputDev.h [deleted file]
pdftops/Lexer.cxx
pdftops/Link.cxx
pdftops/Link.h
pdftops/Object.cxx
pdftops/Object.h
pdftops/OutputDev.cxx
pdftops/OutputDev.h
pdftops/PDFDoc.cxx
pdftops/PDFDoc.h
pdftops/PSOutputDev.cxx
pdftops/PSOutputDev.h
pdftops/Page.cxx
pdftops/Page.h
pdftops/Params.cxx
pdftops/Params.h
pdftops/Parser.cxx
pdftops/StdFontInfo.h
pdftops/Stream.cxx
pdftops/Stream.h
pdftops/XRef.cxx
pdftops/XRef.h
pdftops/config.h
pdftops/gfile.cxx
pdftops/gfile.h
pdftops/gmem.c
pdftops/gmem.h
pdftops/gtypes.h
pdftops/pdftops.cxx
ppd/Makefile
ppd/deskjet.ppd
ppd/deskjet2.ppd
ppd/laserjet.ppd
pstoraster/Makefile
pstoraster/gdevm1.c
pstoraster/gs_fonts.ps
pstoraster/gstype2.c
pstoraster/gxclrast.c
pstoraster/iparam.c
pstoraster/stdpre.h
pstoraster/zfunc.c
scheduler/auth.c
scheduler/cert.c
scheduler/client.c
scheduler/cups-lpd.c
scheduler/cups-polld.c
scheduler/dirsvc.c
scheduler/ipp.c
scheduler/job.c
scheduler/main.c
scheduler/ppds.c
scheduler/printers.c
systemv/accept.c
systemv/cancel.c
systemv/lp.c
systemv/lpadmin.c
systemv/lpinfo.c
systemv/lpmove.c
systemv/lpstat.c
test/get-job-attributes.test

index 93563bc7ad2a68fa595a3bebb5ade1822e429460..bafb94a85ca1bd7bb611eaeda02eda1ce5baab88 100644 (file)
@@ -1,6 +1,47 @@
-CHANGES.txt - 03/29/2001
+CHANGES.txt - 05/07/2001
 ------------------------
 
+CHANGES IN CUPS V1.1.8
+
+       - Updated spec file to generate separate cups-pstoraster
+         package for pstoraster.
+       - The spec file wasn't setting LOGDIR in the install.
+       - The scheduler might restart a stopped printer after
+         stopping a print job. Thanks to Florent
+         Guiliani for finding this bug!
+       - The init script showed run level 0 for the Red Hat
+         chkconfig program.  This is incorrect because Red Hat
+         doesn't use run level 0 for shutdown scripts.
+       - The IPP backend did not handle the
+         client-error-not-found error when checking the status
+         of the job that was sent.  This caused remote queues
+         to stop on client machines when the server had job
+         history disabled.
+       - Added httpConnectEncrypt() function to avoid
+         performance penalty for setting up encrypted
+         connections initially.
+       - Use httpConnectEncrypt() in all client apps and in the
+         CUPS API to ensure consistent usage of encryption
+         throughout.
+       - Jobs weren't queued to remote classes (fix from
+         Richard Begg.)
+       - AIX changes from Richard Begg.
+       - Fixed the pstops fix for GNOME output - no longer use
+         the page numbers in the %%Page: comment since GNOME
+         puts a filename instead (!?@!#?!).  There is still an
+         issue with N-up printing since GNOME defines its fonts
+         in the first page instead of the document setup section
+         (pages must be independent according to the DSC spec)
+         People with GNOME printing problems should consult bug
+         #54489...
+       - The imagetops filter produced PAGE: messages when
+         generating PostScript for a non-PostScript printer
+         (only affects page-label and Classification
+          options.)
+       - The updated pdftops filter was looking for an options
+         file called xpdf.conf instead of pdftops.conf.
+
+
 CHANGES IN CUPS V1.1.7
 
        - Configuration script changes, including new
@@ -13,9 +54,9 @@ CHANGES IN CUPS V1.1.7
        - All scheduler configuration files are now case
          insensitive to match Apache.
        - Added support for Apache ListenBackLog, LogFormat,
-         PassEnv, SetEnv, UnsetEnv, Require, UseCanonicalName,
-         Satisfy, <Limit>, <LimitExcept>, LimitRequestSize, and
-         Options directives.
+         Require, UseCanonicalName, Satisfy, <Limit>,
+         <LimitExcept>, LimitRequestSize, and Options
+         directives.
        - Added support for all Apache log levels...
        - Added support for "double" HostNameLookups.
        - Added new "RunAsUser" directive to support non-root
@@ -133,8 +174,65 @@ CHANGES IN CUPS V1.1.7
          clients or start print jobs as the load allows.
        - Fixed a bug in the Set-Job-Attributes code that could
          crash the scheduler (patch from Martin Zielinski)
-       - cupsSetDests() did not quote option values with embedded
-         spaces.
+       - cupsSetDests() did not quote option values with
+         embedded spaces.
+       - Added support for the Enable-Printer and
+         Disable-Printer extension operations (same as
+         CUPS-Accept-Jobs and CUPS-Reject-Jobs.)
+       - The AppSocket and IPP backends now wait for the print
+         job to be finished before exiting; this should prevent
+         the loss of print jobs with older JetDirect firmware
+         and make consecutive print jobs print faster.
+       - The BMP loading code did not handle resolution values
+         of 0.  This is a problem with BMP image files produced
+         by the GIMP.
+       - The HTTP Upgrade code (upgrade to TLS encryption)
+         bypassed the authentication checks.
+       - The HTTP Upgrade code did not send a 426 status code
+         to the client and end the current request. This caused
+         a race condition between the client and server for the
+         upgrade to TLS.
+       - Fixed a bug in the EOF and Trailer detection code in
+         the pstops filter.
+       - The imagetoraster filter did not add the margins to
+         the custom page size in the raster header.
+       - The imagetops filter did not adjust the custom page
+         size to the size of the printed image.
+       - The imagetops filter did not include DSC comments
+         which are required by some printers.
+       - The imagetops filter did not insert newlines in
+         Base85 encoded output, causing files to contain
+         lines longer than 255 characters (violation of the
+         DSC).
+       - Added support for the DeskJet 900 series duplexer
+         and CRET color modes in the HP driver.
+       - Added support for PPD-defined margins in the HP
+         driver.
+       - Fixed the debugging output from pstoraster - the
+         font list was not terminated by a newline.
+       - Some versions of the HP-UX pam_unix authentication
+         module apparently do not pass the appdata_ptr argument
+         to the conversation function, preventing the scheduler
+         from authenticating users using PAM under HP-UX.  A
+         workaround using a static variable has been added to
+         address this problem.
+       - Fixed a bug in the scheduler SortPrinters() function
+         that could cause printers to disappear or the
+         scheduler to crash when adding a printer.
+       - Changed the pstops filter to not do per-page filtering
+         if the file does not conform to at least version 3.0
+         of the document structuring conventions.  This seems
+         to "fix" printing with broken apps.
+       - The image filters did not handle older TIFF files that
+         lacked the samples-per-pixel and bits-per-pixel tags.
+       - Added new cupsGetJobs() and cupsFreeJobs() functions
+         to manage print jobs.
+       - cupsEncodeOptions() would encode names of 0 length and
+         cupsAddOption() and cupsParseOptions() would add names
+         of 0 length.
+       - The scheduler might block waiting for status messages
+         after starting a new print job. Thanks to Florent
+         Guiliani for finding this bug!
 
 
 CHANGES IN CUPS V1.1.6-3
index 02df345c82dc7b775a5b5043c1d0518056333793..bcfb5e2654f3219dfe345f9fce9e9295fb8b089b 100644 (file)
@@ -1,4 +1,4 @@
-INSTALL - CUPS v1.1.6 - 01/23/2001
+INSTALL - CUPS v1.1.7 - 05/01/2001
 ----------------------------------
 
 This file describes how to compile and install CUPS from source
index 72b55ce4c8863b69858d2aa20f71afc843ff8fd5..8b5bd4d221bc87b9fbaf15fa4fa5ad457326aac8 100644 (file)
@@ -1,5 +1,5 @@
 #
-# "$Id: Makedefs.in,v 1.36 2001/03/01 18:10:40 mike Exp $"
+# "$Id: Makedefs.in,v 1.36.2.1 2001/05/13 18:37:58 mike Exp $"
 #
 #   Common makefile definitions for the Common UNIX Printing System (CUPS).
 #
@@ -70,8 +70,6 @@ LIBZ  =       @LIBZ@
 #
 # Program options...
 #
-# GSOPTIM defines the common compiler optimization/debugging options for
-#         pstoraster (Ghostscript).
 # OPTIM   defines the common compiler optimization/debugging options.
 # OPTIONS defines other compile-time options (currently only -dDEBUG for
 #         extra debug info)
@@ -82,7 +80,6 @@ CFLAGS        =       @CFLAGS@ -I.. $(OPTIONS)
 CXXFLAGS =     @CXXFLAGS@ -I.. $(OPTIONS)
 DSOFLAGS =     @DSOFLAGS@
 DSOLIBS        =       @DSOLIBS@
-GSOPTIM        =       @GSOPTIM@
 IMGLIBS        =       @IMGLIBS@ -lm
 LDFLAGS        =       @LDFLAGS@ $(OPTIM)
 LINKCUPS =     @LINKCUPS@
@@ -168,5 +165,5 @@ MAN8EXT             =       @MAN8EXT@
        $(MV) t.z $@
 
 #
-# End of "$Id: Makedefs.in,v 1.36 2001/03/01 18:10:40 mike Exp $"
+# End of "$Id: Makedefs.in,v 1.36.2.1 2001/05/13 18:37:58 mike Exp $"
 #
index 7ef93dfaa75b41dcd1fc1fda0825da35597929e6..db0cfa236b26499eb9b7b3a67773d48c96ec63a3 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
 #
-# "$Id: Makefile,v 1.31 2001/03/01 20:40:14 mike Exp $"
+# "$Id: Makefile,v 1.31.2.1 2001/05/13 18:37:58 mike Exp $"
 #
 #   Top-level Makefile for the Common UNIX Printing System (CUPS).
 #
@@ -115,6 +115,7 @@ test:       all
 #
 
 EPMFLAGS       =       -v \
+                       AMANDIR=$(AMANDIR) \
                        BINDIR=$(BINDIR) DATADIR=$(DATADIR) \
                        DOCDIR=$(DOCDIR) INCLUDEDIR=$(INCLUDEDIR) \
                        LIBDIR=$(LIBDIR) LOCALEDIR=$(LOCALEDIR) \
@@ -142,5 +143,5 @@ tardist:
        epm $(EPMFLAGS) -f tardist cups
 
 #
-# End of "$Id: Makefile,v 1.31 2001/03/01 20:40:14 mike Exp $".
+# End of "$Id: Makefile,v 1.31.2.1 2001/05/13 18:37:58 mike Exp $".
 #
index 84026cb31728fc4e48befff128a50d1ac37eb17d..1dad6ea49960b8da09b2958a6f9e370bce7a8ddc 100644 (file)
@@ -1,4 +1,4 @@
-README - CUPS v1.1.6 - 01/23/2001
+README - CUPS v1.1.7 - 05/01/2001
 ---------------------------------
 
 Looking for compile instructions?  Read the file "INSTALL.txt"
index ed4e530c5f5d595e058257a5484a7946b559597d..7c10ea60f8e1766e2ea07822f2e2cbc004c87ec7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: ipp.c,v 1.38 2001/02/14 13:59:45 mike Exp $"
+ * "$Id: ipp.c,v 1.38.2.1 2001/05/13 18:37:59 mike Exp $"
  *
  *   IPP backend for the Common UNIX Printing System (CUPS).
  *
@@ -23,7 +23,8 @@
  *
  * Contents:
  *
- *   main() - Send a file to the printer or server.
+ *   main()        - Send a file to the printer or server.
+ *   password_cb() - Disable the password prompt for cupsDoFileRequest().
  */
 
 /*
 #include <signal.h>
 
 
+/*
+ * Local functions...
+ */
+
+const char     *password_cb(const char *);
+
+
+/*
+ * Local globals...
+ */
+
+char   *password = NULL;
+
+
 /*
  * 'main()' - Send a file to the printer or server.
  *
@@ -62,25 +77,20 @@ main(int  argc,             /* I - Number of command-line arguments (6 or 7) */
                resource[1024], /* Resource info (printer name) */
                filename[1024]; /* File to print */
   int          port;           /* Port number (not used) */
-  char         password[255],  /* Password info */
-               uri[HTTP_MAX_URI];/* Updated URI without user/pass */
-  http_status_t        status;         /* Status of HTTP job */
+  char         uri[HTTP_MAX_URI];/* Updated URI without user/pass */
   ipp_status_t ipp_status;     /* Status of IPP request */
-  FILE         *fp;            /* File to print */
   http_t       *http;          /* HTTP connection */
   ipp_t                *request,       /* IPP request */
                *response,      /* IPP response */
                *supported;     /* get-printer-attributes response */
-  ipp_attribute_t *job_id;     /* job-id attribute */
+  ipp_attribute_t *job_id_attr;        /* job-id attribute */
+  int          job_id;         /* job-id value */
+  ipp_attribute_t *job_state;  /* job-state attribute */
   ipp_attribute_t *copies_sup; /* copies-supported attribute */
   ipp_attribute_t *charset_sup;        /* charset-supported attribute */
   ipp_attribute_t *format_sup; /* document-format-supported attribute */
   const char   *charset;       /* Character set to use */
   cups_lang_t  *language;      /* Default language */
-  struct stat  fileinfo;       /* File statistics */
-  size_t       nbytes,         /* Number of bytes written */
-               tbytes;         /* Total bytes written */
-  char         buffer[8192];   /* Output buffer */
   int          copies;         /* Number of copies remaining */
   const char   *content_type;  /* CONTENT_TYPE environment variable */
 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
@@ -159,22 +169,24 @@ main(int  argc,           /* I - Number of command-line arguments (6 or 7) */
   }
 
  /*
-  * Open the print file...
+  * Extract the hostname and printer name from the URI...
   */
 
-  if ((fp = fopen(filename, "rb")) == NULL)
-  {
-    perror("ERROR: Unable to open print file");
-    return (1);
-  }
-  else
-    stat(filename, &fileinfo);
+  httpSeparate(argv[0], method, username, hostname, &port, resource);
 
  /*
-  * Extract the hostname and printer name from the URI...
+  * Set the authentication info, if any...
   */
 
-  httpSeparate(argv[0], method, username, hostname, &port, resource);
+  cupsSetPasswordCB(password_cb);
+
+  if (username[0])
+  {
+    if ((password = strchr(username, ':')) != NULL)
+      *password++ = '\0';
+
+    cupsSetUser(username);
+  }
 
  /*
   * Try connecting to the remote server...
@@ -243,159 +255,65 @@ main(int  argc,          /* I - Number of command-line arguments (6 or 7) */
     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
                 NULL, uri);
 
-   /*
-    * Now fill in the HTTP request stuff...
-    */
-
-    httpClearFields(http);
-    httpSetField(http, HTTP_FIELD_CONTENT_TYPE, "application/ipp");
-    if (username[0])
-    {
-      httpEncode64(password, username);
-      httpSetField(http, HTTP_FIELD_AUTHORIZATION, password);
-    }
-
-    sprintf(buffer, "%u", ippLength(request));
-    httpSetField(http, HTTP_FIELD_CONTENT_LENGTH, buffer);
-
    /*
     * Do the request...
     */
 
-    for (response = NULL, ipp_status = IPP_BAD_REQUEST;;)
+    if ((supported = cupsDoRequest(http, request, resource)) == NULL)
+      ipp_status = cupsLastError();
+    else
+      ipp_status = supported->request.status.status_code;
+
+    if (ipp_status > IPP_OK_CONFLICT)
     {
-     /*
-      * POST the request, retrying as needed...
-      */
+      if (supported)
+        ippDelete(supported);
 
-      if (httpPost(http, resource))
+      if (ipp_status == IPP_PRINTER_BUSY ||
+         ipp_status == IPP_SERVICE_UNAVAILABLE)
       {
-       fputs("INFO: Unable to POST get-printer-attributes request; retrying...\n", stderr);
+       fputs("INFO: Printer busy; will retry in 10 seconds...\n", stderr);
        sleep(10);
-       httpReconnect(http);
-       continue;
-      }
-
-      fputs("INFO: POST successful, sending IPP request...\n", stderr);
-
-     /*
-      * Send the IPP request...
-      */
-
-      request->state = IPP_IDLE;
-
-      if (ippWrite(http, request) == IPP_ERROR)
-      {
-       fputs("ERROR: Unable to send IPP request!\n", stderr);
-       status = HTTP_ERROR;
-       break;
       }
-
-      fputs("INFO: IPP request sent, getting status...\n", stderr);
-
-     /*
-      * Finally, check the status from the HTTP server...
-      */
-
-      while ((status = httpUpdate(http)) == HTTP_CONTINUE);
-
-      if (supported)
-       ippDelete(supported);
-
-      if (status == HTTP_OK)
+      else if ((ipp_status == IPP_BAD_REQUEST ||
+               ipp_status == IPP_VERSION_NOT_SUPPORTED) && version == 1)
       {
-       supported = ippNew();
-       ippRead(http, supported);
+       /*
+       * Switch to IPP/1.0...
+       */
 
-       ipp_status = supported->request.status.status_code;
-
-       if (ipp_status > IPP_OK_CONFLICT)
-       {
-         if (ipp_status == IPP_PRINTER_BUSY ||
-             ipp_status == IPP_SERVICE_UNAVAILABLE)
-         {
-           fputs("INFO: Printer busy; will retry in 10 seconds...\n", stderr);
-           sleep(10);
-         }
-         else if ((ipp_status == IPP_BAD_REQUEST ||
-                   ipp_status == IPP_VERSION_NOT_SUPPORTED) && version == 1)
-         {
-          /*
-           * Switch to IPP/1.0...
-           */
-
-           fputs("INFO: Printer does not support IPP/1.1, trying IPP/1.0...\n", stderr);
-           version = 0;
-         }
-         else
-         {
-           fprintf(stderr, "ERROR: Printer will not accept print file (%x)!\n",
-                   ipp_status);
-           fprintf(stderr, "ERROR: %s\n", ippErrorString(ipp_status));
-            status = HTTP_ERROR;
-         }
-       }
-       else if ((copies_sup = ippFindAttribute(supported, "copies-supported",
-                                               IPP_TAG_RANGE)) != NULL)
-        {
-        /*
-         * Has the "copies-supported" attribute - does it have an upper
-         * bound > 1?
-         */
-
-         if (copies_sup->values[0].range.upper <= 1)
-           copies_sup = NULL; /* No */
-        }
-
-        charset_sup = ippFindAttribute(supported, "charset-supported",
-                                      IPP_TAG_CHARSET);
-        format_sup  = ippFindAttribute(supported, "document-format-supported",
-                                      IPP_TAG_MIMETYPE);
-
-        if (format_sup)
-       {
-         fprintf(stderr, "DEBUG: document-format-supported (%d values)\n",
-                 format_sup->num_values);
-         for (i = 0; i < format_sup->num_values; i ++)
-           fprintf(stderr, "DEBUG: [%d] = \"%s\"\n", i,
-                   format_sup->values[i].string.text);
-       }
+       fputs("INFO: Printer does not support IPP/1.1, trying IPP/1.0...\n", stderr);
+       version = 0;
       }
       else
-      {
-        supported = NULL;
-
-       if (status == HTTP_ERROR)
-       {
-          fprintf(stderr, "WARNING: Did not receive the IPP supported (%d)\n",
-                 errno);
-         status     = HTTP_OK;
-         ipp_status = IPP_PRINTER_BUSY;
-       }
-       else
-       {
-          fprintf(stderr, "ERROR: Validate request was not accepted (%d)!\n",
-                 status);
-         ipp_status = IPP_FORBIDDEN;
-       }
-      }
-
-      httpFlush(http);
-
-      break;
+       fprintf(stderr, "ERROR: Printer will not accept print file (%s)!\n",
+               ippErrorString(ipp_status));
     }
-
-    if (status != HTTP_OK)
+    else if ((copies_sup = ippFindAttribute(supported, "copies-supported",
+                                           IPP_TAG_RANGE)) != NULL)
     {
-      if (fp != stdin)
-       fclose(fp);
+     /*
+      * Has the "copies-supported" attribute - does it have an upper
+      * bound > 1?
+      */
 
-      httpClose(http);
+      if (copies_sup->values[0].range.upper <= 1)
+       copies_sup = NULL; /* No */
+    }
 
-      return (1);
+    charset_sup = ippFindAttribute(supported, "charset-supported",
+                                  IPP_TAG_CHARSET);
+    format_sup  = ippFindAttribute(supported, "document-format-supported",
+                                  IPP_TAG_MIMETYPE);
+
+    if (format_sup)
+    {
+      fprintf(stderr, "DEBUG: document-format-supported (%d values)\n",
+             format_sup->num_values);
+      for (i = 0; i < format_sup->num_values; i ++)
+       fprintf(stderr, "DEBUG: [%d] = \"%s\"\n", i,
+               format_sup->values[i].string.text);
     }
-    else if (ipp_status > IPP_OK_CONFLICT)
-      httpReconnect(http);
   }
   while (ipp_status > IPP_OK_CONFLICT);
 
@@ -525,143 +443,140 @@ main(int  argc,         /* I - Number of command-line arguments (6 or 7) */
       ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_INTEGER, "copies", atoi(argv[4]));
 
    /*
-    * Now fill in the HTTP request stuff...
+    * Do the request...
     */
 
-    httpClearFields(http);
-    httpSetField(http, HTTP_FIELD_CONTENT_TYPE, "application/ipp");
-    if (username[0])
+    if ((response = cupsDoFileRequest(http, request, resource, filename)) == NULL)
+      ipp_status = cupsLastError();
+    else
+      ipp_status = response->request.status.status_code;
+
+    if (ipp_status > IPP_OK_CONFLICT)
+    {
+      if (ipp_status == IPP_SERVICE_UNAVAILABLE ||
+         ipp_status == IPP_PRINTER_BUSY)
+      {
+       fputs("INFO: Printer is busy; retrying print job...\n", stderr);
+       sleep(10);
+      }
+      else
+        fprintf(stderr, "ERROR: Print file was not accepted (%s)!\n",
+               ippErrorString(ipp_status));
+    }
+    else if ((job_id_attr = ippFindAttribute(response, "job-id",
+                                             IPP_TAG_INTEGER)) == NULL)
     {
-      httpEncode64(password, username);
-      httpSetField(http, HTTP_FIELD_AUTHORIZATION, password);
+      fputs("INFO: Print file accepted - job ID unknown.\n", stderr);
+      job_id = 0;
+    }
+    else
+    {
+      job_id = job_id_attr->values[0].integer;
+      fprintf(stderr, "INFO: Print file accepted - job ID %d.\n", job_id);
     }
 
-    sprintf(buffer, "%u", ippLength(request) + (size_t)fileinfo.st_size);
-    httpSetField(http, HTTP_FIELD_CONTENT_LENGTH, buffer);
+    if (response)
+      ippDelete(response);
+
+    if (ipp_status <= IPP_OK_CONFLICT)
+    {
+      fprintf(stderr, "PAGE: 1 %d\n", copies_sup ? atoi(argv[4]) : 1);
+      copies --;
+    }
+    else if (ipp_status != IPP_SERVICE_UNAVAILABLE &&
+            ipp_status != IPP_PRINTER_BUSY)
+      break;
 
    /*
-    * Do the request...
+    * Wait for the job to complete...
     */
 
+    if (!job_id)
+      continue;
+
+    fputs("INFO: Waiting for job to complete...\n", stderr);
+
     for (;;)
     {
      /*
-      * POST the request, retrying as needed...
+      * Build an IPP_GET_JOB_ATTRIBUTES request...
       */
 
-      httpReconnect(http);
-
-      if (httpPost(http, resource))
-      {
-       fputs("INFO: Unable to POST print request; retrying...\n", stderr);
-       sleep(10);
-       continue;
-      }
+      request = ippNew();
+      request->request.op.version[1]   = version;
+      request->request.op.operation_id = IPP_GET_JOB_ATTRIBUTES;
+      request->request.op.request_id   = 1;
 
-      fputs("INFO: POST successful, sending IPP request...\n", stderr);
+      ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+                  "attributes-charset", NULL, charset);
 
-     /*
-      * Send the IPP request...
-      */
+      ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+                  "attributes-natural-language", NULL,
+                  language != NULL ? language->language : "en");
 
-      request->state = IPP_IDLE;
+      ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+                  NULL, uri);
 
-      if (ippWrite(http, request) == IPP_ERROR)
-      {
-       fputs("ERROR: Unable to send IPP request!\n", stderr);
-       status = HTTP_ERROR;
-       break;
-      }
+      ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id",
+                   job_id);
 
-      fputs("INFO: IPP request sent, sending print file...\n", stderr);
+      ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+                   "requested-attributes", NULL, "job-state");
 
      /*
-      * Then send the file...
+      * Do the request...
       */
 
-      rewind(fp);
+      if ((response = cupsDoRequest(http, request, resource)) == NULL)
+       ipp_status = cupsLastError();
+      else
+       ipp_status = response->request.status.status_code;
 
-      tbytes = 0;
-      while ((nbytes = fread(buffer, 1, sizeof(buffer), fp)) > 0)
+      if (ipp_status == IPP_NOT_FOUND)
       {
-       tbytes += nbytes;
-       fprintf(stderr, "INFO: Sending print file, %uk...\n", tbytes / 1024);
+       /*
+        * Job has gone away and the server has no job history...
+       */
 
-       if (httpWrite(http, buffer, nbytes) < nbytes)
-       {
-          perror("ERROR: Unable to send print file to printer");
-         status = HTTP_ERROR;
-          break;
-       }
+        ippDelete(response);
+        break;
       }
 
-      fputs("INFO: Print file sent; checking status...\n", stderr);
-
-     /*
-      * Finally, check the status from the HTTP server...
-      */
-
-      while ((status = httpUpdate(http)) == HTTP_CONTINUE);
-
-      if (status == HTTP_OK)
+      if (ipp_status > IPP_OK_CONFLICT)
       {
-       response = ippNew();
-       ippRead(http, response);
-
-       if ((ipp_status = response->request.status.status_code) > IPP_OK_CONFLICT)
+       if (ipp_status != IPP_SERVICE_UNAVAILABLE &&
+           ipp_status != IPP_PRINTER_BUSY)
        {
-          if (ipp_status == IPP_SERVICE_UNAVAILABLE ||
-             ipp_status == IPP_PRINTER_BUSY)
-         {
-           fputs("INFO: Printer is busy; retrying print job...\n", stderr);
-           sleep(10);
-         }
-         else
-         {
-            fprintf(stderr, "ERROR: Print file was not accepted (%04x)!\n",
-                   response->request.status.status_code);
-           fprintf(stderr, "ERROR: %s\n", ippErrorString(ipp_status));
-         }
+         if (response)
+           ippDelete(response);
+
+          fprintf(stderr, "ERROR: Unable to get job %d attributes (%s)!\n",
+                 job_id, ippErrorString(ipp_status));
+          break;
        }
-       else if ((job_id = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) == NULL)
-          fputs("INFO: Print file accepted - job ID unknown.\n", stderr);
-       else
-          fprintf(stderr, "INFO: Print file accepted - job ID %d.\n",
-                 job_id->values[0].integer);
       }
-      else
+      else if ((job_state = ippFindAttribute(response, "job-state", IPP_TAG_ENUM)) != NULL)
       {
-       response   = NULL;
-       ipp_status = IPP_PRINTER_BUSY;
+       /*
+        * Stop polling if the job is finished...
+       */
 
-       if (status == HTTP_ERROR)
+        if (job_state->values[0].integer > IPP_JOB_PROCESSING)
        {
-          fprintf(stderr, "WARNING: Did not receive the IPP response (%d)\n",
-                 errno);
-         status = HTTP_OK;
+         ippDelete(response);
+         break;
        }
-       else
-          fprintf(stderr, "ERROR: Print request was not accepted (%d)!\n", status);
       }
 
-      httpFlush(http);
-
-      break;
-    }
+     /*
+      * Wait 10 seconds before polling again...
+      */
 
-    if (request != NULL)
-      ippDelete(request);
-    if (response != NULL)
-      ippDelete(response);
+      if (response)
+       ippDelete(response);
 
-    if (ipp_status <= IPP_OK_CONFLICT)
-    {
-      fprintf(stderr, "PAGE: 1 %d\n", copies_sup ? atoi(argv[4]) : 1);
-      copies --;
+      sleep(10);
     }
-    else if (ipp_status != IPP_SERVICE_UNAVAILABLE &&
-            ipp_status != IPP_PRINTER_BUSY)
-      break;
   }
 
  /*
@@ -677,8 +592,6 @@ main(int  argc,             /* I - Number of command-line arguments (6 or 7) */
   * Close and remove the temporary file if necessary...
   */
 
-  fclose(fp);
-
   if (argc < 7)
     unlink(filename);
 
@@ -686,10 +599,26 @@ main(int  argc,           /* I - Number of command-line arguments (6 or 7) */
   * Return the queue status...
   */
 
-  return (status != HTTP_OK);
+  if (ipp_status <= IPP_OK_CONFLICT)
+    fputs("INFO: " CUPS_SVERSION " is ready to print.\n", stderr);
+
+  return (ipp_status > IPP_OK_CONFLICT);
+}
+
+
+/*
+ * 'password_cb()' - Disable the password prompt for cupsDoFileRequest().
+ */
+
+const char *                   /* O - Password  */
+password_cb(const char *prompt)        /* I - Prompt (not used) */
+{
+  (void)prompt;
+
+  return (password);
 }
 
 
 /*
- * End of "$Id: ipp.c,v 1.38 2001/02/14 13:59:45 mike Exp $".
+ * End of "$Id: ipp.c,v 1.38.2.1 2001/05/13 18:37:59 mike Exp $".
  */
index ef21474d83dcb061e8e77b1ae26df93513be1cce..e48fe08c8668cc2d482292e0f5ed5a935e868c4c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: socket.c,v 1.17 2001/01/24 17:14:01 mike Exp $"
+ * "$Id: socket.c,v 1.17.2.1 2001/05/13 18:37:59 mike Exp $"
  *
  *   AppSocket backend for the Common UNIX Printing System (CUPS).
  *
@@ -254,11 +254,16 @@ main(int  argc,           /* I - Number of command-line arguments (6 or 7) */
       * Check for possible data coming back from the printer...
       */
 
-      timeout.tv_sec = 0;
+      timeout.tv_sec  = 0;
       timeout.tv_usec = 0;
+
       FD_ZERO(&input);
       FD_SET(fd, &input);
+#ifdef __hpux
+      if (select(fd + 1, (int *)&input, NULL, NULL, &timeout) > 0)
+#else
       if (select(fd + 1, &input, NULL, NULL, &timeout) > 0)
+#endif /* __hpux */
       {
        /*
        * Grab the data coming back and spit it out to stderr...
@@ -272,6 +277,47 @@ main(int  argc,            /* I - Number of command-line arguments (6 or 7) */
        fprintf(stderr, "INFO: Sending print file, %u bytes...\n", tbytes);
     }
 
+   /*
+    * Shutdown the socket and wait for the other end to finish...
+    */
+
+    fputs("INFO: Print file sent, waiting for printer to finish...\n", stderr);
+
+    shutdown(fd, 1);
+
+    for (;;)
+    {
+     /*
+      * Wait a maximum of 90 seconds for backchannel data or a closed
+      * connection...
+      */
+
+      timeout.tv_sec  = 90;
+      timeout.tv_usec = 0;
+
+      FD_ZERO(&input);
+      FD_SET(fd, &input);
+
+#ifdef __hpux
+      if (select(fd + 1, (int *)&input, NULL, NULL, &timeout) > 0)
+#else
+      if (select(fd + 1, &input, NULL, NULL, &timeout) > 0)
+#endif /* __hpux */
+      {
+       /*
+       * Grab the data coming back and spit it out to stderr...
+       */
+
+       if ((nbytes = recv(fd, buffer, sizeof(buffer), 0)) > 0)
+         fprintf(stderr, "INFO: Received %u bytes of back-channel data!\n",
+                 nbytes);
+        else
+         break;
+      }
+      else
+        break;
+    }
+
    /*
     * Close the socket connection...
     */
@@ -286,10 +332,12 @@ main(int  argc,           /* I - Number of command-line arguments (6 or 7) */
   if (fp != stdin)
     fclose(fp);
 
+  fputs("INFO: " CUPS_SVERSION " is ready to print.\n", stderr);
+
   return (0);
 }
 
 
 /*
- * End of "$Id: socket.c,v 1.17 2001/01/24 17:14:01 mike Exp $".
+ * End of "$Id: socket.c,v 1.17.2.1 2001/05/13 18:37:59 mike Exp $".
  */
index c051d10022b4decaa4c2b2443b11d903c23d9729..9b01aa10f3de0b84d578f923eb56c5c5006a25ff 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: lpc.c,v 1.11 2001/02/13 20:37:42 mike Exp $"
+ * "$Id: lpc.c,v 1.11.2.1 2001/05/13 18:37:59 mike Exp $"
  *
  *   "lpc" command for the Common UNIX Printing System (CUPS).
  *
@@ -69,7 +69,7 @@ main(int  argc,               /* I - Number of command-line arguments */
   * Connect to the scheduler...
   */
 
-  http = httpConnect(cupsServer(), ippPort());
+  http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
 
   if (argc > 1)
   {
@@ -477,5 +477,5 @@ show_status(http_t *http,   /* I - HTTP connection to server */
 
 
 /*
- * End of "$Id: lpc.c,v 1.11 2001/02/13 20:37:42 mike Exp $".
+ * End of "$Id: lpc.c,v 1.11.2.1 2001/05/13 18:37:59 mike Exp $".
  */
index 7a4c7dce1a8ab0aa70e1f82e284b13628c812047..cae40a4d31f54e72a0966b81a54c2a87177d7e2b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: lpq.c,v 1.17 2001/02/13 20:37:42 mike Exp $"
+ * "$Id: lpq.c,v 1.17.2.1 2001/05/13 18:38:00 mike Exp $"
  *
  *   "lpq" command for the Common UNIX Printing System (CUPS).
  *
@@ -79,7 +79,8 @@ main(int  argc,               /* I - Number of command-line arguments */
   * Connect to the scheduler...
   */
 
-  if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+  if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
+                                 cupsEncryption())) == NULL)
   {
     fputs("lpq: Unable to contact server!\n", stderr);
     return (1);
@@ -535,5 +536,5 @@ show_printer(http_t     *http,      /* I - HTTP connection to server */
 
 
 /*
- * End of "$Id: lpq.c,v 1.17 2001/02/13 20:37:42 mike Exp $".
+ * End of "$Id: lpq.c,v 1.17.2.1 2001/05/13 18:38:00 mike Exp $".
  */
index 2b9edf7f3ec5914fe5fd969be82446dfefbb67e6..949a9f3cbc6b84ab4311fa1ae53efdc328dbb087 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: lpr.c,v 1.20 2001/02/13 20:37:43 mike Exp $"
+ * "$Id: lpr.c,v 1.20.2.1 2001/05/13 18:38:00 mike Exp $"
  *
  *   "lpr" command for the Common UNIX Printing System (CUPS).
  *
@@ -82,9 +82,9 @@ main(int  argc,               /* I - Number of command-line arguments */
   int          deletefile;     /* Delete file after print? */
   char         buffer[8192];   /* Copy buffer */
   int          temp;           /* Temporary file descriptor */
-#ifdef HAVE_SIGACTION
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
   struct sigaction action;     /* Signal action */
-#endif /* HAVE_SIGACTION */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
 
 
   deletefile  = 0;
@@ -421,5 +421,5 @@ sighandler(int s)   /* I - Signal number */
 
 
 /*
- * End of "$Id: lpr.c,v 1.20 2001/02/13 20:37:43 mike Exp $".
+ * End of "$Id: lpr.c,v 1.20.2.1 2001/05/13 18:38:00 mike Exp $".
  */
index 8fe43e36f2f0db94ec8c02ec351d7a3ab33c9398..0acd18a82b6066abd686579028359d148580f682 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: lprm.c,v 1.15 2001/03/02 17:35:03 mike Exp $"
+ * "$Id: lprm.c,v 1.15.2.1 2001/05/13 18:38:00 mike Exp $"
  *
  *   "lprm" command for the Common UNIX Printing System (CUPS).
  *
@@ -82,15 +82,13 @@ main(int  argc,                     /* I - Number of command-line arguments */
   * Open a connection to the server...
   */
 
-  if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+  if ((http = httpConnectEncrypt(cupsServer(), ippPort(), encryption)) == NULL)
   {
     fputs("lprm: Unable to contact server!\n", stderr);
     cupsFreeDests(num_dests, dests);
     return (1);
   }
 
-  httpEncryption(http, encryption);
-
  /*
   * Process command-line arguments...
   */
@@ -265,5 +263,5 @@ main(int  argc,                     /* I - Number of command-line arguments */
 
 
 /*
- * End of "$Id: lprm.c,v 1.15 2001/03/02 17:35:03 mike Exp $".
+ * End of "$Id: lprm.c,v 1.15.2.1 2001/05/13 18:38:00 mike Exp $".
  */
index f4f9c36e8d4b4106a86e2dead4a90aa0d092fe80..bd4fc28eb68b65481a98d22aa073ad50f28072f3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: admin.c,v 1.22 2001/03/05 21:37:33 mike Exp $"
+ * "$Id: admin.c,v 1.22.2.1 2001/05/13 18:38:01 mike Exp $"
  *
  *   Administration CGI for the Common UNIX Printing System (CUPS).
  *
@@ -105,7 +105,7 @@ main(int  argc,                     /* I - Number of command-line arguments */
     * Connect to the HTTP server...
     */
 
-    http = httpConnect("localhost", ippPort());
+    http = httpConnectEncrypt("localhost", ippPort(), cupsEncryption());
 
    /*
     * Do the operation...
@@ -1594,5 +1594,5 @@ get_line(char *buf,       /* I - Line buffer */
 
 
 /*
- * End of "$Id: admin.c,v 1.22 2001/03/05 21:37:33 mike Exp $".
+ * End of "$Id: admin.c,v 1.22.2.1 2001/05/13 18:38:01 mike Exp $".
  */
index 8e18e7b68d4e48dab5ce227e01943b96c91208f1..414c930e69b8c62187d2d72b6680dcb2c41e9960 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: classes.c,v 1.18 2001/01/22 15:03:22 mike Exp $"
+ * "$Id: classes.c,v 1.18.2.1 2001/05/13 18:38:01 mike Exp $"
  *
  *   Class status CGI for the Common UNIX Printing System (CUPS).
  *
@@ -71,7 +71,7 @@ main(int  argc,                       /* I - Number of command-line arguments */
   * Connect to the HTTP server...
   */
 
-  http = httpConnect("localhost", ippPort());
+  http = httpConnectEncrypt("localhost", ippPort(), cupsEncryption());
 
  /*
   * Tell the client to expect HTML...
@@ -356,5 +356,5 @@ main(int  argc,                     /* I - Number of command-line arguments */
 
 
 /*
- * End of "$Id: classes.c,v 1.18 2001/01/22 15:03:22 mike Exp $".
+ * End of "$Id: classes.c,v 1.18.2.1 2001/05/13 18:38:01 mike Exp $".
  */
index 287072e808c32679d47a1dfc9cd775aa6c773414..3997acf56688776df91fe3a1b4786909a3df9d3a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: jobs.c,v 1.15 2001/01/22 15:03:22 mike Exp $"
+ * "$Id: jobs.c,v 1.15.2.1 2001/05/13 18:38:01 mike Exp $"
  *
  *   Job status CGI for the Common UNIX Printing System (CUPS).
  *
@@ -64,7 +64,7 @@ main(int  argc,                       /* I - Number of command-line arguments */
   * Connect to the HTTP server...
   */
 
-  http = httpConnect("localhost", ippPort());
+  http = httpConnectEncrypt("localhost", ippPort(), cupsEncryption());
 
  /*
   * Tell the client to expect HTML...
@@ -135,5 +135,5 @@ main(int  argc,                     /* I - Number of command-line arguments */
 
 
 /*
- * End of "$Id: jobs.c,v 1.15 2001/01/22 15:03:22 mike Exp $".
+ * End of "$Id: jobs.c,v 1.15.2.1 2001/05/13 18:38:01 mike Exp $".
  */
index 6cd5c8447fe536e699edfd00e393c1904e440784..7cbdfd73aee91ed75e2bf5df70a1245f82a840a8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: printers.c,v 1.21 2001/01/22 15:03:22 mike Exp $"
+ * "$Id: printers.c,v 1.21.2.1 2001/05/13 18:38:01 mike Exp $"
  *
  *   Printer status CGI for the Common UNIX Printing System (CUPS).
  *
@@ -71,7 +71,7 @@ main(int  argc,                       /* I - Number of command-line arguments */
   * Connect to the HTTP server...
   */
 
-  http = httpConnect("localhost", ippPort());
+  http = httpConnectEncrypt("localhost", ippPort(), cupsEncryption());
 
  /*
   * Tell the client to expect HTML...
@@ -356,5 +356,5 @@ main(int  argc,                     /* I - Number of command-line arguments */
 
 
 /*
- * End of "$Id: printers.c,v 1.21 2001/01/22 15:03:22 mike Exp $".
+ * End of "$Id: printers.c,v 1.21.2.1 2001/05/13 18:38:01 mike Exp $".
  */
index 9f2e3aff64e0ad8354576dea0c238cc107a94c0f..fadc5aad4b4fa7df85319244821cd1c67af7c968 100644 (file)
@@ -1,5 +1,5 @@
 #
-# "$Id: mime.types,v 1.17 2001/03/05 21:37:33 mike Exp $"
+# "$Id: mime.types,v 1.17.2.1 2001/05/13 18:38:02 mike Exp $"
 #
 #   MIME types file for the Common UNIX Printing System (CUPS).
 #
@@ -74,6 +74,7 @@ application/postscript                ai eps ps string(0,%!) string(0,<04>%!)
 application/vnd.hp-HPGL                hpgl string(0,<1B>&)\
                                string(0,<1B>E<1B>%0B) string(0,<201B>)\
                                string(0,BP;) string(0,IN;) string(0,DF;) \
+                               string(0,BPINPS;) \
                                (string(0,<1B>%-12345X) + \
                                 (contains(9,512,"LANGUAGE=HPGL") \
                                  contains(9,512,"LANGUAGE = HPGL")))
@@ -150,5 +151,5 @@ application/vnd.cups-raw    (string(0,<1B>E) + !string(2,<1B>%0B)) \
 #application/octet-stream
 
 #
-# End of "$Id: mime.types,v 1.17 2001/03/05 21:37:33 mike Exp $".
+# End of "$Id: mime.types,v 1.17.2.1 2001/05/13 18:38:02 mike Exp $".
 #
index f47602ba47568f5876d3a8cf865dc68c4e576bfe..369de49c62d0f5ee2b24d59a090709339fe918d2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: config.h.in,v 1.39.2.1 2001/04/02 19:51:40 mike Exp $"
+ * "$Id: config.h.in,v 1.39.2.2 2001/05/13 18:37:58 mike Exp $"
  *
  *   Configuration file for the Common UNIX Printing System (CUPS).
  *
 
 #undef HAVE_CRYPT_H
 
+/*
+ * Use <string.h>, <strings.h>, or both?
+ */
+
+#undef HAVE_STRING_H
+#undef HAVE_STRINGS_H
+
 /*
  * Do we have the strXXX() functions?
  */
 #undef HAVE_SYS_IOCTL_H
 
 /*
- * End of "$Id: config.h.in,v 1.39.2.1 2001/04/02 19:51:40 mike Exp $".
+ * End of "$Id: config.h.in,v 1.39.2.2 2001/05/13 18:37:58 mike Exp $".
  */
index 36c6bf26135359df1271c6604072214315a8a95e..0491dcdf31a8052064dd914652110aee51fd8db0 100644 (file)
@@ -1,5 +1,5 @@
 dnl
-dnl "$Id: configure.in,v 1.83.2.1 2001/04/02 19:51:41 mike Exp $"
+dnl "$Id: configure.in,v 1.83.2.2 2001/05/13 18:37:58 mike Exp $"
 dnl
 dnl   Configuration script for the Common UNIX Printing System (CUPS).
 dnl
@@ -39,8 +39,6 @@ dnl for them...
 
 OPTIM=""
 AC_SUBST(OPTIM)
-GSOPTIM=""
-AC_SUBST(GSOPTIM)
 PICFLAG=1
 CFLAGS="${CFLAGS:=}"
 CXXFLAGS="${CXXFLAGS:=}"
@@ -49,7 +47,6 @@ AC_SUBST(DSOFLAGS)
 
 AC_ARG_ENABLE(debug, [  --enable-debug        turn on debugging [default=no]],[if eval "test x$enable_debug = xyes"; then
        OPTIM="-g"
-       GSOPTIM="-g"
 fi])
 AC_ARG_ENABLE(shared, [  --enable-shared        turn on shared libraries [default=yes]])
 AC_ARG_ENABLE(ssl, [  --enable-ssl           turn on SSL/TLS support [default=yes]])
@@ -96,6 +93,14 @@ if test "$enable_shared" != "no"; then
                        DSO="\$(CC)"
                        DSOFLAGS="$DSOFLAGS -soname \$@ -shared \$(OPTIM)"
                        ;;
+               AIX*)
+                       AC_MSG_WARN(Shared library support for AIX not available yet - defaulting to static)
+                       enable_shared=no
+                       PICFLAG=0
+                       LIBCUPS="libcups.a"
+                       LIBCUPSIMAGE="libcupsimage.a"
+                       DSO=":"
+                       ;;
                *)
                        echo "Warning: shared libraries may not be supported.  Trying -shared"
                        echo "         option with compiler."
@@ -126,9 +131,14 @@ fi
 
 AC_ARG_ENABLE(pam, [  --enable-pam        turn on PAM support [default=yes]])
 
-AC_ARG_WITH(fontpath, [  --with-fontpath     set font path for pstoraster],fontpath="$withval",fontpath="")
+# Don't use PAM with AIX...
+if test $uname = AIX; then
+       enable_pam=no
+fi
 
+AC_ARG_WITH(fontpath, [  --with-fontpath     set font path for pstoraster],fontpath="$withval",fontpath="")
 AC_ARG_WITH(docdir, [  --with-docdir       set path for documentation],docdir="$withval",docdir="")
+AC_ARG_WITH(logdir, [  --with-logdir       set path for log files],logdir="$withval",logdir="")
 
 dnl Checks for programs...
 AC_PROG_AWK
@@ -285,6 +295,9 @@ AC_CHECK_HEADER(malloc.h,AC_DEFINE(HAVE_MALLOC_H))
 AC_CHECK_HEADER(shadow.h,AC_DEFINE(HAVE_SHADOW_H))
 AC_CHECK_HEADER(stddef.h,AC_DEFINE(HAVE_STDDEF_H))
 AC_CHECK_HEADER(stdlib.h,AC_DEFINE(HAVE_STDLIB_H))
+AC_CHECK_HEADER(string.h,AC_DEFINE(HAVE_STRING_H))
+AC_CHECK_HEADER(strings.h,AC_DEFINE(HAVE_STRINGS_H))
+AC_CHECK_HEADER(usersec.h,AC_DEFINE(HAVE_USERSEC_H))
 AC_CHECK_HEADER(sys/ioctl.h,AC_DEFINE(HAVE_SYS_IOCTL_H))
 
 dnl Checks for string functions.
@@ -330,55 +343,49 @@ AC_CHECK_FUNCS(wait3)
 
 dnl Update compiler options...
 if test -n "$GCC"; then
-       GXX="gcc"
+       CXX="$CC"
 
        if test -z "$OPTIM"; then
                OPTIM="-O2"
-               GSOPTIM="-O1"
        fi
        if test $PICFLAG = 1; then
                OPTIM="-fPIC $OPTIM"
-               GSOPTIM="-fPIC $GSOPTIM"
        fi
        OPTIM="-Wall $OPTIM"
-       GSOPTIM="-Wall $GSOPTIM"
 else
        case $uname in
-               IRIX*)
+               AIX*)
                        if test -z "$OPTIM"; then
-                               OPTIM="-O2"
-                               GSOPTIM="-O1"
+                               OPTIM="-O2 -qmaxmem=6000"
                        fi
-                       if test $uversion -ge 62; then
-                               OPTIM="$OPTIM -n32 -mips3"
-                               GSOPTIM="$GSOPTIM -n32 -mips3"
-                       fi
-                       OPTIM="-fullwarn $OPTIM"
-                       GSOPTIM="-fullwarn $GSOPTIM"
                        ;;
                HP-UX*)
                        if test -z "$OPTIM"; then
                                OPTIM="+O2"
-                               GSOPTIM="+O1"
                        fi
-                       OPTIM="-Ae +DAportable $OPTIM"
-                       GSOPTIM="-Ae +DAportable $GSOPTIM"
+                       CFLAGS="-Ae $CFLAGS"
+                       OPTIM="+DAportable $OPTIM"
                        if test $PICFLAG = 1; then
                                OPTIM="+z $OPTIM"
-                               GSOPTIM="+z $GSOPTIM"
                        fi
                        ;;
+               IRIX*)
+                       if test -z "$OPTIM"; then
+                               OPTIM="-O2"
+                       fi
+                       if test $uversion -ge 62; then
+                               OPTIM="$OPTIM -n32 -mips3"
+                       fi
+                       OPTIM="-fullwarn $OPTIM"
+                       ;;
                SunOS*)
                        # Solaris
                        if test -z "$OPTIM"; then
                                OPTIM="-xO4"
-                               GSOPTIM="-xO2"
                        fi
                        OPTIM="$OPTIM -xarch=generic"
-                       GSOPTIM="$GSOPTIM -xarch=generic"
                        if test $PICFLAG = 1; then
                                OPTIM="-KPIC $OPTIM"
-                               GSOPTIM="-KPIC $GSOPTIM"
                        fi
                        ;;
                *)
@@ -494,8 +501,8 @@ fi
 dnl Fix "mandir" variable...
 if test "$mandir" = "\${prefix}/man" -a "$prefix" = "/"; then
        case "$uname" in
-               FreeBSD* | NetBSD* | OpenBSD*)
-                       # *BSD
+               FreeBSD* | NetBSD* | OpenBSD* | AIX*)
+                       # *BSD + AIX
                        mandir="/usr/share/man"
                        AMANDIR="/usr/share/man"
                        ;;
@@ -596,6 +603,11 @@ case "$uname" in
                INITDDIR="../init.d"
                ;;
 
+       AIX*)
+               INITDIR="/etc/rc.d"
+               INITDDIR=".."
+               ;;
+
        *)
                INITDIR="/etc"
                INITDDIR="../init.d"
@@ -608,13 +620,19 @@ AC_SUBST(INITDDIR)
 
 dnl Setup default locations...
 CUPS_SERVERROOT='${sysconfdir}/cups'
-CUPS_LOGDIR='${localstatedir}/log/cups'
 CUPS_REQUESTS='${localstatedir}/spool/cups'
 
 AC_DEFINE_UNQUOTED(CUPS_SERVERROOT, "$sysconfdir/cups")
-AC_DEFINE_UNQUOTED(CUPS_LOGDIR, "$localstatedir/log/cups")
 AC_DEFINE_UNQUOTED(CUPS_REQUESTS, "$localstatedir/spool/cups")
 
+if test x$logdir = x; then
+       CUPS_LOGDIR='${localstatedir}/log/cups'
+       AC_DEFINE_UNQUOTED(CUPS_LOGDIR, "$localstatedir/log/cups")
+else
+       CUPS_LOGDIR="$logdir"
+       AC_DEFINE_UNQUOTED(CUPS_LOGDIR, "$logdir")
+fi
+
 dnl See what directory to put server executables...
 case "$uname" in
        FreeBSD* | NetBSD* | OpenBSD*)
@@ -644,7 +662,7 @@ case "$uname" in
                AC_DEFINE_UNQUOTED(CUPS_LOCALEDIR, "$datadir/locale")
                ;;
 
-       OSF1*)
+       OSF1* | AIX*)
                CUPS_LOCALEDIR='${exec_prefix}/lib/nls/msg'
                AC_DEFINE_UNQUOTED(CUPS_LOCALEDIR, "$exec_prefix/lib/nls/msg")
                ;;
@@ -666,7 +684,7 @@ AC_SUBST(CUPS_DATADIR)
 dnl Set the CUPS_DOCROOT directory...
 if test x$docdir = x; then
        CUPS_DOCROOT='${datadir}/doc/cups'
-       docdir='$datadir/doc/cups'
+       docdir="$datadir/doc/cups"
 else
        CUPS_DOCROOT="$docdir"
 fi
@@ -680,5 +698,5 @@ AC_DEFINE_UNQUOTED(CUPS_FONTPATH, "$fontpath")
 AC_OUTPUT(Makedefs cups.sh)
 
 dnl
-dnl End of "$Id: configure.in,v 1.83.2.1 2001/04/02 19:51:41 mike Exp $".
+dnl End of "$Id: configure.in,v 1.83.2.2 2001/05/13 18:37:58 mike Exp $".
 dnl
index 2f03ed1afc1bcb795c0ab06708036ae13544b225..8d78311b4744aa07300700b31a349f3cfd186c32 100644 (file)
--- a/cups.list
+++ b/cups.list
@@ -1,5 +1,5 @@
 #
-# "$Id: cups.list,v 1.85 2001/02/21 17:01:15 mike Exp $"
+# "$Id: cups.list,v 1.85.2.1 2001/05/13 18:37:58 mike Exp $"
 #
 #   ESP Package Manager (EPM) file list for the Common UNIX Printing
 #   System (CUPS).
@@ -217,37 +217,37 @@ f 0444 root sys $DOCDIR/images doc/images/*.gif
 
 # Man pages
 %system irix
-d 0555 root sys $MANDIR/a_man -
-d 0555 root sys $MANDIR/a_man/cat1 -
-d 0555 root sys $MANDIR/u_man -
-d 0555 root sys $MANDIR/u_man/cat1 -
-d 0555 root sys $MANDIR/u_man/cat5 -
+d 0555 root sys $AMANDIR -
+d 0555 root sys $AMANDIR/cat1 -
+d 0555 root sys $MANDIR -
+d 0555 root sys $MANDIR/cat1 -
+d 0555 root sys $MANDIR/cat5 -
 
-f 0444 root sys $MANDIR/a_man/cat1/accept.z man/accept.z
-l 0444 root sys $MANDIR/a_man/cat1/reject.z accept.z
-f 0444 root sys $MANDIR/u_man/cat1/backend.z man/backend.z
-f 0444 root sys $MANDIR/u_man/cat5/classes.conf.z man/classes.conf.z
-f 0444 root sys $MANDIR/a_man/cat1/cups-lpd.z man/cups-lpd.z
-f 0444 root sys $MANDIR/a_man/cat1/cups-polld.z man/cups-polld.z
-f 0444 root sys $MANDIR/u_man/cat5/cupsd.conf.z man/cupsd.conf.z
-f 0444 root sys $MANDIR/a_man/cat1/cupsd.z man/cupsd.z
-f 0444 root sys $MANDIR/a_man/cat1/enable.z man/enable.z
-l 0444 root sys $MANDIR/a_man/cat1/disable.z enable.z
-f 0444 root sys $MANDIR/u_man/cat1/filter.z man/filter.z
-f 0444 root sys $MANDIR/a_man/cat1/lpadmin.z man/lpadmin.z
-f 0444 root sys $MANDIR/a_man/cat1/lpc.z man/lpc.z
-f 0444 root sys $MANDIR/a_man/cat1/lpinfo.z man/lpinfo.z
-f 0444 root sys $MANDIR/a_man/cat1/lpmove.z man/lpmove.z
-f 0444 root sys $MANDIR/u_man/cat1/lpoptions.z man/lpoptions.z
-f 0444 root sys $MANDIR/u_man/cat1/lpq.z man/lpq.z
-f 0444 root sys $MANDIR/u_man/cat1/lprm.z man/lprm.z
-f 0444 root sys $MANDIR/u_man/cat1/lpr.z man/lpr.z
-f 0444 root sys $MANDIR/u_man/cat1/lpstat.z man/lpstat.z
-f 0444 root sys $MANDIR/u_man/cat1/lp.z man/lp.z
-l 0444 root sys $MANDIR/u_man/cat1/cancel.z lp.z
-f 0444 root sys $MANDIR/u_man/cat5/mime.convs.z man/mime.convs.z
-f 0444 root sys $MANDIR/u_man/cat5/mime.types.z man/mime.types.z
-f 0444 root sys $MANDIR/u_man/cat5/printers.conf.z man/printers.conf.z
+f 0444 root sys $AMANDIR/cat1/accept.z man/accept.z
+l 0444 root sys $AMANDIR/cat1/reject.z accept.z
+f 0444 root sys $MANDIR/cat1/backend.z man/backend.z
+f 0444 root sys $MANDIR/cat5/classes.conf.z man/classes.conf.z
+f 0444 root sys $AMANDIR/cat1/cups-lpd.z man/cups-lpd.z
+f 0444 root sys $AMANDIR/cat1/cups-polld.z man/cups-polld.z
+f 0444 root sys $MANDIR/cat5/cupsd.conf.z man/cupsd.conf.z
+f 0444 root sys $AMANDIR/cat1/cupsd.z man/cupsd.z
+f 0444 root sys $AMANDIR/cat1/enable.z man/enable.z
+l 0444 root sys $AMANDIR/cat1/disable.z enable.z
+f 0444 root sys $MANDIR/cat1/filter.z man/filter.z
+f 0444 root sys $AMANDIR/cat1/lpadmin.z man/lpadmin.z
+f 0444 root sys $AMANDIR/cat1/lpc.z man/lpc.z
+f 0444 root sys $AMANDIR/cat1/lpinfo.z man/lpinfo.z
+f 0444 root sys $AMANDIR/cat1/lpmove.z man/lpmove.z
+f 0444 root sys $MANDIR/cat1/lpoptions.z man/lpoptions.z
+f 0444 root sys $MANDIR/cat1/lpq.z man/lpq.z
+f 0444 root sys $MANDIR/cat1/lprm.z man/lprm.z
+f 0444 root sys $MANDIR/cat1/lpr.z man/lpr.z
+f 0444 root sys $MANDIR/cat1/lpstat.z man/lpstat.z
+f 0444 root sys $MANDIR/cat1/lp.z man/lp.z
+l 0444 root sys $MANDIR/cat1/cancel.z lp.z
+f 0444 root sys $MANDIR/cat5/mime.convs.z man/mime.convs.z
+f 0444 root sys $MANDIR/cat5/mime.types.z man/mime.types.z
+f 0444 root sys $MANDIR/cat5/printers.conf.z man/printers.conf.z
 
 %system solaris hpux
 d 0555 root sys $MANDIR/man1 -
@@ -316,5 +316,5 @@ f 0444 root sys $MANDIR/man5/printers.conf.5 man/printers.conf.man
 i 0555 root sys cups cups.sh
 
 #
-# End of "$Id: cups.list,v 1.85 2001/02/21 17:01:15 mike Exp $".
+# End of "$Id: cups.list,v 1.85.2.1 2001/05/13 18:37:58 mike Exp $".
 #
index a1c3bffef194c707823791ea31a929b9c08bce2f..b310eedbe04332e37245ae1c917689deb3ff0689 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# "$Id: cups.sh.in,v 1.9 2001/03/14 22:02:17 mike Exp $"
+# "$Id: cups.sh.in,v 1.9.2.1 2001/05/13 18:37:58 mike Exp $"
 #
 #   Startup/shutdown script for the Common UNIX Printing System (CUPS).
 #
@@ -28,7 +28,7 @@
 #
 #   Linux chkconfig stuff:
 #
-#   chkconfig: 0235 99 00
+#   chkconfig: 235 99 00
 #   description: Startup/shutdown script for the Common UNIX \
 #                Printing System (CUPS).
 #
@@ -76,7 +76,7 @@ fi
 #
 
 case "`uname`" in
-       IRIX* | HP-UX* | SunOS*)
+       IRIX* | HP-UX* | SunOS* | AIX*)
                pid=`ps -e | awk '{print $1,$4}' | grep cupsd | awk '{print $1}'`
                ;;
        OSF1*)
@@ -139,5 +139,5 @@ exit 0
 
 
 #
-# End of "$Id: cups.sh.in,v 1.9 2001/03/14 22:02:17 mike Exp $".
+# End of "$Id: cups.sh.in,v 1.9.2.1 2001/05/13 18:37:58 mike Exp $".
 #
index 7203c0186bb380ef48ed0cd995e8a4da800a3fd9..707a39cf156de9ad9a6a2a89b0966cc1e278a0ff 100644 (file)
--- a/cups.spec
+++ b/cups.spec
@@ -1,5 +1,5 @@
 #
-# "$Id: cups.spec,v 1.30 2001/03/06 18:37:49 mike Exp $"
+# "$Id: cups.spec,v 1.30.2.1 2001/05/13 18:37:58 mike Exp $"
 #
 #   RPM "spec" file for the Common UNIX Printing System (CUPS).
 #
@@ -27,7 +27,7 @@
 Summary: Common Unix Printing System
 Name: cups
 Version: 1.1.7
-Release: 0
+Release: 1
 Copyright: GPL
 Group: System Environment/Daemons
 Source: ftp://ftp.easysw.com/pub/cups/%{version}/cups-%{version}-source.tar.gz
@@ -37,11 +37,19 @@ Vendor: Easy Software Products
 # use buildroot so as not to disturb the version already installed
 BuildRoot: /var/tmp/%{name}-root
 Conflicts: lpr, LPRng
+Provides: libcups.so.2
+Provides: libcupsimage.so.2
+Provides: cupsd
 
 %package devel
 Summary: Common Unix Printing System - development environment
 Group: Development/Libraries
 
+%package pstoraster
+Summary: Common Unix Printing System - PostScript RIP
+Group: System Environment/Daemons
+Provides: pstoraster
+
 %description
 The Common UNIX Printing System provides a portable printing layer for 
 UNIX® operating systems. It has been developed by Easy Software Products 
@@ -53,6 +61,11 @@ The Common UNIX Printing System provides a portable printing layer for
 UNIX® operating systems. This is the development package for creating
 additional printer drivers, and other CUPS services.
 
+%description devel
+The Common UNIX Printing System provides a portable printing layer for 
+UNIX® operating systems. This is the PostScript RIP package for
+supporting non-PostScript printer drivers.
+
 %prep
 %setup
 
@@ -63,13 +76,8 @@ additional printer drivers, and other CUPS services.
 make
 
 %install
-# these lines just make sure the directory structure in the
-# RPM_BUILD_ROOT exists
+# Make sure the RPM_BUILD_ROOT directory exists.
 rm -rf $RPM_BUILD_ROOT
-mkdir -p $RPM_BUILD_ROOT/etc/rc.d/init.d
-mkdir -p $RPM_BUILD_ROOT/etc/rc.d/rc0.d
-mkdir -p $RPM_BUILD_ROOT/etc/rc.d/rc3.d
-mkdir -p $RPM_BUILD_ROOT/etc/rc.d/rc5.d
 
 make   prefix=$RPM_BUILD_ROOT \
        exec_prefix=$RPM_BUILD_ROOT/usr \
@@ -79,6 +87,7 @@ make  prefix=$RPM_BUILD_ROOT \
        DOCDIR=$RPM_BUILD_ROOT/usr/share/doc/cups \
        INCLUDEDIR=$RPM_BUILD_ROOT/usr/include \
        LIBDIR=$RPM_BUILD_ROOT/usr/lib \
+       LOGDIR=$RPM_BUILD_ROOT/var/log/cups \
        LOCALEDIR=$RPM_BUILD_ROOT/usr/share/locale \
        MANDIR=$RPM_BUILD_ROOT/usr/man \
        PAMDIR=$RPM_BUILD_ROOT/etc/pam.d \
@@ -157,11 +166,32 @@ rm -rf $RPM_BUILD_ROOT
 /usr/bin/*
 /usr/lib/*.so*
 %dir /usr/lib/cups
-/usr/lib/cups/*
+%dir /usr/lib/cups/backend
+/usr/lib/cups/backend/*
+%dir /usr/lib/cups/cgi-bin
+/usr/lib/cups/cgi-bin/*
+%dir /usr/lib/cups/filter
+/usr/lib/cups/filter/hpgltops
+/usr/lib/cups/filter/imagetops
+/usr/lib/cups/filter/imagetoraster
+/usr/lib/cups/filter/pdftops
+/usr/lib/cups/filter/pstops
+/usr/lib/cups/filter/rastertoepson
+/usr/lib/cups/filter/rastertohp
+/usr/lib/cups/filter/texttops
 /usr/man/*
 /usr/sbin/*
 %dir /usr/share/cups
-/usr/share/cups/*
+%dir /usr/share/cups/banners
+/usr/share/cups/banners/*
+%dir /usr/share/cups/charsets
+/usr/share/cups/charsets/*
+%dir /usr/share/cups/data
+/usr/share/cups/data/*
+%dir /usr/share/cups/model
+/usr/share/cups/model/*
+%dir /usr/share/cups/templates
+/usr/share/cups/templates/*
 %dir /usr/share/doc/cups
 /usr/share/doc/cups/*
 %dir /usr/share/locale
@@ -174,6 +204,14 @@ rm -rf $RPM_BUILD_ROOT
 /usr/include/cups/*
 /usr/lib/*.a
 
+%files pstoraster
+%dir /usr/lib/cups/filter
+/usr/lib/cups/filter/pstoraster
+%dir /usr/share/cups/fonts
+/usr/share/cups/fonts/*
+%dir /usr/share/cups/pstoraster
+/usr/share/cups/pstoraster/*
+
 #
-# End of "$Id: cups.spec,v 1.30 2001/03/06 18:37:49 mike Exp $".
+# End of "$Id: cups.spec,v 1.30.2.1 2001/05/13 18:37:58 mike Exp $".
 #
index 4722c0e43de09bfc95077696afd7e2715472980b..94e9adfb36a1d0cf542b10c34c5ffb9ea4268469 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: cups.h,v 1.32 2001/02/06 23:40:07 mike Exp $"
+ * "$Id: cups.h,v 1.32.2.1 2001/05/13 18:38:02 mike Exp $"
  *
  *   API definitions for the Common UNIX Printing System (CUPS).
  *
@@ -94,7 +94,22 @@ typedef struct                               /**** Destination ****/
   cups_option_t        *options;               /* Options */
 } cups_dest_t;
 
-  
+typedef struct                         /**** Job ****/
+{
+  int          id;                     /* The job ID */
+  char         *dest,                  /* Printer or class name */
+               *title,                 /* Title/job name */
+               *user,                  /* User the submitted the job */
+               *format;                /* Document format */
+  ipp_jstate_t state;                  /* Job state */
+  int          size,                   /* Size in kilobytes */
+               priority;               /* Priority (1-100) */
+  time_t       completed_time,         /* Time the job was completed */
+               creation_time,          /* Time the job was created */
+               processing_time;        /* Time the job was processed */
+} cups_job_t;
+
+
 /*
  * Functions...
  */
@@ -104,8 +119,11 @@ extern int         cupsCancelJob(const char *printer, int job);
 extern ipp_t           *cupsDoFileRequest(http_t *http, ipp_t *request,
                                           const char *resource, const char *filename);
 extern http_encryption_t cupsEncryption(void);
+extern void            cupsFreeJobs(int num_jobs, cups_job_t *jobs);
 extern int             cupsGetClasses(char ***classes);
 extern const char      *cupsGetDefault(void);
+extern int             cupsGetJobs(cups_job_t **jobs, const char *dest,
+                                   int myjobs, int completed);
 extern const char      *cupsGetPPD(const char *printer);
 extern int             cupsGetPrinters(char ***printers);
 extern ipp_status_t    cupsLastError(void);
@@ -153,5 +171,5 @@ extern const char   *cupsUser(void);
 #endif /* !_CUPS_CUPS_H_ */
 
 /*
- * End of "$Id: cups.h,v 1.32 2001/02/06 23:40:07 mike Exp $".
+ * End of "$Id: cups.h,v 1.32.2.1 2001/05/13 18:38:02 mike Exp $".
  */
index 1daabd4fb717065b1cba28ca0b1d67f14d02ae0b..b0e55c541fe7e7e00577ee175813742b2b15f35c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: encode.c,v 1.1 2001/03/09 20:06:06 mike Exp $"
+ * "$Id: encode.c,v 1.1.2.1 2001/05/13 18:38:02 mike Exp $"
  *
  *   Option encoding routines for the Common UNIX Printing System (CUPS).
  *
@@ -86,7 +86,8 @@ cupsEncodeOptions(ipp_t         *ipp,         /* I - Request to add to */
     */
 
     if (strcasecmp(options[i].name, "raw") == 0 ||
-        strcasecmp(options[i].name, "document-format") == 0)
+        strcasecmp(options[i].name, "document-format") == 0 ||
+       !options[i].name[0])
       continue;
 
    /*
@@ -306,5 +307,5 @@ cupsEncodeOptions(ipp_t         *ipp,               /* I - Request to add to */
 
 
 /*
- * End of "$Id: encode.c,v 1.1 2001/03/09 20:06:06 mike Exp $".
+ * End of "$Id: encode.c,v 1.1.2.1 2001/05/13 18:38:02 mike Exp $".
  */
index f7844bfe199e8433254ac48c55a309db8543a5b8..c10e3998e65d19052eb18cd77a44979b72cc05f9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: http.c,v 1.82.2.1 2001/04/02 19:51:43 mike Exp $"
+ * "$Id: http.c,v 1.82.2.2 2001/05/13 18:38:03 mike Exp $"
  *
  *   HTTP routines for the Common UNIX Printing System (CUPS).
  *
  *
  * Contents:
  *
- *   httpInitialize()    - Initialize the HTTP interface library and set the
- *                         default HTTP proxy (if any).
- *   httpCheck()         - Check to see if there is a pending response from
- *                         the server.
- *   httpClose()         - Close an HTTP connection...
- *   httpConnect()       - Connect to a HTTP server.
- *   httpEncryption()    - Set the required encryption on the link.
- *   httpReconnect()     - Reconnect to a HTTP server...
- *   httpSeparate()      - Separate a Universal Resource Identifier into its
- *                         components.
- *   httpSetField()      - Set the value of an HTTP header.
- *   httpDelete()        - Send a DELETE request to the server.
- *   httpGet()           - Send a GET request to the server.
- *   httpHead()          - Send a HEAD request to the server.
- *   httpOptions()       - Send an OPTIONS request to the server.
- *   httpPost()          - Send a POST request to the server.
- *   httpPut()           - Send a PUT request to the server.
- *   httpTrace()         - Send an TRACE request to the server.
- *   httpFlush()         - Flush data from a HTTP connection.
- *   httpRead()          - Read data from a HTTP connection.
- *   httpWrite()         - Write data to a HTTP connection.
- *   httpGets()          - Get a line of text from a HTTP connection.
- *   httpPrintf()        - Print a formatted string to a HTTP connection.
- *   httpStatus()        - Return a short string describing a HTTP status code.
- *   httpGetDateString() - Get a formatted date/time string from a time value.
- *   httpGetDateTime()   - Get a time value from a formatted date/time string.
- *   httpUpdate()        - Update the current HTTP state for incoming data.
- *   httpDecode64()      - Base64-decode a string.
- *   httpEncode64()      - Base64-encode a string.
- *   httpGetLength()     - Get the amount of data remaining from the
- *                         content-length or transfer-encoding fields.
- *   http_field()        - Return the field index for a field name.
- *   http_send()         - Send a request with all fields and the trailing
- *                         blank line.
- *   http_upgrade()      - Force upgrade to TLS encryption.
+ *   httpInitialize()     - Initialize the HTTP interface library and set the
+ *                          default HTTP proxy (if any).
+ *   httpCheck()          - Check to see if there is a pending response from
+ *                          the server.
+ *   httpClose()          - Close an HTTP connection...
+ *   httpConnect()        - Connect to a HTTP server.
+ *   httpConnectEncrypt() - Connect to a HTTP server using encryption.
+ *   httpEncryption()     - Set the required encryption on the link.
+ *   httpReconnect()      - Reconnect to a HTTP server...
+ *   httpSeparate()       - Separate a Universal Resource Identifier into its
+ *                          components.
+ *   httpSetField()       - Set the value of an HTTP header.
+ *   httpDelete()         - Send a DELETE request to the server.
+ *   httpGet()            - Send a GET request to the server.
+ *   httpHead()           - Send a HEAD request to the server.
+ *   httpOptions()        - Send an OPTIONS request to the server.
+ *   httpPost()           - Send a POST request to the server.
+ *   httpPut()            - Send a PUT request to the server.
+ *   httpTrace()          - Send an TRACE request to the server.
+ *   httpFlush()          - Flush data from a HTTP connection.
+ *   httpRead()           - Read data from a HTTP connection.
+ *   httpWrite()          - Write data to a HTTP connection.
+ *   httpGets()           - Get a line of text from a HTTP connection.
+ *   httpPrintf()         - Print a formatted string to a HTTP connection.
+ *   httpStatus()         - Return a short string describing a HTTP status code.
+ *   httpGetDateString()  - Get a formatted date/time string from a time value.
+ *   httpGetDateTime()    - Get a time value from a formatted date/time string.
+ *   httpUpdate()         - Update the current HTTP state for incoming data.
+ *   httpDecode64()       - Base64-decode a string.
+ *   httpEncode64()       - Base64-encode a string.
+ *   httpGetLength()      - Get the amount of data remaining from the
+ *                          content-length or transfer-encoding fields.
+ *   http_field()         - Return the field index for a field name.
+ *   http_send()          - Send a request with all fields and the trailing
+ *                          blank line.
+ *   http_upgrade()       - Force upgrade to TLS encryption.
  */
 
 /*
@@ -310,6 +311,32 @@ httpClose(http_t *http)            /* I - Connection to close */
 http_t *                       /* O - New HTTP connection */
 httpConnect(const char *host,  /* I - Host to connect to */
             int        port)   /* I - Port number */
+{
+  http_encryption_t    encrypt;/* Type of encryption to use */
+
+
+ /*
+  * Set the default encryption status...
+  */
+
+  if (port == 443)
+    encrypt = HTTP_ENCRYPT_ALWAYS;
+  else
+    encrypt = HTTP_ENCRYPT_IF_REQUESTED;
+
+  return (httpConnectEncrypt(host, port, encrypt));
+}
+
+
+/*
+ * 'httpConnectEncrypt()' - Connect to a HTTP server using encryption.
+ */
+
+http_t *                               /* O - New HTTP connection */
+httpConnectEncrypt(const char *host,   /* I - Host to connect to */
+                   int        port,    /* I - Port number */
+                  http_encryption_t encrypt)
+                                       /* I - Type of encryption to use */
 {
   int                  i;              /* Looping var */
   http_t               *http;          /* New HTTP connection */
@@ -382,6 +409,12 @@ httpConnect(const char *host,      /* I - Host to connect to */
     http->encryption = HTTP_ENCRYPT_ALWAYS;
   }
 
+ /*
+  * Set the encryption status...
+  */
+
+  http->encryption = encrypt;
+
  /*
   * Loop through the addresses we have until one of them connects...
   */
@@ -2063,5 +2096,5 @@ http_upgrade(http_t *http)        /* I - HTTP data */
 
 
 /*
- * End of "$Id: http.c,v 1.82.2.1 2001/04/02 19:51:43 mike Exp $".
+ * End of "$Id: http.c,v 1.82.2.2 2001/05/13 18:38:03 mike Exp $".
  */
index 020db8ef4cce8204db29594f937d628b9bb4a5c0..a6f7cdcddcbac60e4b0e21e2bdeff70d58107bee 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: http.h,v 1.33.2.1 2001/04/02 19:51:43 mike Exp $"
+ * "$Id: http.h,v 1.33.2.2 2001/05/13 18:38:03 mike Exp $"
  *
  *   Hyper-Text Transport Protocol definitions for the Common UNIX Printing
  *   System (CUPS).
@@ -304,6 +304,8 @@ extern int          httpCheck(http_t *http);
                                                httpSetField((http), HTTP_FIELD_HOST, (http)->hostname)
 extern void            httpClose(http_t *http);
 extern http_t          *httpConnect(const char *host, int port);
+extern http_t          *httpConnectEncrypt(const char *host, int port,
+                                           http_encryption_t encrypt);
 extern int             httpDelete(http_t *http, const char *uri);
 extern int             httpEncryption(http_t *http, http_encryption_t e);
 #  define              httpError(http) ((http)->error)
@@ -362,5 +364,5 @@ extern char         *httpAddrString(const http_addr_t *addr,
 #endif /* !_CUPS_HTTP_H_ */
 
 /*
- * End of "$Id: http.h,v 1.33.2.1 2001/04/02 19:51:43 mike Exp $".
+ * End of "$Id: http.h,v 1.33.2.2 2001/05/13 18:38:03 mike Exp $".
  */
index 2104ed1c2a38c5f25eb5ec2e9296729e815f90f0..1e268d47ed96fdb2134a059f46c866cb4728666d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: ipp.c,v 1.55.2.1 2001/04/02 19:51:44 mike Exp $"
+ * "$Id: ipp.c,v 1.55.2.2 2001/05/13 18:38:03 mike Exp $"
  *
  *   Internet Printing Protocol support functions for the Common UNIX
  *   Printing System (CUPS).
@@ -680,7 +680,7 @@ ippFindAttribute(ipp_t      *ipp,   /* I - IPP request */
     DEBUG_printf(("ippFindAttribute: attr = %p, name = \'%s\'\n", attr,
                   attr->name));
 
-    value_tag = attr->value_tag & ~IPP_TAG_COPY;
+    value_tag = (ipp_tag_t)(attr->value_tag & IPP_TAG_MASK);
 
     if (attr->name != NULL && strcasecmp(attr->name, name) == 0 &&
         (value_tag == type || type == IPP_TAG_ZERO ||
@@ -2683,5 +2683,5 @@ ipp_read(http_t        *http,     /* I - Client connection */
 
 
 /*
- * End of "$Id: ipp.c,v 1.55.2.1 2001/04/02 19:51:44 mike Exp $".
+ * End of "$Id: ipp.c,v 1.55.2.2 2001/05/13 18:38:03 mike Exp $".
  */
index 4a0f8d37720039ac96d7ecd424eb0ad2a251b12c..fa00ad172f7833dcf733d45cbad64362544ba621 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: ipp.h,v 1.36.2.1 2001/04/02 19:51:44 mike Exp $"
+ * "$Id: ipp.h,v 1.36.2.2 2001/05/13 18:38:04 mike Exp $"
  *
  *   Internet Printing Protocol definitions for the Common UNIX Printing
  *   System (CUPS).
@@ -105,7 +105,8 @@ typedef enum                        /**** Format tags for attribute formats... ****/
   IPP_TAG_LANGUAGE,
   IPP_TAG_MIMETYPE,
   IPP_TAG_MEMBERNAME,
-  IPP_TAG_COPY = 0x80000000    /* Bitflag for copied attribute values */
+  IPP_TAG_MASK = 0x3fffffff,   /* Mask for copied attribute values */
+  IPP_TAG_COPY = 0x40000000    /* Bitflag for copied attribute values */
 } ipp_tag_t;
 
 typedef enum                   /**** Resolution units... ****/
@@ -427,5 +428,5 @@ extern void         _ipp_free_attr(ipp_attribute_t *);
 #endif /* !_CUPS_IPP_H_ */
 
 /*
- * End of "$Id: ipp.h,v 1.36.2.1 2001/04/02 19:51:44 mike Exp $".
+ * End of "$Id: ipp.h,v 1.36.2.2 2001/05/13 18:38:04 mike Exp $".
  */
index 0d87a3466f46eded84f788e93b7c09851c118bd7..e2caef283e9a51ba2f45a7dddc5824b41bb39425 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: options.c,v 1.21 2001/03/09 20:06:07 mike Exp $"
+ * "$Id: options.c,v 1.21.2.1 2001/05/13 18:38:04 mike Exp $"
  *
  *   Option routines for the Common UNIX Printing System (CUPS).
  *
@@ -55,8 +55,9 @@ cupsAddOption(const char    *name,            /* I - Name of option */
   cups_option_t        *temp;                          /* Pointer to new option */
 
 
-  if (name == NULL || value == NULL || options == NULL || num_options < 0)
-    return (0);
+  if (name == NULL || !name[0] || value == NULL ||
+      options == NULL || num_options < 0)
+    return (num_options);
 
  /*
   * Look for an existing option with the same name...
@@ -194,6 +195,13 @@ cupsParseOptions(const char    *arg,               /* I - Argument to parse */
     while (!isspace(*ptr) && *ptr != '=' && *ptr != '\0')
       ptr ++;
 
+   /*
+    * Avoid an empty name...
+    */
+
+    if (ptr == name)
+      break;
+
    /*
     * Skip trailing spaces...
     */
@@ -408,5 +416,5 @@ cupsMarkOptions(ppd_file_t    *ppd,         /* I - PPD file */
 
 
 /*
- * End of "$Id: options.c,v 1.21 2001/03/09 20:06:07 mike Exp $".
+ * End of "$Id: options.c,v 1.21.2.1 2001/05/13 18:38:04 mike Exp $".
  */
index 7ebf350384383affd0bfe2180604e3791a34ac4d..0e8c20fb881611aec99ccebf123ea501b071bef6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: ppd.c,v 1.51.2.1 2001/04/11 00:24:11 mike Exp $"
+ * "$Id: ppd.c,v 1.51.2.2 2001/05/13 18:38:04 mike Exp $"
  *
  *   PPD file routines for the Common UNIX Printing System (CUPS).
  *
@@ -1430,7 +1430,7 @@ ppdOpenFile(const char *filename) /* I - File to read from */
  * 'compare_strings()' - Compare two strings.
  */
 
-int                            /* O - Result of comparison */
+static int                     /* O - Result of comparison */
 compare_strings(char *s,       /* I - First string */
                 char *t)       /* I - Second string */
 {
@@ -1940,5 +1940,5 @@ ppd_fix(char *string)             /* IO - String to fix */
 
 
 /*
- * End of "$Id: ppd.c,v 1.51.2.1 2001/04/11 00:24:11 mike Exp $".
+ * End of "$Id: ppd.c,v 1.51.2.2 2001/05/13 18:38:04 mike Exp $".
  */
index 1edbe206f852a46ff6a2e5ebd76e589b84d08da8..6198659b118632c34aaf82000de7ff5caaa46996 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: string.h,v 1.7 2001/01/22 15:03:31 mike Exp $"
+ * "$Id: string.h,v 1.7.2.1 2001/05/13 18:38:05 mike Exp $"
  *
  *   String definitions for the Common UNIX Printing System (CUPS).
  *
 #  include <stdio.h>
 #  include <stdarg.h>
 #  include <config.h>
-#  include <string.h>
+
+#  ifdef HAVE_STRING_H
+#    include <string.h>
+#  endif /* HAVE_STRING_H */
+
+#  ifdef HAVE_STRINGS_H
+#    include <strings.h>
+#  endif /* HAVE_STRINGS_H */
 
 
 /*
@@ -90,5 +97,5 @@ extern int    vsnprintf(char *, size_t, const char *, va_list);
 #endif /* !_CUPS_STRING_H_ */
 
 /*
- * End of "$Id: string.h,v 1.7 2001/01/22 15:03:31 mike Exp $".
+ * End of "$Id: string.h,v 1.7.2.1 2001/05/13 18:38:05 mike Exp $".
  */
index 3572a99e039f271540e29cb0245420638f7b6899..210c4d61b293a07d6987dfeafdc6d85c4d0ad048 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: util.c,v 1.81.2.1 2001/04/02 19:51:44 mike Exp $"
+ * "$Id: util.c,v 1.81.2.2 2001/05/13 18:38:05 mike Exp $"
  *
  *   Printing utilities for the Common UNIX Printing System (CUPS).
  *
  *
  *   cupsCancelJob()     - Cancel a print job.
  *   cupsDoFileRequest() - Do an IPP request...
+ *   cupsFreeJobs()      - Free memory used by job data.
  *   cupsGetClasses()    - Get a list of printer classes.
  *   cupsGetDefault()    - Get the default printer or class.
+ *   cupsGetJobs()       - Get the jobs from the server.
  *   cupsGetPPD()        - Get the PPD file for a printer.
  *   cupsGetPrinters()   - Get a list of printers.
  *   cupsLastError()     - Return the last IPP error that occurred.
@@ -369,6 +371,22 @@ cupsDoFileRequest(http_t     *http,        /* I - HTTP connection to server */
       else
         break;
     }
+#ifdef HAVE_LIBSSL
+    else if (status == HTTP_UPGRADE_REQUIRED)
+    {
+     /*
+      * Flush any error message...
+      */
+
+      httpFlush(http);
+
+     /*
+      * Try again, this time with encryption enabled...
+      */
+
+      continue;
+    }
+#endif /* HAVE_LIBSSL */
     else if (status != HTTP_OK)
     {
       DEBUG_printf(("cupsDoFileRequest: error %d...\n", status));
@@ -437,6 +455,32 @@ cupsDoFileRequest(http_t     *http,        /* I - HTTP connection to server */
 }
 
 
+/*
+ * 'cupsFreeJobs()' - Free memory used by job data.
+ */
+
+void
+cupsFreeJobs(int        num_jobs,/* I - Number of jobs */
+             cups_job_t *jobs) /* I - Jobs */
+{
+  int  i;                      /* Looping var */
+
+
+  if (num_jobs <= 0 || jobs == NULL)
+    return;
+
+  for (i = 0; i < num_jobs; i ++)
+  {
+    free(jobs[i].dest);
+    free(jobs[i].user);
+    free(jobs[i].format);
+    free(jobs[i].title);
+  }
+
+  free(jobs);
+}
+
+
 /*
  * 'cupsGetClasses()' - Get a list of printer classes.
  */
@@ -628,6 +672,260 @@ cupsGetDefault(void)
 }
 
 
+/*
+ * 'cupsGetJobs()' - Get the jobs from the server.
+ */
+
+int                                    /* O - Number of jobs */
+cupsGetJobs(cups_job_t **jobs,         /* O - Job data */
+            const char *mydest,                /* I - Only show jobs for dest? */
+            int        myjobs,         /* I - Only show my jobs? */
+           int        completed)       /* I - Only show completed jobs? */
+{
+  int          n;                      /* Number of jobs */
+  ipp_t                *request,               /* IPP Request */
+               *response;              /* IPP Response */
+  ipp_attribute_t *attr;               /* Current attribute */
+  cups_lang_t  *language;              /* Default language */
+  cups_job_t   *temp;                  /* Temporary pointer */
+  int          id,                     /* job-id */
+               priority,               /* job-priority */
+               size;                   /* job-k-octets */
+  ipp_jstate_t state;                  /* job-state */
+  time_t       completed_time,         /* time-at-completed */
+               creation_time,          /* time-at-creation */
+               processing_time;        /* time-at-processing */
+  const char   *dest,                  /* job-printer-uri */
+               *format,                /* document-format */
+               *title,                 /* job-name */
+               *user;                  /* job-originating-user-name */
+  char         uri[HTTP_MAX_URI];      /* URI for jobs */
+  static const char *attrs[] =         /* Requested attributes */
+               {
+                 "job-id",
+                 "job-priority",
+                 "job-k-octets",
+                 "job-state",
+                 "time-at-completed",
+                 "time-at-creation",
+                 "time-at-processing",
+                 "job-printer-uri",
+                 "document-format",
+                 "job-name",
+                 "job-originating-user-name"
+               };
+
+
+  if (jobs == NULL)
+  {
+    last_error = IPP_INTERNAL_ERROR;
+    return (0);
+  }
+
+ /*
+  * Try to connect to the server...
+  */
+
+  if (!cups_connect("default", NULL, NULL))
+  {
+    last_error = IPP_SERVICE_UNAVAILABLE;
+    return (0);
+  }
+
+ /*
+  * Build an IPP_GET_JOBS request, which requires the following
+  * attributes:
+  *
+  *    attributes-charset
+  *    attributes-natural-language
+  *    printer-uri
+  *    requesting-user-name
+  *    which-jobs
+  *    my-jobs
+  *    requested-attributes
+  */
+
+  request = ippNew();
+
+  request->request.op.operation_id = IPP_GET_JOBS;
+  request->request.op.request_id   = 1;
+
+  language = cupsLangDefault();
+
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+               "attributes-charset", NULL, cupsLangEncoding(language));
+
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+               "attributes-natural-language", NULL, language->language);
+
+  if (mydest)
+    snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", mydest);
+  else
+    strcpy(uri, "ipp://localhost/jobs");
+
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+               "printer-uri", NULL, uri);
+
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+               "requesting-user-name", NULL, cupsUser());
+
+  if (myjobs)
+    ippAddBoolean(request, IPP_TAG_OPERATION, "my-jobs", 1);
+
+  if (completed)
+    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+                 "which-jobs", NULL, "completed");
+
+  ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+                "requested-attributes", sizeof(attrs) / sizeof(attrs[0]),
+               NULL, attrs);
+
+ /*
+  * Do the request and get back a response...
+  */
+
+  n     = 0;
+  *jobs = NULL;
+
+  if ((response = cupsDoRequest(cups_server, request, "/")) != NULL)
+  {
+    last_error = response->request.status.status_code;
+
+    for (attr = response->attrs; attr != NULL; attr = attr->next)
+    {
+     /*
+      * Skip leading attributes until we hit a job...
+      */
+
+      while (attr != NULL && attr->group_tag != IPP_TAG_JOB)
+        attr = attr->next;
+
+      if (attr == NULL)
+        break;
+
+     /*
+      * Pull the needed attributes from this job...
+      */
+
+      id              = 0;
+      size            = 0;
+      priority        = 50;
+      state           = IPP_JOB_PENDING;
+      user            = NULL;
+      dest            = NULL;
+      format          = NULL;
+      title           = NULL;
+      creation_time   = 0;
+      completed_time  = 0;
+      processing_time = 0;
+
+      while (attr != NULL && attr->group_tag == IPP_TAG_JOB)
+      {
+        if (strcmp(attr->name, "job-id") == 0 &&
+           attr->value_tag == IPP_TAG_INTEGER)
+         id = attr->values[0].integer;
+        else if (strcmp(attr->name, "job-state") == 0 &&
+                attr->value_tag == IPP_TAG_ENUM)
+         state = (ipp_jstate_t)attr->values[0].integer;
+        else if (strcmp(attr->name, "job-priority") == 0 &&
+                attr->value_tag == IPP_TAG_INTEGER)
+         priority = attr->values[0].integer;
+        else if (strcmp(attr->name, "job-k-octets") == 0 &&
+                attr->value_tag == IPP_TAG_INTEGER)
+         size = attr->values[0].integer;
+        else if (strcmp(attr->name, "time-at-completed") == 0 &&
+                attr->value_tag == IPP_TAG_INTEGER)
+         completed_time = attr->values[0].integer;
+        else if (strcmp(attr->name, "time-at-creation") == 0 &&
+                attr->value_tag == IPP_TAG_INTEGER)
+         creation_time = attr->values[0].integer;
+        else if (strcmp(attr->name, "time-at-processing") == 0 &&
+                attr->value_tag == IPP_TAG_INTEGER)
+         processing_time = attr->values[0].integer;
+        else if (strcmp(attr->name, "job-printer-uri") == 0 &&
+                attr->value_tag == IPP_TAG_URI)
+       {
+         if ((dest = strrchr(attr->values[0].string.text, '/')) != NULL)
+           dest ++;
+        }
+        else if (strcmp(attr->name, "job-originating-user-name") == 0 &&
+                attr->value_tag == IPP_TAG_NAME)
+         user = attr->values[0].string.text;
+        else if (strcmp(attr->name, "document-format") == 0 &&
+                attr->value_tag == IPP_TAG_MIMETYPE)
+         format = attr->values[0].string.text;
+        else if (strcmp(attr->name, "job-name") == 0 &&
+                attr->value_tag == IPP_TAG_TEXT)
+         title = attr->values[0].string.text;
+
+        attr = attr->next;
+      }
+
+     /*
+      * See if we have everything needed...
+      */
+
+      if (dest == NULL || format == NULL || title == NULL || user == NULL ||
+          id == 0)
+      {
+        if (attr == NULL)
+         break;
+       else
+          continue;
+      }
+
+     /*
+      * Allocate memory for the job...
+      */
+
+      if (n == 0)
+        temp = malloc(sizeof(cups_job_t));
+      else
+       temp = realloc(*jobs, sizeof(cups_job_t) * (n + 1));
+
+      if (temp == NULL)
+      {
+       /*
+        * Ran out of memory!
+        */
+
+       cupsFreeJobs(n, *jobs);
+       *jobs = NULL;
+
+        ippDelete(response);
+       return (0);
+      }
+
+      *jobs = temp;
+      temp  += n;
+      n ++;
+
+     /*
+      * Copy the data over...
+      */
+
+      temp->dest            = strdup(dest);
+      temp->user            = strdup(user);
+      temp->format          = strdup(format);
+      temp->title           = strdup(title);
+      temp->id              = id;
+      temp->priority        = priority;
+      temp->state           = state;
+      temp->size            = size;
+      temp->completed_time  = completed_time;
+      temp->creation_time   = creation_time;
+      temp->processing_time = processing_time;
+    }
+
+    ippDelete(response);
+  }
+  else
+    last_error = IPP_BAD_REQUEST;
+
+  return (n);
+}
+
+
 /*
  * 'cupsGetPPD()' - Get the PPD file for a printer.
  */
@@ -783,7 +1081,8 @@ cupsGetPPD(const char *name)               /* I - Printer name */
   {
     httpClose(cups_server);
 
-    if ((cups_server = httpConnect(hostname, ippPort())) == NULL)
+    if ((cups_server = httpConnectEncrypt(hostname, ippPort(),
+                                          cupsEncryption())) == NULL)
     {
       last_error = IPP_SERVICE_UNAVAILABLE;
       return (NULL);
@@ -898,7 +1197,7 @@ cupsGetPPD(const char *name)               /* I - Printer name */
         break;
     }
   }
-  while (status == HTTP_UNAUTHORIZED);
+  while (status == HTTP_UNAUTHORIZED || status == HTTP_UPGRADE_REQUIRED);
 
  /*
   * See if we actually got the file or an error...
@@ -1257,6 +1556,8 @@ cups_connect(const char *name,            /* I - Destination (printer[@host]) */
                                        /* Name of printer or class */
 
 
+  DEBUG_printf(("cups_connect(\"%s\", %p, %p)\n", name, printer, hostname));
+
   if (name == NULL)
   {
     last_error = IPP_BAD_REQUEST;
@@ -1293,16 +1594,16 @@ cups_connect(const char *name,          /* I - Destination (printer[@host]) */
     httpClose(cups_server);
   }
 
-  if ((cups_server = httpConnect(hostname, ippPort())) == NULL)
+  DEBUG_printf(("connecting to %s on port %d...\n", hostname, ippPort()));
+
+  if ((cups_server = httpConnectEncrypt(hostname, ippPort(),
+                                        cupsEncryption())) == NULL)
   {
     last_error = IPP_SERVICE_UNAVAILABLE;
     return (NULL);
   }
   else
-  {
-    httpEncryption(cups_server, cupsEncryption());
     return (printer);
-  }
 }
 
 
@@ -1376,5 +1677,5 @@ cups_local_auth(http_t *http)     /* I - Connection */
 
 
 /*
- * End of "$Id: util.c,v 1.81.2.1 2001/04/02 19:51:44 mike Exp $".
+ * End of "$Id: util.c,v 1.81.2.2 2001/05/13 18:38:05 mike Exp $".
  */
index efd3697e62d2f957208040b1ea8cf72cb54be007..990f61b9662a1860145875e093aa1b4f6032abc7 100644 (file)
Binary files a/doc/cmp.pdf and b/doc/cmp.pdf differ
index 2faa7a5b9859b7b04f2f646004da84319b44e226..8857c0288f6f6766f4a03250e278099006d430ce 100644 (file)
Binary files a/doc/idd.pdf and b/doc/idd.pdf differ
index f2ba509fefa9f28e24f3a30f53a26aa878024c02..4036884ec97dd1a5f37b14c61561eaebb59657d4 100644 (file)
Binary files a/doc/ipp.pdf and b/doc/ipp.pdf differ
index bc5ecd470bdcb8b42bb272acaba63bb03272f9c9..20259176fab75ef8c435b1a8458c4a99fb305781 100644 (file)
Binary files a/doc/overview.pdf and b/doc/overview.pdf differ
index d76c4c8f6167041a1ffd84e3554246e647cc5f6b..5a45b1dacef4e7774d4f2d622b9b4d53c26ebfc1 100644 (file)
@@ -1,27 +1,27 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
 <HTML>
 <HEAD>
-<TITLE> CUPS Software Administrators Manual</TITLE>
+<TITLE>CUPS Software Administrators Manual</TITLE>
 <META NAME="author" CONTENT="Easy Software Products">
 <META NAME="copyright" CONTENT="Copyright 1997-2001, All Rights Reserved">
 <META NAME="docnumber" CONTENT="CUPS-SAM-1.1.7">
 <META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-8859-1">
 <STYLE TYPE="text/css"><!--
-BODY { font-family: serif; font-size: 11.0pt }
-H1 { font-family: sans-serif; font-size: 20.0pt }
-H2 { font-family: sans-serif; font-size: 17.0pt }
-H3 { font-family: sans-serif; font-size: 14.0pt }
-H4 { font-family: sans-serif; font-size: 11.0pt }
-H5 { font-family: sans-serif; font-size: 9.0pt }
-H6 { font-family: sans-serif; font-size: 8.0pt }
-SUB { font-size: 8.0pt }
-SUP { font-size: 8.0pt }
-PRE { font-size: 9.0pt }
+BODY { font-family: serif }
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
+SUB { font-size: smaller }
+SUP { font-size: smaller }
+PRE { font-family: monospace }
 --></STYLE>
 </HEAD>
 <BODY BGCOLOR="#ffffff">
-<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="100%"><BR>
-<H1> CUPS Software Administrators Manual</H1></A><BR>
+<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="431" HEIGHT="511"><BR>
+<H1>CUPS Software Administrators Manual</H1></A><BR>
 CUPS-SAM-1.1.7<BR>
 Easy Software Products<BR>
 Copyright 1997-2001, All Rights Reserved<BR>
@@ -123,6 +123,7 @@ Copyright 1997-2001, All Rights Reserved<BR>
 <LI><A HREF="#BrowseShortNames">BrowseShortNames</A></LI>
 <LI><A HREF="#BrowseTimeout">BrowseTimeout</A></LI>
 <LI><A HREF="#Browsing">Browsing</A></LI>
+<LI><A HREF="#Classification">Classification</A></LI>
 <LI><A HREF="#DataDir">DataDir</A></LI>
 <LI><A HREF="#DefaultCharset">DefaultCharset</A></LI>
 <LI><A HREF="#DefaultLanguage">DefaultLanguage</A></LI>
@@ -145,6 +146,8 @@ Copyright 1997-2001, All Rights Reserved<BR>
 <LI><A HREF="#LogLevel">LogLevel</A></LI>
 <LI><A HREF="#MaxClients">MaxClients</A></LI>
 <LI><A HREF="#MaxJobs">MaxJobs</A></LI>
+<LI><A HREF="#MaxJobsPerPrinter">MaxJobsPerPrinter</A></LI>
+<LI><A HREF="#MaxJobsPerUser">MaxJobsPerUser</A></LI>
 <LI><A HREF="#MaxLogSize">MaxLogSize</A></LI>
 <LI><A HREF="#MaxRequestSize">MaxRequestSize</A></LI>
 <LI><A HREF="#Order">Order</A></LI>
@@ -279,7 +282,6 @@ are used to support non-PostScript printers. Sample drivers for HP and
 EPSON printers are included that use these filters. </P>
 
 <!-- NEED 3in -->
-
 <H2><A NAME="1_2">Document Overview</A></H2>
 <P>This software administrators manual is organized into the following 
 sections:</P>
@@ -583,7 +585,6 @@ by typing: </P>
 </UL>
 
 <!-- NEED 4in -->
-
 <H2><A NAME="BINARY">Installing a Binary Distribution</A></H2>
 <P>CUPS comes in a variety of binary distribution formats. Easy 
 Software Products provides binaries in TAR format with installation and 
@@ -1064,6 +1065,7 @@ determine how the server operates: </P>
 <LI><A HREF="#BrowseShortNames"><CODE>BrowseShortNames</CODE></A></LI>
 <LI><A HREF="#BrowseTimeout"><CODE>BrowseTimeout</CODE></A></LI>
 <LI><A HREF="#Browsing"><CODE>Browsing</CODE></A></LI>
+<LI><A HREF="#Classification"><CODE>Classification</CODE></A></LI>
 <LI><A HREF="#DataDir"><CODE>DataDir</CODE></A></LI>
 <LI><A HREF="#DefaultCharset"><CODE>DefaultCharset</CODE></A></LI>
 <LI><A HREF="#DefaultLanguage"><CODE>DefaultLanguage</CODE></A></LI>
@@ -1087,12 +1089,14 @@ determine how the server operates: </P>
 <LI><A HREF="#LogLevel"><CODE>LogLevel</CODE></A></LI>
 <LI><A HREF="#MaxClients"><CODE>MaxClients</CODE></A></LI>
 <LI><A HREF="#MaxJobs"><CODE>MaxJobs</CODE></A></LI>
+<LI><A HREF="#MaxJobsPerPrinter"><CODE>MaxJobsPerPrinter</CODE></A></LI>
+<LI><A HREF="#MaxJobsPerUser"><CODE>MaxJobsPerUser</CODE></A></LI>
 <LI><A HREF="#MaxLogSize"><CODE>MaxLogSize</CODE></A></LI>
 <LI><A HREF="#MaxRequestSize"><CODE>MaxRequestSize</CODE></A></LI>
 <LI><A HREF="#Order"><CODE>Order</CODE></A></LI>
 <LI><A HREF="#PageLog"><CODE>PageLog</CODE></A></LI>
-<LI><A HREF="#Port"><CODE>Port</CODE></A></LI>
 </TD><TD VALIGN="TOP"> &nbsp;&nbsp;&nbsp; </TD><TD VALIGN="TOP">
+<LI><A HREF="#Port"><CODE>Port</CODE></A></LI>
 <LI><A HREF="#PreserveJobFiles"><CODE>PreserveJobFiles</CODE></A></LI>
 <LI><A HREF="#PreserveJobHistory"><CODE>PreserveJobHistory</CODE></A></LI>
 <LI><A HREF="#Printcap"><CODE>Printcap</CODE></A></LI>
@@ -1120,7 +1124,6 @@ determine how the server operates: </P>
 </UL>
 
 <!-- NEED 3in -->
-
 <H3><A NAME="AccessLog">AccessLog</A></H3>
 <HR>
 <H4>Examples</H4>
@@ -1143,7 +1146,6 @@ web access reporting tool to generate a report on CUPS server activity. </P>
 to the system log instead of a plain file. </P>
 <P>The default access log file is <VAR>/var/log/cups/access_log</VAR>. 
 <!-- NEED 6in -->
-
 </P>
 <H3><A NAME="Allow">Allow</A></H3>
 <HR>
@@ -1377,7 +1379,6 @@ allow/deny processing. The default order is <CODE>deny,allow</CODE>: </P>
 </UL>
 
 <!-- NEED 3in -->
-
 <H3><A NAME="BrowseInterval">BrowseInterval</A></H3>
 <HR>
 <H4>Examples</H4>
@@ -1528,6 +1529,27 @@ work. This problem appears to be fixed in  HP-UX 11.0. </P>
 </TABLE>
 </CENTER>
 
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Classification">Classification</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+Classification
+Classification classified
+Classification confidential
+Classification secret
+Classification topsecret
+Classification unclassified
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>Classification</CODE> directive sets the classification 
+level on the server. When this option is set, at least one of the 
+banner pages is forced to the classification level, and the 
+classification is placed on each page of output. The default is no 
+classification level. 
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="DataDir">DataDir</A></H3>
@@ -1559,7 +1581,6 @@ set to use for client connections. The default character set is <CODE>
 utf-8</CODE> but is overridden by the character set for the language 
 specified by the client or the <CODE>DefaultLanguage</CODE> directive. 
 <!-- NEED 3in -->
-
 </P>
 <H3><A NAME="DefaultLanguage">DefaultLanguage</A></H3>
 <HR>
@@ -1736,7 +1757,6 @@ Group root
 filter and CGI programs run as. The default group is <CODE>sys</CODE>, <CODE>
 system</CODE>, or <CODE>root</CODE> depending on the operating system. 
 <!-- NEED 3in -->
-
 </P>
 <H3><A NAME="HostNameLookups">HostNameLookups</A></H3>
 <HR>
@@ -1952,7 +1972,6 @@ server from running. </LI>
 </UL>
 
 <!-- NEED 3in -->
-
 <H3><A NAME="MaxClients">MaxClients</A></H3>
 <HR>
 <H4>Examples</H4>
@@ -1995,8 +2014,46 @@ jobs that are kept in memory. Once the number of jobs reaches the
 limit, the oldest completed job is automatically purged from the system 
 to make room for the new one. If all of the known jobs are still 
 pending or active then the new job will be rejected. </P>
-<P>Setting the maximum size to 0 disables this functionality. The 
-default setting is 0. 
+<P>Setting the maximum to 0 disables this functionality. The default 
+setting is 0. 
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="MaxJobsPerPrinter">MaxJobsPerPrinter</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+MaxJobsPerPrinter 100
+MaxJobsPerPrinter 9999
+MaxJobsPerPrinter 0
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>MaxJobsPerPrinter</CODE> directive controls the maximum 
+number of active jobs that are allowed for each printer or class. Once 
+a printer or class reaches the limit, new jobs will be rejected until 
+one of the active jobs is completed, stopped, aborted, or cancelled. </P>
+<P>Setting the maximum to 0 disables this functionality. The default 
+setting is 0. 
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="MaxJobsPerUser">MaxJobsPerUser</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+MaxJobsPerUser 100
+MaxJobsPerUser 9999
+MaxJobsPerUser 0
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>MaxJobsPerUser</CODE> directive controls the maximum 
+number of active jobs that are allowed for each user. Once a user 
+reaches the limit, new jobs will be rejected until one of the active 
+jobs is completed, stopped, aborted, or cancelled. </P>
+<P>Setting the maximum to 0 disables this functionality. The default 
+setting is 0. 
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="MaxLogSize">MaxLogSize</A></H3>
@@ -2167,7 +2224,6 @@ PrintcapFormat Solaris
 <P>The <CODE>PrintcapFormat</CODE> directive controls the output format 
 of the printcap file. The default is to generate a BSD printcap file. 
 <!-- NEED 3in -->
-
 </P>
 <H3><A NAME="RemoteRoot">RemoteRoot</A></H3>
 <HR>
@@ -2411,7 +2467,6 @@ appropriate temporary directory called <VAR>/foo/bar/tmp</VAR>: </P>
 </UL>
 
 <!-- NEED 3in -->
-
 <H3><A NAME="Timeout">Timeout</A></H3>
 <HR>
 <H4>Examples</H4>
@@ -2557,7 +2612,6 @@ AuthType Basic
 </UL>
 
 <!-- NEED 7in -->
-
 <H3><A NAME="7_5_3">Using Digest Authentication</A></H3>
 <P>Digest authentication uses users and passwords defined in the <VAR>
 /etc/cups/passwd.md5</VAR> file to authenticate access to resources 
@@ -2604,7 +2658,6 @@ Password again: <B>(password) ENTER</B> [password is not echoed]
 </UL>
 
 <!-- NEED 2in -->
-
 <P>Once added, a user can change his/her password by typing: </P>
 <UL>
 <PRE>
@@ -2616,7 +2669,6 @@ Password again: <B>(password) ENTER</B> [password is not echoed]
 </UL>
 
 <!-- NEED 1in -->
-
 <P>To remove a user from the password file, type: </P>
 <UL>
 <PRE>
@@ -2673,7 +2725,6 @@ Password again: <B>(password) ENTER</B> [password is not echoed]
 </UL>
 
 <!-- NEW PAGE -->
-
 <H2><A NAME="PRINTER_ACCOUNTING">Printer Accounting</A></H2>
 <P>ESP Print Pro maintains a log of all accesses, errors, and pages 
 that are printed. The log files are normally stored in the <VAR>
@@ -3010,7 +3061,6 @@ lwsrv -n &quot;<I>Name</I>&quot; -p <I>printer</I> -a /usr/lib/adicts -f /usr/li
 <P>where <CODE>Name</CODE> is the name you want to use when sharing the 
 printer, and <CODE>printer</CODE> is the name of the CUPS print queue. 
 <!-- NEED 3in -->
-
 </P>
 <H3><A NAME="8_4_2">XINET KA/Spool</A></H3>
 <P>To use your system as a print server for Mac OS clients, configure 
@@ -3048,7 +3098,6 @@ Printer Description:MyPrinter@MyServer:\
 </UL>
 
 <!-- NEED 2in -->
-
 <H2><A NAME="8_5">Printing to Mac OS Servers</A></H2>
 <P>CUPS currently does not provide a backend to communicate with a Mac 
 OS server. However, you can write and install a short shell script in 
@@ -3119,7 +3168,6 @@ exit 0
 </UL>
 
 <!-- NEED 2in -->
-
 <H2><A NAME="8_6">Printing from Windows Clients</A></H2>
 <P>While CUPS does not provide Windows support directly, the free SAMBA 
 software package does. SAMBA version 2.0.6 is the first release of 
@@ -3257,7 +3305,6 @@ find out more at our web site: </P>
 </UL>
 
 <!-- NEW PAGE -->
-
 <H2><A NAME="9_2">GNU GENERAL PUBLIC LICENSE</A></H2>
 <P>Version 2, June 1991 </P>
 <PRE>
@@ -3515,7 +3562,6 @@ DAMAGES. </LI>
 <H4>END OF TERMS AND CONDITIONS</H4>
 
 <!-- NEW PAGE -->
-
 <H2><A NAME="9_3">GNU LIBRARY GENERAL PUBLIC LICENSE</A></H2>
 <P>Version 2, June 1991 </P>
 <PRE>
@@ -3981,7 +4027,6 @@ myprinter 08:00:69:00:12:34 192.0.2.2 <VAR>myprinter.boot</VAR>
 </UL>
 
 <!-- NEED 1in -->
-
 <P>Newer versions of <CODE>bootpd</CODE> use a different format: </P>
 <UL>
 <PRE>
@@ -4041,7 +4086,6 @@ URI(s)</TH></TR>
 address</I>/PASSTHRU</TD></TR>
 
 <!-- NEED 1in -->
-
 <TR ALIGN="LEFT" VALIGN="TOP"><TD>Axis w/o IPP
 <BR><A HREF="#AXIS"> (see directions)</A></TD><TD>socket://<I>address</I>
 :9100
@@ -4049,21 +4093,18 @@ address</I>/PASSTHRU</TD></TR>
 <BR> socket://<I>address</I>:9102</TD></TR>
 
 <!-- NEED 1in -->
-
 <TR ALIGN="LEFT" VALIGN="TOP"><TD>Axis w/IPP</TD><TD>ipp://<I>address</I>
 /LPT1
 <BR> ipp://<I>address</I>/LPT2
 <BR> ipp://<I>address</I>/COM1</TD></TR>
 
 <!-- NEED 1in -->
-
 <TR ALIGN="LEFT" VALIGN="TOP"><TD>Castelle LANpress<SUP>TM</SUP></TD><TD>
 lpd://<I>address</I>/pr1
 <BR> lpd://<I>address</I>/pr2
 <BR> lpd://<I>address</I>/pr3</TD></TR>
 
 <!-- NEED 1in -->
-
 <TR ALIGN="LEFT" VALIGN="TOP"><TD>DPI NETPrint</TD><TD>lpd://<I>address</I>
 /pr1
 <BR> lpd://<I>address</I>/pr2
@@ -4074,21 +4115,18 @@ address</I>/print</TD></TR>
 Interface Board</TD><TD>socket://<I>address</I></TD></TR>
 
 <!-- NEED 1in -->
-
 <TR ALIGN="LEFT" VALIGN="TOP"><TD>Extended System ExtendNET</TD><TD>
 lpd://<I>address</I>/pr1
 <BR> lpd://<I>address</I>/pr2
 <BR> lpd://<I>address</I>/pr3</TD></TR>
 
 <!-- NEED 1in -->
-
 <TR ALIGN="LEFT" VALIGN="TOP"><TD>Hewlett Packard JetDirect w/o IPP</TD><TD>
 socket://<I>address</I>:9100
 <BR> socket://<I>address</I>:9101
 <BR> socket://<I>address</I>:9102</TD></TR>
 
 <!-- NEED 1in -->
-
 <TR ALIGN="LEFT" VALIGN="TOP"><TD>Hewlett Packard JetDirect w/IPP</TD><TD>
 ipp://<I>address</I>/ipp
 <BR> ipp://<I>address</I>/ipp/port1
@@ -4096,7 +4134,6 @@ ipp://<I>address</I>/ipp
 <BR> ipp://<I>address</I>/ipp/port3</TD></TR>
 
 <!-- NEED 1in -->
-
 <TR ALIGN="LEFT" VALIGN="TOP"><TD>Intel&reg; NetportExpress XL, PRO/100</TD><TD>
 lpd://<I>address</I>/LPT1_PASSTHRU
 <BR> lpd://<I>address</I>/LPT2_PASSTHRU
@@ -4105,7 +4142,6 @@ lpd://<I>address</I>/LPT1_PASSTHRU
 lpd://<I>address</I>/ps</TD></TR>
 
 <!-- NEED 1in -->
-
 <TR ALIGN="LEFT" VALIGN="TOP"><TD>Linksys EtherFast&reg;
 <BR><A HREF="#LINKSYS"> (see directions)</A></TD><TD>socket://<I>address</I>
 :4010
@@ -4159,7 +4195,6 @@ ftp&gt; <B>quit ENTER</B>
 </UL>
 
 <!-- NEED 2in -->
-
 <P>Next, edit the file with your favorite text editor and locate the 
 lines beginning with: </P>
 <UL>
@@ -4185,7 +4220,6 @@ RTN_OPT.     : <B>NO</B>
 </UL>
 
 <!-- NEED 2in -->
-
 <P>This disables the Reverse TELNET protocol and enables the standard 
 TELNET protocol on the print server. Next, assign a port number for 
 each parallel and serial port on the server as follows: </P>
@@ -4203,7 +4237,6 @@ RTEL_PR8.    : <B>9107</B>
 </UL>
 
 <!-- NEED 4in -->
-
 <P>This essentially makes the Axis print server look like a Hewlett 
 Packard JetDirect EX print server. Save the file and then upload the 
 new <VAR>config</VAR> file using the <CODE>ftp</CODE> command: </P>
@@ -4262,7 +4295,6 @@ ftp&gt; <B>quit ENTER</B>
 </UL>
 
 <!-- NEED 2in -->
-
 <P>Next, edit the file with your favorite text editor and locate the 
 lines beginning with: </P>
 <UL>
@@ -4283,7 +4315,6 @@ server as follows: </P>
 </UL>
 
 <!-- NEED 4in -->
-
 <P>This maps each virtual printer with a physical port. Save the file 
 and then upload the new <VAR>CONFIG</VAR> file using the <CODE>ftp</CODE>
  command: </P>
@@ -4541,7 +4572,6 @@ ways to minimize them. </P>
 </CENTER>
 
 <!-- NEED 4in -->
-
 <H2><A NAME="13_4">I Can't Do Administration Tasks from My Web Browser!</A>
 </H2>
 <P>This problem is usually caused by: </P>
index 3d8d7b3cc7e2638898e8d35d56edc4f60962fe3e..fc3fa1a4ee4b72a08830fd6577aa9318164d6c11 100644 (file)
Binary files a/doc/sam.pdf and b/doc/sam.pdf differ
index 0e68b96b532e95ae1d66cfe19a1f933616020bfc..b801309fdb0b903df252f5a9d3d08411e38e3c48 100644 (file)
Binary files a/doc/sdd.pdf and b/doc/sdd.pdf differ
index 340e35bb7b7f105b5c4781e4bb376968cf948b57..672132355ad5b3883ce9a4a0d78914cf236260ee 100644 (file)
Binary files a/doc/spm.pdf and b/doc/spm.pdf differ
index 3ccd030e76f9c75834712b7ad838f5da1437f6af..79527d3fb57b18eab62b0b6cd87413e48a65eeb6 100644 (file)
Binary files a/doc/sps.pdf and b/doc/sps.pdf differ
index 83925c4501a2ede37aa6d2aa30856b1101749741..f24244cd93deca569d3e80431307c6010d454491 100644 (file)
Binary files a/doc/ssr.pdf and b/doc/ssr.pdf differ
index dac652a0c5207f24e503dc6cd5d4443cee6c3d79..00637189090c1b30795aa9f046c0e8eb7de0a6a0 100644 (file)
Binary files a/doc/stp.pdf and b/doc/stp.pdf differ
index b13118241ef468fd7d313ecb7ce1eb9e81fff55d..576c6c8b05349cac3fbc08b1ba9f5238d735add0 100644 (file)
@@ -1,28 +1,28 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
 <HTML>
 <HEAD>
-<TITLE> CUPS Software Users Manual</TITLE>
+<TITLE>CUPS Software Users Manual</TITLE>
 <META NAME="author" CONTENT="Easy Software Products">
 <META NAME="copyright" CONTENT="Copyright 1997-2001, All Rights Reserved">
-<META NAME="docnumber" CONTENT="CUPS-SUM-1.1.6">
+<META NAME="docnumber" CONTENT="CUPS-SUM-1.1.7">
 <META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-8859-1">
 <STYLE TYPE="text/css"><!--
-BODY { font-family: serif; font-size: 11.0pt }
-H1 { font-family: sans-serif; font-size: 20.0pt }
-H2 { font-family: sans-serif; font-size: 17.0pt }
-H3 { font-family: sans-serif; font-size: 14.0pt }
-H4 { font-family: sans-serif; font-size: 11.0pt }
-H5 { font-family: sans-serif; font-size: 9.0pt }
-H6 { font-family: sans-serif; font-size: 8.0pt }
-SUB { font-size: 8.0pt }
-SUP { font-size: 8.0pt }
-PRE { font-size: 9.0pt }
+BODY { font-family: serif }
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
+SUB { font-size: smaller }
+SUP { font-size: smaller }
+PRE { font-family: monospace }
 --></STYLE>
 </HEAD>
 <BODY BGCOLOR="#ffffff">
-<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="100%"><BR>
-<H1> CUPS Software Users Manual</H1></A><BR>
-CUPS-SUM-1.1.6<BR>
+<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="431" HEIGHT="511"><BR>
+<H1>CUPS Software Users Manual</H1></A><BR>
+CUPS-SUM-1.1.7<BR>
 Easy Software Products<BR>
 Copyright 1997-2001, All Rights Reserved<BR>
 </CENTER>
@@ -125,7 +125,7 @@ Copyright 1997-2001, All Rights Reserved<BR>
 <HR>
 <H1 ALIGN="RIGHT"><A NAME="1">Preface</A></H1>
 <P>This software users manual describes how to use the Common UNIX 
-Printing System<SUP>TM</SUP> (&quot;CUPS<SUP>TM</SUP>&quot;) Version 1.1.6. </P>
+Printing System<SUP>TM</SUP> (&quot;CUPS<SUP>TM</SUP>&quot;) Version 1.1.7. </P>
 <H2><A NAME="1_1">System Overview</A></H2>
 <P>CUPS provides a portable printing layer for UNIX&reg;-based operating 
 systems. It has been developed by <A HREF="http://www.easysw.com">Easy 
index 5b47d9364b47af9260ddbd2592366a2e5c233d85..34bdc62d904101182b974b7c8d6c993d6ab613b3 100644 (file)
Binary files a/doc/sum.pdf and b/doc/sum.pdf differ
index 3341f9ddf219bbd9726f71cee52af53b17b50af6..46e689c3a0122ffca5821bf5cf5e1fa2ff620a96 100644 (file)
@@ -2,7 +2,7 @@
 <HEAD>
        <META NAME="Description" CONTENT="Common UNIX Printing System Software Users Manual">
        <META NAME="COPYRIGHT" CONTENT="Copyright 1997-2001, All Rights Reserved">
-       <META NAME="DOCNUMBER" CONTENT="CUPS-SUM-1.1.6">
+       <META NAME="DOCNUMBER" CONTENT="CUPS-SUM-1.1.7">
        <META NAME="Author" CONTENT="Easy Software Products">
        <TITLE>CUPS Software Users Manual</TITLE>
 </HEAD>
@@ -11,7 +11,7 @@
 <H1 ALIGN="RIGHT">Preface</H1>
 
 <P>This software users manual describes how to use the Common UNIX Printing
-System<SUP>TM</SUP> ("CUPS<SUP>TM</SUP>") Version 1.1.6.
+System<SUP>TM</SUP> ("CUPS<SUP>TM</SUP>") Version 1.1.7.
 
 <EMBED SRC="system-overview.shtml">
 
index 01f3a25f76f855dbae551f6e3f8df68cc4f81906..05918d142a635eca69e96fa89da53dba113acc8e 100644 (file)
Binary files a/doc/svd.pdf and b/doc/svd.pdf differ
index b050aa429d9da1a32a2b9595f7afa2fc2686bb91..08a99c43d84347910bda0d363a78ea61fa402cb5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: common.c,v 1.15 2001/03/27 20:54:15 mike Exp $"
+ * "$Id: common.c,v 1.15.2.1 2001/05/13 18:38:18 mike Exp $"
  *
  *   Common filter routines for the Common UNIX Printing System (CUPS).
  *
  *
  * Contents:
  *
- *   SetCommonOptions() - Set common filter options for media size, etc.
+ *   SetCommonOptions()          - Set common filter options for media size,
+ *                                 etc.
+ *   UpdatePageVars()            - Update the page variables for the
+ *                                 orientation.
+ *   WriteClassificationProlog() - Write the prolog with the classification
+ *                                 and page label.
  */
 
 /*
@@ -58,7 +63,6 @@ SetCommonOptions(int           num_options,   /* I - Number of options */
                  cups_option_t *options,       /* I - Options */
                 int           change_size)     /* I - Change page size? */
 {
-  float                temp;           /* Swapping variable */
   ppd_file_t   *ppd;           /* PPD file */
   ppd_size_t   *pagesize;      /* Current page size */
   const char   *val;           /* Option value */
@@ -184,57 +188,7 @@ SetCommonOptions(int           num_options,        /* I - Number of options */
   }
 
   if (change_size)
-    switch (Orientation)
-    {
-      case 0 : /* Portait */
-          break;
-
-      case 1 : /* Landscape */
-         temp       = PageLeft;
-         PageLeft   = PageBottom;
-         PageBottom = temp;
-
-         temp       = PageRight;
-         PageRight  = PageTop;
-         PageTop    = temp;
-
-         temp       = PageWidth;
-         PageWidth  = PageLength;
-         PageLength = temp;
-         break;
-
-      case 2 : /* Reverse Portrait */
-         temp       = PageWidth - PageLeft;
-         PageLeft   = PageWidth - PageRight;
-         PageRight  = temp;
-
-         temp       = PageLength - PageBottom;
-         PageBottom = PageLength - PageTop;
-         PageTop    = temp;
-          break;
-
-      case 3 : /* Reverse Landscape */
-         temp       = PageWidth - PageLeft;
-         PageLeft   = PageWidth - PageRight;
-         PageRight  = temp;
-
-         temp       = PageLength - PageBottom;
-         PageBottom = PageLength - PageTop;
-         PageTop    = temp;
-
-         temp       = PageLeft;
-         PageLeft   = PageBottom;
-         PageBottom = temp;
-
-         temp       = PageRight;
-         PageRight  = PageTop;
-         PageTop    = temp;
-
-         temp       = PageWidth;
-         PageWidth  = PageLength;
-         PageLength = temp;
-         break;
-    }
+    UpdatePageVars();
 
   if ((val = cupsGetOption("sides", num_options, options)) != NULL &&
       strncasecmp(val, "two-", 4) == 0)
@@ -250,6 +204,70 @@ SetCommonOptions(int           num_options,        /* I - Number of options */
 }
 
 
+/*
+ * 'UpdatePageVars()' - Update the page variables for the orientation.
+ */
+
+void
+UpdatePageVars(void)
+{
+  float                temp;           /* Swapping variable */
+
+
+  switch (Orientation)
+  {
+    case 0 : /* Portait */
+        break;
+
+    case 1 : /* Landscape */
+       temp       = PageLeft;
+       PageLeft   = PageBottom;
+       PageBottom = temp;
+
+       temp       = PageRight;
+       PageRight  = PageTop;
+       PageTop    = temp;
+
+       temp       = PageWidth;
+       PageWidth  = PageLength;
+       PageLength = temp;
+       break;
+
+    case 2 : /* Reverse Portrait */
+       temp       = PageWidth - PageLeft;
+       PageLeft   = PageWidth - PageRight;
+       PageRight  = temp;
+
+       temp       = PageLength - PageBottom;
+       PageBottom = PageLength - PageTop;
+       PageTop    = temp;
+        break;
+
+    case 3 : /* Reverse Landscape */
+       temp       = PageWidth - PageLeft;
+       PageLeft   = PageWidth - PageRight;
+       PageRight  = temp;
+
+       temp       = PageLength - PageBottom;
+       PageBottom = PageLength - PageTop;
+       PageTop    = temp;
+
+       temp       = PageLeft;
+       PageLeft   = PageBottom;
+       PageBottom = temp;
+
+       temp       = PageRight;
+       PageRight  = PageTop;
+       PageTop    = temp;
+
+       temp       = PageWidth;
+       PageWidth  = PageLength;
+       PageLength = temp;
+       break;
+  }
+}
+
+
 /*
  * 'WriteClassificationProlog()' - Write the prolog with the classification
  *                                 and page label.
@@ -333,5 +351,5 @@ WriteLabelProlog(const char *label) /* I - Page label */
 
 
 /*
- * End of "$Id: common.c,v 1.15 2001/03/27 20:54:15 mike Exp $".
+ * End of "$Id: common.c,v 1.15.2.1 2001/05/13 18:38:18 mike Exp $".
  */
index e92bfa12eadf5ed20824a566c2ccd72bdf185111..4b62e0caaf7b4c4c5344568aa63978b638789f17 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: common.h,v 1.6 2001/03/14 13:45:33 mike Exp $"
+ * "$Id: common.h,v 1.6.2.1 2001/05/13 18:38:18 mike Exp $"
  *
  *   Common filter definitions for the Common UNIX Printing System (CUPS).
  *
@@ -60,10 +60,11 @@ extern float        PageLeft,       /* Left margin */
 
 extern ppd_file_t *SetCommonOptions(int num_options, cups_option_t *options,
                                    int change_size);
+extern void    UpdatePageVars(void);
 extern void    WriteLabelProlog(const char *label);
 #define                WriteLabels() puts("espWL");
 
 
 /*
- * End of "$Id: common.h,v 1.6 2001/03/14 13:45:33 mike Exp $".
+ * End of "$Id: common.h,v 1.6.2.1 2001/05/13 18:38:18 mike Exp $".
  */
index 7511c6ce531f71644904f667e4b4f9ca6c7838d3..3d746c45e9b9375676c49ad26e20a6a898a8edf7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: image-bmp.c,v 1.3 2001/01/22 15:03:38 mike Exp $"
+ * "$Id: image-bmp.c,v 1.3.2.1 2001/05/13 18:38:18 mike Exp $"
  *
  *   BMP image routines for the Common UNIX Printing System (CUPS).
  *
@@ -90,6 +90,8 @@ ImageReadBMP(image_t    *img,         /* IO - Image */
   ib_t         colormap[256][4];       /* Colormap */
 
 
+  (void)secondary;
+
  /*
   * Get the header...
   */
@@ -119,6 +121,15 @@ ImageReadBMP(image_t    *img,              /* IO - Image */
   colors_used      = read_dword(fp);
   colors_important = read_dword(fp);
 
+ /*
+  * Make sure the resolution info is valid...
+  */
+
+  if (img->xppi == 0)
+    img->xppi = 128;
+  if (img->yppi == 0)
+    img->yppi = 128;
+
   fprintf(stderr, "info_size = %d, xsize = %d, ysize = %d, planes = %d, depth = %d\n",
           info_size, img->xsize, img->ysize, planes, depth);
   fprintf(stderr, "compression = %d, image_size = %d, xppi = %d, yppi = %d\n",
@@ -495,5 +506,5 @@ read_long(FILE *fp)               /* I - File to read from */
 
 
 /*
- * End of "$Id: image-bmp.c,v 1.3 2001/01/22 15:03:38 mike Exp $".
+ * End of "$Id: image-bmp.c,v 1.3.2.1 2001/05/13 18:38:18 mike Exp $".
  */
index a0eddc9b1f2976929a18df3b01758520b178dc82..2344fb50ee6aa2bc99eef15b54f17a9aa08b9121 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: image-tiff.c,v 1.17 2001/01/22 15:03:39 mike Exp $"
+ * "$Id: image-tiff.c,v 1.17.2.1 2001/05/13 18:38:18 mike Exp $"
  *
  *   TIFF file routines for the Common UNIX Printing System (CUPS).
  *
@@ -96,22 +96,49 @@ ImageReadTIFF(image_t    *img,              /* IO - Image */
 
   if ((tif = TIFFFdOpen(fileno(fp), "", "r")) == NULL)
   {
+    fputs("ERROR: TIFFFdOpen() failed!\n", stderr);
     fclose(fp);
     return (-1);
   }
 
-  if (!TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width) ||
-      !TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height) ||
-      !TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric) ||
-      !TIFFGetField(tif, TIFFTAG_COMPRESSION, &compression) ||
-      !TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samples) ||
-      !TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bits))
+  if (!TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width))
   {
+    fputs("ERROR: No image width tag in the file!\n", stderr);
     TIFFClose(tif);
     fclose(fp);
     return (-1);
   }
 
+  if (!TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height))
+  {
+    fputs("ERROR: No image height tag in the file!\n", stderr);
+    TIFFClose(tif);
+    fclose(fp);
+    return (-1);
+  }
+
+  if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric))
+  {
+    fputs("ERROR: No photometric tag in the file!\n", stderr);
+    TIFFClose(tif);
+    fclose(fp);
+    return (-1);
+  }
+
+  if (!TIFFGetField(tif, TIFFTAG_COMPRESSION, &compression))
+  {
+    fputs("ERROR: No compression tag in the file!\n", stderr);
+    TIFFClose(tif);
+    fclose(fp);
+    return (-1);
+  }
+
+  if (!TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samples))
+    samples = 1;
+
+  if (!TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bits))
+    bits = 1;
+
  /*
   * Get the image orientation...
   */
@@ -1657,5 +1684,5 @@ ImageReadTIFF(image_t    *img,            /* IO - Image */
 
 
 /*
- * End of "$Id: image-tiff.c,v 1.17 2001/01/22 15:03:39 mike Exp $".
+ * End of "$Id: image-tiff.c,v 1.17.2.1 2001/05/13 18:38:18 mike Exp $".
  */
index 7af7997e126b9bb4a5c792f444a365dd3a3b1e0c..ac1db10bafc918165c573a723ab37e87caf21656 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: imagetops.c,v 1.36 2001/03/14 13:45:33 mike Exp $"
+ * "$Id: imagetops.c,v 1.36.2.1 2001/05/13 18:38:18 mike Exp $"
  *
  *   Image file to PostScript filter for the Common UNIX Printing System (CUPS).
  *
@@ -52,7 +52,7 @@ int   Flip = 0,               /* Flip/mirror pages */
  * Local functions...
  */
 
-static void    ps_hex(ib_t *, int);
+static void    ps_hex(ib_t *, int, int);
 static void    ps_ascii85(ib_t *, int, int);
 
 
@@ -87,6 +87,7 @@ main(int  argc,               /* I - Number of command-line arguments */
   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 */
@@ -99,6 +100,9 @@ main(int  argc,              /* I - Number of command-line arguments */
   int          realcopies;     /* Real copies being printed */
   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 */
 
 
  /*
@@ -431,9 +435,78 @@ main(int  argc,            /* I - Number of command-line arguments */
     }
   }
 
+ /*
+  * 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;
+
+ /*
+  * Update the page size for custom sizes...
+  */
+
+  if ((choice = ppdFindMarkedChoice(ppd, "PageSize")) != NULL &&
+      strcasecmp(choice->choice, "Custom") == 0)
+  {
+    float      width,          /* New width in points */
+               length;         /* New length in points */
+    char       s[255];         /* New custom page size... */
+
+
+    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];
+
+   /*
+    * 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];
+
+    UpdatePageVars();
+  }
+
  /*
   * See if we need to collate, and if so how we need to do it...
   */
@@ -443,6 +516,14 @@ main(int  argc,            /* I - Number of command-line arguments */
 
   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...
   */
@@ -459,7 +540,25 @@ main(int  argc,            /* I - Number of command-line arguments */
   * Start sending the document with any commands needed...
   */
 
-  puts("%!");
+  curtime = time(NULL);
+  curtm   = localtime(&curtime);
+
+  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);
+  puts("%%DocumentData: Clean7Bit");
+  puts("%%DocumentNeededResources: font Helvetica-Bold");
+  puts("%%Creator: imagetops/" CUPS_SVERSION);
+  strftime(curdate, sizeof(curdate), CUPS_STRFTIME_FORMAT, curtm);
+  printf("%%%%CreationDate: %s\n", curdate);
+  printf("%%%%Title: %s\n", argv[3]);
+  printf("%%%%For: %s\n", argv[2]);
+  if (Orientation & 1)
+    puts("%%Orientation: Landscape");
+  puts("%%EndComments");
+  puts("%%BeginProlog");
 
   if (ppd != NULL && ppd->patches != NULL)
     puts(ppd->patches);
@@ -474,33 +573,32 @@ main(int  argc,           /* I - Number of command-line arguments */
 
   WriteLabelProlog(cupsGetOption("page-label", num_options, options));
 
-  if (Copies > 1 && !slowcollate)
+  if (realcopies > 1)
   {
     if (ppd == NULL || ppd->language_level == 1)
-      printf("/#copies %d def\n", Copies);
+      printf("/#copies %d def\n", realcopies);
     else
-      printf("<</NumCopies %d>>setpagedevice\n", Copies);
-
-    realcopies = Copies;
-    Copies     = 1;
+      printf("<</NumCopies %d>>setpagedevice\n", realcopies);
   }
-  else
-    realcopies = 1;
+
+  puts("%%EndProlog");
 
  /*
   * Output the pages...
   */
 
-  xprint = xinches / xpages;
-  yprint = yinches / ypages;
-  row    = malloc(img->xsize * abs(colorspace) + 3);
+  row = malloc(img->xsize * abs(colorspace) + 3);
 
   for (page = 1; Copies > 0; Copies --)
     for (xpage = 0; xpage < xpages; xpage ++)
       for (ypage = 0; ypage < ypages; ypage ++, page ++)
       {
-        fprintf(stderr, "PAGE: %d %d\n", page, realcopies);
-        fprintf(stderr, "INFO: Printing page %d...\n", page);
+        if (ppd && ppd->num_filters == 0)
+          fprintf(stderr, "PAGE: %d %d\n", page, realcopies);
+
+       fprintf(stderr, "INFO: Printing page %d...\n", page);
+
+        printf("%%%%Page: %d %d\n", page, page);
 
         ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
 
@@ -572,7 +670,7 @@ main(int  argc,             /* I - Number of command-line arguments */
           for (y = y0; y <= y1; y ++)
           {
             ImageGetRow(img, x0, y, x1 - x0 + 1, row);
-            ps_hex(row, (x1 - x0 + 1) * abs(colorspace));
+            ps_hex(row, (x1 - x0 + 1) * abs(colorspace), y == y1);
           }
        }
        else
@@ -620,6 +718,8 @@ main(int  argc,             /* I - Number of command-line arguments */
        puts("showpage");
       }
 
+  puts("%%EOF");
+
  /*
   * End the job with the appropriate JCL command or CTRL-D otherwise.
   */
@@ -645,15 +745,15 @@ main(int  argc,           /* I - Number of command-line arguments */
  */
 
 static void
-ps_hex(ib_t *data,     /* I - Data to print */
-       int  length)    /* I - Number of bytes to print */
+ps_hex(ib_t *data,             /* I - Data to print */
+       int  length,            /* I - Number of bytes to print */
+       int  last_line)         /* I - Last line of raster data? */
 {
-  int          col;
+  static int   col = 0;        /* Current column */
   static char  *hex = "0123456789ABCDEF";
+                               /* Hex digits */
 
 
-  col = 0;
-
   while (length > 0)
   {
    /*
@@ -667,12 +767,19 @@ ps_hex(ib_t *data,        /* I - Data to print */
     data ++;
     length --;
 
-    col = (col + 1) & 31;
-    if (col == 0 && length > 0)
+    col += 2;
+    if (col > 78)
+    {
       putchar('\n');
+      col = 0;
+    }
   }
 
-  putchar('\n');
+  if (last_line && col)
+  {
+    putchar('\n');
+    col = 0;
+  }
 }
 
 
@@ -687,6 +794,7 @@ ps_ascii85(ib_t *data,              /* I - Data to print */
 {
   unsigned     b;              /* Binary data word */
   unsigned char        c[5];           /* ASCII85 encoded chars */
+  static int   col = 0;        /* Current column */
 
 
   while (length > 3)
@@ -694,7 +802,10 @@ ps_ascii85(ib_t *data,             /* I - Data to print */
     b = (((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3];
 
     if (b == 0)
+    {
       putchar('z');
+      col ++;
+    }
     else
     {
       c[4] = (b % 85) + '!';
@@ -708,10 +819,17 @@ ps_ascii85(ib_t *data,            /* I - Data to print */
       c[0] = b + '!';
 
       fwrite(c, 5, 1, stdout);
+      col += 5;
     }
 
     data += 4;
     length -= 4;
+
+    if (col >= 75)
+    {
+      putchar('\n');
+      col = 0;
+    }
   }
 
   if (last_line)
@@ -735,10 +853,11 @@ ps_ascii85(ib_t *data,            /* I - Data to print */
     }
 
     puts("~>");
+    col = 0;
   }
 }
 
 
 /*
- * End of "$Id: imagetops.c,v 1.36 2001/03/14 13:45:33 mike Exp $".
+ * End of "$Id: imagetops.c,v 1.36.2.1 2001/05/13 18:38:18 mike Exp $".
  */
index 323c94dcf44783323cf8eb1c4228da6b22a2ae06..22c457f4395f8b50a4dcc4cc85a93da88e5fca72 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: imagetoraster.c,v 1.56 2001/03/15 17:48:07 mike Exp $"
+ * "$Id: imagetoraster.c,v 1.56.2.1 2001/05/13 18:38:19 mike Exp $"
  *
  *   Image file to raster filter for the Common UNIX Printing System (CUPS).
  *
@@ -804,20 +804,69 @@ main(int  argc,           /* I - Number of command-line arguments */
   if ((choice = ppdFindMarkedChoice(ppd, "PageSize")) != NULL &&
       strcasecmp(choice->choice, "Custom") == 0)
   {
+    float      width,          /* New width in points */
+               length;         /* New length in points */
+
+
     if (Orientation & 1)
     {
-      header.cupsWidth   = yprint * header.HWResolution[0];
-      header.cupsHeight  = xprint * header.HWResolution[1];
-      header.PageSize[0] = yprint * 72.0;
-      header.PageSize[1] = xprint * 72.0;
+      width  = yprint * 72.0;
+      length = xprint * 72.0;
     }
     else
     {
-      header.cupsWidth   = xprint * header.HWResolution[0];
-      header.cupsHeight  = yprint * header.HWResolution[1];
-      header.PageSize[0] = xprint * 72.0;
-      header.PageSize[1] = yprint * 72.0;
+      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];
+
+   /*
+    * Set the new custom size...
+    */
+
+    header.PageSize[0] = width + 0.5;
+    header.PageSize[1] = length + 0.5;
+
+   /*
+    * 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];
+
+   /*
+    * Remove margins from page size...
+    */
+
+    width  -= ppd->custom_margins[0] + ppd->custom_margins[2];
+    length -= ppd->custom_margins[1] + ppd->custom_margins[3];
+
+   /*
+    * Set the bitmap size...
+    */
+
+    header.cupsWidth  = width * header.HWResolution[0] / 72.0;
+    header.cupsHeight = length * header.HWResolution[1] / 72.0;
   }
   else
   {
@@ -2197,6 +2246,8 @@ format_K(cups_page_header_t *header,      /* I - Page header */
                *dither;        /* Pointer into dither array */
 
 
+  (void)z;
+
   switch (XPosition)
   {
     case -1 :
@@ -3461,6 +3512,8 @@ format_W(cups_page_header_t *header,      /* I - Page header */
                *dither;        /* Pointer into dither array */
 
 
+  (void)z;
+
   switch (XPosition)
   {
     case -1 :
@@ -4389,5 +4442,5 @@ make_lut(ib_t  *lut,              /* I - Lookup table */
 
 
 /*
- * End of "$Id: imagetoraster.c,v 1.56 2001/03/15 17:48:07 mike Exp $".
+ * End of "$Id: imagetoraster.c,v 1.56.2.1 2001/05/13 18:38:19 mike Exp $".
  */
index b5ee71dcd757416e4457f75bf026329189b9195c..bc4e585860f4c7d6265abc4528c3ee9df45cc14d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: pstops.c,v 1.54 2001/03/29 15:14:47 mike Exp $"
+ * "$Id: pstops.c,v 1.54.2.1 2001/05/13 18:38:20 mike Exp $"
  *
  *   PostScript filter for the Common UNIX Printing System (CUPS).
  *
@@ -59,7 +59,8 @@ int           Order = 0,              /* 0 = normal, 1 = reverse pages */
                Flip = 0,               /* Flip/mirror pages */
                NUp = 1,                /* Number of pages on each sheet (1, 2, 4) */
                Collate = 0,            /* Collate copies? */
-               Copies = 1;             /* Number of copies */
+               Copies = 1,             /* Number of copies */
+               UseESPsp = 0;           /* Use ESPshowpage? */
 
 
 /*
@@ -262,26 +263,46 @@ main(int  argc,                   /* I - Number of command-line arguments */
   ppdEmit(ppd, stdout, PPD_ORDER_ANY);
   ppdEmit(ppd, stdout, PPD_ORDER_PROLOG);
 
-  puts("userdict begin\n"
-       "/ESPshowpage /showpage load def\n"
-       "/showpage { } def\n"
-       "end");
-
   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);
 
-  WriteLabelProlog(cupsGetOption("page-label", num_options, options));
+ /*
+  * Figure out if we should use ESPshowpage or not...
+  */
+
+  val = cupsGetOption("page-label", num_options, options);
+
+  if (val != NULL || getenv("CLASSIFICATION") != NULL || NUp > 1)
+  {
+   /*
+    * Yes, use ESPshowpage...
+    */
+
+    UseESPsp = 1;
+
+    WriteLabelProlog(val);
+
+    puts("userdict begin\n"
+        "/ESPshowpage /showpage load def\n"
+        "/showpage { } def\n"
+        "end");
+  }
 
   if (Copies > 1 && (!Collate || !slowcollate))
   {
-    if (ppd == NULL || ppd->language_level == 1)
+    if (Collate)
+      printf("%%%%Requirements: numcopies(%d) collate\n", Copies);
+    else
+      printf("%%%%Requirements: numcopies(%d)\n", Copies);
+
+    if (LanguageLevel == 1)
       printf("/#copies %d def\n", Copies);
     else
       printf("<</NumCopies %d>>setpagedevice\n", Copies);
   }
 
-  if (strncmp(line, "%!PS-Adobe-", 11) == 0)
+  if (strncmp(line, "%!PS-Adobe-", 11) == 0 && atof(line + 11) >= 3.0)
   {
    /*
     * OK, we have DSC comments; read until we find a %%Page comment...
@@ -293,7 +314,7 @@ main(int  argc,                     /* I - Number of command-line arguments */
       if (strncmp(line, "%%BeginDocument:", 16) == 0 ||
           strncmp(line, "%%BeginDocument ", 16) == 0)  /* Adobe Acrobat BUG */
         level ++;
-      else if (strcmp(line, "%%EndDocument") == 0 && level > 0)
+      else if (strncmp(line, "%%EndDocument", 13) == 0 && level > 0)
         level --;
       else if (strncmp(line, "%%Page:", 7) == 0 && level == 0)
         break;
@@ -329,51 +350,54 @@ main(int  argc,                   /* I - Number of command-line arguments */
       if (strncmp(line, "%%BeginDocument:", 16) == 0 ||
           strncmp(line, "%%BeginDocument ", 16) == 0)  /* Adobe Acrobat BUG */
         level ++;
-      else if (strcmp(line, "%%EndDocument") == 0 && level > 0)
+      else if (strncmp(line, "%%EndDocument", 13) == 0 && level > 0)
         level --;
-      else if (strcmp(line, "%%EOF") == 0 && level == 0)
+      else if (strcmp(line, "\004") == 0)
+        continue;
+      else if (strncmp(line, "%%EOF", 5) == 0 && level == 0)
+      {
+        fputs("DEBUG: Saw EOF!\n", stderr);
         saweof = 1;
+       break;
+      }
       else if (strncmp(line, "%%Page:", 7) == 0 && level == 0)
       {
-        if (sscanf(line, "%*s%*s%d", &number) == 1)
+       if (!check_range(NumPages + 1))
        {
-         if (!check_range(number))
-         {
-           while (psgets(line, sizeof(line), fp) != NULL)
-             if (strncmp(line, "%%BeginDocument:", 16) == 0 ||
-                 strncmp(line, "%%BeginDocument ", 16) == 0)   /* Adobe Acrobat BUG */
-               level ++;
-             else if (strcmp(line, "%%EndDocument") == 0 && level > 0)
-               level --;
-             else if (strncmp(line, "%%Page:", 7) == 0 && level == 0)
-               break;
-
-            continue;
-          }
+         while (psgets(line, sizeof(line), fp) != NULL)
+           if (strncmp(line, "%%BeginDocument:", 16) == 0 ||
+               strncmp(line, "%%BeginDocument ", 16) == 0)     /* Adobe Acrobat BUG */
+              level ++;
+           else if (strcmp(line, "%%EndDocument") == 0 && level > 0)
+              level --;
+           else if (strncmp(line, "%%Page:", 7) == 0 && level == 0)
+             break;
+
+          continue;
+        }
 
-          if (!sloworder && NumPages > 0)
-           end_nup(NumPages - 1);
+        if (!sloworder && NumPages > 0)
+         end_nup(NumPages - 1);
 
-         if (slowcollate || sloworder)
-           Pages[NumPages] = ftell(temp);
+       if (slowcollate || sloworder)
+         Pages[NumPages] = ftell(temp);
 
-          if (!sloworder)
+        if (!sloworder)
+       {
+         if ((NumPages & (NUp - 1)) == 0)
          {
-           if ((NumPages & (NUp - 1)) == 0)
-           {
-             if (ppd == NULL || ppd->num_filters == 0)
-               fprintf(stderr, "PAGE: %d %d\n", page, Copies);
-
-              printf("%%%%Page: %d %d\n", page, page);
-             page ++;
-             ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
-           }
+           if (ppd == NULL || ppd->num_filters == 0)
+             fprintf(stderr, "PAGE: %d %d\n", page, Copies);
 
-           start_nup(NumPages);
+            printf("%%%%Page: %d %d\n", page, page);
+           page ++;
+           ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
          }
 
-         NumPages ++;
+         start_nup(NumPages);
        }
+
+       NumPages ++;
       }
       else if (strncmp(line, "%%BeginBinary:", 14) == 0 ||
                (strncmp(line, "%%BeginData:", 12) == 0 &&
@@ -400,8 +424,11 @@ main(int  argc,                    /* I - Number of command-line arguments */
          tbytes -= nbytes;
        }
       }
-      else if (strcmp(line, "%%Trailer") == 0 && level == 0)
+      else if (strncmp(line, "%%Trailer", 9) == 0 && level == 0)
+      {
+        fputs("DEBUG: Saw Trailer!\n", stderr);
         break;
+      }
       else
       {
         if (!sloworder)
@@ -511,8 +538,18 @@ main(int  argc,                    /* I - Number of command-line arguments */
     * Copy the trailer, if any...
     */
 
-    while ((nbytes = fread(line, 1, sizeof(line), fp)) > 0)
-      fwrite(line, 1, nbytes, stdout);
+    while (psgets(line, sizeof(line), fp) != NULL)
+    {
+      if (strcmp(line, "\004") != 0)
+        fputs(line, stdout);
+
+      if (strncmp(line, "%%EOF", 5) == 0)
+      {
+        fputs("DEBUG: Saw EOF!\n", stderr);
+        saweof = 1;
+       break;
+      }
+    }
   }
   else
   {
@@ -533,7 +570,8 @@ main(int  argc,                     /* I - Number of command-line arguments */
        fputs(line, temp);
     }
 
-    puts("ESPshowpage");
+    if (UseESPsp)
+      puts("ESPshowpage");
 
     if (slowcollate)
     {
@@ -547,7 +585,8 @@ main(int  argc,                     /* I - Number of command-line arguments */
        copy_bytes(temp, 0);
        Copies --;
 
-        puts("ESPshowpage");
+        if (UseESPsp)
+          puts("ESPshowpage");
       }
     }
   }
@@ -565,7 +604,7 @@ main(int  argc,                     /* I - Number of command-line arguments */
 
   if (ppd != NULL && ppd->jcl_end)
     fputs(ppd->jcl_end, stdout);
-  else if (ppd->num_filters == 0)
+  else if (ppd != NULL && ppd->num_filters == 0)
     putchar(0x04);
 
  /*
@@ -696,12 +735,15 @@ end_nup(int number)       /* I - Page number */
   switch (NUp)
   {
     case 1 :
-       WriteLabels();
-        puts("ESPshowpage");
+       if (UseESPsp)
+       {
+         WriteLabels();
+          puts("ESPshowpage");
+       }
        break;
 
     case 2 :
-       if ((number & 1) == 1)
+       if ((number & 1) == 1 && UseESPsp)
        {
          WriteLabels();
           puts("ESPshowpage");
@@ -709,7 +751,7 @@ end_nup(int number) /* I - Page number */
         break;
 
     case 4 :
-       if ((number & 3) == 3)
+       if ((number & 3) == 3 && UseESPsp)
        {
          WriteLabels();
           puts("ESPshowpage");
@@ -921,5 +963,5 @@ start_nup(int number)       /* I - Page number */
 
 
 /*
- * End of "$Id: pstops.c,v 1.54 2001/03/29 15:14:47 mike Exp $".
+ * End of "$Id: pstops.c,v 1.54.2.1 2001/05/13 18:38:20 mike Exp $".
  */
index a48dfc1f8b6420f3be982ed8c7275acdbf7eb7b4..9d942130e42705e098658a8f5ef81e9b81491e27 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: rastertoepson.c,v 1.10 2001/03/05 22:09:18 mike Exp $"
+ * "$Id: rastertoepson.c,v 1.10.2.1 2001/05/13 18:38:20 mike Exp $"
  *
  *   EPSON ESC/P and ESC/P2 filter for the Common UNIX Printing System
  *   (CUPS).
@@ -1082,12 +1082,12 @@ main(int  argc,                 /* I - Number of command-line arguments */
   if (page == 0)
     fputs("ERROR: No pages found!\n", stderr);
   else
-    fputs("INFO: Ready to print.\n", stderr);
+    fputs("INFO: " CUPS_SVERSION " is ready to print.\n", stderr);
 
   return (page == 0);
 }
 
 
 /*
- * End of "$Id: rastertoepson.c,v 1.10 2001/03/05 22:09:18 mike Exp $".
+ * End of "$Id: rastertoepson.c,v 1.10.2.1 2001/05/13 18:38:20 mike Exp $".
  */
index 4c0ed877eaf9702193800fe6fbf7436212f128f9..fda12cee0ef85650976666d3c9a7e6a1eb59d8c4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: rastertohp.c,v 1.15 2001/03/02 14:30:15 mike Exp $"
+ * "$Id: rastertohp.c,v 1.15.2.1 2001/05/13 18:38:21 mike Exp $"
  *
  *   Hewlett-Packard Page Control Language filter for the Common UNIX
  *   Printing System (CUPS).
  */
 
 unsigned char  *Planes[4],             /* Output buffers */
-               *CompBuffer;            /* Compression buffer */
+               *CompBuffer,            /* Compression buffer */
+               *BitBuffer;             /* Buffer for output bits */
 int            NumPlanes,              /* Number of color planes */
+               ColorBits,              /* Number of bits per color */
                Feed,                   /* Number of lines to skip */
                Duplex,                 /* Current duplex mode */
                Page;                   /* Current page number */
@@ -64,7 +66,7 @@ int           NumPlanes,              /* Number of color planes */
  */
 
 void   Setup(void);
-void   StartPage(cups_page_header_t *header);
+void   StartPage(ppd_file_t *ppd, cups_page_header_t *header);
 void   EndPage(void);
 void   Shutdown(void);
 
@@ -94,7 +96,8 @@ Setup(void)
  */
 
 void
-StartPage(cups_page_header_t *header)  /* I - Page header */
+StartPage(ppd_file_t         *ppd,     /* I - PPD file */
+          cups_page_header_t *header)  /* I - Page header */
 {
   int  plane;                          /* Looping var */
 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
@@ -123,7 +126,8 @@ StartPage(cups_page_header_t *header)       /* I - Page header */
   * Setup printer/job attributes...
   */
 
-  Duplex = header->Duplex;
+  Duplex    = header->Duplex;
+  ColorBits = header->cupsBitsPerColor;
 
   if (!Duplex || (Page & 1))
   {
@@ -132,6 +136,7 @@ StartPage(cups_page_header_t *header)       /* I - Page header */
     */
 
     printf("\033&l6D\033&k12H");               /* Set 6 LPI, 10 CPI */
+    printf("\033&l0O");                                /* Set portrait orientation */
 
     switch (header->PageSize[1])
     {
@@ -199,6 +204,9 @@ StartPage(cups_page_header_t *header)       /* I - Page header */
              header->Duplex + header->Tumble);
 
     printf("\033&l0L");                                /* Turn off perforation skip */
+
+    if (ppd && ppd->model_number == 2)
+      printf("\033&l-2H");                     /* Load media */
   }
   else
     printf("\033&a2G");                                /* Set back side */
@@ -208,23 +216,86 @@ StartPage(cups_page_header_t *header)     /* I - Page header */
   */
 
   printf("\033*t%dR", header->HWResolution[0]);        /* Set resolution */
-  printf("\033*r%dS", header->cupsWidth);      /* Set width */
-  printf("\033*r%dT", header->cupsHeight);     /* Set height */
 
-  if (header->cupsColorSpace == CUPS_CSPACE_KCMY)
+  if (ppd->model_number == 2)
   {
-    NumPlanes = 4;
-    printf("\033*r-4U");                       /* Set KCMY graphics */
+   /*
+    * Figure out the number of color planes...
+    */
+
+    if (header->cupsColorSpace == CUPS_CSPACE_KCMY)
+      NumPlanes = 4;
+    else
+      NumPlanes = 1;
+
+   /*
+    * Send 26-byte configure image data command with horizontal and
+    * vertical resolutions as well as a color count...
+    */
+
+    printf("\033*g26W");
+    putchar(2);                                        /* Format 2 */
+    putchar(NumPlanes);                                /* Output planes */
+
+    putchar(header->HWResolution[0] >> 8);     /* Black resolution */
+    putchar(header->HWResolution[0]);
+    putchar(header->HWResolution[1] >> 8);
+    putchar(header->HWResolution[1]);
+    putchar(0);
+    putchar(1 << ColorBits);                   /* # of black levels */
+
+    putchar(header->HWResolution[0] >> 8);     /* Cyan resolution */
+    putchar(header->HWResolution[0]);
+    putchar(header->HWResolution[1] >> 8);
+    putchar(header->HWResolution[1]);
+    putchar(0);
+    putchar(1 << ColorBits);                   /* # of cyan levels */
+
+    putchar(header->HWResolution[0] >> 8);     /* Magenta resolution */
+    putchar(header->HWResolution[0]);
+    putchar(header->HWResolution[1] >> 8);
+    putchar(header->HWResolution[1]);
+    putchar(0);
+    putchar(1 << ColorBits);                   /* # of magenta levels */
+
+    putchar(header->HWResolution[0] >> 8);     /* Yellow resolution */
+    putchar(header->HWResolution[0]);
+    putchar(header->HWResolution[1] >> 8);
+    putchar(header->HWResolution[1]);
+    putchar(0);
+    putchar(1 << ColorBits);                   /* # of yellow levels */
   }
-  else if (header->cupsColorSpace == CUPS_CSPACE_CMY)
+  else
   {
-    NumPlanes = 3;
-    printf("\033*r-3U");                       /* Set CMY graphics */
+    if (header->cupsColorSpace == CUPS_CSPACE_KCMY)
+    {
+      NumPlanes = 4;
+      printf("\033*r-4U");                     /* Set KCMY graphics */
+    }
+    else if (header->cupsColorSpace == CUPS_CSPACE_CMY)
+    {
+      NumPlanes = 3;
+      printf("\033*r-3U");                     /* Set CMY graphics */
+    }
+    else
+      NumPlanes = 1;                           /* Black&white graphics */
   }
+
+ /*
+  * Set size and position of graphics...
+  */
+
+  printf("\033*r%dS", header->cupsWidth);      /* Set width */
+  printf("\033*r%dT", header->cupsHeight);     /* Set height */
+
+  printf("\033&a0H");                          /* Set horizontal position */
+
+  if (ppd)
+    printf("\033&a%.0fV",                      /* Set vertical position */
+           10.0 * (ppd->sizes[0].length - ppd->sizes[0].top));
   else
-    NumPlanes = 1;                             /* Black&white graphics */
+    printf("\033&a0V");                                /* Set top-of-page */
 
-  printf("\033&a0H\033&a330V");                        /* Set top-of-page */
   printf("\033*r1A");                          /* Start graphics */
 
   if (header->cupsCompression)
@@ -241,6 +312,11 @@ StartPage(cups_page_header_t *header)      /* I - Page header */
   for (plane = 1; plane < NumPlanes; plane ++)
     Planes[plane] = Planes[0] + plane * header->cupsBytesPerLine / NumPlanes;
 
+  if (ColorBits > 1)
+    BitBuffer = malloc(ColorBits * ((header->cupsWidth + 7) / 8));
+  else
+    BitBuffer = NULL;
+
   if (header->cupsCompression)
     CompBuffer = malloc(header->cupsBytesPerLine * 2);
   else
@@ -267,7 +343,9 @@ EndPage(void)
   if (NumPlanes > 1)
   {
      printf("\033*rC");                        /* End color GFX */
-     printf("\033&l0H");               /* Eject current page */
+
+     if (!(Duplex && (Page & 1)))
+       printf("\033&l0H");             /* Eject current page */
   }
   else
   {
@@ -301,6 +379,9 @@ EndPage(void)
 
   free(Planes[0]);
 
+  if (BitBuffer)
+    free(BitBuffer);
+
   if (CompBuffer)
     free(CompBuffer);
 }
@@ -490,7 +571,14 @@ CompressData(unsigned char *line,  /* I - Data to compress */
 void
 OutputLine(cups_page_header_t *header) /* I - Page header */
 {
-  int  plane;  /* Current plane */
+  int          plane,                  /* Current plane */
+               bytes,                  /* Bytes to write */
+               count;                  /* Bytes to convert */
+  unsigned char        bit,                    /* Current plane data */
+               bit0,                   /* Current low bit data */
+               bit1,                   /* Current high bit data */
+               *plane_ptr,             /* Pointer into Planes */
+               *bit_ptr;               /* Pointer into BitBuffer */
 
 
  /*
@@ -507,10 +595,54 @@ OutputLine(cups_page_header_t *header)    /* I - Page header */
   * Write bitmap data as needed...
   */
 
+  bytes = (header->cupsWidth + 7) / 8;
+
   for (plane = 0; plane < NumPlanes; plane ++)
-    CompressData(Planes[plane], header->cupsBytesPerLine / NumPlanes,
-                plane < (NumPlanes - 1) ? 'V' : 'W',
-                header->cupsCompression);
+    if (ColorBits == 1)
+    {
+     /*
+      * Send bits as-is...
+      */
+
+      CompressData(Planes[plane], bytes, plane < (NumPlanes - 1) ? 'V' : 'W',
+                  header->cupsCompression);
+    }
+    else
+    {
+     /*
+      * Separate low and high bit data into separate buffers.
+      */
+
+      for (count = header->cupsBytesPerLine / NumPlanes,
+               plane_ptr = Planes[plane], bit_ptr = BitBuffer;
+          count > 0;
+          count -= 2, plane_ptr += 2, bit_ptr ++)
+      {
+        bit = plane_ptr[0];
+
+        bit0 = ((bit & 64) << 1) | ((bit & 16) << 2) | ((bit & 4) << 3) | ((bit & 1) << 4);
+        bit1 = (bit & 128) | ((bit & 32) << 1) | ((bit & 8) << 2) | ((bit & 2) << 3);
+
+        if (count > 1)
+       {
+         bit = plane_ptr[1];
+
+          bit0 |= (bit & 1) | ((bit & 4) >> 1) | ((bit & 16) >> 2) | ((bit & 64) >> 3);
+          bit1 |= ((bit & 2) >> 1) | ((bit & 8) >> 2) | ((bit & 32) >> 3) | ((bit & 128) >> 4);
+       }
+
+        bit_ptr[0]     = bit0;
+       bit_ptr[bytes] = bit1;
+      }
+
+     /*
+      * Send low and high bits...
+      */
+
+      CompressData(BitBuffer, bytes, 'V', header->cupsCompression);
+      CompressData(BitBuffer + bytes, bytes, plane < (NumPlanes - 1) ? 'V' : 'W',
+                  header->cupsCompression);
+    }
 
   fflush(stdout);
 }
@@ -528,6 +660,7 @@ main(int  argc,             /* I - Number of command-line arguments */
   cups_raster_t                *ras;   /* Raster stream for printing */
   cups_page_header_t   header; /* Page header from file */
   int                  y;      /* Current line */
+  ppd_file_t           *ppd;   /* PPD file */
 
 
  /*
@@ -573,6 +706,8 @@ main(int  argc,             /* I - Number of command-line arguments */
   * Initialize the print device...
   */
 
+  ppd = ppdOpenFile(getenv("PPD"));
+
   Setup();
 
  /*
@@ -595,7 +730,7 @@ main(int  argc,             /* I - Number of command-line arguments */
     * Start the page...
     */
 
-    StartPage(&header);
+    StartPage(ppd, &header);
 
    /*
     * Loop for each line on the page...
@@ -642,6 +777,9 @@ main(int  argc,             /* I - Number of command-line arguments */
 
   Shutdown();
 
+  if (ppd)
+    ppdClose(ppd);
+
  /*
   * Close the raster stream...
   */
@@ -657,12 +795,12 @@ main(int  argc,           /* I - Number of command-line arguments */
   if (Page == 0)
     fputs("ERROR: No pages found!\n", stderr);
   else
-    fputs("INFO: Ready to print.\n", stderr);
+    fputs("INFO: " CUPS_SVERSION " is ready to print.\n", stderr);
 
   return (Page == 0);
 }
 
 
 /*
- * End of "$Id: rastertohp.c,v 1.15 2001/03/02 14:30:15 mike Exp $".
+ * End of "$Id: rastertohp.c,v 1.15.2.1 2001/05/13 18:38:21 mike Exp $".
  */
index fb0dc83a9968b256fce1bb2cd6fb4087702aead4..0700d211b6da2a59a8a6588a0bbb6ea9003937a8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: textcommon.c,v 1.16 2001/01/24 17:18:59 mike Exp $"
+ * "$Id: textcommon.c,v 1.16.2.1 2001/05/13 18:38:21 mike Exp $"
  *
  *   Common text filter routines for the Common UNIX Printing System (CUPS).
  *
@@ -482,9 +482,9 @@ static int  getutf8(FILE *fp);
  */
 
 int                            /* O - Exit status */
-TextMain(char *name,           /* I - Name of filter */
-         int  argc,            /* I - Number of command-line arguments */
-         char *argv[])         /* I - Command-line arguments */
+TextMain(const char *name,     /* I - Name of filter */
+         int        argc,      /* I - Number of command-line arguments */
+         char       *argv[])   /* I - Command-line arguments */
 {
   FILE         *fp;            /* Print file */
   ppd_file_t   *ppd;           /* PPD file */
@@ -608,7 +608,8 @@ TextMain(char *name,                /* I - Name of filter */
 
   Copies = atoi(argv[4]);
 
-  WriteProlog(argv[3], argv[2], ppd);
+  WriteProlog(argv[3], argv[2], getenv("CLASSIFICATION"),
+              cupsGetOption("page-label", num_options, options), ppd);
 
  /*
   * Read text from the specified source and print it...
@@ -1141,5 +1142,5 @@ getutf8(FILE *fp) /* I - File to read from */
 
 
 /*
- * End of "$Id: textcommon.c,v 1.16 2001/01/24 17:18:59 mike Exp $".
+ * End of "$Id: textcommon.c,v 1.16.2.1 2001/05/13 18:38:21 mike Exp $".
  */
index 6f83042ebb5537b3856edd3d1e0e0a9c1223d4f1..52527cba8f1d3a640fae73afc545752a978fed44 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: textcommon.h,v 1.6 2001/01/22 15:03:42 mike Exp $"
+ * "$Id: textcommon.h,v 1.6.2.1 2001/05/13 18:38:21 mike Exp $"
  *
  *   Common text filter definitions for the Common UNIX Printing System (CUPS).
  *
@@ -89,12 +89,14 @@ extern char **Keywords;     /* List of known keywords... */
  * Required functions...
  */
 
-extern int     TextMain(char *name, int argc, char *argv[]);
+extern int     TextMain(const char *name, int argc, char *argv[]);
 extern void    WriteEpilogue(void);
 extern void    WritePage(void);
-extern void    WriteProlog(char *title, char *user, ppd_file_t *ppd);
+extern void    WriteProlog(const char *title, const char *user,
+                           const char *classification, const char *label,
+                           ppd_file_t *ppd);
 
 
 /*
- * End of "$Id: textcommon.h,v 1.6 2001/01/22 15:03:42 mike Exp $".
+ * End of "$Id: textcommon.h,v 1.6.2.1 2001/05/13 18:38:21 mike Exp $".
  */
index 1d4d3ca147b0c21181eff4f1ab729fbfe748990f..719470db75aae3110240aaa64cd3e12886d4ffa3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: texttops.c,v 1.34 2001/03/02 14:30:15 mike Exp $"
+ * "$Id: texttops.c,v 1.34.2.1 2001/05/13 18:38:21 mike Exp $"
  *
  *   Text to PostScript filter for the Common UNIX Printing System (CUPS).
  *
@@ -57,7 +57,7 @@ int           Directions[256];/* Text directions for each font */
 
 static void    write_line(int row, lchar_t *line);
 static void    write_string(int col, int row, int len, lchar_t *s);
-static void    write_text(char *s);
+static void    write_text(const char *s);
 
 
 /*
@@ -121,9 +121,11 @@ WritePage(void)
  */
 
 void
-WriteProlog(char       *title, /* I - Title of job */
-           char       *user,   /* I - Username */
-            ppd_file_t *ppd)   /* I - PPD file info */
+WriteProlog(const char *title,         /* I - Title of job */
+           const char *user,           /* I - Username */
+            const char *classification,        /* I - Classification */
+           const char *label,          /* I - Page label */
+            ppd_file_t *ppd)           /* I - PPD file info */
 {
   int          i, j, k;        /* Looping vars */
   char         *charset;       /* Character set string */
@@ -156,6 +158,20 @@ WriteProlog(char       *title,     /* I - Title of job */
   if ((datadir = getenv("CUPS_DATADIR")) == NULL)
     datadir = CUPS_DATADIR;
 
+ /*
+  * Adjust margins as necessary...
+  */
+
+  if (classification || label)
+  {
+   /*
+    * Leave room for labels...
+    */
+
+    PageBottom += 36;
+    PageTop    -= 36;
+  }
+
  /*
   * Allocate memory for the page...
   */
@@ -1202,10 +1218,10 @@ write_string(int     col,       /* I - Start column */
  */
 
 static void
-write_text(char *s)    /* I - String to write */
+write_text(const char *s)      /* I - String to write */
 {
-  int          ch;     /* Actual character value (UTF8) */
-  unsigned char        *utf8;  /* UTF8 text */
+  int                  ch;     /* Actual character value (UTF8) */
+  const unsigned char  *utf8;  /* UTF8 text */
 
 
   if (NumFonts > 1)
@@ -1216,7 +1232,7 @@ write_text(char *s)       /* I - String to write */
 
     putchar('<');
 
-    utf8 = (unsigned char *)s;
+    utf8 = (const unsigned char *)s;
 
     while (*utf8)
     {
@@ -1276,5 +1292,5 @@ write_text(char *s)       /* I - String to write */
 
 
 /*
- * End of "$Id: texttops.c,v 1.34 2001/03/02 14:30:15 mike Exp $".
+ * End of "$Id: texttops.c,v 1.34.2.1 2001/05/13 18:38:21 mike Exp $".
  */
index c6426602977dfdec3d9ed42cc49ece700884a77d..159f4bf36bb512bbcfb05d0e1316f30b813f80b7 100644 (file)
@@ -9,7 +9,7 @@
 #ifndef COMPACTFONTINFO_H
 #define COMPACTFONTINFO_H
 
-static char *type1CStdStrings[391] = {
+static const char *type1CStdStrings[391] = {
   ".notdef",
   "space",
   "exclam",
index c9f4feca6963f8fbdd0b664d7c9ba19493d648dd..9ec4815bd98cb3ad1e945f90f85f4fefe57951aa 100644 (file)
@@ -31,13 +31,13 @@ Dict::~Dict() {
   int i;
 
   for (i = 0; i < length; ++i) {
-    gfree(entries[i].key);
+    gfree((void *)entries[i].key);
     entries[i].val.free();
   }
   gfree(entries);
 }
 
-void Dict::add(char *key, Object *val) {
+void Dict::add(const char *key, Object *val) {
   if (length + 1 > size) {
     size += 8;
     entries = (DictEntry *)grealloc(entries, size * sizeof(DictEntry));
@@ -47,7 +47,7 @@ void Dict::add(char *key, Object *val) {
   ++length;
 }
 
-inline DictEntry *Dict::find(char *key) {
+inline DictEntry *Dict::find(const char *key) {
   int i;
 
   for (i = 0; i < length; ++i) {
@@ -57,25 +57,25 @@ inline DictEntry *Dict::find(char *key) {
   return NULL;
 }
 
-GBool Dict::is(char *type) {
+GBool Dict::is(const char *type) {
   DictEntry *e;
 
   return (e = find("Type")) && e->val.isName(type);
 }
 
-Object *Dict::lookup(char *key, Object *obj) {
+Object *Dict::lookup(const char *key, Object *obj) {
   DictEntry *e;
 
   return (e = find(key)) ? e->val.fetch(obj) : obj->initNull();
 }
 
-Object *Dict::lookupNF(char *key, Object *obj) {
+Object *Dict::lookupNF(const char *key, Object *obj) {
   DictEntry *e;
 
   return (e = find(key)) ? e->val.copy(obj) : obj->initNull();
 }
 
-char *Dict::getKey(int i) {
+const char *Dict::getKey(int i) {
   return entries[i].key;
 }
 
index cfc64d3b22bacd9dce14b8634ecf8f2b3ed33750..37f656587cbfc8d2c53aab90154c124cdbde1685 100644 (file)
@@ -20,7 +20,7 @@
 //------------------------------------------------------------------------
 
 struct DictEntry {
-  char *key;
+  const char *key;
   Object val;
 };
 
@@ -41,18 +41,18 @@ public:
   int getLength() { return length; }
 
   // Add an entry.  NB: does not copy key.
-  void add(char *key, Object *val);
+  void add(const char *key, Object *val);
 
   // Check if dictionary is of specified type.
-  GBool is(char *type);
+  GBool is(const char *type);
 
   // Look up an entry and return the value.  Returns a null object
   // if <key> is not in the dictionary.
-  Object *lookup(char *key, Object *obj);
-  Object *lookupNF(char *key, Object *obj);
+  Object *lookup(const char *key, Object *obj);
+  Object *lookupNF(const char *key, Object *obj);
 
   // Iterative accessors.
-  char *getKey(int i);
+  const char *getKey(int i);
   Object *getVal(int i, Object *obj);
   Object *getValNF(int i, Object *obj);
 
@@ -63,7 +63,7 @@ private:
   int length;                  // number of entries in dictionary
   int ref;                     // reference count
 
-  DictEntry *find(char *key);
+  DictEntry *find(const char *key);
 };
 
 #endif
index 4594516a6befac83b49cad7fdc67ddd705ffb6b8..96a96d2bf2fdbdeb4bafe72057b6b31692f6b712 100644 (file)
@@ -21,10 +21,14 @@ FILE *errFile;
 GBool errQuiet;
 
 void errorInit() {
-  errFile = stderr;
+  if (errQuiet) {
+    errFile = NULL;
+  } else {
+    errFile = stderr;
+  }
 }
 
-void CDECL error(int pos, char *msg, ...) {
+void CDECL error(int pos, const char *msg, ...) {
   va_list args;
 
   if (errQuiet) {
index f651678c85c44405b3e9c83c5e294591e10254f8..926abcd5a4e07d8fe93b53436b2c15be0d374e62 100644 (file)
@@ -21,6 +21,6 @@ extern FILE *errFile;
 
 extern void errorInit();
 
-extern void CDECL error(int pos, char *msg, ...);
+extern void CDECL error(int pos, const char *msg, ...);
 
 #endif
index ac852c4581fb8e3984b8709e075f45dc461b5385..f526445019628ec60b34af043e807b6771a61b18 100644 (file)
@@ -21,7 +21,7 @@
 // FontEncoding
 //------------------------------------------------------------------------
 
-inline int FontEncoding::hash(char *name) {
+inline int FontEncoding::hash(const char *name) {
   Guint h;
 
   h = (Guint)name[0] & 0xff;
@@ -33,7 +33,7 @@ inline int FontEncoding::hash(char *name) {
 FontEncoding::FontEncoding() {
   int i;
 
-  encoding = (char **)gmalloc(256 * sizeof(char *));
+  encoding = (const char **)gmalloc(256 * sizeof(const char *));
   size = 256;
   freeEnc = gTrue;
   for (i = 0; i < 256; ++i)
@@ -42,34 +42,34 @@ FontEncoding::FontEncoding() {
     hashTab[i] = -1;
 }
 
-FontEncoding::FontEncoding(char **encoding, int size) {
+FontEncoding::FontEncoding(const char **nencoding, int nsize) {
   int i;
 
-  this->encoding = encoding;
-  this->size = size;
+  encoding = nencoding;
+  size = nsize;
   freeEnc = gFalse;
   for (i = 0; i < fontEncHashSize; ++i)
     hashTab[i] = -1;
   for (i = 0; i < size; ++i) {
-    if (encoding[i])
-      addChar1(i, encoding[i]);
+    if (nencoding[i])
+      addChar1(i, nencoding[i]);
   }
 }
 
 FontEncoding::FontEncoding(FontEncoding *fontEnc) {
   int i;
 
-  encoding = (char **)gmalloc(fontEnc->size * sizeof(char *));
+  encoding = (const char **)gmalloc(fontEnc->size * sizeof(const char *));
   size = fontEnc->size;
   freeEnc = gTrue;
   for (i = 0; i < size; ++i) {
     encoding[i] =
-      fontEnc->encoding[i] ? copyString(fontEnc->encoding[i]) : NULL;
+      fontEnc->encoding[i] ? copyString(fontEnc->encoding[i]) : (char *)NULL;
   }
   memcpy(hashTab, fontEnc->hashTab, fontEncHashSize * sizeof(short));
 }
 
-void FontEncoding::addChar(int code, char *name) {
+void FontEncoding::addChar(int code, const char *name) {
   int h, i;
 
   // replace character associated with code
@@ -83,7 +83,7 @@ void FontEncoding::addChar(int code, char *name) {
       if (++h == fontEncHashSize)
        h = 0;
     }
-    gfree(encoding[code]);
+    gfree((void *)encoding[code]);
   }
 
   // associate name with code
@@ -93,7 +93,7 @@ void FontEncoding::addChar(int code, char *name) {
   addChar1(code, name);
 }
 
-void FontEncoding::addChar1(int code, char *name) {
+void FontEncoding::addChar1(int code, const char *name) {
   int h, i, code2;
 
   // insert name in hash table
@@ -121,13 +121,13 @@ FontEncoding::~FontEncoding() {
   if (freeEnc) {
     for (i = 0; i < size; ++i) {
       if (encoding[i])
-       gfree(encoding[i]);
+       gfree((void *)encoding[i]);
     }
-    gfree(encoding);
+    gfree((void *)encoding);
   }
 }
 
-int FontEncoding::getCharCode(char *name) {
+int FontEncoding::getCharCode(const char *name) {
   int h, i, code;
 
   h = hash(name);
index 7c811536a8c852ee8e5024ccf4661dfdf78fed74..120858b9bdcf5327c8539d5b90d8af231f0de912 100644 (file)
@@ -28,7 +28,7 @@ public:
   FontEncoding();
 
   // Construct an encoding from an array of char names.
-  FontEncoding(char **encoding, int size);
+  FontEncoding(const char **encoding, int size);
 
   // Destructor.
   ~FontEncoding();
@@ -40,21 +40,21 @@ public:
   int getSize() { return size; }
 
   // Add a char to the encoding.
-  void addChar(int code, char *name);
+  void addChar(int code, const char *name);
 
   // Return the character name associated with <code>.
-  char *getCharName(int code) { return encoding[code]; }
+  const char *getCharName(int code) { return encoding[code]; }
 
   // Return the code associated with <name>.
-  int getCharCode(char *name);
+  int getCharCode(const char *name);
 
 private:
 
   FontEncoding(FontEncoding *fontEnc);
-  int hash(char *name);
-  void addChar1(int code, char *name);
+  int hash(const char *name);
+  void addChar1(int code, const char *name);
 
-  char **encoding;             // code --> name mapping
+  const char **encoding;       // code --> name mapping
   int size;                    // number of codes
   GBool freeEnc;               // should we free the encoding array?
   short                                // name --> code hash table
index a0ab63af5d2da4240dc8a2203d960f82c21ed23f..5ec923a0dbfa3e8146558d9ad6cf10c5c6661da5 100644 (file)
@@ -32,7 +32,7 @@ static char *getString(int sid, Guchar *stringIdxPtr,
 
 //------------------------------------------------------------------------
 
-static inline char *nextLine(char *line, char *end) {
+static inline const char *nextLine(const char *line, const char *end) {
   while (line < end && *line != '\n' && *line != '\r')
     ++line;
   while (line < end && *line == '\n' || *line == '\r')
@@ -56,9 +56,11 @@ FontFile::~FontFile() {
 // Type1FontFile
 //------------------------------------------------------------------------
 
-Type1FontFile::Type1FontFile(char *file, int len) {
-  char *line, *line1, *p;
+Type1FontFile::Type1FontFile(const char *file, int len) {
+  const char *line, *line1;
+  char *p, *p2;
   char buf[256];
+  char c;
   int n, code, i;
 
   name = NULL;
@@ -87,19 +89,27 @@ Type1FontFile::Type1FontFile(char *file, int len) {
          n = 255;
        strncpy(buf, line, n);
        buf[n] = '\0';
-       p = strtok(buf, " \t");
-       if (p && !strcmp(p, "dup")) {
-         if ((p = strtok(NULL, " \t"))) {
+       for (p = buf; *p == ' ' || *p == '\t'; ++p) ;
+       if (!strncmp(p, "dup", 3)) {
+         for (p += 3; *p == ' ' || *p == '\t'; ++p) ;
+         for (p2 = p; *p2 >= '0' && *p2 <= '9'; ++p2) ;
+         if (*p2) {
+           c = *p2;
+           *p2 = '\0';
            if ((code = atoi(p)) < 256) {
-             if ((p = strtok(NULL, " \t"))) {
-               if (p[0] == '/') {
-                 encoding->addChar(code, copyString(p+1));
-               }
+             *p2 = c;
+             for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
+             if (*p == '/') {
+               ++p;
+               for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ;
+               *p2 = '\0';
+               encoding->addChar(code, copyString(p));
              }
            }
          }
        } else {
-         if ((p = strtok(NULL, " \t\n\r")) && !strcmp(p, "def")) {
+         if (strtok(buf, " \t") &&
+             (p = strtok(NULL, " \t\n\r")) && !strcmp(p, "def")) {
            break;
          }
        }
@@ -115,7 +125,7 @@ Type1FontFile::Type1FontFile(char *file, int len) {
 
 Type1FontFile::~Type1FontFile() {
   if (name)
-    gfree(name);
+    gfree((void *)name);
   if (encoding && freeEnc)
     delete encoding;
 }
@@ -130,11 +140,11 @@ FontEncoding *Type1FontFile::getEncoding(GBool taken) {
 // Type1CFontFile
 //------------------------------------------------------------------------
 
-Type1CFontFile::Type1CFontFile(char *file, int len) {
+Type1CFontFile::Type1CFontFile(const char *file, int len) {
   char buf[256];
   Guchar *topPtr, *idxStartPtr, *idxPtr0, *idxPtr1;
   Guchar *stringIdxPtr, *stringStartPtr;
-  int topOffSize, idxOffSize, stringOffSize;
+  int idxOffSize, stringOffSize;
   int nFonts, nStrings, nGlyphs;
   int nCodes, nRanges, nLeft, nSups;
   Gushort *glyphNames;
@@ -147,13 +157,14 @@ Type1CFontFile::Type1CFontFile(char *file, int len) {
   int key;
   int i, j, n;
 
+  (void)len;
+
   name = NULL;
   encoding = NULL;
   freeEnc = gTrue;
 
   // read header
   topPtr = (Guchar *)file + (file[2] & 0xff);
-  topOffSize = file[3] & 0xff;
 
   // read name index (first font only)
   nFonts = getWord(topPtr, 2);
@@ -164,7 +175,7 @@ Type1CFontFile::Type1CFontFile(char *file, int len) {
   idxPtr1 = idxStartPtr + getWord(topPtr + idxOffSize, idxOffSize);
   if ((n = idxPtr1 - idxPtr0) > 255)
     n = 255;
-  strncpy(buf, (char *)idxPtr0, n);
+  strncpy(buf, (const char *)idxPtr0, n);
   buf[n] = '\0';
   name = copyString(buf);
   topPtr = idxStartPtr + getWord(topPtr + nFonts * idxOffSize, idxOffSize);
@@ -307,7 +318,7 @@ Type1CFontFile::Type1CFontFile(char *file, int len) {
 
 Type1CFontFile::~Type1CFontFile() {
   if (name)
-    gfree(name);
+    gfree((void *)name);
   if (encoding && freeEnc)
     delete encoding;
 }
@@ -404,7 +415,7 @@ static char *getString(int sid, Guchar *stringIdxPtr,
                                       stringOffSize);
     if ((len = idxPtr1 - idxPtr0) > 255)
       len = 255;
-    strncpy(buf, (char *)idxPtr0, len);
+    strncpy(buf, (const char *)idxPtr0, len);
     buf[len] = '\0';
   }
   return buf;
@@ -414,10 +425,10 @@ static char *getString(int sid, Guchar *stringIdxPtr,
 // Type1CFontConverter
 //------------------------------------------------------------------------
 
-Type1CFontConverter::Type1CFontConverter(char *file, int len, FILE *out) {
-  this->file = file;
-  this->len = len;
-  this->out = out;
+Type1CFontConverter::Type1CFontConverter(const char *nfile, int nlen, FILE *nout) {
+  file = nfile;
+  len = nlen;
+  out = nout;
   r1 = 55665;
   line = 0;
 }
@@ -426,7 +437,7 @@ Type1CFontConverter::~Type1CFontConverter() {
 }
 
 void Type1CFontConverter::convert() {
-  char *fontName;
+  const char *fontName;
   struct {
     int version;
     int notice;
@@ -453,7 +464,7 @@ void Type1CFontConverter::convert() {
   char buf[256], eBuf[256];
   Guchar *topPtr, *idxStartPtr, *idxPtr0, *idxPtr1;
   Guchar *stringIdxPtr, *stringStartPtr;
-  int topOffSize, idxOffSize, stringOffSize;
+  int idxOffSize, stringOffSize;
   int nFonts, nStrings, nGlyphs;
   int nCodes, nRanges, nLeft, nSups;
   Gushort *glyphNames;
@@ -468,7 +479,6 @@ void Type1CFontConverter::convert() {
 
   // read header
   topPtr = (Guchar *)file + (file[2] & 0xff);
-  topOffSize = file[3] & 0xff;
 
   // read name (first font only)
   nFonts = getWord(topPtr, 2);
@@ -479,7 +489,7 @@ void Type1CFontConverter::convert() {
   idxPtr1 = idxStartPtr + getWord(topPtr + idxOffSize, idxOffSize);
   if ((n = idxPtr1 - idxPtr0) > 255)
     n = 255;
-  strncpy(buf, (char *)idxPtr0, n);
+  strncpy(buf, (const char *)idxPtr0, n);
   buf[n] = '\0';
   fontName = copyString(buf);
   topPtr = idxStartPtr + getWord(topPtr + nFonts * idxOffSize, idxOffSize);
@@ -577,15 +587,8 @@ void Type1CFontConverter::convert() {
   topPtr = stringStartPtr + getWord(topPtr + nStrings * stringOffSize,
                                    stringOffSize);
 
-#if 1 //~
-  // get global subrs
-  int nGSubrs;
-  int gSubrOffSize;
-
-  nGSubrs = getWord(topPtr, 2);
-  gSubrOffSize = topPtr[2];
+  // skip global subrs
   topPtr += 3;
-#endif
 
   // write header and font dictionary, up to encoding
   fprintf(out, "%%!FontType1-1.0: %s", fontName);
@@ -915,11 +918,11 @@ void Type1CFontConverter::convert() {
 
   // clean up
   if (dict.charset > 2)
-    gfree(glyphNames);
-  gfree(fontName);
+    gfree((void *)glyphNames);
+  gfree((void *)fontName);
 }
 
-void Type1CFontConverter::eexecWrite(char *s) {
+void Type1CFontConverter::eexecWrite(const char *s) {
   Guchar *p;
   Guchar x;
 
@@ -936,7 +939,7 @@ void Type1CFontConverter::eexecWrite(char *s) {
   }
 }
 
-void Type1CFontConverter::cvtGlyph(char *name, Guchar *s, int n) {
+void Type1CFontConverter::cvtGlyph(const char *name, Guchar *s, int n) {
   int nHints;
   int x;
   GBool first = gTrue;
@@ -1506,12 +1509,12 @@ void Type1CFontConverter::cvtGlyphWidth(GBool useOp) {
   eexecDumpOp1(13);
 }
 
-void Type1CFontConverter::eexecDumpNum(double x, GBool fp) {
+void Type1CFontConverter::eexecDumpNum(double x, GBool nfp) {
   Guchar buf[12];
   int y, n;
 
   n = 0;
-  if (fp) {
+  if (nfp) {
     if (x >= -32768 && x < 32768) {
       y = (int)(x * 256.0);
       buf[0] = 255;
@@ -1554,16 +1557,16 @@ void Type1CFontConverter::eexecDumpNum(double x, GBool fp) {
       n = 5;
     }
   }
-  charBuf->append((char *)buf, n);
+  charBuf->append((const char *)buf, n);
 }
 
-void Type1CFontConverter::eexecDumpOp1(int op) {
-  charBuf->append((char)op);
+void Type1CFontConverter::eexecDumpOp1(int nop) {
+  charBuf->append((char)nop);
 }
 
-void Type1CFontConverter::eexecDumpOp2(int op) {
+void Type1CFontConverter::eexecDumpOp2(int nop) {
   charBuf->append((char)12);
-  charBuf->append((char)op);
+  charBuf->append((char)nop);
 }
 
 void Type1CFontConverter::eexecWriteCharstring(Guchar *s, int n) {
@@ -1592,7 +1595,7 @@ void Type1CFontConverter::eexecWriteCharstring(Guchar *s, int n) {
   }
 }
 
-void Type1CFontConverter::getDeltaInt(char *buf, char *name, double *op,
+void Type1CFontConverter::getDeltaInt(char *buf, const char *name, double *nop,
                                      int n) {
   int x, i;
 
@@ -1600,14 +1603,14 @@ void Type1CFontConverter::getDeltaInt(char *buf, char *name, double *op,
   buf += strlen(buf);
   x = 0;
   for (i = 0; i < n; ++i) {
-    x += (int)op[i];
+    x += (int)nop[i];
     sprintf(buf, "%s%d", i > 0 ? " " : "", x);
     buf += strlen(buf);
   }
   sprintf(buf, "] def\n");
 }
 
-void Type1CFontConverter::getDeltaReal(char *buf, char *name, double *op,
+void Type1CFontConverter::getDeltaReal(char *buf, const char *name, double *nop,
                                       int n) {
   double x;
   int i;
@@ -1616,7 +1619,7 @@ void Type1CFontConverter::getDeltaReal(char *buf, char *name, double *op,
   buf += strlen(buf);
   x = 0;
   for (i = 0; i < n; ++i) {
-    x += op[i];
+    x += nop[i];
     sprintf(buf, "%s%g", i > 0 ? " " : "", x);
     buf += strlen(buf);
   }
index ec625ef28bd75a3e4222b7d0a300f103e92494a7..59382a962a47087dd86a66911b13e295abe0a688 100644 (file)
@@ -30,7 +30,7 @@ public:
 
   // Returns the font name, as specified internally by the font file.
   // Returns NULL if no name is available.
-  virtual char *getName() = 0;
+  virtual const char *getName() = 0;
 
   // Returns the custom font encoding, or NULL if the encoding is
   // not available.  If <taken> is set, the caller of this function
@@ -45,14 +45,14 @@ public:
 class Type1FontFile: public FontFile {
 public:
 
-  Type1FontFile(char *file, int len);
+  Type1FontFile(const char *file, int len);
   virtual ~Type1FontFile();
-  virtual char *getName() { return name; }
+  virtual const char *getName() { return name; }
   virtual FontEncoding *getEncoding(GBool taken);
 
 private:
 
-  char *name;
+  const char *name;
   FontEncoding *encoding;
   GBool freeEnc;
 };
@@ -64,14 +64,14 @@ private:
 class Type1CFontFile: public FontFile {
 public:
 
-  Type1CFontFile(char *file, int len);
+  Type1CFontFile(const char *file, int len);
   virtual ~Type1CFontFile();
-  virtual char *getName() { return name; }
+  virtual const char *getName() { return name; }
   virtual FontEncoding *getEncoding(GBool taken);
 
 private:
 
-  char *name;
+  const char *name;
   FontEncoding *encoding;
   GBool freeEnc;
 };
@@ -83,23 +83,23 @@ private:
 class Type1CFontConverter {
 public:
 
-  Type1CFontConverter(char *file, int len, FILE *out);
+  Type1CFontConverter(const char *file, int len, FILE *out);
   ~Type1CFontConverter();
   void convert();
 
 private:
 
-  void eexecWrite(char *s);
-  void cvtGlyph(char *name, Guchar *s, int n);
+  void eexecWrite(const char *s);
+  void cvtGlyph(const char *name, Guchar *s, int n);
   void cvtGlyphWidth(GBool useOp);
   void eexecDumpNum(double x, GBool fp);
   void eexecDumpOp1(int op);
   void eexecDumpOp2(int op);
   void eexecWriteCharstring(Guchar *s, int n);
-  void getDeltaInt(char *buf, char *name, double *op, int n);
-  void getDeltaReal(char *buf, char *name, double *op, int n);
+  void getDeltaInt(char *buf, const char *name, double *op, int n);
+  void getDeltaReal(char *buf, const char *name, double *op, int n);
 
-  char *file;
+  const char *file;
   int len;
   FILE *out;
   double op[48];               // operands
index ee85b95b4997349b37dabe6f684dbf75051c0a20..9b20f0faa33cf14ed7e5c9cc66fad1b12bac9c9f 100644 (file)
@@ -16,7 +16,7 @@
 //------------------------------------------------------------------------
 
 #define standardEncodingSize 335
-static char *standardEncodingNames[standardEncodingSize] = {
+static const char *standardEncodingNames[standardEncodingSize] = {
   NULL,
   NULL,
   NULL,
@@ -357,7 +357,7 @@ static FontEncoding standardEncoding(standardEncodingNames,
                                      standardEncodingSize);
 
 #define symbolEncodingSize 257
-static char *symbolEncodingNames[symbolEncodingSize] = {
+static const char *symbolEncodingNames[symbolEncodingSize] = {
   NULL,
   NULL,
   NULL,
@@ -620,7 +620,7 @@ static FontEncoding symbolEncoding(symbolEncodingNames,
                                    symbolEncodingSize);
 
 #define zapfDingbatsEncodingSize 270
-static char *zapfDingbatsEncodingNames[zapfDingbatsEncodingSize] = {
+static const char *zapfDingbatsEncodingNames[zapfDingbatsEncodingSize] = {
   NULL,
   NULL,
   NULL,
@@ -896,7 +896,7 @@ static FontEncoding zapfDingbatsEncoding(zapfDingbatsEncodingNames,
                                          zapfDingbatsEncodingSize);
 
 #define macRomanEncodingSize 256
-static char *macRomanEncodingNames[macRomanEncodingSize] = {
+static const char *macRomanEncodingNames[macRomanEncodingSize] = {
   NULL,
   NULL,
   NULL,
@@ -1158,7 +1158,7 @@ static FontEncoding macRomanEncoding(macRomanEncodingNames,
                                      macRomanEncodingSize);
 
 #define winAnsiEncodingSize 256
-static char *winAnsiEncodingNames[winAnsiEncodingSize] = {
+static const char *winAnsiEncodingNames[winAnsiEncodingSize] = {
   NULL,
   NULL,
   NULL,
@@ -2041,7 +2041,7 @@ static Gushort zapfDingbatsWidths[270] = {
 //------------------------------------------------------------------------
 
 struct BuiltinFont {
-  char *name;
+  const char *name;
   Gushort *widths;
   FontEncoding *encoding;
 };
index f9ec94fa25e760f7500198ea85fb4be9ee2e0618..76428d05e6da8e325c1cea32124d0215cae76df0 100644 (file)
@@ -21,6 +21,7 @@
 
 FormWidget::FormWidget(Dict *dict) {
   Object obj1, obj2;
+  double t;
 
   ok = gFalse;
 
@@ -52,6 +53,16 @@ FormWidget::FormWidget(Dict *dict) {
     obj1.arrayGet(3, &obj2);
     yMax = obj2.getNum();
     obj2.free();
+    if (xMin > xMax) {
+      t = xMin; xMin = xMax; xMax = t;
+    }
+    if (yMin > yMax) {
+      t = yMin; yMin = yMax; yMax = t;
+    }
+  } else {
+    //~ this should return an error
+    xMin = yMin = 0;
+    xMax = yMax = 1;
   }
   obj1.free();
 }
@@ -64,7 +75,7 @@ void FormWidget::draw(Gfx *gfx) {
   Object obj;
 
   if (appearance.fetch(&obj)->isStream()) {
-    gfx->doWidgetForm(&obj, xMin, yMin);
+    gfx->doWidgetForm(&obj, xMin, yMin, xMax, yMax);
   }
   obj.free();
 }
@@ -86,7 +97,9 @@ FormWidgets::FormWidgets(Object *annots) {
   if (annots->isArray()) {
     for (i = 0; i < annots->arrayGetLength(); ++i) {
       if (annots->arrayGet(i, &obj1)->isDict()) {
-       if (obj1.dictLookup("Subtype", &obj2)->isName("Widget")) {
+       obj1.dictLookup("Subtype", &obj2);
+       if (obj2.isName("Widget") ||
+           obj2.isName("Stamp")) {
          widget = new FormWidget(obj1.getDict());
          if (widget->isOk()) {
            if (nWidgets >= size) {
index 9ec60bbc71ab0a02f8869139ec578ab5153cdbad..fb323930da9fad9acdad864f98e14b42302fd3eb 100644 (file)
@@ -13,6 +13,7 @@
 #include <stdio.h>
 #include <stddef.h>
 #include <string.h>
+#include <math.h>
 #include "gmem.h"
 #include "Object.h"
 #include "Array.h"
@@ -193,38 +194,157 @@ Operator Gfx::opTab[] = {
 GBool printCommands = gFalse;
 
 //------------------------------------------------------------------------
-// Gfx
+// GfxResources
 //------------------------------------------------------------------------
 
-Gfx::Gfx(OutputDev *out1, int pageNum, Dict *resDict,
-        int dpi, double x1, double y1, double x2, double y2, GBool crop,
-        double cropX1, double cropY1, double cropX2, double cropY2,
-        int rotate) {
+GfxResources::GfxResources(Dict *resDict, GfxResources *next) {
   Object obj1;
 
-  // start the resource stack
-  res = new GfxResources(NULL);
-
-  // build font dictionary
-  res->fonts = NULL;
   if (resDict) {
+
+    // build font dictionary
+    fonts = NULL;
     resDict->lookup("Font", &obj1);
-    if (obj1.isDict())
-      res->fonts = new GfxFontDict(obj1.getDict());
+    if (obj1.isDict()) {
+      fonts = new GfxFontDict(obj1.getDict());
+    }
     obj1.free();
+
+    // get XObject dictionary
+    resDict->lookup("XObject", &xObjDict);
+
+    // get color space dictionary
+    resDict->lookup("ColorSpace", &colorSpaceDict);
+
+    // get pattern dictionary
+    resDict->lookup("Pattern", &patternDict);
+
+    // get graphics state parameter dictionary
+    resDict->lookup("ExtGState", &gStateDict);
+
+  } else {
+    fonts = NULL;
+    xObjDict.initNull();
+    colorSpaceDict.initNull();
+    patternDict.initNull();
+    gStateDict.initNull();
+  }
+
+  this->next = next;
+}
+
+GfxResources::~GfxResources() {
+  if (fonts) {
+    delete fonts;
+  }
+  xObjDict.free();
+  colorSpaceDict.free();
+  patternDict.free();
+  gStateDict.free();
+}
+
+GfxFont *GfxResources::lookupFont(const char *name) {
+  GfxFont *font;
+  GfxResources *resPtr;
+
+  for (resPtr = this; resPtr; resPtr = resPtr->next) {
+    if (resPtr->fonts) {
+      if ((font = resPtr->fonts->lookup(name)))
+       return font;
+    }
+  }
+  error(-1, "Unknown font tag '%s'", name);
+  return NULL;
+}
+
+GBool GfxResources::lookupXObject(const char *name, Object *obj) {
+  GfxResources *resPtr;
+
+  for (resPtr = this; resPtr; resPtr = resPtr->next) {
+    if (resPtr->xObjDict.isDict()) {
+      if (!resPtr->xObjDict.dictLookup(name, obj)->isNull())
+       return gTrue;
+      obj->free();
+    }
   }
+  error(-1, "XObject '%s' is unknown", name);
+  return gFalse;
+}
+
+GBool GfxResources::lookupXObjectNF(const char *name, Object *obj) {
+  GfxResources *resPtr;
+
+  for (resPtr = this; resPtr; resPtr = resPtr->next) {
+    if (resPtr->xObjDict.isDict()) {
+      if (!resPtr->xObjDict.dictLookupNF(name, obj)->isNull())
+       return gTrue;
+      obj->free();
+    }
+  }
+  error(-1, "XObject '%s' is unknown", name);
+  return gFalse;
+}
+
+void GfxResources::lookupColorSpace(const char *name, Object *obj) {
+  GfxResources *resPtr;
+
+  for (resPtr = this; resPtr; resPtr = resPtr->next) {
+    if (resPtr->colorSpaceDict.isDict()) {
+      if (!resPtr->colorSpaceDict.dictLookup(name, obj)->isNull()) {
+       return;
+      }
+      obj->free();
+    }
+  }
+  obj->initNull();
+}
+
+GfxPattern *GfxResources::lookupPattern(const char *name) {
+  GfxResources *resPtr;
+  GfxPattern *pattern;
+  Object obj;
+
+  for (resPtr = this; resPtr; resPtr = resPtr->next) {
+    if (resPtr->patternDict.isDict()) {
+      if (!resPtr->patternDict.dictLookup(name, &obj)->isNull()) {
+       pattern = GfxPattern::parse(&obj);
+       obj.free();
+       return pattern;
+      }
+      obj.free();
+    }
+  }
+  error(-1, "Unknown pattern '%s'", name);
+  return NULL;
+}
+
+GBool GfxResources::lookupGState(const char *name, Object *obj) {
+  GfxResources *resPtr;
+
+  for (resPtr = this; resPtr; resPtr = resPtr->next) {
+    if (resPtr->gStateDict.isDict()) {
+      if (!resPtr->gStateDict.dictLookup(name, obj)->isNull()) {
+       return gTrue;
+      }
+      obj->free();
+    }
+  }
+  error(-1, "ExtGState '%s' is unknown", name);
+  return gFalse;
+}
+
+//------------------------------------------------------------------------
+// Gfx
+//------------------------------------------------------------------------
 
-  // get XObject dictionary
-  if (resDict)
-    resDict->lookup("XObject", &res->xObjDict);
-  else
-    res->xObjDict.initNull();
+Gfx::Gfx(OutputDev *out1, int pageNum, Dict *resDict,
+        double dpi, double x1, double y1, double x2, double y2, GBool crop,
+        double cropX1, double cropY1, double cropX2, double cropY2,
+        int rotate) {
+  int i;
 
-  // get colorspace dictionary
-  if (resDict)
-    resDict->lookup("ColorSpace", &res->colorSpaceDict);
-  else
-    res->colorSpaceDict.initNull();
+  // start the resource stack
+  res = new GfxResources(resDict, NULL);
 
   // initialize
   out = out1;
@@ -235,6 +355,9 @@ Gfx::Gfx(OutputDev *out1, int pageNum, Dict *resDict,
   out->startPage(pageNum, state);
   out->setDefaultCTM(state->getCTM());
   out->updateAll(state);
+  for (i = 0; i < 6; ++i) {
+    baseMatrix[i] = state->getCTM()[i];
+  }
 
   // set crop box
   if (crop) {
@@ -257,7 +380,7 @@ Gfx::~Gfx() {
   }
   out->endPage();
   while (res) {
-    resPtr = res->next;
+    resPtr = res->getNext();
     delete res;
     res = resPtr;
   }
@@ -265,14 +388,7 @@ Gfx::~Gfx() {
     delete state;
 }
 
-GfxResources::~GfxResources() {
-  if (fonts)
-    delete fonts;
-  xObjDict.free();
-  colorSpaceDict.free();
-}
-
-void Gfx::display(Object *obj) {
+void Gfx::display(Object *obj, GBool topLevel) {
   Object obj2;
   int i;
 
@@ -291,12 +407,12 @@ void Gfx::display(Object *obj) {
     return;
   }
   parser = new Parser(new Lexer(obj));
-  go();
+  go(topLevel);
   delete parser;
   parser = NULL;
 }
 
-void Gfx::go() {
+void Gfx::go(GBool topLevel) {
   Object obj;
   Object args[maxArgs];
   int numCmds, numArgs;
@@ -366,17 +482,19 @@ void Gfx::go() {
   }
 
   // update display
-  if (numCmds > 0)
+  if (topLevel && numCmds > 0) {
     out->dump();
+  }
 
   // clean up
-  if (printCommands)
+  if (printCommands) {
     fflush(stdout);
+  }
 }
 
 void Gfx::execOp(Object *cmd, Object args[], int numArgs) {
   Operator *op;
-  char *name;
+  const char *name;
   int i;
 
   // find operator
@@ -413,7 +531,7 @@ void Gfx::execOp(Object *cmd, Object args[], int numArgs) {
   (this->*op->func)(args, numArgs);
 }
 
-Operator *Gfx::findOp(char *name) {
+Operator *Gfx::findOp(const char *name) {
   int a, b, m, cmp;
 
   a = -1;
@@ -453,57 +571,22 @@ int Gfx::getPos() {
   return parser ? parser->getPos() : -1;
 }
 
-GfxFont *Gfx::lookupFont(char *name) {
-  GfxFont *font;
-  GfxResources *resPtr;
-
-  for (resPtr = res; resPtr; resPtr = resPtr->next) {
-    if (resPtr->fonts) {
-      if ((font = resPtr->fonts->lookup(name)))
-       return font;
-    }
-  }
-  error(getPos(), "unknown font tag '%s'", name);
-  return NULL;
-}
-
-GBool Gfx::lookupXObject(char *name, Object *obj) {
-  GfxResources *resPtr;
-
-  for (resPtr = res; resPtr; resPtr = resPtr->next) {
-    if (resPtr->xObjDict.isDict()) {
-      if (!resPtr->xObjDict.dictLookup(name, obj)->isNull())
-       return gTrue;
-      obj->free();
-    }
-  }
-  error(getPos(), "XObject '%s' is unknown", name);
-  return gFalse;
-}
-
-void Gfx::lookupColorSpace(char *name, Object *obj) {
-  GfxResources *resPtr;
-
-  for (resPtr = res; resPtr; resPtr = resPtr->next) {
-    if (resPtr->colorSpaceDict.isDict()) {
-      if (!resPtr->colorSpaceDict.dictLookup(name, obj)->isNull())
-       return;
-      obj->free();
-    }
-  }
-  obj->initNull();
-}
-
 //------------------------------------------------------------------------
 // graphics state operators
 //------------------------------------------------------------------------
 
 void Gfx::opSave(Object args[], int numArgs) {
+  (void)args;
+  (void)numArgs;
+
   out->saveState(state);
   state = state->save();
 }
 
 void Gfx::opRestore(Object args[], int numArgs) {
+  (void)args;
+  (void)numArgs;
+
   state = state->restore();
   out->restoreState(state);
 
@@ -515,6 +598,8 @@ void Gfx::opRestore(Object args[], int numArgs) {
 }
 
 void Gfx::opConcat(Object args[], int numArgs) {
+  (void)numArgs;
+
   state->concatCTM(args[0].getNum(), args[1].getNum(),
                   args[2].getNum(), args[3].getNum(),
                   args[4].getNum(), args[5].getNum());
@@ -531,6 +616,8 @@ void Gfx::opSetDash(Object args[], int numArgs) {
   double *dash;
   int i;
 
+  (void)numArgs;
+
   a = args[0].getArray();
   length = a->getLength();
   if (length == 0) {
@@ -572,6 +659,27 @@ void Gfx::opSetLineWidth(Object args[], int numArgs) {
 }
 
 void Gfx::opSetExtGState(Object args[], int numArgs) {
+  Object obj1, obj2;
+
+  if (!res->lookupGState(args[0].getName(), &obj1)) {
+    return;
+  }
+  if (!obj1.isDict()) {
+    error(getPos(), "ExtGState '%s' is wrong type", args[0].getName());
+    obj1.free();
+    return;
+  }
+  if (obj1.dictLookup("ca", &obj2)->isNum()) {
+    state->setFillOpacity(obj2.getNum());
+    out->updateFillOpacity(state);
+  }
+  obj2.free();
+  if (obj1.dictLookup("CA", &obj2)->isNum()) {
+    state->setStrokeOpacity(obj2.getNum());
+    out->updateStrokeOpacity(state);
+  }
+  obj2.free();
+  obj1.free();
 }
 
 void Gfx::opSetRenderingIntent(Object args[], int numArgs) {
@@ -582,137 +690,215 @@ void Gfx::opSetRenderingIntent(Object args[], int numArgs) {
 //------------------------------------------------------------------------
 
 void Gfx::opSetFillGray(Object args[], int numArgs) {
-  state->setFillColorSpace(new GfxColorSpace(colorGray));
-  state->setFillGray(args[0].getNum());
+  GfxColor color;
+
+  state->setFillPattern(NULL);
+  state->setFillColorSpace(new GfxDeviceGrayColorSpace());
+  color.c[0] = args[0].getNum();
+  state->setFillColor(&color);
   out->updateFillColor(state);
 }
 
 void Gfx::opSetStrokeGray(Object args[], int numArgs) {
-  state->setStrokeColorSpace(new GfxColorSpace(colorGray));
-  state->setStrokeGray(args[0].getNum());
+  GfxColor color;
+
+  state->setStrokePattern(NULL);
+  state->setStrokeColorSpace(new GfxDeviceGrayColorSpace());
+  color.c[0] = args[0].getNum();
+  state->setStrokeColor(&color);
   out->updateStrokeColor(state);
 }
 
 void Gfx::opSetFillCMYKColor(Object args[], int numArgs) {
-  state->setFillColorSpace(new GfxColorSpace(colorCMYK));
-  state->setFillCMYK(args[0].getNum(), args[1].getNum(),
-                    args[2].getNum(), args[3].getNum());
+  GfxColor color;
+  int i;
+
+  state->setFillPattern(NULL);
+  state->setFillColorSpace(new GfxDeviceCMYKColorSpace());
+  for (i = 0; i < 4; ++i) {
+    color.c[i] = args[i].getNum();
+  }
+  state->setFillColor(&color);
   out->updateFillColor(state);
 }
 
 void Gfx::opSetStrokeCMYKColor(Object args[], int numArgs) {
-  state->setStrokeColorSpace(new GfxColorSpace(colorCMYK));
-  state->setStrokeCMYK(args[0].getNum(), args[1].getNum(),
-                      args[2].getNum(), args[3].getNum());
+  GfxColor color;
+  int i;
+
+  state->setStrokePattern(NULL);
+  state->setStrokeColorSpace(new GfxDeviceCMYKColorSpace());
+  for (i = 0; i < 4; ++i) {
+    color.c[i] = args[i].getNum();
+  }
+  state->setStrokeColor(&color);
   out->updateStrokeColor(state);
 }
 
 void Gfx::opSetFillRGBColor(Object args[], int numArgs) {
-  state->setFillColorSpace(new GfxColorSpace(colorRGB));
-  state->setFillRGB(args[0].getNum(), args[1].getNum(), args[2].getNum());
+  GfxColor color;
+  int i;
+
+  state->setFillPattern(NULL);
+  state->setFillColorSpace(new GfxDeviceRGBColorSpace());
+  for (i = 0; i < 3; ++i) {
+    color.c[i] = args[i].getNum();
+  }
+  state->setFillColor(&color);
   out->updateFillColor(state);
 }
 
 void Gfx::opSetStrokeRGBColor(Object args[], int numArgs) {
-  state->setStrokeColorSpace(new GfxColorSpace(colorRGB));
-  state->setStrokeRGB(args[0].getNum(), args[1].getNum(), args[2].getNum());
+  GfxColor color;
+  int i;
+
+  state->setStrokePattern(NULL);
+  state->setStrokeColorSpace(new GfxDeviceRGBColorSpace());
+  for (i = 0; i < 3; ++i) {
+    color.c[i] = args[i].getNum();
+  }
+  state->setStrokeColor(&color);
   out->updateStrokeColor(state);
 }
 
 void Gfx::opSetFillColorSpace(Object args[], int numArgs) {
   Object obj;
   GfxColorSpace *colorSpace;
-  double x[4];
+  GfxColor color;
+  int i;
 
-  lookupColorSpace(args[0].getName(), &obj);
-  if (obj.isNull())
-    colorSpace = new GfxColorSpace(&args[0]);
-  else
-    colorSpace = new GfxColorSpace(&obj);
+  state->setFillPattern(NULL);
+  res->lookupColorSpace(args[0].getName(), &obj);
+  if (obj.isNull()) {
+    colorSpace = GfxColorSpace::parse(&args[0]);
+  } else {
+    colorSpace = GfxColorSpace::parse(&obj);
+  }
   obj.free();
-  if (colorSpace->isOk()) {
+  if (colorSpace) {
     state->setFillColorSpace(colorSpace);
   } else {
-    delete colorSpace;
-    error(getPos(), "Bad colorspace");
+    error(getPos(), "Bad color space");
+  }
+  for (i = 0; i < gfxColorMaxComps; ++i) {
+    color.c[i] = 0;
   }
-  x[0] = x[1] = x[2] = x[3] = 0;
-  state->setFillColor(x);
+  state->setFillColor(&color);
   out->updateFillColor(state);
 }
 
 void Gfx::opSetStrokeColorSpace(Object args[], int numArgs) {
   Object obj;
   GfxColorSpace *colorSpace;
-  double x[4];
+  GfxColor color;
+  int i;
 
-  lookupColorSpace(args[0].getName(), &obj);
-  if (obj.isNull())
-    colorSpace = new GfxColorSpace(&args[0]);
-  else
-    colorSpace = new GfxColorSpace(&obj);
+  state->setStrokePattern(NULL);
+  res->lookupColorSpace(args[0].getName(), &obj);
+  if (obj.isNull()) {
+    colorSpace = GfxColorSpace::parse(&args[0]);
+  } else {
+    colorSpace = GfxColorSpace::parse(&obj);
+  }
   obj.free();
-  if (colorSpace->isOk()) {
+  if (colorSpace) {
     state->setStrokeColorSpace(colorSpace);
   } else {
-    delete colorSpace;
-    error(getPos(), "Bad colorspace");
+    error(getPos(), "Bad color space");
   }
-  x[0] = x[1] = x[2] = x[3] = 0;
-  state->setStrokeColor(x);
+  for (i = 0; i < gfxColorMaxComps; ++i) {
+    color.c[i] = 0;
+  }
+  state->setStrokeColor(&color);
   out->updateStrokeColor(state);
 }
 
 void Gfx::opSetFillColor(Object args[], int numArgs) {
-  double x[4];
+  GfxColor color;
   int i;
 
-  x[0] = x[1] = x[2] = x[3] = 0;
-  for (i = 0; i < numArgs; ++i)
-    x[i] = args[i].getNum();
-  state->setFillColor(x);
+  state->setFillPattern(NULL);
+  for (i = 0; i < numArgs; ++i) {
+    color.c[i] = args[i].getNum();
+  }
+  state->setFillColor(&color);
   out->updateFillColor(state);
 }
 
 void Gfx::opSetStrokeColor(Object args[], int numArgs) {
-  double x[4];
+  GfxColor color;
   int i;
 
-  x[0] = x[1] = x[2] = x[3] = 0;
-  for (i = 0; i < numArgs; ++i)
-    x[i] = args[i].getNum();
-  state->setStrokeColor(x);
+  state->setStrokePattern(NULL);
+  for (i = 0; i < numArgs; ++i) {
+    color.c[i] = args[i].getNum();
+  }
+  state->setStrokeColor(&color);
   out->updateStrokeColor(state);
 }
 
 void Gfx::opSetFillColorN(Object args[], int numArgs) {
-  double x[4];
+  GfxColor color;
+  GfxPattern *pattern;
   int i;
 
-  x[0] = x[1] = x[2] = x[3] = 0;
-  for (i = 0; i < numArgs && i < 4; ++i) {
-    if (args[i].isNum())
-      x[i] = args[i].getNum();
-    else
-      break;
+  if (state->getFillColorSpace()->getMode() == csPattern) {
+    if (numArgs > 1) {
+      for (i = 0; i < numArgs && i < 4; ++i) {
+       if (args[i].isNum()) {
+         color.c[i] = args[i].getNum();
+       }
+      }
+      state->setFillColor(&color);
+      out->updateFillColor(state);
+    }
+    if (args[numArgs-1].isName() &&
+       (pattern = res->lookupPattern(args[numArgs-1].getName()))) {
+      state->setFillPattern(pattern);
+    }
+
+  } else {
+    state->setFillPattern(NULL);
+    for (i = 0; i < numArgs && i < 4; ++i) {
+      if (args[i].isNum()) {
+       color.c[i] = args[i].getNum();
+      }
+    }
+    state->setFillColor(&color);
+    out->updateFillColor(state);
   }
-  state->setFillColor(x);
-  out->updateFillColor(state);
 }
 
 void Gfx::opSetStrokeColorN(Object args[], int numArgs) {
-  double x[4];
+  GfxColor color;
+  GfxPattern *pattern;
   int i;
 
-  x[0] = x[1] = x[2] = x[3] = 0;
-  for (i = 0; i < numArgs && i < 4; ++i) {
-    if (args[i].isNum())
-      x[i] = args[i].getNum();
-    else
-      break;
+  if (state->getStrokeColorSpace()->getMode() == csPattern) {
+    if (numArgs > 1) {
+      for (i = 0; i < numArgs && i < 4; ++i) {
+       if (args[i].isNum()) {
+         color.c[i] = args[i].getNum();
+       }
+      }
+      state->setStrokeColor(&color);
+      out->updateStrokeColor(state);
+    }
+    if (args[numArgs-1].isName() &&
+       (pattern = res->lookupPattern(args[numArgs-1].getName()))) {
+      state->setStrokePattern(pattern);
+    }
+
+  } else {
+    state->setStrokePattern(NULL);
+    for (i = 0; i < numArgs && i < 4; ++i) {
+      if (args[i].isNum()) {
+       color.c[i] = args[i].getNum();
+      }
+    }
+    state->setStrokeColor(&color);
+    out->updateStrokeColor(state);
   }
-  state->setStrokeColor(x);
-  out->updateStrokeColor(state);
 }
 
 //------------------------------------------------------------------------
@@ -720,10 +906,14 @@ void Gfx::opSetStrokeColorN(Object args[], int numArgs) {
 //------------------------------------------------------------------------
 
 void Gfx::opMoveTo(Object args[], int numArgs) {
+  (void)numArgs;
+
   state->moveTo(args[0].getNum(), args[1].getNum());
 }
 
 void Gfx::opLineTo(Object args[], int numArgs) {
+  (void)numArgs;
+
   if (!state->isCurPt()) {
     error(getPos(), "No current point in lineto");
     return;
@@ -734,6 +924,8 @@ void Gfx::opLineTo(Object args[], int numArgs) {
 void Gfx::opCurveTo(Object args[], int numArgs) {
   double x1, y1, x2, y2, x3, y3;
 
+  (void)numArgs;
+
   if (!state->isCurPt()) {
     error(getPos(), "No current point in curveto");
     return;
@@ -750,6 +942,8 @@ void Gfx::opCurveTo(Object args[], int numArgs) {
 void Gfx::opCurveTo1(Object args[], int numArgs) {
   double x1, y1, x2, y2, x3, y3;
 
+  (void)numArgs;
+
   if (!state->isCurPt()) {
     error(getPos(), "No current point in curveto1");
     return;
@@ -766,6 +960,8 @@ void Gfx::opCurveTo1(Object args[], int numArgs) {
 void Gfx::opCurveTo2(Object args[], int numArgs) {
   double x1, y1, x2, y2, x3, y3;
 
+  (void)numArgs;
+
   if (!state->isCurPt()) {
     error(getPos(), "No current point in curveto2");
     return;
@@ -782,6 +978,8 @@ void Gfx::opCurveTo2(Object args[], int numArgs) {
 void Gfx::opRectangle(Object args[], int numArgs) {
   double x, y, w, h;
 
+  (void)numArgs;
+
   x = args[0].getNum();
   y = args[1].getNum();
   w = args[2].getNum();
@@ -794,6 +992,9 @@ void Gfx::opRectangle(Object args[], int numArgs) {
 }
 
 void Gfx::opClosePath(Object args[], int numArgs) {
+  (void)args;
+  (void)numArgs;
+
   if (!state->isPath()) {
     error(getPos(), "No current point in closepath");
     return;
@@ -806,10 +1007,16 @@ void Gfx::opClosePath(Object args[], int numArgs) {
 //------------------------------------------------------------------------
 
 void Gfx::opEndPath(Object args[], int numArgs) {
+  (void)args;
+  (void)numArgs;
+
   doEndPath();
 }
 
 void Gfx::opStroke(Object args[], int numArgs) {
+  (void)args;
+  (void)numArgs;
+
   if (!state->isCurPt()) {
     //error(getPos(), "No path in stroke");
     return;
@@ -820,6 +1027,9 @@ void Gfx::opStroke(Object args[], int numArgs) {
 }
 
 void Gfx::opCloseStroke(Object args[], int numArgs) {
+  (void)args;
+  (void)numArgs;
+
   if (!state->isCurPt()) {
     //error(getPos(), "No path in closepath/stroke");
     return;
@@ -832,76 +1042,262 @@ void Gfx::opCloseStroke(Object args[], int numArgs) {
 }
 
 void Gfx::opFill(Object args[], int numArgs) {
+  (void)args;
+  (void)numArgs;
+
   if (!state->isCurPt()) {
     //error(getPos(), "No path in fill");
     return;
   }
-  if (state->isPath())
-    out->fill(state);
+  if (state->isPath()) {
+    if (state->getFillColorSpace()->getMode() == csPattern) {
+      doPatternFill(gFalse);
+    } else {
+      out->fill(state);
+    }
+  }
   doEndPath();
 }
 
 void Gfx::opEOFill(Object args[], int numArgs) {
+  (void)args;
+  (void)numArgs;
+
   if (!state->isCurPt()) {
     //error(getPos(), "No path in eofill");
     return;
   }
-  if (state->isPath())
-    out->eoFill(state);
+  if (state->isPath()) {
+    if (state->getFillColorSpace()->getMode() == csPattern) {
+      doPatternFill(gTrue);
+    } else {
+      out->eoFill(state);
+    }
+  }
   doEndPath();
 }
 
 void Gfx::opFillStroke(Object args[], int numArgs) {
+  (void)args;
+  (void)numArgs;
+
   if (!state->isCurPt()) {
     //error(getPos(), "No path in fill/stroke");
     return;
   }
   if (state->isPath()) {
-    out->fill(state);
+    if (state->getFillColorSpace()->getMode() == csPattern) {
+      doPatternFill(gFalse);
+    } else {
+      out->fill(state);
+    }
     out->stroke(state);
   }
   doEndPath();
 }
 
 void Gfx::opCloseFillStroke(Object args[], int numArgs) {
+  (void)args;
+  (void)numArgs;
+
   if (!state->isCurPt()) {
     //error(getPos(), "No path in closepath/fill/stroke");
     return;
   }
   if (state->isPath()) {
     state->closePath();
-    out->fill(state);
+    if (state->getFillColorSpace()->getMode() == csPattern) {
+      doPatternFill(gFalse);
+    } else {
+      out->fill(state);
+    }
     out->stroke(state);
   }
   doEndPath();
 }
 
 void Gfx::opEOFillStroke(Object args[], int numArgs) {
+  (void)args;
+  (void)numArgs;
+
   if (!state->isCurPt()) {
     //error(getPos(), "No path in eofill/stroke");
     return;
   }
   if (state->isPath()) {
-    out->eoFill(state);
+    if (state->getFillColorSpace()->getMode() == csPattern) {
+      doPatternFill(gTrue);
+    } else {
+      out->eoFill(state);
+    }
     out->stroke(state);
   }
   doEndPath();
 }
 
 void Gfx::opCloseEOFillStroke(Object args[], int numArgs) {
+  (void)args;
+  (void)numArgs;
+
   if (!state->isCurPt()) {
     //error(getPos(), "No path in closepath/eofill/stroke");
     return;
   }
   if (state->isPath()) {
     state->closePath();
-    out->eoFill(state);
+    if (state->getFillColorSpace()->getMode() == csPattern) {
+      doPatternFill(gTrue);
+    } else {
+      out->eoFill(state);
+    }
     out->stroke(state);
   }
   doEndPath();
 }
 
 void Gfx::opShFill(Object args[], int numArgs) {
+  (void)args;
+  (void)numArgs;
+}
+
+void Gfx::doPatternFill(GBool eoFill) {
+  GfxPatternColorSpace *patCS;
+  GfxPattern *pattern;
+  GfxTilingPattern *tPat;
+  GfxColorSpace *cs;
+  GfxPath *path;
+  GfxSubpath *subpath;
+  double xMin, yMin, xMax, yMax, x, y, x1, y1;
+  int xi0, yi0, xi1, yi1, xi, yi;
+  double *ctm, *btm, *ptm;
+  double m[6], ictm[6], m1[6], im[6];
+  double det;
+  double xstep, ystep;
+  int i, j;
+
+  // get color space
+  patCS = (GfxPatternColorSpace *)state->getFillColorSpace();
+
+  // get pattern
+  if (!(pattern = state->getFillPattern())) {
+    return;
+  }
+  if (pattern->getType() != 1) {
+    return;
+  }
+  tPat = (GfxTilingPattern *)pattern;
+
+  // construct a (pattern space) -> (current space) transform matrix
+  ctm = state->getCTM();
+  btm = baseMatrix;
+  ptm = tPat->getMatrix();
+  // iCTM = invert CTM
+  det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]);
+  ictm[0] = ctm[3] * det;
+  ictm[1] = -ctm[1] * det;
+  ictm[2] = -ctm[2] * det;
+  ictm[3] = ctm[0] * det;
+  ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det;
+  ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det;
+  // m1 = PTM * BTM = PTM * base transform matrix
+  m1[0] = ptm[0] * btm[0] + ptm[1] * btm[2];
+  m1[1] = ptm[0] * btm[1] + ptm[1] * btm[3];
+  m1[2] = ptm[2] * btm[0] + ptm[3] * btm[2];
+  m1[3] = ptm[2] * btm[1] + ptm[3] * btm[3];
+  m1[4] = ptm[4] * btm[0] + ptm[5] * btm[2] + btm[4];
+  m1[5] = ptm[4] * btm[1] + ptm[5] * btm[3] + btm[5];
+  // m = m1 * iCTM = (PTM * BTM) * (iCTM)
+  m[0] = m1[0] * ictm[0] + m1[1] * ictm[2];
+  m[1] = m1[0] * ictm[1] + m1[1] * ictm[3];
+  m[2] = m1[2] * ictm[0] + m1[3] * ictm[2];
+  m[3] = m1[2] * ictm[1] + m1[3] * ictm[3];
+  m[4] = m1[4] * ictm[0] + m1[5] * ictm[2] + ictm[4];
+  m[5] = m1[4] * ictm[1] + m1[5] * ictm[3] + ictm[5];
+
+  // construct a (current space) -> (pattern space) transform matrix
+  det = 1 / (m[0] * m[3] - m[1] * m[2]);
+  im[0] = m[3] * det;
+  im[1] = -m[1] * det;
+  im[2] = -m[2] * det;
+  im[3] = m[0] * det;
+  im[4] = (m[2] * m[5] - m[3] * m[4]) * det;
+  im[5] = (m[1] * m[4] - m[0] * m[5]) * det;
+
+  // compute bounding box of current path, in pattern space
+  xMin = xMax = yMin = yMax = 0; // make gcc happy
+  path = state->getPath();
+  for (i = 0; i < path->getNumSubpaths(); ++i) {
+    subpath = path->getSubpath(i);
+    for (j = 0; j < subpath->getNumPoints(); ++j) {
+      x = subpath->getX(j);
+      y = subpath->getY(j);
+      x1 = x * im[0] + y * im[2] + im[4];
+      y1 = x * im[1] + y * im[3] + im[5];
+      if (i == 0 && j == 0) {
+       xMin = xMax = x1;
+       yMin = yMax = y1;
+      } else {
+       if (x1 < xMin) {
+         xMin = x1;
+       } else if (x1 > xMax) {
+         xMax = x1;
+       }
+       if (y1 < yMin) {
+         yMin = y1;
+       } else if (y1 > yMax) {
+         yMax = y1;
+       }
+      }
+    }
+  }
+
+  // save current graphics state
+  out->saveState(state);
+  state = state->save();
+
+  // set underlying color space (for uncolored tiling patterns)
+  if (tPat->getPaintType() == 2 && (cs = patCS->getUnder())) {
+    state->setFillColorSpace(cs->copy());
+  } else {
+    state->setFillColorSpace(new GfxDeviceGrayColorSpace());
+  }
+  state->setFillPattern(NULL);
+  out->updateFillColor(state);
+
+  // clip to current path
+  if (eoFill) {
+    out->eoClip(state);
+  } else {
+    out->clip(state);
+  }
+  state->clearPath();
+
+  // draw the pattern
+  //~ this should treat negative steps differently -- start at right/top
+  //~ edge instead of left/bottom (?)
+  xstep = fabs(tPat->getXStep());
+  ystep = fabs(tPat->getYStep());
+  xi0 = (int)floor(xMin / xstep);
+  xi1 = (int)ceil(xMax / xstep);
+  yi0 = (int)floor(yMin / ystep);
+  yi1 = (int)ceil(yMax / ystep);
+  for (i = 0; i < 4; ++i) {
+    m1[i] = m[i];
+  }
+  for (yi = yi0; yi < yi1; ++yi) {
+    for (xi = xi0; xi < xi1; ++xi) {
+      x = xi * xstep;
+      y = yi * ystep;
+      m1[4] = x * m[0] + y * m[2] + m[4];
+      m1[5] = x * m[1] + y * m[3] + m[5];
+      doForm1(tPat->getContentStream(), tPat->getResDict(),
+             m1, tPat->getBBox());
+    }
+  }
+
+  // restore graphics state
+  state = state->restore();
+  out->restoreState(state);
 }
 
 void Gfx::doEndPath() {
@@ -920,10 +1316,16 @@ void Gfx::doEndPath() {
 //------------------------------------------------------------------------
 
 void Gfx::opClip(Object args[], int numArgs) {
+  (void)args;
+  (void)numArgs;
+
   clip = clipNormal;
 }
 
 void Gfx::opEOClip(Object args[], int numArgs) {
+  (void)args;
+  (void)numArgs;
+
   clip = clipEO;
 }
 
@@ -932,6 +1334,9 @@ void Gfx::opEOClip(Object args[], int numArgs) {
 //------------------------------------------------------------------------
 
 void Gfx::opBeginText(Object args[], int numArgs) {
+  (void)args;
+  (void)numArgs;
+
   state->setTextMat(1, 0, 0, 1, 0, 0);
   state->textMoveTo(0, 0);
   out->updateTextMat(state);
@@ -940,6 +1345,8 @@ void Gfx::opBeginText(Object args[], int numArgs) {
 }
 
 void Gfx::opEndText(Object args[], int numArgs) {
+  (void)args;
+  (void)numArgs;
 }
 
 //------------------------------------------------------------------------
@@ -947,6 +1354,9 @@ void Gfx::opEndText(Object args[], int numArgs) {
 //------------------------------------------------------------------------
 
 void Gfx::opSetCharSpacing(Object args[], int numArgs) {
+  (void)args;
+  (void)numArgs;
+
   state->setCharSpace(args[0].getNum());
   out->updateCharSpace(state);
 }
@@ -954,8 +1364,9 @@ void Gfx::opSetCharSpacing(Object args[], int numArgs) {
 void Gfx::opSetFont(Object args[], int numArgs) {
   GfxFont *font;
 
-  if (!(font = lookupFont(args[0].getName())))
+  if (!(font = res->lookupFont(args[0].getName()))) {
     return;
+  }
   if (printCommands) {
     printf("  font: '%s' %g\n",
           font->getName() ? font->getName()->getCString() : "???",
@@ -966,25 +1377,35 @@ void Gfx::opSetFont(Object args[], int numArgs) {
 }
 
 void Gfx::opSetTextLeading(Object args[], int numArgs) {
+  (void)numArgs;
+
   state->setLeading(args[0].getNum());
 }
 
 void Gfx::opSetTextRender(Object args[], int numArgs) {
+  (void)numArgs;
+
   state->setRender(args[0].getInt());
   out->updateRender(state);
 }
 
 void Gfx::opSetTextRise(Object args[], int numArgs) {
+  (void)numArgs;
+
   state->setRise(args[0].getNum());
   out->updateRise(state);
 }
 
 void Gfx::opSetWordSpacing(Object args[], int numArgs) {
+  (void)numArgs;
+
   state->setWordSpace(args[0].getNum());
   out->updateWordSpace(state);
 }
 
 void Gfx::opSetHorizScaling(Object args[], int numArgs) {
+  (void)numArgs;
+
   state->setHorizScaling(args[0].getNum());
   out->updateHorizScaling(state);
 }
@@ -996,6 +1417,8 @@ void Gfx::opSetHorizScaling(Object args[], int numArgs) {
 void Gfx::opTextMove(Object args[], int numArgs) {
   double tx, ty;
 
+  (void)numArgs;
+
   tx = state->getLineX() + args[0].getNum();
   ty = state->getLineY() + args[1].getNum();
   state->textMoveTo(tx, ty);
@@ -1005,6 +1428,8 @@ void Gfx::opTextMove(Object args[], int numArgs) {
 void Gfx::opTextMoveSet(Object args[], int numArgs) {
   double tx, ty;
 
+  (void)numArgs;
+
   tx = state->getLineX() + args[0].getNum();
   ty = args[1].getNum();
   state->setLeading(-ty);
@@ -1014,6 +1439,8 @@ void Gfx::opTextMoveSet(Object args[], int numArgs) {
 }
 
 void Gfx::opSetTextMatrix(Object args[], int numArgs) {
+  (void)numArgs;
+
   state->setTextMat(args[0].getNum(), args[1].getNum(),
                    args[2].getNum(), args[3].getNum(),
                    args[4].getNum(), args[5].getNum());
@@ -1026,6 +1453,9 @@ void Gfx::opSetTextMatrix(Object args[], int numArgs) {
 void Gfx::opTextNextLine(Object args[], int numArgs) {
   double tx, ty;
 
+  (void)args;
+  (void)numArgs;
+
   tx = state->getLineX();
   ty = state->getLineY() - state->getLeading();
   state->textMoveTo(tx, ty);
@@ -1037,6 +1467,8 @@ void Gfx::opTextNextLine(Object args[], int numArgs) {
 //------------------------------------------------------------------------
 
 void Gfx::opShowText(Object args[], int numArgs) {
+  (void)numArgs;
+
   if (!state->getFont()) {
     error(getPos(), "No font in show");
     return;
@@ -1047,6 +1479,8 @@ void Gfx::opShowText(Object args[], int numArgs) {
 void Gfx::opMoveShowText(Object args[], int numArgs) {
   double tx, ty;
 
+  (void)numArgs;
+
   if (!state->getFont()) {
     error(getPos(), "No font in move/show");
     return;
@@ -1061,6 +1495,8 @@ void Gfx::opMoveShowText(Object args[], int numArgs) {
 void Gfx::opMoveSetShowText(Object args[], int numArgs) {
   double tx, ty;
 
+  (void)numArgs;
+
   if (!state->getFont()) {
     error(getPos(), "No font in move/set/show");
     return;
@@ -1081,6 +1517,8 @@ void Gfx::opShowSpaceText(Object args[], int numArgs) {
   Object obj;
   int i;
 
+  (void)numArgs;
+
   if (!state->getFont()) {
     error(getPos(), "No font in show/space");
     return;
@@ -1209,7 +1647,7 @@ void Gfx::doShowText(GString *s) {
        state->setCTM(newCTM[0], newCTM[1], newCTM[2], newCTM[3], x, y);
        //~ out->updateCTM(???)
        if (charProc.isStream()) {
-         display(&charProc);
+         display(&charProc, gFalse);
        } else {
          error(getPos(), "Missing or bad Type3 CharProc entry");
        }
@@ -1291,13 +1729,14 @@ int Gfx::getNextChar16(GfxFontEncoding16 *enc, Guchar *p, int *c16) {
 //------------------------------------------------------------------------
 
 void Gfx::opXObject(Object args[], int numArgs) {
-  Object obj1, obj2;
+  Object obj1, obj2, refObj;
 #if OPI_SUPPORT
   Object opiDict;
 #endif
 
-  if (!lookupXObject(args[0].getName(), &obj1))
+  if (!res->lookupXObject(args[0].getName(), &obj1)) {
     return;
+  }
   if (!obj1.isStream()) {
     error(getPos(), "XObject '%s' is wrong type", args[0].getName());
     obj1.free();
@@ -1310,14 +1749,17 @@ void Gfx::opXObject(Object args[], int numArgs) {
   }
 #endif
   obj1.streamGetDict()->lookup("Subtype", &obj2);
-  if (obj2.isName("Image"))
-    doImage(obj1.getStream(), gFalse);
-  else if (obj2.isName("Form"))
+  if (obj2.isName("Image")) {
+    res->lookupXObjectNF(args[0].getName(), &refObj);
+    doImage(&refObj, obj1.getStream(), gFalse);
+    refObj.free();
+  } else if (obj2.isName("Form")) {
     doForm(&obj1);
-  else if (obj2.isName())
+  } else if (obj2.isName()) {
     error(getPos(), "Unknown XObject subtype '%s'", obj2.getName());
-  else
+  } else {
     error(getPos(), "XObject subtype is missing or wrong type");
+  }
   obj2.free();
 #if OPI_SUPPORT
   if (opiDict.isDict()) {
@@ -1328,7 +1770,7 @@ void Gfx::opXObject(Object args[], int numArgs) {
   obj1.free();
 }
 
-void Gfx::doImage(Stream *str, GBool inlineImg) {
+void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
   Dict *dict;
   Object obj1, obj2;
   int width, height;
@@ -1408,7 +1850,7 @@ void Gfx::doImage(Stream *str, GBool inlineImg) {
     obj1.free();
 
     // draw it
-    out->drawImageMask(state, str, width, height, invert, inlineImg);
+    out->drawImageMask(state, ref, str, width, height, invert, inlineImg);
 
   } else {
 
@@ -1419,7 +1861,7 @@ void Gfx::doImage(Stream *str, GBool inlineImg) {
       dict->lookup("CS", &obj1);
     }
     if (obj1.isName()) {
-      lookupColorSpace(obj1.getName(), &obj2);
+      res->lookupColorSpace(obj1.getName(), &obj2);
       if (!obj2.isNull()) {
        obj1.free();
        obj1 = obj2;
@@ -1427,10 +1869,9 @@ void Gfx::doImage(Stream *str, GBool inlineImg) {
        obj2.free();
       }
     }
-    colorSpace = new GfxColorSpace(&obj1);
+    colorSpace = GfxColorSpace::parse(&obj1);
     obj1.free();
-    if (!colorSpace->isOk()) {
-      delete colorSpace;
+    if (!colorSpace) {
       goto err1;
     }
     dict->lookup("Decode", &obj1);
@@ -1441,13 +1882,14 @@ void Gfx::doImage(Stream *str, GBool inlineImg) {
     colorMap = new GfxImageColorMap(bits, &obj1, colorSpace);
     obj1.free();
     if (!colorMap->isOk()) {
-      delete colorSpace;
+      delete colorMap;
       goto err1;
     }
 
     // draw it
-    out->drawImage(state, str, width, height, colorMap, inlineImg);
+    out->drawImage(state, ref, str, width, height, colorMap, inlineImg);
     delete colorMap;
+    str->close();
   }
 
   return;
@@ -1461,7 +1903,11 @@ void Gfx::doImage(Stream *str, GBool inlineImg) {
 void Gfx::doForm(Object *str) {
   Dict *dict;
   Object matrixObj, bboxObj;
+  double m[6], bbox[6];
+  Object resObj;
+  Dict *resDict;
   Object obj1;
+  int i;
 
   // get stream dict
   dict = str->streamGetDict();
@@ -1473,13 +1919,7 @@ void Gfx::doForm(Object *str) {
   }
   obj1.free();
 
-  // get matrix and bounding box
-  dict->lookup("Matrix", &matrixObj);
-  if (!matrixObj.isArray()) {
-    matrixObj.free();
-    error(getPos(), "Bad form matrix");
-    return;
-  }
+  // get bounding box
   dict->lookup("BBox", &bboxObj);
   if (!bboxObj.isArray()) {
     matrixObj.free();
@@ -1487,17 +1927,46 @@ void Gfx::doForm(Object *str) {
     error(getPos(), "Bad form bounding box");
     return;
   }
+  for (i = 0; i < 4; ++i) {
+    bboxObj.arrayGet(i, &obj1);
+    bbox[i] = obj1.getNum();
+    obj1.free();
+  }
+  bboxObj.free();
 
-  doForm1(str, dict, &matrixObj, &bboxObj);
-
+  // get matrix
+  dict->lookup("Matrix", &matrixObj);
+  if (matrixObj.isArray()) {
+    for (i = 0; i < 6; ++i) {
+      matrixObj.arrayGet(i, &obj1);
+      m[i] = obj1.getNum();
+      obj1.free();
+    }
+  } else {
+    m[0] = 1; m[1] = 0;
+    m[2] = 0; m[3] = 1;
+    m[4] = 0; m[5] = 0;
+  }
   matrixObj.free();
-  bboxObj.free();
+
+  // get resources
+  dict->lookup("Resources", &resObj);
+  resDict = resObj.isDict() ? resObj.getDict() : NULL;
+
+  // draw it
+  doForm1(str, resDict, m, bbox);
+
+  resObj.free();
 }
 
-void Gfx::doWidgetForm(Object *str, double x, double y) {
-  Dict *dict;
-  Object matrixObj, bboxObj;
+void Gfx::doWidgetForm(Object *str, double xMin, double yMin,
+                      double xMax, double yMax) {
+  Dict *dict, *resDict;
+  Object matrixObj, bboxObj, resObj;
   Object obj1;
+  double m[6], bbox[6];
+  double sx, sy;
+  int i;
 
   // get stream dict
   dict = str->streamGetDict();
@@ -1509,51 +1978,58 @@ void Gfx::doWidgetForm(Object *str, double x, double y) {
     error(getPos(), "Bad form bounding box");
     return;
   }
+  for (i = 0; i < 4; ++i) {
+    bboxObj.arrayGet(i, &obj1);
+    bbox[i] = obj1.getNum();
+    obj1.free();
+  }
+  bboxObj.free();
 
-  // construct matrix
-  matrixObj.initArray();
-  obj1.initReal(1);
-  matrixObj.arrayAdd(&obj1);
-  obj1.initReal(0);
-  matrixObj.arrayAdd(&obj1);
-  obj1.initReal(0);
-  matrixObj.arrayAdd(&obj1);
-  obj1.initReal(1);
-  matrixObj.arrayAdd(&obj1);
-  obj1.initReal(x);
-  matrixObj.arrayAdd(&obj1);
-  obj1.initReal(y);
-  matrixObj.arrayAdd(&obj1);
+  // get matrix
+  dict->lookup("Matrix", &matrixObj);
+  if (matrixObj.isArray()) {
+    for (i = 0; i < 6; ++i) {
+      matrixObj.arrayGet(i, &obj1);
+      m[i] = obj1.getNum();
+      obj1.free();
+    }
+  } else {
+    m[0] = 1; m[1] = 0;
+    m[2] = 0; m[3] = 1;
+    m[4] = 0; m[5] = 0;
+  }
+  matrixObj.free();
 
-  doForm1(str, dict, &matrixObj, &bboxObj);
+  // scale form bbox to widget rectangle
+  sx = fabs((xMax - xMin) / (bbox[2] - bbox[0]));
+  sy = fabs((yMax - yMin) / (bbox[3] - bbox[1]));
+  m[0] *= sx;  m[1] *= sy;
+  m[2] *= sx;  m[3] *= sy;
+  m[4] *= sx;  m[5] *= sy;
 
-  matrixObj.free();
+  // translate to widget rectangle
+  m[4] += xMin;
+  m[5] += yMin;
+
+  // get resources
+  dict->lookup("Resources", &resObj);
+  resDict = resObj.isDict() ? resObj.getDict() : NULL;
+
+  // draw it
+  doForm1(str, resDict, m, bbox);
+
+  resObj.free();
   bboxObj.free();
 }
 
-void Gfx::doForm1(Object *str, Dict *dict,
-                 Object *matrixObj, Object *bboxObj) {
+void Gfx::doForm1(Object *str, Dict *resDict, double *matrix, double *bbox) {
   Parser *oldParser;
+  double oldBaseMatrix[6];
   GfxResources *resPtr;
-  Dict *resDict;
-  double m[6];
-  Object obj1, obj2;
   int i;
 
   // push new resources on stack
-  res = new GfxResources(res);
-  dict->lookup("Resources", &obj1);
-  if (obj1.isDict()) {
-    resDict = obj1.getDict();
-    res->fonts = NULL;
-    resDict->lookup("Font", &obj2);
-    if (obj2.isDict())
-      res->fonts = new GfxFontDict(obj2.getDict());
-    obj2.free();
-    resDict->lookup("XObject", &res->xObjDict);
-    resDict->lookup("ColorSpace", &res->colorSpaceDict);
-    obj1.free();
-  }
+  res = new GfxResources(resDict, res);
 
   // save current graphics state
   out->saveState(state);
@@ -1563,30 +2039,33 @@ void Gfx::doForm1(Object *str, Dict *dict,
   oldParser = parser;
 
   // set form transformation matrix
+  state->concatCTM(matrix[0], matrix[1], matrix[2],
+                  matrix[3], matrix[4], matrix[5]);
+  out->updateCTM(state, matrix[0], matrix[1], matrix[2],
+                matrix[3], matrix[4], matrix[5]);
+
+  // set new base matrix
   for (i = 0; i < 6; ++i) {
-    matrixObj->arrayGet(i, &obj1);
-    m[i] = obj1.getNum();
-    obj1.free();
+    oldBaseMatrix[i] = baseMatrix[i];
+    baseMatrix[i] = state->getCTM()[i];
   }
-  state->concatCTM(m[0], m[1], m[2], m[3], m[4], m[5]);
-  out->updateCTM(state, m[0], m[1], m[2], m[3], m[4], m[5]);
 
   // set form bounding box
-  for (i = 0; i < 4; ++i) {
-    bboxObj->arrayGet(i, &obj1);
-    m[i] = obj1.getNum();
-    obj1.free();
-  }
-  state->moveTo(m[0], m[1]);
-  state->lineTo(m[2], m[1]);
-  state->lineTo(m[2], m[3]);
-  state->lineTo(m[0], m[3]);
+  state->moveTo(bbox[0], bbox[1]);
+  state->lineTo(bbox[2], bbox[1]);
+  state->lineTo(bbox[2], bbox[3]);
+  state->lineTo(bbox[0], bbox[3]);
   state->closePath();
   out->clip(state);
   state->clearPath();
 
   // draw the form
-  display(str);
+  display(str, gFalse);
+
+  // restore base matrix
+  for (i = 0; i < 6; ++i) {
+    baseMatrix[i] = oldBaseMatrix[i];
+  }
 
   // restore parser
   parser = oldParser;
@@ -1596,7 +2075,7 @@ void Gfx::doForm1(Object *str, Dict *dict,
   out->restoreState(state);
 
   // pop resource stack
-  resPtr = res->next;
+  resPtr = res->getNext();
   delete res;
   res = resPtr;
 
@@ -1611,12 +2090,15 @@ void Gfx::opBeginImage(Object args[], int numArgs) {
   Stream *str;
   int c1, c2;
 
+  (void)args;
+  (void)numArgs;
+
   // build dict/stream
   str = buildImageStream();
 
   // display the image
   if (str) {
-    doImage(str, gTrue);
+    doImage(NULL, str, gTrue);
   
     // skip 'EI' tag
     c1 = str->getBaseStream()->getChar();
@@ -1632,7 +2114,7 @@ void Gfx::opBeginImage(Object args[], int numArgs) {
 Stream *Gfx::buildImageStream() {
   Object dict;
   Object obj;
-  char *key;
+  const char *key;
   Stream *str;
 
   // build dictionary
@@ -1665,10 +2147,16 @@ Stream *Gfx::buildImageStream() {
 }
 
 void Gfx::opImageData(Object args[], int numArgs) {
+  (void)args;
+  (void)numArgs;
+
   error(getPos(), "Internal: got 'ID' operator");
 }
 
 void Gfx::opEndImage(Object args[], int numArgs) {
+  (void)args;
+  (void)numArgs;
+
   error(getPos(), "Internal: got 'EI' operator");
 }
 
@@ -1677,10 +2165,16 @@ void Gfx::opEndImage(Object args[], int numArgs) {
 //------------------------------------------------------------------------
 
 void Gfx::opSetCharWidth(Object args[], int numArgs) {
+  (void)args;
+  (void)numArgs;
+
   error(getPos(), "Encountered 'd0' operator in content stream");
 }
 
 void Gfx::opSetCacheDevice(Object args[], int numArgs) {
+  (void)args;
+  (void)numArgs;
+
   error(getPos(), "Encountered 'd1' operator in content stream");
 }
 
@@ -1689,10 +2183,16 @@ void Gfx::opSetCacheDevice(Object args[], int numArgs) {
 //------------------------------------------------------------------------
 
 void Gfx::opBeginIgnoreUndef(Object args[], int numArgs) {
+  (void)args;
+  (void)numArgs;
+
   ++ignoreUndef;
 }
 
 void Gfx::opEndIgnoreUndef(Object args[], int numArgs) {
+  (void)args;
+  (void)numArgs;
+
   if (ignoreUndef > 0)
     --ignoreUndef;
 }
@@ -1702,6 +2202,8 @@ void Gfx::opEndIgnoreUndef(Object args[], int numArgs) {
 //------------------------------------------------------------------------
 
 void Gfx::opBeginMarkedContent(Object args[], int numArgs) {
+  (void)numArgs;
+
   if (printCommands) {
     printf("  marked content: %s ", args[0].getName());
     if (numArgs == 2)
@@ -1711,9 +2213,13 @@ void Gfx::opBeginMarkedContent(Object args[], int numArgs) {
 }
 
 void Gfx::opEndMarkedContent(Object args[], int numArgs) {
+  (void)args;
+  (void)numArgs;
 }
 
 void Gfx::opMarkPoint(Object args[], int numArgs) {
+  (void)numArgs;
+
   if (printCommands) {
     printf("  mark point: %s ", args[0].getName());
     if (numArgs == 2)
index 239c1a18769ff712a7a98d01e663259e7fcf3966..011fbfcd145b0b9d7a16ef961cfe5652dfaa27c8 100644 (file)
@@ -24,6 +24,7 @@ class OutputDev;
 class GfxFontDict;
 class GfxFont;
 struct GfxFontEncoding16;
+class GfxPattern;
 class GfxState;
 class Gfx;
 
@@ -61,12 +62,25 @@ struct Operator {
 class GfxResources {
 public:
 
-  GfxResources(GfxResources *next1) { fonts = NULL; next = next1; }
+  GfxResources(Dict *resDict, GfxResources *next);
   ~GfxResources();
 
+  GfxFont *lookupFont(const char *name);
+  GBool lookupXObject(const char *name, Object *obj);
+  GBool lookupXObjectNF(const char *name, Object *obj);
+  void lookupColorSpace(const char *name, Object *obj);
+  GfxPattern *lookupPattern(const char *name);
+  GBool lookupGState(const char *name, Object *obj);
+
+  GfxResources *getNext() { return next; }
+
+private:
+
   GfxFontDict *fonts;
   Object xObjDict;
   Object colorSpaceDict;
+  Object patternDict;
+  Object gStateDict;
   GfxResources *next;
 };
 
@@ -75,7 +89,7 @@ public:
 
   // Constructor for regular output.
   Gfx(OutputDev *out1, int pageNum, Dict *resDict,
-      int dpi, double x1, double y1, double x2, double y2, GBool crop,
+      double dpi, double x1, double y1, double x2, double y2, GBool crop,
       double cropX1, double cropY1, double cropX2, double cropY2,
       int rotate);
 
@@ -83,9 +97,10 @@ public:
   ~Gfx();
 
   // Interpret a stream or array of streams.
-  void display(Object *obj);
+  void display(Object *obj, GBool topLevel = gTrue);
 
-  void doWidgetForm(Object *str, double x, double y);
+  void doWidgetForm(Object *str, double xMin, double yMin,
+                   double xMax, double yMax);
 
 private:
 
@@ -96,19 +111,18 @@ private:
   GBool fontChanged;           // set if font or text matrix has changed
   GfxClipType clip;            // do a clip?
   int ignoreUndef;             // current BX/EX nesting level
+  double baseMatrix[6];                // default matrix for most recent
+                               //   page/form/pattern
 
   Parser *parser;              // parser for page content stream(s)
 
   static Operator opTab[];     // table of operators
 
-  void go();
+  void go(GBool topLevel);
   void execOp(Object *cmd, Object args[], int numArgs);
-  Operator *findOp(char *name);
+  Operator *findOp(const char *name);
   GBool checkArg(Object *arg, TchkType type);
   int getPos();
-  GfxFont *lookupFont(char *name);
-  GBool lookupXObject(char *name, Object *obj);
-  void lookupColorSpace(char *name, Object *obj);
 
   // graphics state operators
   void opSave(Object args[], int numArgs);
@@ -157,6 +171,7 @@ private:
   void opEOFillStroke(Object args[], int numArgs);
   void opCloseEOFillStroke(Object args[], int numArgs);
   void opShFill(Object args[], int numArgs);
+  void doPatternFill(GBool eoFill);
   void doEndPath();
 
   // path clipping operators
@@ -192,10 +207,9 @@ private:
 
   // XObject operators
   void opXObject(Object args[], int numArgs);
-  void doImage(Stream *str, GBool inlineImg);
+  void doImage(Object *ref, Stream *str, GBool inlineImg);
   void doForm(Object *str);
-  void doForm1(Object *str, Dict *dict,
-              Object *matrixObj, Object *bboxObj);
+  void doForm1(Object *str, Dict *resDict, double *matrix, double *bbox);
 
   // in-line image operators
   void opBeginImage(Object args[], int numArgs);
index b6085729b445ce680f1e596fd505f732314c3aa6..413796f2d9abb76efea8ea47851d27003f297fee 100644 (file)
 #if JAPANESE_SUPPORT
 #include "Japan12CMapInfo.h"
 #endif
-#if CHINESE_SUPPORT
+#if CHINESE_GB_SUPPORT
 #include "GB12CMapInfo.h"
 #endif
+#if CHINESE_CNS_SUPPORT
+#include "CNS13CMapInfo.h"
+#endif
 
 //------------------------------------------------------------------------
 
-static int CDECL cmpWidthExcep(const void *w1, const void *w2);
-static int CDECL cmpWidthExcepV(const void *w1, const void *w2);
+#if defined(JAPANESE_SUPPORT) || defined(CHINESE_GB_SUPPORT) || defined(CHINESE_CNS_SUPPORT)
+extern "C" {
+static int cmpWidthExcep(const void *w1, const void *w2);
+static int cmpWidthExcepV(const void *w1, const void *w2);
+}
+#endif /* JAPANESE_SUPPORT || CHINESE_GB_SUPPORT || CHINESE_CNS_SUPPORT */
 
 //------------------------------------------------------------------------
 
@@ -61,35 +68,17 @@ static Gushort *defCharWidths[12] = {
 // GfxFont
 //------------------------------------------------------------------------
 
-GfxFont::GfxFont(char *tag1, Ref id1, Dict *fontDict) {
+GfxFont::GfxFont(const char *tag1, Ref id1, Dict *fontDict) {
   BuiltinFont *builtinFont;
   Object obj1, obj2, obj3, obj4;
   int missingWidth;
-  char *name2, *p;
+  const char *name2, *p;
   int i;
 
   // get font tag and ID
   tag = new GString(tag1);
   id = id1;
 
-  // get base font name
-  name = NULL;
-  fontDict->lookup("BaseFont", &obj1);
-  if (obj1.isName())
-    name = new GString(obj1.getName());
-  obj1.free();
-
-  // is it a built-in font?
-  builtinFont = NULL;
-  if (name) {
-    for (i = 0; i < numBuiltinFonts; ++i) {
-      if (!strcmp(builtinFonts[i].name, name->getCString())) {
-       builtinFont = &builtinFonts[i];
-       break;
-      }
-    }
-  }
-
   // get font type
   type = fontUnknownType;
   fontDict->lookup("Subtype", &obj1);
@@ -106,8 +95,12 @@ GfxFont::GfxFont(char *tag1, Ref id1, Dict *fontDict) {
   obj1.free();
   is16 = gFalse;
 
-  // assume Times-Roman by default (for substitution purposes)
-  flags = fontSerif;
+  // get base font name
+  name = NULL;
+  fontDict->lookup("BaseFont", &obj1);
+  if (obj1.isName())
+    name = new GString(obj1.getName());
+  obj1.free();
 
   // Newer Adobe tools are using Base14-compatible TrueType fonts
   // without embedding them, so munge the names into the equivalent
@@ -119,29 +112,29 @@ GfxFont::GfxFont(char *tag1, Ref id1, Dict *fontDict) {
     if (!strncmp(p, "Arial", 5)) {
       if (!strcmp(p+5, ",Bold")) {
        name2 = "Helvetica-Bold";
-      } else if (!strcmp(p+5, "Italic")) {
+      } else if (!strcmp(p+5, ",Italic")) {
        name2 = "Helvetica-Oblique";
-      } else if (!strcmp(p+5, "BoldItalic")) {
+      } else if (!strcmp(p+5, ",BoldItalic")) {
        name2 = "Helvetica-BoldOblique";
       } else {
        name2 = "Helvetica";
       }
     } else if (!strncmp(p, "TimesNewRoman", 13)) {
-      if (!strcmp(p+5, ",Bold")) {
+      if (!strcmp(p+13, ",Bold")) {
        name2 = "Times-Bold";
-      } else if (!strcmp(p+5, "Italic")) {
+      } else if (!strcmp(p+13, ",Italic")) {
        name2 = "Times-Italic";
-      } else if (!strcmp(p+5, "BoldItalic")) {
+      } else if (!strcmp(p+13, ",BoldItalic")) {
        name2 = "Times-BoldItalic";
       } else {
        name2 = "Times-Roman";
       }
     } else if (!strncmp(p, "CourierNew", 10)) {
-      if (!strcmp(p+5, ",Bold")) {
+      if (!strcmp(p+10, ",Bold")) {
        name2 = "Courier-Bold";
-      } else if (!strcmp(p+5, "Italic")) {
+      } else if (!strcmp(p+10, ",Italic")) {
        name2 = "Courier-Oblique";
-      } else if (!strcmp(p+5, "BoldItalic")) {
+      } else if (!strcmp(p+10, ",BoldItalic")) {
        name2 = "Courier-BoldOblique";
       } else {
        name2 = "Courier";
@@ -153,6 +146,20 @@ GfxFont::GfxFont(char *tag1, Ref id1, Dict *fontDict) {
     }
   }
 
+  // is it a built-in font?
+  builtinFont = NULL;
+  if (name) {
+    for (i = 0; i < numBuiltinFonts; ++i) {
+      if (!strcmp(builtinFonts[i].name, name->getCString())) {
+       builtinFont = &builtinFonts[i];
+       break;
+      }
+    }
+  }
+
+  // assume Times-Roman by default (for substitution purposes)
+  flags = fontSerif;
+
   // get info from font descriptor
   embFontName = NULL;
   embFontID.num = -1;
@@ -386,7 +393,7 @@ Object *GfxFont::getCharProc(int code, Object *proc) {
 void GfxFont::getEncAndWidths(Dict *fontDict, BuiltinFont *builtinFont,
                              int missingWidth) {
   Object obj1, obj2, obj3;
-  char *buf;
+  const char *buf;
   int len;
   FontFile *fontFile;
   int code, i;
@@ -445,7 +452,7 @@ void GfxFont::getEncAndWidths(Dict *fontDict, BuiltinFont *builtinFont,
       if (!encoding)
        encoding = fontFile->getEncoding(gTrue);
       delete fontFile;
-      gfree(buf);
+      gfree((void *)buf);
     }
   }
 
@@ -493,7 +500,7 @@ void GfxFont::getEncAndWidths(Dict *fontDict, BuiltinFont *builtinFont,
 }
 
 void GfxFont::findExtFontFile() {
-  char **path;
+  const char **path;
   FILE *f;
 
   for (path = fontPath; *path; ++path) {
@@ -517,7 +524,7 @@ void GfxFont::findExtFontFile() {
   }
 }
 
-char *GfxFont::readExtFontFile(int *len) {
+const char *GfxFont::readExtFontFile(int *len) {
   FILE *f;
   char *buf;
 
@@ -535,7 +542,7 @@ char *GfxFont::readExtFontFile(int *len) {
   return buf;
 }
 
-char *GfxFont::readEmbFontFile(int *len) {
+const char *GfxFont::readEmbFontFile(int *len) {
   char *buf;
   Object obj1, obj2;
   Stream *str;
@@ -564,6 +571,7 @@ char *GfxFont::readEmbFontFile(int *len) {
     buf[i++] = c;
   }
   *len = i;
+  str->close();
 
   obj2.free();
   obj1.free();
@@ -576,7 +584,7 @@ void GfxFont::makeWidths(Dict *fontDict, FontEncoding *builtinEncoding,
   Object obj1, obj2;
   int firstChar, lastChar;
   int code, code2;
-  char *charName;
+  const char *charName;
   Gushort *defWidths;
   int index;
   double mult;
@@ -648,8 +656,10 @@ void GfxFont::makeWidths(Dict *fontDict, FontEncoding *builtinEncoding,
 
 void GfxFont::getType0EncAndWidths(Dict *fontDict) {
   Object obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8;
+#if defined(JAPANESE_SUPPORT) || defined(CHINESE_GB_SUPPORT) || defined(CHINESE_CNS_SUPPORT)
   int excepsSize;
   int i, j, k, n;
+#endif /* JAPANESE_SUPPORT || CHINESE_GB_SUPPORT || CHINESE_CNS_SUPPORT */
 
   widths16.exceps = NULL;
   widths16.excepsV = NULL;
@@ -686,11 +696,20 @@ void GfxFont::getType0EncAndWidths(Dict *fontDict) {
 #endif
     } else if (obj4.getString()->cmp("Adobe") == 0 &&
               obj5.getString()->cmp("GB1") == 0) {
-#if CHINESE_SUPPORT
+#if CHINESE_GB_SUPPORT
       is16 = gTrue;
       enc16.charSet = font16AdobeGB12;
 #else
-      error(-1, "Xpdf was compiled without Chinese font support");
+      error(-1, "Xpdf was compiled without Chinese GB font support");
+      goto err4;
+#endif
+    } else if (obj4.getString()->cmp("Adobe") == 0 &&
+              obj5.getString()->cmp("CNS1") == 0) {
+#if CHINESE_CNS_SUPPORT
+      is16 = gTrue;
+      enc16.charSet = font16AdobeCNS13;
+#else
+      error(-1, "Xpdf was compiled without Chinese CNS font support");
       goto err4;
 #endif
     } else {
@@ -702,6 +721,8 @@ void GfxFont::getType0EncAndWidths(Dict *fontDict) {
     error(-1, "Unknown Type 0 character set");
     goto err4;
   }
+
+#if defined(JAPANESE_SUPPORT) || defined(CHINESE_GB_SUPPORT) || defined(CHINESE_CNS_SUPPORT)
   obj5.free();
   obj4.free();
   obj3.free();
@@ -893,7 +914,7 @@ void GfxFont::getType0EncAndWidths(Dict *fontDict) {
     error(-1, "Bad encoding for Type 0 font");
     goto err1;
   }
-#if JAPANESE_SUPPORT
+#  if JAPANESE_SUPPORT
   if (enc16.charSet == font16AdobeJapan12) {
     for (i = 0; gfxJapan12Tab[i].name; ++i) {
       if (!strcmp(obj1.getName(), gfxJapan12Tab[i].name))
@@ -906,8 +927,8 @@ void GfxFont::getType0EncAndWidths(Dict *fontDict) {
     }
     enc16.enc = gfxJapan12Tab[i].enc;
   }
-#endif
-#if CHINESE_SUPPORT
+#  endif
+#  if CHINESE_GB_SUPPORT
   if (enc16.charSet == font16AdobeGB12) {
     for (i = 0; gfxGB12Tab[i].name; ++i) {
       if (!strcmp(obj1.getName(), gfxGB12Tab[i].name))
@@ -920,10 +941,25 @@ void GfxFont::getType0EncAndWidths(Dict *fontDict) {
     }
     enc16.enc = gfxGB12Tab[i].enc;
   }
-#endif
+#  endif
+#  if CHINESE_CNS_SUPPORT
+  if (enc16.charSet == font16AdobeCNS13) {
+    for (i = 0; gfxCNS13Tab[i].name; ++i) {
+      if (!strcmp(obj1.getName(), gfxCNS13Tab[i].name))
+       break;
+    }
+    if (!gfxCNS13Tab[i].name) {
+      error(-1, "Unknown encoding '%s' for Adobe-CNS1-3 font",
+           obj1.getName());
+      goto err1;
+    }
+    enc16.enc = gfxCNS13Tab[i].enc;
+  }
+#  endif
   obj1.free();
 
   return;
+#endif /* JAPANESE_SUPPORT || CHINESE_GB_SUPPORT || CHINESE_CNS_SUPPORT */
 
  err4:
   obj5.free();
@@ -939,13 +975,15 @@ void GfxFont::getType0EncAndWidths(Dict *fontDict) {
   makeWidths(fontDict, NULL, NULL, 0);
 }
 
-static int CDECL cmpWidthExcep(const void *w1, const void *w2) {
+#if defined(JAPANESE_SUPPORT) || defined(CHINESE_GB_SUPPORT) || defined(CHINESE_CNS_SUPPORT)
+static int cmpWidthExcep(const void *w1, const void *w2) {
   return ((GfxFontWidthExcep *)w1)->first - ((GfxFontWidthExcep *)w2)->first;
 }
 
-static int CDECL cmpWidthExcepV(const void *w1, const void *w2) {
+static int cmpWidthExcepV(const void *w1, const void *w2) {
   return ((GfxFontWidthExcepV *)w1)->first - ((GfxFontWidthExcepV *)w2)->first;
 }
+#endif /* JAPANESE_SUPPORT || CHINESE_GB_SUPPORT || CHINESE_CNS_SUPPORT */
 
 //------------------------------------------------------------------------
 // GfxFontDict
@@ -980,7 +1018,7 @@ GfxFontDict::~GfxFontDict() {
   gfree(fonts);
 }
 
-GfxFont *GfxFontDict::lookup(char *tag) {
+GfxFont *GfxFontDict::lookup(const char *tag) {
   int i;
 
   for (i = 0; i < numFonts; ++i) {
index 524a8ad535fdc5f5d3ef7abe7a2b1241a04bd3a1..6853b1cc1afd4cd98fb2e526af19dd3178201d83 100644 (file)
@@ -27,7 +27,8 @@ struct BuiltinFont;
 
 enum GfxFontCharSet16 {
   font16AdobeJapan12,          // Adobe-Japan1-2
-  font16AdobeGB12              // Adobe-GB1-2 (Chinese)
+  font16AdobeGB12,             // Adobe-GB1-2 (Chinese)
+  font16AdobeCNS13             // Adobe-CNS1-3 (Chinese)
 };
 
 //------------------------------------------------------------------------
@@ -97,7 +98,7 @@ class GfxFont {
 public:
 
   // Constructor.
-  GfxFont(char *tag1, Ref id1, Dict *fontDict);
+  GfxFont(const char *tag1, Ref id1, Dict *fontDict);
 
   // Destructor.
   ~GfxFont();
@@ -109,7 +110,7 @@ public:
   Ref getID() { return id; }
 
   // Does this font match the tag?
-  GBool matches(char *tag1) { return !tag->cmp(tag1); }
+  GBool matches(const char *tag1) { return !tag->cmp(tag1); }
 
   // Get base font name.
   GString *getName() { return name; }
@@ -127,8 +128,8 @@ public:
 
   // Get the PostScript font name for the embedded font.  Returns
   // NULL if there is no embedded font.
-  char *getEmbeddedFontName()
-    { return embFontName ? embFontName->getCString() : (char *)NULL; }
+  const char *getEmbeddedFontName()
+    { return embFontName ? embFontName->getCString() : (const char *)NULL; }
 
   // Get the name of the external font file.  Returns NULL if there
   // is no external font file.
@@ -155,10 +156,10 @@ public:
   FontEncoding *getEncoding() { return encoding; }
 
   // Return the character name associated with <code>.
-  char *getCharName(int code) { return encoding->getCharName(code); }
+  const char *getCharName(int code) { return encoding->getCharName(code); }
 
   // Return the code associated with <name>.
-  int getCharCode(char *charName) { return encoding->getCharCode(charName); }
+  int getCharCode(const char *charName) { return encoding->getCharCode(charName); }
 
   // Return the Type 3 CharProc for the character associated with <code>.
   Object *getCharProc(int code, Object *proc);
@@ -174,8 +175,8 @@ public:
   double *getFontMatrix() { return fontMat; }
 
   // Read an external or embedded font file into a buffer.
-  char *readExtFontFile(int *len);
-  char *readEmbFontFile(int *len);
+  const char *readExtFontFile(int *len);
+  const char *readEmbFontFile(int *len);
 
 private:
 
@@ -224,7 +225,7 @@ public:
   ~GfxFontDict();
 
   // Get the specified font.
-  GfxFont *lookup(char *tag);
+  GfxFont *lookup(const char *tag);
 
   // Iterative access.
   int getNumFonts() { return numFonts; }
index 0d191eaa0d9396dbecbeadc6e91a7f2597ced376..1abf9a56ec47025632d26f02c6ad3f769bbccbde 100644 (file)
 #include "gmem.h"
 #include "Error.h"
 #include "Object.h"
+#include "Array.h"
 #include "GfxState.h"
 
 //------------------------------------------------------------------------
-// GfxColor
+
+static inline double clip01(double x) {
+  return (x < 0) ? 0 : ((x > 1) ? 1 : x);
+}
+
 //------------------------------------------------------------------------
+// GfxColorSpace
+//------------------------------------------------------------------------
+
+GfxColorSpace::GfxColorSpace() {
+}
 
-void GfxColor::setGray(double gray) {
-  if (gray < 0) {
-    r = g = b = 0;
-  } else if (gray > 1) {
-    r = g = b = 1;
+GfxColorSpace::~GfxColorSpace() {
+}
+
+GfxColorSpace *GfxColorSpace::parse(Object *csObj) {
+  GfxColorSpace *cs;
+  Object obj1;
+
+  cs = NULL;
+  if (csObj->isName()) {
+    if (csObj->isName("DeviceGray") || csObj->isName("G")) {
+      cs = new GfxDeviceGrayColorSpace();
+    } else if (csObj->isName("DeviceRGB") || csObj->isName("RGB")) {
+      cs = new GfxDeviceRGBColorSpace();
+    } else if (csObj->isName("DeviceCMYK") || csObj->isName("CMYK")) {
+      cs = new GfxDeviceCMYKColorSpace();
+    } else if (csObj->isName("Pattern")) {
+      cs = new GfxPatternColorSpace(NULL);
+    } else {
+      error(-1, "Bad color space '%s'", csObj->getName());
+    }
+  } else if (csObj->isArray()) {
+    csObj->arrayGet(0, &obj1);
+    if (obj1.isName("DeviceGray") || obj1.isName("G")) {
+      cs = new GfxDeviceGrayColorSpace();
+    } else if (obj1.isName("DeviceRGB") || obj1.isName("RGB")) {
+      cs = new GfxDeviceRGBColorSpace();
+    } else if (obj1.isName("DeviceCMYK") || obj1.isName("CMYK")) {
+      cs = new GfxDeviceCMYKColorSpace();
+    } else if (obj1.isName("CalGray")) {
+      cs = GfxCalGrayColorSpace::parse(csObj->getArray());
+    } else if (obj1.isName("CalRGB")) {
+      cs = GfxCalRGBColorSpace::parse(csObj->getArray());
+    } else if (obj1.isName("Lab")) {
+      cs = GfxLabColorSpace::parse(csObj->getArray());
+    } else if (obj1.isName("ICCBased")) {
+      cs = GfxICCBasedColorSpace::parse(csObj->getArray());
+    } else if (obj1.isName("Indexed") || obj1.isName("I")) {
+      cs = GfxIndexedColorSpace::parse(csObj->getArray());
+    } else if (obj1.isName("Separation")) {
+      cs = GfxSeparationColorSpace::parse(csObj->getArray());
+    } else if (obj1.isName("DeviceN")) {
+      cs = GfxDeviceNColorSpace::parse(csObj->getArray());
+    } else if (obj1.isName("Pattern")) {
+      cs = GfxPatternColorSpace::parse(csObj->getArray());
+    } else {
+      error(-1, "Bad color space '%s'", csObj->getName());
+    }
+    obj1.free();
   } else {
-    r = g = b = gray;
+    error(-1, "Bad color space - expected name or array");
+  }
+  return cs;
+}
+
+void GfxColorSpace::getDefaultRanges(double *decodeLow, double *decodeRange,
+                                    int maxImgPixel) {
+  int i;
+
+  for (i = 0; i < getNComps(); ++i) {
+    decodeLow[i] = 0;
+    decodeRange[i] = 1;
+  }
+}
+
+//------------------------------------------------------------------------
+// GfxDeviceGrayColorSpace
+//------------------------------------------------------------------------
+
+GfxDeviceGrayColorSpace::GfxDeviceGrayColorSpace() {
+}
+
+GfxDeviceGrayColorSpace::~GfxDeviceGrayColorSpace() {
+}
+
+GfxColorSpace *GfxDeviceGrayColorSpace::copy() {
+  return new GfxDeviceGrayColorSpace();
+}
+
+void GfxDeviceGrayColorSpace::getGray(GfxColor *color, double *gray) {
+  *gray = clip01(color->c[0]);
+}
+
+void GfxDeviceGrayColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+  rgb->r = rgb->g = rgb->b = clip01(color->c[0]);
+}
+
+void GfxDeviceGrayColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+  cmyk->c = cmyk->m = cmyk->y = 0;
+  cmyk->k = clip01(1 - color->c[0]);
+}
+
+//------------------------------------------------------------------------
+// GfxCalGrayColorSpace
+//------------------------------------------------------------------------
+
+GfxCalGrayColorSpace::GfxCalGrayColorSpace() {
+  whiteX = whiteY = whiteZ = 1;
+  blackX = blackY = blackZ = 0;
+  gamma = 1;
+}
+
+GfxCalGrayColorSpace::~GfxCalGrayColorSpace() {
+}
+
+GfxColorSpace *GfxCalGrayColorSpace::copy() {
+  GfxCalGrayColorSpace *cs;
+
+  cs = new GfxCalGrayColorSpace();
+  cs->whiteX = whiteX;
+  cs->whiteY = whiteY;
+  cs->whiteZ = whiteZ;
+  cs->blackX = blackX;
+  cs->blackY = blackY;
+  cs->blackZ = blackZ;
+  cs->gamma = gamma;
+  return cs;
+}
+
+GfxColorSpace *GfxCalGrayColorSpace::parse(Array *arr) {
+  GfxCalGrayColorSpace *cs;
+  Object obj1, obj2, obj3;
+
+  arr->get(1, &obj1);
+  if (!obj1.isDict()) {
+    error(-1, "Bad CalGray color space");
+    obj1.free();
+    return NULL;
   }
+  cs = new GfxCalGrayColorSpace();
+  if (obj1.dictLookup("WhitePoint", &obj2)->isArray() &&
+      obj2.arrayGetLength() == 3) {
+    obj2.arrayGet(0, &obj3);
+    cs->whiteX = obj3.getNum();
+    obj3.free();
+    obj2.arrayGet(1, &obj3);
+    cs->whiteY = obj3.getNum();
+    obj3.free();
+    obj2.arrayGet(2, &obj3);
+    cs->whiteZ = obj3.getNum();
+    obj3.free();
+  }
+  obj2.free();
+  if (obj1.dictLookup("BlackPoint", &obj2)->isArray() &&
+      obj2.arrayGetLength() == 3) {
+    obj2.arrayGet(0, &obj3);
+    cs->blackX = obj3.getNum();
+    obj3.free();
+    obj2.arrayGet(1, &obj3);
+    cs->blackY = obj3.getNum();
+    obj3.free();
+    obj2.arrayGet(2, &obj3);
+    cs->blackZ = obj3.getNum();
+    obj3.free();
+  }
+  obj2.free();
+  if (obj1.dictLookup("Gamma", &obj2)->isNum()) {
+    cs->gamma = obj2.getNum();
+  }
+  obj2.free();
+  obj1.free();
+  return cs;
+}
+
+void GfxCalGrayColorSpace::getGray(GfxColor *color, double *gray) {
+  *gray = clip01(color->c[0]);
+}
+
+void GfxCalGrayColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+  rgb->r = rgb->g = rgb->b = clip01(color->c[0]);
+}
+
+void GfxCalGrayColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+  cmyk->c = cmyk->m = cmyk->y = 0;
+  cmyk->k = clip01(1 - color->c[0]);
+}
+
+//------------------------------------------------------------------------
+// GfxDeviceRGBColorSpace
+//------------------------------------------------------------------------
+
+GfxDeviceRGBColorSpace::GfxDeviceRGBColorSpace() {
+}
+
+GfxDeviceRGBColorSpace::~GfxDeviceRGBColorSpace() {
+}
+
+GfxColorSpace *GfxDeviceRGBColorSpace::copy() {
+  return new GfxDeviceRGBColorSpace();
+}
+
+void GfxDeviceRGBColorSpace::getGray(GfxColor *color, double *gray) {
+  *gray = clip01(0.299 * color->c[0] +
+                0.587 * color->c[1] +
+                0.114 * color->c[2]);
+}
+
+void GfxDeviceRGBColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+  rgb->r = clip01(color->c[0]);
+  rgb->g = clip01(color->c[1]);
+  rgb->b = clip01(color->c[2]);
 }
 
-void GfxColor::setCMYK(double c, double m, double y, double k) {
-  if ((r = 1 - (c + k)) < 0) {
-    r = 0;
-  } else if (r > 1) {
-    r = 1;
+void GfxDeviceRGBColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+  double c, m, y, k;
+
+  c = clip01(1 - color->c[0]);
+  m = clip01(1 - color->c[1]);
+  y = clip01(1 - color->c[2]);
+  k = c;
+  if (m < k) {
+    k = m;
   }
-  if ((g = 1 - (m + k)) < 0) {
-    g = 0;
-  } else if (g > 1) {
-    g = 1;
+  if (y < k) {
+    k = y;
   }
-  if ((b = 1 - (y + k)) < 0) {
-    b = 0;
-  } else if (b > 1) {
-    b = 1;
+  cmyk->c = c - k;
+  cmyk->m = m - k;
+  cmyk->y = y - k;
+  cmyk->k = k;
+}
+
+//------------------------------------------------------------------------
+// GfxCalRGBColorSpace
+//------------------------------------------------------------------------
+
+GfxCalRGBColorSpace::GfxCalRGBColorSpace() {
+  whiteX = whiteY = whiteZ = 1;
+  blackX = blackY = blackZ = 0;
+  gammaR = gammaG = gammaB = 1;
+  m[0] = 1; m[1] = 0; m[2] = 0;
+  m[3] = 0; m[4] = 1; m[5] = 0;
+  m[6] = 0; m[7] = 0; m[8] = 1;
+}
+
+GfxCalRGBColorSpace::~GfxCalRGBColorSpace() {
+}
+
+GfxColorSpace *GfxCalRGBColorSpace::copy() {
+  GfxCalRGBColorSpace *cs;
+  int i;
+
+  cs = new GfxCalRGBColorSpace();
+  cs->whiteX = whiteX;
+  cs->whiteY = whiteY;
+  cs->whiteZ = whiteZ;
+  cs->blackX = blackX;
+  cs->blackY = blackY;
+  cs->blackZ = blackZ;
+  cs->gammaR = gammaR;
+  cs->gammaG = gammaG;
+  cs->gammaB = gammaB;
+  for (i = 0; i < 9; ++i) {
+    cs->m[i] = m[i];
   }
+  return cs;
 }
 
-void GfxColor::setRGB(double r1, double g1, double b1) {
-  if (r1 < 0) {
-    r = 0;
-  } else if (r1 > 1) {
-    r = 1;
-  } else {
-    r = r1;
+GfxColorSpace *GfxCalRGBColorSpace::parse(Array *arr) {
+  GfxCalRGBColorSpace *cs;
+  Object obj1, obj2, obj3;
+  int i;
+
+  arr->get(1, &obj1);
+  if (!obj1.isDict()) {
+    error(-1, "Bad CalRGB color space");
+    obj1.free();
+    return NULL;
   }
-  if (g1 < 0) {
-    g = 0;
-  } else if (g1 > 1) {
-    g = 1;
-  } else {
-    g = g1;
+  cs = new GfxCalRGBColorSpace();
+  if (obj1.dictLookup("WhitePoint", &obj2)->isArray() &&
+      obj2.arrayGetLength() == 3) {
+    obj2.arrayGet(0, &obj3);
+    cs->whiteX = obj3.getNum();
+    obj3.free();
+    obj2.arrayGet(1, &obj3);
+    cs->whiteY = obj3.getNum();
+    obj3.free();
+    obj2.arrayGet(2, &obj3);
+    cs->whiteZ = obj3.getNum();
+    obj3.free();
   }
-  if (b1 < 0) {
-    b = 0;
-  } else if (b1 > 1) {
-    b = 1;
-  } else {
-    b = b1;
+  obj2.free();
+  if (obj1.dictLookup("BlackPoint", &obj2)->isArray() &&
+      obj2.arrayGetLength() == 3) {
+    obj2.arrayGet(0, &obj3);
+    cs->blackX = obj3.getNum();
+    obj3.free();
+    obj2.arrayGet(1, &obj3);
+    cs->blackY = obj3.getNum();
+    obj3.free();
+    obj2.arrayGet(2, &obj3);
+    cs->blackZ = obj3.getNum();
+    obj3.free();
+  }
+  obj2.free();
+  if (obj1.dictLookup("Gamma", &obj2)->isArray() &&
+      obj2.arrayGetLength() == 3) {
+    obj2.arrayGet(0, &obj3);
+    cs->gammaR = obj3.getNum();
+    obj3.free();
+    obj2.arrayGet(1, &obj3);
+    cs->gammaG = obj3.getNum();
+    obj3.free();
+    obj2.arrayGet(2, &obj3);
+    cs->gammaB = obj3.getNum();
+    obj3.free();
+  }
+  obj2.free();
+  if (obj1.dictLookup("Matrix", &obj2)->isArray() &&
+      obj2.arrayGetLength() == 9) {
+    for (i = 0; i < 9; ++i) {
+      obj2.arrayGet(i, &obj3);
+      cs->m[i] = obj3.getNum();
+      obj3.free();
+    }
+  }
+  obj2.free();
+  obj1.free();
+  return cs;
+}
+
+void GfxCalRGBColorSpace::getGray(GfxColor *color, double *gray) {
+  *gray = clip01(0.299 * color->c[0] +
+                0.587 * color->c[1] +
+                0.114 * color->c[2]);
+}
+
+void GfxCalRGBColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+  rgb->r = clip01(color->c[0]);
+  rgb->g = clip01(color->c[1]);
+  rgb->b = clip01(color->c[2]);
+}
+
+void GfxCalRGBColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+  double c, m, y, k;
+
+  c = clip01(1 - color->c[0]);
+  m = clip01(1 - color->c[1]);
+  y = clip01(1 - color->c[2]);
+  k = c;
+  if (m < k) {
+    k = m;
+  }
+  if (y < k) {
+    k = y;
+  }
+  cmyk->c = c - k;
+  cmyk->m = m - k;
+  cmyk->y = y - k;
+  cmyk->k = k;
+}
+
+//------------------------------------------------------------------------
+// GfxDeviceCMYKColorSpace
+//------------------------------------------------------------------------
+
+GfxDeviceCMYKColorSpace::GfxDeviceCMYKColorSpace() {
+}
+
+GfxDeviceCMYKColorSpace::~GfxDeviceCMYKColorSpace() {
+}
+
+GfxColorSpace *GfxDeviceCMYKColorSpace::copy() {
+  return new GfxDeviceCMYKColorSpace();
+}
+
+void GfxDeviceCMYKColorSpace::getGray(GfxColor *color, double *gray) {
+  *gray = clip01(1 - color->c[3]
+                - 0.299 * color->c[0]
+                - 0.587 * color->c[1]
+                - 0.114 * color->c[2]);
+}
+
+void GfxDeviceCMYKColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+  rgb->r = clip01(1 - (color->c[0] + color->c[3]));
+  rgb->g = clip01(1 - (color->c[1] + color->c[3]));
+  rgb->b = clip01(1 - (color->c[2] + color->c[3]));
+}
+
+void GfxDeviceCMYKColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+  cmyk->c = clip01(color->c[0]);
+  cmyk->m = clip01(color->c[1]);
+  cmyk->y = clip01(color->c[2]);
+  cmyk->k = clip01(color->c[3]);
+}
+
+//------------------------------------------------------------------------
+// GfxLabColorSpace
+//------------------------------------------------------------------------
+
+// This is the inverse of MatrixLMN in Example 4.10 from the PostScript
+// Language Reference, Third Edition.
+static double xyzrgb[3][3] = {
+  {  3.240449, -1.537136, -0.498531 },
+  { -0.969265,  1.876011,  0.041556 },
+  {  0.055643, -0.204026,  1.057229 }
+};
+
+GfxLabColorSpace::GfxLabColorSpace() {
+  whiteX = whiteY = whiteZ = 1;
+  blackX = blackY = blackZ = 0;
+  aMin = bMin = -100;
+  aMax = bMax = 100;
+}
+
+GfxLabColorSpace::~GfxLabColorSpace() {
+}
+
+GfxColorSpace *GfxLabColorSpace::copy() {
+  GfxLabColorSpace *cs;
+
+  cs = new GfxLabColorSpace();
+  cs->whiteX = whiteX;
+  cs->whiteY = whiteY;
+  cs->whiteZ = whiteZ;
+  cs->blackX = blackX;
+  cs->blackY = blackY;
+  cs->blackZ = blackZ;
+  cs->aMin = aMin;
+  cs->aMax = aMax;
+  cs->bMin = bMin;
+  cs->bMax = bMax;
+  cs->kr = kr;
+  cs->kg = kg;
+  cs->kb = kb;
+  return cs;
+}
+
+GfxColorSpace *GfxLabColorSpace::parse(Array *arr) {
+  GfxLabColorSpace *cs;
+  Object obj1, obj2, obj3;
+
+  arr->get(1, &obj1);
+  if (!obj1.isDict()) {
+    error(-1, "Bad Lab color space");
+    obj1.free();
+    return NULL;
+  }
+  cs = new GfxLabColorSpace();
+  if (obj1.dictLookup("WhitePoint", &obj2)->isArray() &&
+      obj2.arrayGetLength() == 3) {
+    obj2.arrayGet(0, &obj3);
+    cs->whiteX = obj3.getNum();
+    obj3.free();
+    obj2.arrayGet(1, &obj3);
+    cs->whiteY = obj3.getNum();
+    obj3.free();
+    obj2.arrayGet(2, &obj3);
+    cs->whiteZ = obj3.getNum();
+    obj3.free();
   }
+  obj2.free();
+  if (obj1.dictLookup("BlackPoint", &obj2)->isArray() &&
+      obj2.arrayGetLength() == 3) {
+    obj2.arrayGet(0, &obj3);
+    cs->blackX = obj3.getNum();
+    obj3.free();
+    obj2.arrayGet(1, &obj3);
+    cs->blackY = obj3.getNum();
+    obj3.free();
+    obj2.arrayGet(2, &obj3);
+    cs->blackZ = obj3.getNum();
+    obj3.free();
+  }
+  obj2.free();
+  if (obj1.dictLookup("Range", &obj2)->isArray() &&
+      obj2.arrayGetLength() == 4) {
+    obj2.arrayGet(0, &obj3);
+    cs->aMin = obj3.getNum();
+    obj3.free();
+    obj2.arrayGet(1, &obj3);
+    cs->aMax = obj3.getNum();
+    obj3.free();
+    obj2.arrayGet(2, &obj3);
+    cs->bMin = obj3.getNum();
+    obj3.free();
+    obj2.arrayGet(3, &obj3);
+    cs->bMax = obj3.getNum();
+    obj3.free();
+  }
+  obj2.free();
+  obj1.free();
+
+  cs->kr = 1 / (xyzrgb[0][0] * cs->whiteX +
+               xyzrgb[0][1] * cs->whiteY +
+               xyzrgb[0][2] * cs->whiteZ);
+  cs->kg = 1 / (xyzrgb[1][0] * cs->whiteX +
+               xyzrgb[1][1] * cs->whiteY +
+               xyzrgb[1][2] * cs->whiteZ);
+  cs->kb = 1 / (xyzrgb[2][0] * cs->whiteX +
+               xyzrgb[2][1] * cs->whiteY +
+               xyzrgb[2][2] * cs->whiteZ);
+
+  return cs;
 }
 
-// Handle colors in the L*a*b* color space.
-void GfxColor::setLab(double L, double a, double bb, LabParams *params) {
+void GfxLabColorSpace::getGray(GfxColor *color, double *gray) {
+  GfxRGB rgb;
+
+  getRGB(color, &rgb);
+  *gray = clip01(0.299 * rgb.r +
+                0.587 * rgb.g +
+                0.114 * rgb.b);
+}
+
+void GfxLabColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
   double X, Y, Z;
   double t1, t2;
+  double r, g, b;
 
   // convert L*a*b* to CIE 1931 XYZ color space
-  // (This ignores the white point parameter, because I don't
-  // understand exactly how it should work.)
-  t1 = (L + 16) / 116;
-  t2 = t1 + a / 500;
+  t1 = (color->c[0] + 16) / 116;
+  t2 = t1 + color->c[1] / 500;
   if (t2 >= (6.0 / 29.0)) {
     X = t2 * t2 * t2;
   } else {
     X = (108.0 / 841.0) * (t2 - (4.0 / 29.0));
   }
-#if 0 //~
-  X *= params->whiteX;
-#endif
+  X *= whiteX;
   if (t1 >= (6.0 / 29.0)) {
     Y = t1 * t1 * t1;
   } else {
     Y = (108.0 / 841.0) * (t1 - (4.0 / 29.0));
   }
-#if 0 //~
-  Y *= params->whiteY;
-#endif
-  t2 = t1 - bb / 200;
+  Y *= whiteY;
+  t2 = t1 - color->c[2] / 200;
   if (t2 >= (6.0 / 29.0)) {
     Z = t2 * t2 * t2;
   } else {
     Z = (108.0 / 841.0) * (t2 - (4.0 / 29.0));
   }
-#if 0 //~
-  Z *= params->whiteZ;
-#endif
+  Z *= whiteZ;
+
+  // convert XYZ to RGB, including gamut mapping and gamma correction
+  r = xyzrgb[0][0] * X + xyzrgb[0][1] * Y + xyzrgb[0][2] * Z;
+  g = xyzrgb[1][0] * X + xyzrgb[1][1] * Y + xyzrgb[1][2] * Z;
+  b = xyzrgb[2][0] * X + xyzrgb[2][1] * Y + xyzrgb[2][2] * Z;
+  rgb->r = pow(clip01(r * kr), 0.5);
+  rgb->g = pow(clip01(g * kg), 0.5);
+  rgb->b = pow(clip01(b * kb), 0.5);
+}
 
-  // convert XYZ to RGB
-#if 0 //~
-  X *= 0.9505;
-  Z *= 1.0890;
-#endif
-  r =  3.240479 * X - 1.537150 * Y - 0.498535 * Z;
-  g = -0.969256 * X + 1.875992 * Y + 0.041556 * Z;
-  b =  0.055648 * X - 0.204043 * Y + 1.057311 * Z;
+void GfxLabColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+  GfxRGB rgb;
+  double c, m, y, k;
+
+  getRGB(color, &rgb);
+  c = clip01(1 - rgb.r);
+  m = clip01(1 - rgb.g);
+  y = clip01(1 - rgb.b);
+  k = c;
+  if (m < k) {
+    k = m;
+  }
+  if (y < k) {
+    k = y;
+  }
+  cmyk->c = c - k;
+  cmyk->m = m - k;
+  cmyk->y = y - k;
+  cmyk->k = k;
+}
+
+void GfxLabColorSpace::getDefaultRanges(double *decodeLow, double *decodeRange,
+                                       int maxImgPixel) {
+  decodeLow[0] = 0;
+  decodeRange[0] = 100;
+  decodeLow[1] = aMin;
+  decodeRange[1] = aMax - aMin;
+  decodeLow[2] = bMin;
+  decodeRange[2] = bMax - bMin;
+}
+
+//------------------------------------------------------------------------
+// GfxICCBasedColorSpace
+//------------------------------------------------------------------------
+
+GfxICCBasedColorSpace::GfxICCBasedColorSpace(int nComps, GfxColorSpace *alt,
+                                            Ref *iccProfileStream) {
+  this->nComps = nComps;
+  this->alt = alt;
+  this->iccProfileStream = *iccProfileStream;
+  rangeMin[0] = rangeMin[1] = rangeMin[2] = rangeMin[3] = 0;
+  rangeMax[0] = rangeMax[1] = rangeMax[2] = rangeMax[3] = 1;
+}
+
+GfxICCBasedColorSpace::~GfxICCBasedColorSpace() {
+  delete alt;
+}
+
+GfxColorSpace *GfxICCBasedColorSpace::copy() {
+  GfxICCBasedColorSpace *cs;
+  int i;
+
+  cs = new GfxICCBasedColorSpace(nComps, alt->copy(), &iccProfileStream);
+  for (i = 0; i < 4; ++i) {
+    cs->rangeMin[i] = rangeMin[i];
+    cs->rangeMax[i] = rangeMax[i];
+  }
+  return cs;
+}
+
+GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr) {
+  GfxICCBasedColorSpace *cs;
+  Ref iccProfileStream;
+  int nComps;
+  GfxColorSpace *alt;
+  Dict *dict;
+  Object obj1, obj2, obj3;
+  int i;
 
-  // clip RGB
-  if (r < 0) {
-    r = 0;
-  } else if (r > 1) {
-    r = 1;
+  arr->getNF(1, &obj1);
+  if (obj1.isRef()) {
+    iccProfileStream = obj1.getRef();
+  } else {
+    iccProfileStream.num = 0;
+    iccProfileStream.gen = 0;
+  }
+  obj1.free();
+  arr->get(1, &obj1);
+  if (!obj1.isStream()) {
+    error(-1, "Bad ICCBased color space (stream)");
+    obj1.free();
+    return NULL;
+  }
+  dict = obj1.streamGetDict();
+  if (!dict->lookup("N", &obj2)->isInt()) {
+    error(-1, "Bad ICCBased color space (N)");
+    obj2.free();
+    obj1.free();
+    return NULL;
+  }
+  nComps = obj2.getInt();
+  obj2.free();
+  if (dict->lookup("Alternate", &obj2)->isNull() ||
+      !(alt = GfxColorSpace::parse(&obj2))) {
+    switch (nComps) {
+    case 1:
+      alt = new GfxDeviceGrayColorSpace();
+      break;
+    case 3:
+      alt = new GfxDeviceRGBColorSpace();
+      break;
+    case 4:
+      alt = new GfxDeviceCMYKColorSpace();
+      break;
+    default:
+      error(-1, "Bad ICCBased color space - invalid N");
+      obj2.free();
+      obj1.free();
+      return NULL;
+    }
   }
-  if (g < 0) {
-    g = 0;
-  } else if (g > 1) {
-    g = 1;
+  obj2.free();
+  cs = new GfxICCBasedColorSpace(nComps, alt, &iccProfileStream);
+  if (dict->lookup("Range", &obj2)->isArray() &&
+      obj2.arrayGetLength() == 2 * nComps) {
+    for (i = 0; i < nComps; ++i) {
+      obj2.arrayGet(2*i, &obj3);
+      cs->rangeMin[i] = obj3.getNum();
+      obj3.free();
+      obj2.arrayGet(2*i+1, &obj3);
+      cs->rangeMax[i] = obj3.getNum();
+      obj3.free();
+    }
   }
-  if (b < 0) {
-    b = 0;
-  } else if (b > 1) {
-    b = 1;
+  obj2.free();
+  obj1.free();
+  return cs;
+}
+
+void GfxICCBasedColorSpace::getGray(GfxColor *color, double *gray) {
+  alt->getGray(color, gray);
+}
+
+void GfxICCBasedColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+  alt->getRGB(color, rgb);
+}
+
+void GfxICCBasedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+  alt->getCMYK(color, cmyk);
+}
+
+void GfxICCBasedColorSpace::getDefaultRanges(double *decodeLow,
+                                            double *decodeRange,
+                                            int maxImgPixel) {
+  int i;
+
+  for (i = 0; i < nComps; ++i) {
+    decodeLow[i] = rangeMin[i];
+    decodeRange[i] = rangeMax[i] - rangeMin[i];
   }
 }
 
 //------------------------------------------------------------------------
-// GfxColorSpace
+// GfxIndexedColorSpace
 //------------------------------------------------------------------------
 
-GfxColorSpace::GfxColorSpace(Object *colorSpace) {
-  Object csObj;
-  Object obj, obj2, obj3;
-  Dict *dict;
-  char *s;
+GfxIndexedColorSpace::GfxIndexedColorSpace(GfxColorSpace *base,
+                                          int indexHigh) {
+  this->base = base;
+  this->indexHigh = indexHigh;
+  this->lookup = (Guchar *)gmalloc((indexHigh + 1) * base->getNComps() *
+                                  sizeof(Guchar));
+}
+
+GfxIndexedColorSpace::~GfxIndexedColorSpace() {
+  delete base;
+  gfree(lookup);
+}
+
+GfxColorSpace *GfxIndexedColorSpace::copy() {
+  GfxIndexedColorSpace *cs;
+
+  cs = new GfxIndexedColorSpace(base->copy(), indexHigh);
+  memcpy(cs->lookup, lookup,
+        (indexHigh + 1) * base->getNComps() * sizeof(Guchar));
+  return cs;
+}
+
+GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr) {
+  GfxIndexedColorSpace *cs;
+  GfxColorSpace *base;
+  int indexHigh;
+  Object obj1;
   int x;
-  int i, j;
+  char *s;
+  int n, i, j;
 
-  ok = gTrue;
-  lookup = NULL;
-
-  // check for Separation, DeviceN, ICCBased, and Pattern colorspaces
-  colorSpace->copy(&csObj);
-  sepFunc = NULL;
-  if (colorSpace->isArray()) {
-    colorSpace->arrayGet(0, &obj);
-    if (obj.isName("Separation") || obj.isName("DeviceN")) {
-      csObj.free();
-      colorSpace->arrayGet(2, &csObj);
-      sepFunc = new Function(colorSpace->arrayGet(3, &obj2));
-      obj2.free();
-      if (!sepFunc->isOk()) {
-       delete sepFunc;
-       sepFunc = NULL;
-      }
-    } else if (obj.isName("ICCBased")) {
-      colorSpace->arrayGet(1, &obj2);
-      if (obj2.isStream()) {
-       if ((dict = obj2.streamGetDict())) {
-         dict->lookup("Alternate", &obj3);
-         if (!obj3.isNull()) {
-           csObj.free();
-           csObj = obj3;
-         } else {
-           obj3.free();
-           dict->lookup("N", &obj3);
-           if (!obj3.isNull()) {
-             csObj.free();
-             if (obj3.getInt() == 4) {
-               csObj.initName("DeviceCMYK");
-             } else if (obj3.getInt() == 3) {
-               csObj.initName("DeviceRGB");
-             } else {
-               csObj.initName("DeviceGray");
-             }
-           }
-           obj3.free();
-         }
+  if (arr->getLength() != 4) {
+    error(-1, "Bad Indexed color space");
+    goto err1;
+  }
+  arr->get(1, &obj1);
+  if (!(base = GfxColorSpace::parse(&obj1))) {
+    error(-1, "Bad Indexed color space (base color space)");
+    goto err2;
+  }
+  obj1.free();
+  if (!arr->get(2, &obj1)->isInt()) {
+    error(-1, "Bad Indexed color space (hival)");
+    goto err2;
+  }
+  indexHigh = obj1.getInt();
+  obj1.free();
+  cs = new GfxIndexedColorSpace(base, indexHigh);
+  arr->get(3, &obj1);
+  n = base->getNComps();
+  if (obj1.isStream()) {
+    obj1.streamReset();
+    for (i = 0; i <= indexHigh; ++i) {
+      for (j = 0; j < n; ++j) {
+       if ((x = obj1.streamGetChar()) == EOF) {
+         error(-1, "Bad Indexed color space (lookup table stream too short)");
+         goto err3;
        }
+       cs->lookup[i*n + j] = (Guchar)x;
       }
-      obj2.free();
-    } else if (obj.isName("Pattern")) {
-      csObj.free();
-      colorSpace->arrayGet(1, &csObj);
     }
-    obj.free();
-  }
-
-  // get mode
-  indexed = gFalse;
-  if (csObj.isName()) {
-    setMode(&csObj);
-  } else if (csObj.isArray()) {
-    csObj.arrayGet(0, &obj);
-    if (obj.isName("Indexed") || obj.isName("I")) {
-      indexed = gTrue;
-      setMode(csObj.arrayGet(1, &obj2));
-      obj2.free();
-    } else {
-      setMode(&csObj);
+    obj1.streamClose();
+  } else if (obj1.isString()) {
+    if (obj1.getString()->getLength() < (indexHigh + 1) * n) {
+      error(-1, "Bad Indexed color space (lookup table string too short)");
+      goto err3;
+    }
+    s = obj1.getString()->getCString();
+    for (i = 0; i <= indexHigh; ++i) {
+      for (j = 0; j < n; ++j) {
+       cs->lookup[i*n + j] = (Guchar)*s++;
+      }
     }
-    obj.free();
   } else {
-    goto err1;
+    error(-1, "Bad Indexed color space (lookup table)");
+    goto err3;
+  }
+  obj1.free();
+  return cs;
+
+ err3:
+  delete cs;
+ err2:
+  obj1.free();
+ err1:
+  return NULL;
+}
+
+void GfxIndexedColorSpace::getGray(GfxColor *color, double *gray) {
+  Guchar *p;
+  GfxColor color2;
+  int n, i;
+
+  n = base->getNComps();
+  p = &lookup[(int)(color->c[0] + 0.5) * n];
+  for (i = 0; i < n; ++i) {
+    color2.c[i] = p[i] / 255.0;
+  }
+  base->getGray(&color2, gray);
+}
+
+void GfxIndexedColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+  Guchar *p;
+  GfxColor color2;
+  int n, i;
+
+  n = base->getNComps();
+  p = &lookup[(int)(color->c[0] + 0.5) * n];
+  for (i = 0; i < n; ++i) {
+    color2.c[i] = p[i] / 255.0;
+  }
+  base->getRGB(&color2, rgb);
+}
+
+void GfxIndexedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+  Guchar *p;
+  GfxColor color2;
+  int n, i;
+
+  n = base->getNComps();
+  p = &lookup[(int)(color->c[0] + 0.5) * n];
+  for (i = 0; i < n; ++i) {
+    color2.c[i] = p[i] / 255.0;
   }
-  if (!ok) {
+  base->getCMYK(&color2, cmyk);
+}
+
+void GfxIndexedColorSpace::getDefaultRanges(double *decodeLow,
+                                           double *decodeRange,
+                                           int maxImgPixel) {
+  decodeLow[0] = 0;
+  decodeRange[0] = maxImgPixel;
+}
+
+//------------------------------------------------------------------------
+// GfxSeparationColorSpace
+//------------------------------------------------------------------------
+
+GfxSeparationColorSpace::GfxSeparationColorSpace(GString *name,
+                                                GfxColorSpace *alt,
+                                                Function *func) {
+  this->name = name;
+  this->alt = alt;
+  this->func = func;
+}
+
+GfxSeparationColorSpace::~GfxSeparationColorSpace() {
+  delete name;
+  delete alt;
+  delete func;
+}
+
+GfxColorSpace *GfxSeparationColorSpace::copy() {
+  return new GfxSeparationColorSpace(name->copy(), alt->copy(), func->copy());
+}
+
+//~ handle the 'All' and 'None' colorants
+GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr) {
+  GfxSeparationColorSpace *cs;
+  GString *name;
+  GfxColorSpace *alt;
+  Function *func;
+  Object obj1;
+
+  if (arr->getLength() != 4) {
+    error(-1, "Bad Separation color space");
     goto err1;
   }
+  if (!arr->get(1, &obj1)->isName()) {
+    error(-1, "Bad Separation color space (name)");
+    goto err2;
+  }
+  name = new GString(obj1.getName());
+  obj1.free();
+  arr->get(2, &obj1);
+  if (!(alt = GfxColorSpace::parse(&obj1))) {
+    error(-1, "Bad Separation color space (alternate color space)");
+    goto err3;
+  }
+  obj1.free();
+  func = Function::parse(arr->get(3, &obj1));
+  obj1.free();
+  if (!func->isOk()) {
+    goto err4;
+  }
+  cs = new GfxSeparationColorSpace(name, alt, func);
+  return cs;
 
-  // get lookup table for indexed colorspace
-  if (indexed) {
-    csObj.arrayGet(2, &obj);
-    if (!obj.isInt())
-      goto err2;
-    indexHigh = obj.getInt();
-    obj.free();
-    lookup = (Guchar (*)[4])gmalloc((indexHigh + 1) * 4 * sizeof(Guchar));
-    csObj.arrayGet(3, &obj);
-    if (obj.isStream()) {
-      obj.streamReset();
-      for (i = 0; i <= indexHigh; ++i) {
-       for (j = 0; j < numComps; ++j) {
-         if ((x = obj.streamGetChar()) == EOF)
-           goto err2;
-         lookup[i][j] = (Guchar)x;
-       }
-      }
-    } else if (obj.isString()) {
-      s = obj.getString()->getCString();
-      for (i = 0; i <= indexHigh; ++i)
-       for (j = 0; j < numComps; ++j)
-         lookup[i][j] = (Guchar)*s++;
-    } else {
+ err4:
+  delete func;
+  delete alt;
+ err3:
+  delete name;
+ err2:
+  obj1.free();
+ err1:
+  return NULL;
+}
+
+void GfxSeparationColorSpace::getGray(GfxColor *color, double *gray) {
+  GfxColor color2;
+
+  func->transform(color->c, color2.c);
+  alt->getGray(&color2, gray);
+}
+
+void GfxSeparationColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+  GfxColor color2;
+
+  func->transform(color->c, color2.c);
+  alt->getRGB(&color2, rgb);
+}
+
+void GfxSeparationColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+  GfxColor color2;
+
+  func->transform(color->c, color2.c);
+  alt->getCMYK(&color2, cmyk);
+}
+
+//------------------------------------------------------------------------
+// GfxDeviceNColorSpace
+//------------------------------------------------------------------------
+
+GfxDeviceNColorSpace::GfxDeviceNColorSpace(int nComps,
+                                          GfxColorSpace *alt,
+                                          Function *func) {
+  this->nComps = nComps;
+  this->alt = alt;
+  this->func = func;
+}
+
+GfxDeviceNColorSpace::~GfxDeviceNColorSpace() {
+  int i;
+
+  for (i = 0; i < nComps; ++i) {
+    delete names[i];
+  }
+  delete alt;
+  delete func;
+}
+
+GfxColorSpace *GfxDeviceNColorSpace::copy() {
+  GfxDeviceNColorSpace *cs;
+  int i;
+
+  cs = new GfxDeviceNColorSpace(nComps, alt->copy(), func->copy());
+  for (i = 0; i < nComps; ++i) {
+    cs->names[i] = names[i]->copy();
+  }
+  return cs;
+}
+
+//~ handle the 'None' colorant
+GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr) {
+  GfxDeviceNColorSpace *cs;
+  int nComps;
+  GString *names[gfxColorMaxComps];
+  GfxColorSpace *alt;
+  Function *func;
+  Object obj1, obj2;
+  int i;
+
+  if (arr->getLength() != 4 && arr->getLength() != 5) {
+    error(-1, "Bad DeviceN color space");
+    goto err1;
+  }
+  if (!arr->get(1, &obj1)->isArray()) {
+    error(-1, "Bad DeviceN color space (names)");
+    goto err2;
+  }
+  nComps = obj1.arrayGetLength();
+  for (i = 0; i < nComps; ++i) {
+    if (!obj1.arrayGet(i, &obj2)->isName()) {
+      error(-1, "Bad DeviceN color space (names)");
+      obj2.free();
       goto err2;
     }
-    obj.free();
+    names[i] = new GString(obj2.getName());
+    obj2.free();
   }
+  obj1.free();
+  arr->get(2, &obj1);
+  if (!(alt = GfxColorSpace::parse(&obj1))) {
+    error(-1, "Bad DeviceN color space (alternate color space)");
+    goto err3;
+  }
+  obj1.free();
+  func = Function::parse(arr->get(3, &obj1));
+  obj1.free();
+  if (!func->isOk()) {
+    goto err4;
+  }
+  cs = new GfxDeviceNColorSpace(nComps, alt, func);
+  for (i = 0; i < nComps; ++i) {
+    cs->names[i] = names[i];
+  }
+  return cs;
 
-  csObj.free();
-  return;
-
+ err4:
+  delete func;
+  delete alt;
+ err3:
+  for (i = 0; i < nComps; ++i) {
+    delete names[i];
+  }
  err2:
-  obj.free();
+  obj1.free();
  err1:
-  csObj.free();
-  ok = gFalse;
+  return NULL;
+}
+
+void GfxDeviceNColorSpace::getGray(GfxColor *color, double *gray) {
+  GfxColor color2;
+
+  func->transform(color->c, color2.c);
+  alt->getGray(&color2, gray);
+}
+
+void GfxDeviceNColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+  GfxColor color2;
+
+  func->transform(color->c, color2.c);
+  alt->getRGB(&color2, rgb);
+}
+
+void GfxDeviceNColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+  GfxColor color2;
+
+  func->transform(color->c, color2.c);
+  alt->getCMYK(&color2, cmyk);
 }
 
-GfxColorSpace::GfxColorSpace(GfxColorMode mode1) {
-  sepFunc = NULL;
-  mode = mode1;
-  indexed = gFalse;
-  switch (mode) {
-  case colorGray: numComps = 1; break;
-  case colorCMYK: numComps = 4; break;
-  case colorRGB:  numComps = 3; break;
-  case colorLab:  numComps = 3; break;
+//------------------------------------------------------------------------
+// GfxPatternColorSpace
+//------------------------------------------------------------------------
+
+GfxPatternColorSpace::GfxPatternColorSpace(GfxColorSpace *under) {
+  this->under = under;
+}
+
+GfxPatternColorSpace::~GfxPatternColorSpace() {
+  if (under) {
+    delete under;
   }
-  lookup = NULL;
-  ok = gTrue;
 }
 
-GfxColorSpace::~GfxColorSpace() {
-  if (sepFunc)
-    delete sepFunc;
-  gfree(lookup);
+GfxColorSpace *GfxPatternColorSpace::copy() {
+  return new GfxPatternColorSpace(under ? under->copy() :
+                                         (GfxColorSpace *)NULL);
 }
 
-GfxColorSpace::GfxColorSpace(GfxColorSpace *colorSpace) {
-  int size;
-
-  if (colorSpace->sepFunc)
-    sepFunc = colorSpace->sepFunc->copy();
-  else
-    sepFunc = NULL;
-  mode = colorSpace->mode;
-  indexed = colorSpace->indexed;
-  numComps = colorSpace->numComps;
-  indexHigh = colorSpace->indexHigh;
-  if (indexed) {
-    size = (indexHigh + 1) * 4 * sizeof(Guchar);
-    lookup = (Guchar (*)[4])gmalloc(size);
-    memcpy(lookup, colorSpace->lookup, size);
-  } else {
-    lookup = NULL;
+GfxColorSpace *GfxPatternColorSpace::parse(Array *arr) {
+  GfxPatternColorSpace *cs;
+  GfxColorSpace *under;
+  Object obj1;
+
+  if (arr->getLength() != 1 && arr->getLength() != 2) {
+    error(-1, "Bad Pattern color space");
+    return NULL;
   }
-  ok = gTrue;
+  under = NULL;
+  if (arr->getLength() == 2) {
+    arr->get(1, &obj1);
+    if (!(under = GfxColorSpace::parse(&obj1))) {
+      error(-1, "Bad Pattern color space (underlying color space)");
+      obj1.free();
+      return NULL;
+    }
+    obj1.free();
+  }
+  cs = new GfxPatternColorSpace(under);
+  return cs;
 }
 
-void GfxColorSpace::setMode(Object *colorSpace) {
-  Object obj1, obj2, obj3, obj4;
-
-  if (colorSpace->isName("DeviceGray") || colorSpace->isName("G")) {
-    mode = colorGray;
-    numComps = 1;
-  } else if (colorSpace->isName("DeviceRGB") || colorSpace->isName("RGB")) {
-    mode = colorRGB;
-    numComps = 3;
-  } else if (colorSpace->isName("DeviceCMYK") || colorSpace->isName("CMYK")) {
-    mode = colorCMYK;
-    numComps = 4;
-  } else if (colorSpace->isArray()) {
-    colorSpace->arrayGet(0, &obj1);
-    if (obj1.isName("CalGray")) {
-      mode = colorGray;
-      numComps = 1;
-    } else if (obj1.isName("CalRGB")) {
-      mode = colorRGB;
-      numComps = 3;
-    } else if (obj1.isName("CalCMYK")) {
-      mode = colorCMYK;
-      numComps = 4;
-    } else if (obj1.isName("Lab")) {
-      mode = colorLab;
-      numComps = 3;
-      labParams.whiteX = 0.9505;
-      labParams.whiteY = 1;
-      labParams.whiteZ = 1.0890;
-      labParams.aMin = -100;
-      labParams.aMax = 100;
-      labParams.bMin = -100;
-      labParams.bMax = 100;
-      colorSpace->arrayGet(1, &obj2);
-      if (obj2.isDict()) {
-       obj2.dictLookup("WhitePoint", &obj3);
-       if (obj3.isArray() && obj3.arrayGetLength() == 3) {
-         obj3.arrayGet(0, &obj4);
-         if (obj4.isNum()) {
-           labParams.whiteX = obj4.getNum();
-         }
-         obj4.free();
-         obj3.arrayGet(1, &obj4);
-         if (obj4.isNum()) {
-           labParams.whiteY = obj4.getNum();
-         }
-         obj4.free();
-         obj3.arrayGet(2, &obj4);
-         if (obj4.isNum()) {
-           labParams.whiteZ = obj4.getNum();
-         }
-         obj4.free();
-       }
-       obj3.free();
-       obj2.dictLookup("Range", &obj3);
-       if (obj3.isArray() && obj3.arrayGetLength() == 4) {
-         obj3.arrayGet(0, &obj4);
-         if (obj4.isNum()) {
-           labParams.aMin = obj4.getNum();
-         }
-         obj4.free();
-         obj3.arrayGet(1, &obj4);
-         if (obj4.isNum()) {
-           labParams.aMax = obj4.getNum();
-         }
-         obj4.free();
-         obj3.arrayGet(2, &obj4);
-         if (obj4.isNum()) {
-           labParams.bMin = obj4.getNum();
-         }
-         obj4.free();
-         obj3.arrayGet(3, &obj4);
-         if (obj4.isNum()) {
-           labParams.bMax = obj4.getNum();
-         }
-         obj4.free();
-       }
-       obj3.free();
-      }
-      obj2.free();
-    } else {
-      ok = gFalse;
+void GfxPatternColorSpace::getGray(GfxColor *color, double *gray) {
+  *gray = 0;
+}
+
+void GfxPatternColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+  rgb->r = rgb->g = rgb->b = 0;
+}
+
+void GfxPatternColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+  cmyk->c = cmyk->m = cmyk->y = 0;
+  cmyk->k = 1;
+}
+
+//------------------------------------------------------------------------
+// Pattern
+//------------------------------------------------------------------------
+
+GfxPattern::GfxPattern(int type) {
+  this->type = type;
+}
+
+GfxPattern::~GfxPattern() {
+}
+
+GfxPattern *GfxPattern::parse(Object *obj) {
+  GfxPattern *pattern;
+  Dict *dict;
+  Object obj1;
+
+  pattern = NULL;
+  if (obj->isStream()) {
+    dict = obj->streamGetDict();
+    dict->lookup("PatternType", &obj1);
+    if (obj1.isInt() && obj1.getInt() == 1) {
+      pattern = new GfxTilingPattern(dict, obj);
     }
     obj1.free();
-  } else {
-    ok = gFalse;
   }
+  return pattern;
 }
 
-void GfxColorSpace::getDefaultRanges(double *decodeLow, double *decodeRange,
-                                    int maxPixel) {
+//------------------------------------------------------------------------
+// GfxTilingPattern
+//------------------------------------------------------------------------
+
+GfxTilingPattern::GfxTilingPattern(Dict *streamDict, Object *stream):
+  GfxPattern(1)
+{
+  Object obj1, obj2;
   int i;
 
-  if (indexed) {
-    decodeLow[0] = 0;
-    decodeRange[0] = maxPixel;
-  } else if (mode == colorLab) {
-    decodeLow[0] = 0;
-    decodeRange[0] = 100;
-    decodeLow[1] = labParams.aMin;
-    decodeRange[1] = labParams.aMax - labParams.aMin;
-    decodeLow[2] = labParams.bMin;
-    decodeRange[2] = labParams.bMax - labParams.bMin;
+  if (streamDict->lookup("PaintType", &obj1)->isInt()) {
+    paintType = obj1.getInt();
+  } else {
+    paintType = 1;
+    error(-1, "Invalid or missing PaintType in pattern");
+  }
+  obj1.free();
+  if (streamDict->lookup("TilingType", &obj1)->isInt()) {
+    tilingType = obj1.getInt();
+  } else {
+    tilingType = 1;
+    error(-1, "Invalid or missing TilingType in pattern");
+  }
+  obj1.free();
+  bbox[0] = bbox[1] = 0;
+  bbox[2] = bbox[3] = 1;
+  if (streamDict->lookup("BBox", &obj1)->isArray() &&
+      obj1.arrayGetLength() == 4) {
+    for (i = 0; i < 4; ++i) {
+      if (obj1.arrayGet(i, &obj2)->isNum()) {
+       bbox[i] = obj2.getNum();
+      }
+      obj2.free();
+    }
+  } else {
+    error(-1, "Invalid or missing BBox in pattern");
+  }
+  obj1.free();
+  if (streamDict->lookup("XStep", &obj1)->isNum()) {
+    xStep = obj1.getNum();
   } else {
-    for (i = 0; i < numComps; ++i) {
-      decodeLow[i] = 0;
-      decodeRange[i] = 1;
+    xStep = 1;
+    error(-1, "Invalid or missing XStep in pattern");
+  }
+  obj1.free();
+  if (streamDict->lookup("YStep", &obj1)->isNum()) {
+    yStep = obj1.getNum();
+  } else {
+    yStep = 1;
+    error(-1, "Invalid or missing YStep in pattern");
+  }
+  obj1.free();
+  if (!streamDict->lookup("Resources", &resDict)->isDict()) {
+    resDict.free();
+    resDict.initNull();
+    error(-1, "Invalid or missing Resources in pattern");
+  }
+  matrix[0] = 1; matrix[1] = 0;
+  matrix[2] = 0; matrix[3] = 1;
+  matrix[4] = 0; matrix[5] = 0;
+  if (streamDict->lookup("Matrix", &obj1)->isArray() &&
+      obj1.arrayGetLength() == 6) {
+    for (i = 0; i < 6; ++i) {
+      if (obj1.arrayGet(i, &obj2)->isNum()) {
+       matrix[i] = obj2.getNum();
+      }
+      obj2.free();
     }
   }
+  obj1.free();
+  stream->copy(&contentStream);
+}
+
+GfxTilingPattern::~GfxTilingPattern() {
+  resDict.free();
+  contentStream.free();
 }
 
-void GfxColorSpace::getColor(double x[4], GfxColor *color) {
-  double y[4];
-  Guchar *p;
+GfxPattern *GfxTilingPattern::copy() {
+  return new GfxTilingPattern(this);
+}
 
-  if (sepFunc) {
-    sepFunc->transform(x, y);
-  } else {
-    y[0] = x[0];
-    y[1] = x[1];
-    y[2] = x[2];
-    y[3] = x[3];
-  }
-  if (indexed) {
-    p = lookup[(int)(y[0] + 0.5)];
-    switch (mode) {
-    case colorGray:
-      color->setGray(p[0] / 255.0);
-      break;
-    case colorCMYK:
-      color->setCMYK(p[0] / 255.0, p[1] / 255.0, p[2] / 255.0, p[3] / 255.0);
-      break;
-    case colorRGB:
-      color->setRGB(p[0] / 255.0, p[1] / 255.0, p[2] / 255.0);
-      break;
-    case colorLab:
-      color->setLab(p[0] / 255.0, p[1] / 255.0, p[2] / 255.0, &labParams);
-      break;
-    }
-  } else {
-    switch (mode) {
-    case colorGray:
-      color->setGray(y[0]);
-      break;
-    case colorCMYK:
-      color->setCMYK(y[0], y[1], y[2], y[3]);
-      break;
-    case colorRGB:
-      color->setRGB(y[0], y[1], y[2]);
-      break;
-    case colorLab:
-      color->setLab(y[0], y[1], y[2], &labParams);
-      break;
-    }
-  }
+GfxTilingPattern::GfxTilingPattern(GfxTilingPattern *pat):
+  GfxPattern(1)
+{
+  memcpy(this, pat, sizeof(GfxTilingPattern));
+  pat->resDict.copy(&resDict);
+  pat->contentStream.copy(&contentStream);
 }
 
 //------------------------------------------------------------------------
 // Function
 //------------------------------------------------------------------------
 
-Function::Function(Object *funcObj) {
-  Stream *str;
-  Dict *dict;
-  int nSamples, sampleBits;
-  double sampleMul;
-  Object obj1, obj2;
-  Guint buf, bitMask;
-  int bits;
-  int s;
-  int i;
+Function::Function() {
+}
 
-  ok = gFalse;
-  samples = NULL;
+Function::~Function() {
+}
 
-  if (!funcObj->isStream()) {
-    error(-1, "Expected function dictionary");
-    goto err3;
+Function *Function::parse(Object *funcObj) {
+  Function *func;
+  Dict *dict;
+  int funcType;
+  Object obj1;
+
+  if (funcObj->isStream()) {
+    dict = funcObj->streamGetDict();
+  } else if (funcObj->isDict()) {
+    dict = funcObj->getDict();
+  } else {
+    error(-1, "Expected function dictionary or stream");
+    return NULL;
   }
-  str = funcObj->getStream();
-  dict = str->getDict();
 
-  //----- FunctionType
-  if (!dict->lookup("FunctionType", &obj1)->isInt() ||
-      obj1.getInt() != 0) {
-    error(-1, "Unknown function type");
-    goto err2;
+  if (!dict->lookup("FunctionType", &obj1)->isInt()) {
+    error(-1, "Function type is missing or wrong type");
+    obj1.free();
+    return NULL;
   }
+  funcType = obj1.getInt();
   obj1.free();
 
+  if (funcType == 0) {
+    func = new SampledFunction(funcObj, dict);
+  } else if (funcType == 2) {
+    func = new ExponentialFunction(funcObj, dict);
+  } else {
+    error(-1, "Unimplemented function type");
+    return NULL;
+  }
+  if (!func->isOk()) {
+    delete func;
+    return NULL;
+  }
+
+  return func;
+}
+
+GBool Function::init(Dict *dict) {
+  Object obj1, obj2;
+  int i;
+
   //----- Domain
   if (!dict->lookup("Domain", &obj1)->isArray()) {
     error(-1, "Function is missing domain");
     goto err2;
   }
   m = obj1.arrayGetLength() / 2;
-  if (m > 1) {
-    error(-1, "Functions with more than 1 input are unsupported");
+  if (m > funcMaxInputs) {
+    error(-1, "Functions with more than %d inputs are unsupported",
+         funcMaxInputs);
     goto err2;
   }
   for (i = 0; i < m; ++i) {
@@ -519,32 +1319,76 @@ Function::Function(Object *funcObj) {
   obj1.free();
 
   //----- Range
-  if (!dict->lookup("Range", &obj1)->isArray()) {
-    error(-1, "Function is missing range");
-    goto err2;
-  }
-  n = obj1.arrayGetLength() / 2;
-  if (n > 4) {
-    error(-1, "Functions with more than 4 outputs are unsupported");
-    goto err2;
-  }
-  for (i = 0; i < n; ++i) {
-    obj1.arrayGet(2*i, &obj2);
-    if (!obj2.isNum()) {
-      error(-1, "Illegal value in function range array");
-      goto err1;
+  hasRange = gFalse;
+  n = 0;
+  if (dict->lookup("Range", &obj1)->isArray()) {
+    hasRange = gTrue;
+    n = obj1.arrayGetLength() / 2;
+    if (n > funcMaxOutputs) {
+      error(-1, "Functions with more than %d outputs are unsupported",
+           funcMaxOutputs);
+      goto err2;
     }
-    range[i][0] = obj2.getNum();
-    obj2.free();
-    obj1.arrayGet(2*i+1, &obj2);
-    if (!obj2.isNum()) {
-      error(-1, "Illegal value in function range array");
-      goto err1;
+    for (i = 0; i < n; ++i) {
+      obj1.arrayGet(2*i, &obj2);
+      if (!obj2.isNum()) {
+       error(-1, "Illegal value in function range array");
+       goto err1;
+      }
+      range[i][0] = obj2.getNum();
+      obj2.free();
+      obj1.arrayGet(2*i+1, &obj2);
+      if (!obj2.isNum()) {
+       error(-1, "Illegal value in function range array");
+       goto err1;
+      }
+      range[i][1] = obj2.getNum();
+      obj2.free();
     }
-    range[i][1] = obj2.getNum();
-    obj2.free();
+    obj1.free();
   }
+
+  return gTrue;
+
+ err1:
+  obj2.free();
+ err2:
   obj1.free();
+  return gFalse;
+}
+
+//------------------------------------------------------------------------
+// SampledFunction
+//------------------------------------------------------------------------
+
+SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
+  Stream *str;
+  int nSamples, sampleBits;
+  double sampleMul;
+  Object obj1, obj2;
+  Guint buf, bitMask;
+  int bits;
+  int s;
+  int i;
+
+  samples = NULL;
+  ok = gFalse;
+
+  //----- initialize the generic stuff
+  if (!init(dict)) {
+    goto err1;
+  }
+  if (!hasRange) {
+    error(-1, "Type 0 function is missing range");
+    goto err1;
+  }
+
+  //----- get the stream
+  if (!funcObj->isStream()) {
+    error(-1, "Type 0 function isn't a stream");
+    goto err1;
+  }
+  str = funcObj->getStream();
 
   //----- Size
   if (!dict->lookup("Size", &obj1)->isArray() ||
@@ -556,7 +1400,7 @@ Function::Function(Object *funcObj) {
     obj1.arrayGet(i, &obj2);
     if (!obj2.isInt()) {
       error(-1, "Illegal value in function size array");
-      goto err1;
+      goto err3;
     }
     sampleSize[i] = obj2.getInt();
     obj2.free();
@@ -579,14 +1423,14 @@ Function::Function(Object *funcObj) {
       obj1.arrayGet(2*i, &obj2);
       if (!obj2.isNum()) {
        error(-1, "Illegal value in function encode array");
-       goto err1;
+       goto err3;
       }
       encode[i][0] = obj2.getNum();
       obj2.free();
       obj1.arrayGet(2*i+1, &obj2);
       if (!obj2.isNum()) {
        error(-1, "Illegal value in function encode array");
-       goto err1;
+       goto err3;
       }
       encode[i][1] = obj2.getNum();
       obj2.free();
@@ -606,14 +1450,14 @@ Function::Function(Object *funcObj) {
       obj1.arrayGet(2*i, &obj2);
       if (!obj2.isNum()) {
        error(-1, "Illegal value in function decode array");
-       goto err1;
+       goto err3;
       }
       decode[i][0] = obj2.getNum();
       obj2.free();
       obj1.arrayGet(2*i+1, &obj2);
       if (!obj2.isNum()) {
        error(-1, "Illegal value in function decode array");
-       goto err1;
+       goto err3;
       }
       decode[i][1] = obj2.getNum();
       obj2.free();
@@ -656,44 +1500,39 @@ Function::Function(Object *funcObj) {
     }
     samples[i] = (double)s * sampleMul;
   }
+  str->close();
 
   ok = gTrue;
   return;
 
- err1:
+ err3:
   obj2.free();
  err2:
   obj1.free();
- err3:
+ err1:
   return;
 }
 
-Function::Function(Function *func) {
+SampledFunction::~SampledFunction() {
+  if (samples) {
+    gfree(samples);
+  }
+}
+
+SampledFunction::SampledFunction(SampledFunction *func) {
   int nSamples, i;
 
-  m = func->m;
-  n = func->n;
-  memcpy(domain, func->domain, sizeof(domain));
-  memcpy(range, func->range, sizeof(range));
-  memcpy(sampleSize, func->sampleSize, sizeof(sampleSize));
-  memcpy(encode, func->encode, sizeof(encode));
-  memcpy(decode, func->decode, sizeof(decode));
+  memcpy(this, func, sizeof(SampledFunction));
 
   nSamples = n;
-  for (i = 0; i < m; ++i)
+  for (i = 0; i < m; ++i) {
     nSamples *= sampleSize[i];
+  }
   samples = (double *)gmalloc(nSamples * sizeof(double));
   memcpy(samples, func->samples, nSamples * sizeof(double));
-
-  ok = gTrue;
-}
-
-Function::~Function() {
-  if (samples)
-    gfree(samples);
 }
 
-void Function::transform(double *in, double *out) {
+void SampledFunction::transform(double *in, double *out) {
   double e[4];
   double s;
   double x0, x1;
@@ -705,10 +1544,11 @@ void Function::transform(double *in, double *out) {
   for (i = 0; i < m; ++i) {
     e[i] = ((in[i] - domain[i][0]) / (domain[i][1] - domain[i][0])) *
            (encode[i][1] - encode[i][0]) + encode[i][0];
-    if (e[i] < 0)
+    if (e[i] < 0) {
       e[i] = 0;
-    else if (e[i] > sampleSize[i] - 1)
+    } else if (e[i] > sampleSize[i] - 1) {
       e[i] = sampleSize[i] - 1;
+    }
   }
 
   for (i = 0; i < n; ++i) {
@@ -724,53 +1564,174 @@ void Function::transform(double *in, double *out) {
 
     // map output values to range
     out[i] = s * (decode[i][1] - decode[i][0]) + decode[i][0];
-    if (out[i] < range[i][0])
+    if (out[i] < range[i][0]) {
       out[i] = range[i][0];
-    else if (out[i] > range[i][1])
+    } else if (out[i] > range[i][1]) {
       out[i] = range[i][1];
+    }
   }
 }
 
+//------------------------------------------------------------------------
+// ExponentialFunction
+//------------------------------------------------------------------------
+
+ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) {
+  Object obj1, obj2;
+  GBool hasN;
+  int i;
+
+  ok = gFalse;
+  hasN = gFalse;
+
+  //----- initialize the generic stuff
+  if (!init(dict)) {
+    goto err1;
+  }
+  if (m != 1) {
+    error(-1, "Exponential function with more than one input");
+    goto err1;
+  }
+
+  //----- default values
+  for (i = 0; i < funcMaxOutputs; ++i) {
+    c0[i] = 0;
+    c1[i] = 1;
+  }
+
+  //----- C0
+  if (dict->lookup("C0", &obj1)->isArray()) {
+    if (!hasN) {
+      n = obj1.arrayGetLength();
+    } else if (obj1.arrayGetLength() != n) {
+      error(-1, "Function's C0 array is wrong length");
+      goto err2;
+    }
+    for (i = 0; i < n; ++i) {
+      obj1.arrayGet(i, &obj2);
+      if (!obj2.isNum()) {
+       error(-1, "Illegal value in function C0 array");
+       goto err3;
+      }
+      c0[i] = obj2.getNum();
+      obj2.free();
+    }
+    obj1.free();
+  }
+
+  //----- C1
+  if (dict->lookup("C1", &obj1)->isArray()) {
+    if (!hasN) {
+      n = obj1.arrayGetLength();
+    } else if (obj1.arrayGetLength() != n) {
+      error(-1, "Function's C1 array is wrong length");
+      goto err2;
+    }
+    for (i = 0; i < n; ++i) {
+      obj1.arrayGet(i, &obj2);
+      if (!obj2.isNum()) {
+       error(-1, "Illegal value in function C1 array");
+       goto err3;
+      }
+      c1[i] = obj2.getNum();
+      obj2.free();
+    }
+    obj1.free();
+  }
+
+  //----- N (exponent)
+  if (!dict->lookup("N", &obj1)->isNum()) {
+    error(-1, "Function has missing or invalid N");
+    goto err2;
+  }
+  e = obj1.getNum();
+  obj1.free();
+
+  ok = gTrue;
+  return;
+
+ err3:
+  obj2.free();
+ err2:
+  obj1.free();
+ err1:
+  return;
+}
+
+ExponentialFunction::~ExponentialFunction() {
+}
+
+ExponentialFunction::ExponentialFunction(ExponentialFunction *func) {
+  memcpy(this, func, sizeof(ExponentialFunction));
+}
+
+void ExponentialFunction::transform(double *in, double *out) {
+  double x;
+  int i;
+
+  if (in[0] < domain[0][0]) {
+    x = domain[0][0];
+  } else if (in[0] > domain[0][1]) {
+    x = domain[0][1];
+  } else {
+    x = in[0];
+  }
+  for (i = 0; i < n; ++i) {
+    out[i] = c0[i] + pow(x, e) * (c1[i] - c0[i]);
+    if (hasRange) {
+      if (out[i] < range[i][0]) {
+       out[i] = range[i][0];
+      } else if (out[i] > range[i][1]) {
+       out[i] = range[i][1];
+      }
+    }
+  }
+  return;
+}
+
 //------------------------------------------------------------------------
 // GfxImageColorMap
 //------------------------------------------------------------------------
 
-GfxImageColorMap::GfxImageColorMap(int bits1, Object *decode,
-                                  GfxColorSpace *colorSpace1) {
-  GfxColor color;
-  double x[4];
-  int maxPixel;
+GfxImageColorMap::GfxImageColorMap(int bits, Object *decode,
+                                  GfxColorSpace *colorSpace) {
+  GfxIndexedColorSpace *indexedCS;
+  GfxSeparationColorSpace *sepCS;
+  int maxPixel, indexHigh;
+  Guchar *lookup2;
+  Function *sepFunc;
   Object obj;
-  int i, j;
+  double x;
+  double y[gfxColorMaxComps];
+  int i, j, k;
 
   ok = gTrue;
 
-  // bits per component and colorspace
-  bits = bits1;
+  // bits per component and color space
+  this->bits = bits;
   maxPixel = (1 << bits) - 1;
-  colorSpace = colorSpace1;
-  mode = colorSpace->getMode();
+  this->colorSpace = colorSpace;
 
   // get decode map
-  indexed = colorSpace->isIndexed();
-  sep = colorSpace->isSeparation();
   if (decode->isNull()) {
-    numComps = colorSpace->getNumPixelComps();
+    nComps = colorSpace->getNComps();
     colorSpace->getDefaultRanges(decodeLow, decodeRange, maxPixel);
   } else if (decode->isArray()) {
-    numComps = decode->arrayGetLength() / 2;
-    if (numComps != colorSpace->getNumPixelComps())
+    nComps = decode->arrayGetLength() / 2;
+    if (nComps != colorSpace->getNComps()) {
       goto err1;
-    indexed = colorSpace->isIndexed();
-    for (i = 0; i < numComps; ++i) {
+    }
+    for (i = 0; i < nComps; ++i) {
       decode->arrayGet(2*i, &obj);
-      if (!obj.isNum())
+      if (!obj.isNum()) {
        goto err2;
+      }
       decodeLow[i] = obj.getNum();
       obj.free();
       decode->arrayGet(2*i+1, &obj);
-      if (!obj.isNum())
+      if (!obj.isNum()) {
        goto err2;
+      }
       decodeRange[i] = obj.getNum() - decodeLow[i];
       obj.free();
     }
@@ -778,42 +1739,64 @@ GfxImageColorMap::GfxImageColorMap(int bits1, Object *decode,
     goto err1;
   }
 
+#if 0 //~
   // handle the case where fewer than 2^n palette entries of an n-bit
   // indexed color space are populated (this happens, e.g., in files
   // optimized by Distiller)
-  if (colorSpace->isIndexed() && maxPixel > colorSpace->getIndexHigh()) {
-    maxPixel = colorSpace->getIndexHigh();
-  }
-
-  // handle the case where fewer than 2^n palette entries of an n-bit
-  // indexed color space are populated (this happens, e.g., in files
-  // optimized by Distiller)
-  if (indexed && maxPixel > colorSpace->getIndexHigh()) {
-    maxPixel = colorSpace->getIndexHigh();
+  if (colorSpace->getMode() == csIndexed) {
+    i = ((GfxIndexedColorSpace *)colorSpace)->getIndexHigh();
+    if (i < maxPixel) {
+      maxPixel = i;
+    }
   }
+#endif
 
-  // construct lookup table
-  lookup = (double (*)[4])gmalloc((maxPixel + 1) * 4 * sizeof(double));
-  if (sep) {
-    for (i = 0; i <= maxPixel; ++i) {
-      x[0] = (double)i / (double)maxPixel;
-      colorSpace->getColor(x, &color);
-      lookup[i][0] = color.getR();
-      lookup[i][1] = color.getG();
-      lookup[i][2] = color.getB();
+  // Construct a lookup table -- this stores pre-computed decoded
+  // values for each component, i.e., the result of applying the
+  // decode mapping to each possible image pixel component value.
+  //
+  // Optimization: for Indexed and Separation color spaces (which have
+  // only one component), we store color values in the lookup table
+  // rather than component values.
+  colorSpace2 = NULL;
+  nComps2 = 0;
+  if (colorSpace->getMode() == csIndexed) {
+    // Note that indexHigh may not be the same as maxPixel --
+    // Distiller will remove unused palette entries, resulting in
+    // indexHigh < maxPixel.
+    indexedCS = (GfxIndexedColorSpace *)colorSpace;
+    colorSpace2 = indexedCS->getBase();
+    indexHigh = indexedCS->getIndexHigh();
+    nComps2 = colorSpace2->getNComps();
+    lookup = (double *)gmalloc((indexHigh + 1) * nComps2 * sizeof(double));
+    lookup2 = indexedCS->getLookup();
+    for (i = 0; i <= indexHigh; ++i) {
+      j = (int)(decodeLow[0] +(i * decodeRange[0]) / maxPixel + 0.5);
+      for (k = 0; k < nComps2; ++k) {
+       lookup[i*nComps2 + k] = lookup2[i*nComps2 + k] / 255.0;
+      }
     }
-  } else if (indexed) {
+  } else if (colorSpace->getMode() == csSeparation) {
+    sepCS = (GfxSeparationColorSpace *)colorSpace;
+    colorSpace2 = sepCS->getAlt();
+    nComps2 = colorSpace2->getNComps();
+    lookup = (double *)gmalloc((maxPixel + 1) * nComps2 * sizeof(double));
+    sepFunc = sepCS->getFunc();
     for (i = 0; i <= maxPixel; ++i) {
-      x[0] = (double)i;
-      colorSpace->getColor(x, &color);
-      lookup[i][0] = color.getR();
-      lookup[i][1] = color.getG();
-      lookup[i][2] = color.getB();
+      x = decodeLow[0] + (i * decodeRange[0]) / maxPixel;
+      sepFunc->transform(&x, y);
+      for (k = 0; k < nComps2; ++k) {
+       lookup[i*nComps2 + k] = y[k];
+      }
     }
   } else {
-    for (i = 0; i <= maxPixel; ++i)
-      for (j = 0; j < numComps; ++j)
-       lookup[i][j] = decodeLow[j] + (i * decodeRange[j]) / maxPixel;
+    lookup = (double *)gmalloc((maxPixel + 1) * nComps * sizeof(double));
+    for (i = 0; i <= maxPixel; ++i) {
+      for (k = 0; k < nComps; ++k) {
+       lookup[i*nComps + k] = decodeLow[k] +
+                                (i * decodeRange[k]) / maxPixel;
+      }
+    }
   }
 
   return;
@@ -829,29 +1812,60 @@ GfxImageColorMap::~GfxImageColorMap() {
   gfree(lookup);
 }
 
-void GfxImageColorMap::getColor(Guchar x[4], GfxColor *color) {
+void GfxImageColorMap::getGray(Guchar *x, double *gray) {
+  GfxColor color;
   double *p;
+  int i;
 
-  if (sep || indexed) {
-    p = lookup[x[0]];
-    color->setRGB(p[0], p[1], p[2]);
+  if (colorSpace2) {
+    p = &lookup[x[0] * nComps2];
+    for (i = 0; i < nComps2; ++i) {
+      color.c[i] = *p++;
+    }
+    colorSpace2->getGray(&color, gray);
   } else {
-    switch (mode) {
-    case colorGray:
-      color->setGray(lookup[x[0]][0]);
-      break;
-    case colorCMYK:
-      color->setCMYK(lookup[x[0]][0], lookup[x[1]][1],
-                    lookup[x[2]][2], lookup[x[3]][3]);
-      break;
-    case colorRGB:
-      color->setRGB(lookup[x[0]][0], lookup[x[1]][1], lookup[x[2]][2]);
-      break;
-    case colorLab:
-      color->setLab(lookup[x[0]][0], lookup[x[1]][1], lookup[x[2]][2],
-                   colorSpace->getLabParams());
-      break;
+    for (i = 0; i < nComps; ++i) {
+      color.c[i] = lookup[x[i] * nComps + i];
+    }
+    colorSpace->getGray(&color, gray);
+  }
+}
+
+void GfxImageColorMap::getRGB(Guchar *x, GfxRGB *rgb) {
+  GfxColor color;
+  double *p;
+  int i;
+
+  if (colorSpace2) {
+    p = &lookup[x[0] * nComps2];
+    for (i = 0; i < nComps2; ++i) {
+      color.c[i] = *p++;
+    }
+    colorSpace2->getRGB(&color, rgb);
+  } else {
+    for (i = 0; i < nComps; ++i) {
+      color.c[i] = lookup[x[i] * nComps + i];
+    }
+    colorSpace->getRGB(&color, rgb);
+  }
+}
+
+void GfxImageColorMap::getCMYK(Guchar *x, GfxCMYK *cmyk) {
+  GfxColor color;
+  double *p;
+  int i;
+
+  if (colorSpace2) {
+    p = &lookup[x[0] * nComps2];
+    for (i = 0; i < nComps2; ++i) {
+      color.c[i] = *p++;
     }
+    colorSpace2->getCMYK(&color, cmyk);
+  } else {
+    for (i = 0; i < nComps; ++i) {
+      color.c[i] = lookup[x[i] * nComps + i];
+    }
+    colorSpace->getCMYK(&color, cmyk);
   }
 }
 
@@ -1000,15 +2014,15 @@ void GfxPath::curveTo(double x1, double y1, double x2, double y2,
 // GfxState
 //------------------------------------------------------------------------
 
-GfxState::GfxState(int dpi, double px1a, double py1a, double px2a, double py2a,
-                  int rotate, GBool upsideDown) {
+GfxState::GfxState(double dpi, double px1a, double py1a,
+                  double px2a, double py2a, int rotate, GBool upsideDown) {
   double k;
 
   px1 = px1a;
   py1 = py1a;
   px2 = px2a;
   py2 = py2a;
-  k = (double)dpi / 72.0;
+  k = dpi / 72.0;
   if (rotate == 90) {
     ctm[0] = 0;
     ctm[1] = upsideDown ? k : -k;
@@ -1047,10 +2061,14 @@ GfxState::GfxState(int dpi, double px1a, double py1a, double px2a, double py2a,
     pageHeight = k * (py2 - py1);
   }
 
-  fillColorSpace = new GfxColorSpace(colorGray);
-  strokeColorSpace = new GfxColorSpace(colorGray);
-  fillColor.setGray(0);
-  strokeColor.setGray(0);
+  fillColorSpace = new GfxDeviceGrayColorSpace();
+  strokeColorSpace = new GfxDeviceGrayColorSpace();
+  fillColor.c[0] = 0;
+  strokeColor.c[0] = 0;
+  fillPattern = NULL;
+  strokePattern = NULL;
+  fillOpacity = 1;
+  strokeOpacity = 1;
 
   lineWidth = 1;
   lineDash = NULL;
@@ -1081,23 +2099,40 @@ GfxState::GfxState(int dpi, double px1a, double py1a, double px2a, double py2a,
 }
 
 GfxState::~GfxState() {
-  if (fillColorSpace)
+  if (fillColorSpace) {
     delete fillColorSpace;
-  if (strokeColorSpace)
+  }
+  if (strokeColorSpace) {
     delete strokeColorSpace;
+  }
+  if (fillPattern) {
+    delete fillPattern;
+  }
+  if (strokePattern) {
+    delete strokePattern;
+  }
   gfree(lineDash);
   delete path;
-  if (saved)
+  if (saved) {
     delete saved;
+  }
 }
 
 // Used for copy();
 GfxState::GfxState(GfxState *state) {
   memcpy(this, state, sizeof(GfxState));
-  if (fillColorSpace)
+  if (fillColorSpace) {
     fillColorSpace = state->fillColorSpace->copy();
-  if (strokeColorSpace)
+  }
+  if (strokeColorSpace) {
     strokeColorSpace = state->strokeColorSpace->copy();
+  }
+  if (fillPattern) {
+    fillPattern = state->fillPattern->copy();
+  }
+  if (strokePattern) {
+    strokePattern = state->strokePattern->copy();
+  }
   if (lineDashLength > 0) {
     lineDash = (double *)gmalloc(lineDashLength * sizeof(double));
     memcpy(lineDash, state->lineDash, lineDashLength * sizeof(double));
@@ -1158,17 +2193,33 @@ void GfxState::concatCTM(double a, double b, double c,
 }
 
 void GfxState::setFillColorSpace(GfxColorSpace *colorSpace) {
-  if (fillColorSpace)
+  if (fillColorSpace) {
     delete fillColorSpace;
+  }
   fillColorSpace = colorSpace;
 }
 
 void GfxState::setStrokeColorSpace(GfxColorSpace *colorSpace) {
-  if (strokeColorSpace)
+  if (strokeColorSpace) {
     delete strokeColorSpace;
+  }
   strokeColorSpace = colorSpace;
 }
 
+void GfxState::setFillPattern(GfxPattern *pattern) {
+  if (fillPattern) {
+    delete fillPattern;
+  }
+  fillPattern = pattern;
+}
+
+void GfxState::setStrokePattern(GfxPattern *pattern) {
+  if (strokePattern) {
+    delete strokePattern;
+  }
+  strokePattern = pattern;
+}
+
 void GfxState::setLineDash(double *dash, int length, double start) {
   if (lineDash)
     gfree(lineDash);
index 83fd69ddcc1098c3490cb8700b26b9191bbfbeb3..2056c4d1fb36f6f110a82fbb08d103f3e3e64e4e 100644 (file)
 #endif
 
 #include "gtypes.h"
+#include "Object.h"
 
-class Object;
+class Array;
 class Function;
 class GfxFont;
 
 //------------------------------------------------------------------------
-// LabParams
+// GfxColor
 //------------------------------------------------------------------------
 
-// Parameters for L*a*b* color spaces.
-struct LabParams {
-  double whiteX, whiteY, whiteZ;
-  double aMin, aMax, bMin, bMax;
+#define gfxColorMaxComps 8
+
+struct GfxColor {
+  double c[gfxColorMaxComps];
 };
 
 //------------------------------------------------------------------------
-// GfxColor
+// GfxRGB
+//------------------------------------------------------------------------
+
+struct GfxRGB {
+  double r, g, b;
+};
+
+//------------------------------------------------------------------------
+// GfxCMYK
+//------------------------------------------------------------------------
+
+struct GfxCMYK {
+  double c, m, y, k;
+};
+
 //------------------------------------------------------------------------
+// GfxColorSpace
+//------------------------------------------------------------------------
+
+enum GfxColorSpaceMode {
+  csDeviceGray,
+  csCalGray,
+  csDeviceRGB,
+  csCalRGB,
+  csDeviceCMYK,
+  csLab,
+  csICCBased,
+  csIndexed,
+  csSeparation,
+  csDeviceN,
+  csPattern
+};
 
-class GfxColor {
+class GfxColorSpace {
 public:
 
-  GfxColor(): r(0), g(0), b(0) {}
+  GfxColorSpace();
+  virtual ~GfxColorSpace();
+  virtual GfxColorSpace *copy() = 0;
+  virtual GfxColorSpaceMode getMode() = 0;
 
-  // Set color.
-  void setGray(double gray);
-  void setCMYK(double c, double m, double y, double k);
-  void setRGB(double r1, double g1, double b1);
-  void setLab(double L, double a, double bb, LabParams *params);
+  // Construct a color space.  Returns NULL if unsuccessful.
+  static GfxColorSpace *parse(Object *csObj);
 
-  // Accessors.
-  double getR() { return r; }
-  double getG() { return g; }
-  double getB() { return b; }
-  double getGray() { return 0.299 * r + 0.587 * g + 0.114 * b; }
+  // Convert to gray, RGB, or CMYK.
+  virtual void getGray(GfxColor *color, double *gray) = 0;
+  virtual void getRGB(GfxColor *color, GfxRGB *rgb) = 0;
+  virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk) = 0;
+
+  // Return the number of color components.
+  virtual int getNComps() = 0;
+
+  // Return the default ranges for each component, assuming an image
+  // with a max pixel value of <maxImgPixel>.
+  virtual void getDefaultRanges(double *decodeLow, double *decodeRange,
+                               int maxImgPixel);
 
 private:
+};
 
-  double r, g, b;
+//------------------------------------------------------------------------
+// GfxDeviceGrayColorSpace
+//------------------------------------------------------------------------
+
+class GfxDeviceGrayColorSpace: public GfxColorSpace {
+public:
+
+  GfxDeviceGrayColorSpace();
+  virtual ~GfxDeviceGrayColorSpace();
+  virtual GfxColorSpace *copy();
+  virtual GfxColorSpaceMode getMode() { return csDeviceGray; }
+
+  virtual void getGray(GfxColor *color, double *gray);
+  virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+  virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
+
+  virtual int getNComps() { return 1; }
+
+private:
 };
 
 //------------------------------------------------------------------------
-// GfxColorSpace
+// GfxCalGrayColorSpace
 //------------------------------------------------------------------------
 
-enum GfxColorMode {
-  colorGray, colorCMYK, colorRGB, colorLab
+class GfxCalGrayColorSpace: public GfxColorSpace {
+public:
+
+  GfxCalGrayColorSpace();
+  virtual ~GfxCalGrayColorSpace();
+  virtual GfxColorSpace *copy();
+  virtual GfxColorSpaceMode getMode() { return csCalGray; }
+
+  // Construct a CalGray color space.  Returns NULL if unsuccessful.
+  static GfxColorSpace *parse(Array *arr);
+
+  virtual void getGray(GfxColor *color, double *gray);
+  virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+  virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
+
+  virtual int getNComps() { return 1; }
+
+  // CalGray-specific access.
+  double getWhiteX() { return whiteX; }
+  double getWhiteY() { return whiteY; }
+  double getWhiteZ() { return whiteZ; }
+  double getBlackX() { return blackX; }
+  double getBlackY() { return blackY; }
+  double getBlackZ() { return blackZ; }
+  double getGamma() { return gamma; }
+
+private:
+
+  double whiteX, whiteY, whiteZ;    // white point
+  double blackX, blackY, blackZ;    // black point
+  double gamma;                            // gamma value
 };
 
-class GfxColorSpace {
+//------------------------------------------------------------------------
+// GfxDeviceRGBColorSpace
+//------------------------------------------------------------------------
+
+class GfxDeviceRGBColorSpace: public GfxColorSpace {
 public:
 
-  // Construct a colorspace.
-  GfxColorSpace(Object *colorSpace);
+  GfxDeviceRGBColorSpace();
+  virtual ~GfxDeviceRGBColorSpace();
+  virtual GfxColorSpace *copy();
+  virtual GfxColorSpaceMode getMode() { return csDeviceRGB; }
 
-  // Construct a simple colorspace: DeviceGray, DeviceCMYK, or
-  // DeviceRGB.
-  GfxColorSpace(GfxColorMode mode1);
+  virtual void getGray(GfxColor *color, double *gray);
+  virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+  virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
 
-  // Destructor.
-  ~GfxColorSpace();
+  virtual int getNComps() { return 3; }
 
-  // Copy.
-  GfxColorSpace *copy() { return new GfxColorSpace(this); }
+private:
+};
 
-  // Is color space valid?
-  GBool isOk() { return ok; }
+//------------------------------------------------------------------------
+// GfxCalRGBColorSpace
+//------------------------------------------------------------------------
+
+class GfxCalRGBColorSpace: public GfxColorSpace {
+public:
+
+  GfxCalRGBColorSpace();
+  virtual ~GfxCalRGBColorSpace();
+  virtual GfxColorSpace *copy();
+  virtual GfxColorSpaceMode getMode() { return csCalRGB; }
+
+  // Construct a CalRGB color space.  Returns NULL if unsuccessful.
+  static GfxColorSpace *parse(Array *arr);
+
+  virtual void getGray(GfxColor *color, double *gray);
+  virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+  virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
+
+  virtual int getNComps() { return 3; }
+
+  // CalRGB-specific access.
+  double getWhiteX() { return whiteX; }
+  double getWhiteY() { return whiteY; }
+  double getWhiteZ() { return whiteZ; }
+  double getBlackX() { return blackX; }
+  double getBlackY() { return blackY; }
+  double getBlackZ() { return blackZ; }
+  double getGammaR() { return gammaR; }
+  double getGammaG() { return gammaG; }
+  double getGammaB() { return gammaB; }
+  double *getMatrix() { return m; }
+
+private:
+
+  double whiteX, whiteY, whiteZ;    // white point
+  double blackX, blackY, blackZ;    // black point
+  double gammaR, gammaG, gammaB;    // gamma values
+  double m[9];                     // ABC -> XYZ transform matrix
+};
+
+//------------------------------------------------------------------------
+// GfxDeviceCMYKColorSpace
+//------------------------------------------------------------------------
+
+class GfxDeviceCMYKColorSpace: public GfxColorSpace {
+public:
 
-  // Get the color mode.
-  GfxColorMode getMode() { return mode; }
+  GfxDeviceCMYKColorSpace();
+  virtual ~GfxDeviceCMYKColorSpace();
+  virtual GfxColorSpace *copy();
+  virtual GfxColorSpaceMode getMode() { return csDeviceCMYK; }
 
-  // Get number of components in pixels of this colorspace.
-  int getNumPixelComps() { return (sepFunc || indexed) ? 1 : numComps; }
+  virtual void getGray(GfxColor *color, double *gray);
+  virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+  virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
+
+  virtual int getNComps() { return 4; }
+
+private:
+};
+
+//------------------------------------------------------------------------
+// GfxLabColorSpace
+//------------------------------------------------------------------------
+
+class GfxLabColorSpace: public GfxColorSpace {
+public:
 
-  // Get number of components in colors of this colorspace.
-  int getNumColorComps() { return numComps; }
+  GfxLabColorSpace();
+  virtual ~GfxLabColorSpace();
+  virtual GfxColorSpace *copy();
+  virtual GfxColorSpaceMode getMode() { return csLab; }
 
-  // Return true if colorspace is indexed.
-  GBool isIndexed() { return indexed; }
+  // Construct a Lab color space.  Returns NULL if unsuccessful.
+  static GfxColorSpace *parse(Array *arr);
 
-  // Return true for a separation colorspace.
-  GBool isSeparation() { return sepFunc ? gTrue : gFalse; }
+  virtual void getGray(GfxColor *color, double *gray);
+  virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+  virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
 
-  // Get default ranges for the components.
-  void getDefaultRanges(double *decodeLow, double *decodeRange, int maxPixel);
+  virtual int getNComps() { return 3; }
 
-  // Get lookup table (only for indexed colorspaces).
+  virtual void getDefaultRanges(double *decodeLow, double *decodeRange,
+                               int maxImgPixel);
+
+  // Lab-specific access.
+  double getWhiteX() { return whiteX; }
+  double getWhiteY() { return whiteY; }
+  double getWhiteZ() { return whiteZ; }
+  double getBlackX() { return blackX; }
+  double getBlackY() { return blackY; }
+  double getBlackZ() { return blackZ; }
+  double getAMin() { return aMin; }
+  double getAMax() { return aMax; }
+  double getBMin() { return bMin; }
+  double getBMax() { return bMax; }
+
+private:
+
+  double whiteX, whiteY, whiteZ;    // white point
+  double blackX, blackY, blackZ;    // black point
+  double aMin, aMax, bMin, bMax;    // range for the a and b components
+  double kr, kg, kb;               // gamut mapping mulitpliers
+};
+
+//------------------------------------------------------------------------
+// GfxICCBasedColorSpace
+//------------------------------------------------------------------------
+
+class GfxICCBasedColorSpace: public GfxColorSpace {
+public:
+
+  GfxICCBasedColorSpace(int nComps, GfxColorSpace *alt,
+                       Ref *iccProfileStream);
+  virtual ~GfxICCBasedColorSpace();
+  virtual GfxColorSpace *copy();
+  virtual GfxColorSpaceMode getMode() { return csICCBased; }
+
+  // Construct an ICCBased color space.  Returns NULL if unsuccessful.
+  static GfxColorSpace *parse(Array *arr);
+
+  virtual void getGray(GfxColor *color, double *gray);
+  virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+  virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
+
+  virtual int getNComps() { return nComps; }
+
+  virtual void getDefaultRanges(double *decodeLow, double *decodeRange,
+                               int maxImgPixel);
+
+  // ICCBased-specific access.
+  GfxColorSpace *getAlt() { return alt; }
+
+private:
+
+  int nComps;                  // number of color components (1, 3, or 4)
+  GfxColorSpace *alt;          // alternate color space
+  double rangeMin[4];          // min values for each component
+  double rangeMax[4];          // max values for each component
+  Ref iccProfileStream;                // the ICC profile
+};
+
+//------------------------------------------------------------------------
+// GfxIndexedColorSpace
+//------------------------------------------------------------------------
+
+class GfxIndexedColorSpace: public GfxColorSpace {
+public:
+
+  GfxIndexedColorSpace(GfxColorSpace *base, int indexHigh);
+  virtual ~GfxIndexedColorSpace();
+  virtual GfxColorSpace *copy();
+  virtual GfxColorSpaceMode getMode() { return csIndexed; }
+
+  // Construct a Lab color space.  Returns NULL if unsuccessful.
+  static GfxColorSpace *parse(Array *arr);
+
+  virtual void getGray(GfxColor *color, double *gray);
+  virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+  virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
+
+  virtual int getNComps() { return 1; }
+
+  virtual void getDefaultRanges(double *decodeLow, double *decodeRange,
+                               int maxImgPixel);
+
+  // Indexed-specific access.
+  GfxColorSpace *getBase() { return base; }
   int getIndexHigh() { return indexHigh; }
-  Guchar *getLookupVal(int i) { return lookup[i]; }
+  Guchar *getLookup() { return lookup; }
+
+private:
+
+  GfxColorSpace *base;         // base color space
+  int indexHigh;               // max pixel value
+  Guchar *lookup;              // lookup table
+};
+
+//------------------------------------------------------------------------
+// GfxSeparationColorSpace
+//------------------------------------------------------------------------
+
+class GfxSeparationColorSpace: public GfxColorSpace {
+public:
+
+  GfxSeparationColorSpace(GString *name, GfxColorSpace *alt,
+                         Function *func);
+  virtual ~GfxSeparationColorSpace();
+  virtual GfxColorSpace *copy();
+  virtual GfxColorSpaceMode getMode() { return csSeparation; }
+
+  // Construct a Separation color space.  Returns NULL if unsuccessful.
+  static GfxColorSpace *parse(Array *arr);
+
+  virtual void getGray(GfxColor *color, double *gray);
+  virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+  virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
+
+  virtual int getNComps() { return 1; }
+
+  // Separation-specific access.
+  GString *getName() { return name; }
+  GfxColorSpace *getAlt() { return alt; }
+  Function *getFunc() { return func; }
+
+private:
+
+  GString *name;               // colorant name
+  GfxColorSpace *alt;          // alternate color space
+  Function *func;              // tint transform (into alternate color space)
+};
+
+//------------------------------------------------------------------------
+// GfxDeviceNColorSpace
+//------------------------------------------------------------------------
+
+class GfxDeviceNColorSpace: public GfxColorSpace {
+public:
+
+  GfxDeviceNColorSpace(int nComps, GfxColorSpace *alt, Function *func);
+  virtual ~GfxDeviceNColorSpace();
+  virtual GfxColorSpace *copy();
+  virtual GfxColorSpaceMode getMode() { return csDeviceN; }
+
+  // Construct a DeviceN color space.  Returns NULL if unsuccessful.
+  static GfxColorSpace *parse(Array *arr);
+
+  virtual void getGray(GfxColor *color, double *gray);
+  virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+  virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
+
+  virtual int getNComps() { return nComps; }
+
+  // DeviceN-specific access.
+  GfxColorSpace *getAlt() { return alt; }
+
+private:
+
+  int nComps;                  // number of components
+  GString                      // colorant names
+    *names[gfxColorMaxComps];
+  GfxColorSpace *alt;          // alternate color space
+  Function *func;              // tint transform (into alternate color space)
+  
+};
+
+//------------------------------------------------------------------------
+// GfxPatternColorSpace
+//------------------------------------------------------------------------
+
+class GfxPatternColorSpace: public GfxColorSpace {
+public:
+
+  GfxPatternColorSpace(GfxColorSpace *under);
+  virtual ~GfxPatternColorSpace();
+  virtual GfxColorSpace *copy();
+  virtual GfxColorSpaceMode getMode() { return csPattern; }
+
+  // Construct a Pattern color space.  Returns NULL if unsuccessful.
+  static GfxColorSpace *parse(Array *arr);
+
+  virtual void getGray(GfxColor *color, double *gray);
+  virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+  virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
+
+  virtual int getNComps() { return 0; }
+
+  // Pattern-specific access.
+  GfxColorSpace *getUnder() { return under; }
+
+private:
 
-  // Convert a pixel to a color.
-  void getColor(double x[4], GfxColor *color);
+  GfxColorSpace *under;                // underlying color space (for uncolored
+                               //   patterns)
+};
+
+//------------------------------------------------------------------------
+// GfxPattern
+//------------------------------------------------------------------------
+
+class GfxPattern {
+public:
+
+  GfxPattern(int type);
+  virtual ~GfxPattern();
+
+  static GfxPattern *parse(Object *obj);
+
+  virtual GfxPattern *copy() = 0;
+
+  int getType() { return type; }
+
+private:
+
+  int type;
+};
+
+//------------------------------------------------------------------------
+// GfxTilingPattern
+//------------------------------------------------------------------------
+
+class GfxTilingPattern: public GfxPattern {
+public:
+
+  GfxTilingPattern(Dict *streamDict, Object *stream);
+  virtual ~GfxTilingPattern();
 
-  // Get the L*a*b* color space parameters.
-  LabParams *getLabParams() { return &labParams; }
+  virtual GfxPattern *copy();
+
+  int getPaintType() { return paintType; }
+  int getTilingType() { return tilingType; }
+  double *getBBox() { return bbox; }
+  double getXStep() { return xStep; }
+  double getYStep() { return yStep; }
+  Dict *getResDict()
+    { return resDict.isDict() ? resDict.getDict() : (Dict *)NULL; }
+  double *getMatrix() { return matrix; }
+  Object *getContentStream() { return &contentStream; }
 
 private:
 
-  Function *sepFunc;           // separation tint transform function
-  GfxColorMode mode;           // color mode
-  GBool indexed;               // set for indexed colorspaces
-  int numComps;                        // number of components in colors
-  int indexHigh;               // max pixel for indexed colorspace
-  Guchar (*lookup)[4];         // lookup table (only for indexed
-                               //   colorspaces)
-  LabParams labParams;         // parameters for L*a*b* color space
-  GBool ok;                    // is color space valid?
-
-  GfxColorSpace(GfxColorSpace *colorSpace);
-  void setMode(Object *colorSpace);
+  GfxTilingPattern(GfxTilingPattern *pat);
+
+  int paintType;
+  int tilingType;
+  double bbox[4];
+  double xStep, yStep;
+  Object resDict;
+  double matrix[6];
+  Object contentStream;
 };
 
 //------------------------------------------------------------------------
 // Function
 //------------------------------------------------------------------------
 
+#define funcMaxInputs  1
+#define funcMaxOutputs 8
+
 class Function {
 public:
 
-  // Create a PDF function object.
-  Function(Object *funcObj);
+  Function();
 
-  ~Function();
-  
-  Function *copy() { return new Function(this); }
+  virtual ~Function();
 
-  GBool isOk() { return ok; }
+  // Construct a function.  Returns NULL if unsuccessful.
+  static Function *parse(Object *funcObj);
+
+  // Initialize the entries common to all function types.
+  GBool init(Dict *dict);
+
+  virtual Function *copy() = 0;
 
   // Return size of input and output tuples.
   int getInputSize() { return m; }
   int getOutputSize() { return n; }
 
   // Transform an input tuple into an output tuple.
-  void transform(double *in, double *out);
+  virtual void transform(double *in, double *out) = 0;
 
-private:
+  virtual GBool isOk() = 0;
 
-  Function(Function *func);
+protected:
 
   int m, n;                    // size of input and output tuples
-  double domain[1][2];         // min and max values for function domain
-  double range[4][2];          // min and max values for function range
-  int sampleSize[1];           // number of samples for each domain element
-  double encode[1][2];         // min and max values for domain encoder
-  double decode[4][2];         // min and max values for range decoder
+  double                       // min and max values for function domain
+    domain[funcMaxInputs][2];
+  double                       // min and max values for function range
+    range[funcMaxOutputs][2];
+  GBool hasRange;              // set if range is defined
+};
+
+//------------------------------------------------------------------------
+// SampledFunction
+//------------------------------------------------------------------------
+
+class SampledFunction: public Function {
+public:
+
+  SampledFunction(Object *funcObj, Dict *dict);
+  virtual ~SampledFunction();
+  virtual Function *copy() { return new SampledFunction(this); }
+  virtual void transform(double *in, double *out);
+  virtual GBool isOk() { return ok; }
+
+private:
+
+  SampledFunction(SampledFunction *func);
+
+  int                          // number of samples for each domain element
+    sampleSize[funcMaxInputs];
+  double                       // min and max values for domain encoder
+    encode[funcMaxInputs][2];
+  double                       // min and max values for range decoder
+    decode[funcMaxOutputs][2];
   double *samples;             // the samples
   GBool ok;
 };
 
+//------------------------------------------------------------------------
+// ExponentialFunction
+//------------------------------------------------------------------------
+
+class ExponentialFunction: public Function {
+public:
+
+  ExponentialFunction(Object *funcObj, Dict *dict);
+  virtual ~ExponentialFunction();
+  virtual Function *copy() { return new ExponentialFunction(this); }
+  virtual void transform(double *in, double *out);
+  virtual GBool isOk() { return ok; }
+
+private:
+
+  ExponentialFunction(ExponentialFunction *func);
+
+  double c0[funcMaxOutputs];
+  double c1[funcMaxOutputs];
+  double e;
+  GBool ok;
+};
+
 //------------------------------------------------------------------------
 // GfxImageColorMap
 //------------------------------------------------------------------------
@@ -171,7 +602,7 @@ class GfxImageColorMap {
 public:
 
   // Constructor.
-  GfxImageColorMap(int bits1, Object *decode, GfxColorSpace *colorSpace1);
+  GfxImageColorMap(int bits, Object *decode, GfxColorSpace *colorSpace);
 
   // Destructor.
   ~GfxImageColorMap();
@@ -183,27 +614,30 @@ public:
   GfxColorSpace *getColorSpace() { return colorSpace; }
 
   // Get stream decoding info.
-  int getNumPixelComps() { return numComps; }
+  int getNumPixelComps() { return nComps; }
   int getBits() { return bits; }
 
   // Get decode table.
   double getDecodeLow(int i) { return decodeLow[i]; }
   double getDecodeHigh(int i) { return decodeLow[i] + decodeRange[i]; }
 
-  // Convert a pixel to a color.
-  void getColor(Guchar x[4], GfxColor *color);
+  // Convert an image pixel to a color.
+  void getGray(Guchar *x, double *gray);
+  void getRGB(Guchar *x, GfxRGB *rgb);
+  void getCMYK(Guchar *x, GfxCMYK *cmyk);
 
 private:
 
-  GfxColorSpace *colorSpace;   // the image colorspace
+  GfxColorSpace *colorSpace;   // the image color space
   int bits;                    // bits per component
-  int numComps;                        // number of components in a pixel
-  GBool indexed;               // set for indexed color space
-  GBool sep;                   // set for separation colorspaces
-  GfxColorMode mode;           // color mode
-  double (*lookup)[4];         // lookup table
-  double decodeLow[4];         // minimum values for each component
-  double decodeRange[4];       // max - min value for each component
+  int nComps;                  // number of components in a pixel
+  GfxColorSpace *colorSpace2;  // secondary color space
+  int nComps2;                 // number of components in colorSpace2
+  double *lookup;              // lookup table
+  double                       // minimum values for each component
+    decodeLow[gfxColorMaxComps];
+  double                       // max - min value for each component
+    decodeRange[gfxColorMaxComps];
   GBool ok;
 };
 
@@ -318,8 +752,8 @@ public:
   // Construct a default GfxState, for a device with resolution <dpi>,
   // page box (<x1>,<y1>)-(<x2>,<y2>), page rotation <rotate>, and
   // coordinate system specified by <upsideDown>.
-  GfxState(int dpi, double px1a, double py1a, double px2a, double py2a,
-          int rotate, GBool upsideDown);
+  GfxState(double dpi, double px1a, double py1a,
+          double px2a, double py2a, int rotate, GBool upsideDown);
 
   // Destructor.
   ~GfxState();
@@ -337,6 +771,20 @@ public:
   double getPageHeight() { return pageHeight; }
   GfxColor *getFillColor() { return &fillColor; }
   GfxColor *getStrokeColor() { return &strokeColor; }
+  void getFillRGB(GfxRGB *rgb)
+    { fillColorSpace->getRGB(&fillColor, rgb); }
+  void getStrokeRGB(GfxRGB *rgb)
+    { strokeColorSpace->getRGB(&strokeColor, rgb); }
+  void getFillCMYK(GfxCMYK *cmyk)
+    { fillColorSpace->getCMYK(&fillColor, cmyk); }
+  void getStrokeCMYK(GfxCMYK *cmyk)
+    { strokeColorSpace->getCMYK(&strokeColor, cmyk); }
+  GfxColorSpace *getFillColorSpace() { return fillColorSpace; }
+  GfxColorSpace *getStrokeColorSpace() { return strokeColorSpace; }
+  GfxPattern *getFillPattern() { return fillPattern; }
+  GfxPattern *getStrokePattern() { return strokePattern; }
+  double getFillOpacity() { return fillOpacity; }
+  double getStrokeOpacity() { return strokeOpacity; }
   double getLineWidth() { return lineWidth; }
   void getLineDash(double **dash, int *length, double *start)
     { *dash = lineDash; *length = lineDashLength; *start = lineDashStart; }
@@ -387,26 +835,15 @@ public:
              double d, double e, double f);
   void concatCTM(double a, double b, double c,
                 double d, double e, double f);
-  void setFillGray(double gray)
-    { fillColor.setGray(gray); }
-  void setFillCMYK(double c, double m, double y, double k)
-    { fillColor.setCMYK(c, m, y, k); }
-  void setFillRGB(double r, double g, double b)
-    { fillColor.setRGB(r, g, b); }
-  void setStrokeGray(double gray)
-    { strokeColor.setGray(gray); }
-  void setStrokeCMYK(double c, double m, double y, double k)
-    { strokeColor.setCMYK(c, m, y, k); }
-  void setStrokeRGB(double r, double g, double b)
-    { strokeColor.setRGB(r, g, b); }
   void setFillColorSpace(GfxColorSpace *colorSpace);
   void setStrokeColorSpace(GfxColorSpace *colorSpace);
-  void setFillColor(double x[4])
-    { fillColorSpace->getColor(x, &fillColor); }
-  void setStrokeColor(double x[4])
-    { strokeColorSpace->getColor(x, &strokeColor); }
-  void setLineWidth(double width)
-    { lineWidth = width; }
+  void setFillColor(GfxColor *color) { fillColor = *color; }
+  void setStrokeColor(GfxColor *color) { strokeColor = *color; }
+  void setFillPattern(GfxPattern *pattern);
+  void setStrokePattern(GfxPattern *pattern);
+  void setFillOpacity(double opac) { fillOpacity = opac; }
+  void setStrokeOpacity(double opac) { strokeOpacity = opac; }
+  void setLineWidth(double width) { lineWidth = width; }
   void setLineDash(double *dash, int length, double start);
   void setFlatness(int flatness1) { flatness = flatness1; }
   void setLineJoin(int lineJoin1) { lineJoin = lineJoin1; }
@@ -464,6 +901,10 @@ private:
   GfxColorSpace *strokeColorSpace; // stroke color space
   GfxColor fillColor;          // fill color
   GfxColor strokeColor;                // stroke color
+  GfxPattern *fillPattern;     // fill pattern
+  GfxPattern *strokePattern;   // stroke pattern
+  double fillOpacity;          // fill opacity
+  double strokeOpacity;                // stroke opacity
 
   double lineWidth;            // line width
   double *lineDash;            // line dash
diff --git a/pdftops/ImageOutputDev.cxx b/pdftops/ImageOutputDev.cxx
deleted file mode 100644 (file)
index 93d1c31..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-//========================================================================
-//
-// ImageOutputDev.cc
-//
-// Copyright 1998 Derek B. Noonburg
-//
-//========================================================================
-
-#ifdef __GNUC__
-#pragma implementation
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <ctype.h>
-#include "gmem.h"
-#include "config.h"
-#include "Error.h"
-#include "GfxState.h"
-#include "Object.h"
-#include "Stream.h"
-#include "ImageOutputDev.h"
-
-ImageOutputDev::ImageOutputDev(char *fileRoot1, GBool dumpJPEG1) {
-  fileRoot = copyString(fileRoot1);
-  fileName = (char *)gmalloc(strlen(fileRoot) + 20);
-  dumpJPEG = dumpJPEG1;
-  imgNum = 0;
-  ok = gTrue;
-}
-
-ImageOutputDev::~ImageOutputDev() {
-  gfree(fileName);
-  gfree(fileRoot);
-}
-
-void ImageOutputDev::drawImageMask(GfxState *state, Stream *str,
-                                  int width, int height, GBool invert,
-                                  GBool inlineImg) {
-  FILE *f;
-  int c;
-
-  // dump JPEG file
-  if (dumpJPEG && str->getKind() == strDCT) {
-
-    // open the image file
-    sprintf(fileName, "%s-%03d.jpg", fileRoot, imgNum);
-    ++imgNum;
-    if (!(f = fopen(fileName, "wb"))) {
-      error(-1, "Couldn't open image file '%s'", fileName);
-      return;
-    }
-
-    // initialize stream
-    str = ((DCTStream *)str)->getRawStream();
-    str->reset();
-
-    // copy the stream
-    while ((c = str->getChar()) != EOF)
-      fputc(c, f);
-
-    fclose(f);
-
-  // dump PBM file
-  } else {
-
-    // open the image file and write the PBM header
-    sprintf(fileName, "%s-%03d.pbm", fileRoot, imgNum);
-    ++imgNum;
-    if (!(f = fopen(fileName, "wb"))) {
-      error(-1, "Couldn't open image file '%s'", fileName);
-      return;
-    }
-    fprintf(f, "P4\n");
-    fprintf(f, "%d %d\n", width, height);
-
-    // initialize stream
-    str->reset();
-
-    // copy the stream
-    while ((c = str->getChar()) != EOF)
-      fputc(c, f);
-
-    fclose(f);
-  }
-}
-
-void ImageOutputDev::drawImage(GfxState *state, Stream *str, int width,
-                              int height, GfxImageColorMap *colorMap,
-                              GBool inlineImg) {
-  FILE *f;
-  ImageStream *imgStr;
-  Guchar pixBuf[4];
-  GfxColor color;
-  int x, y;
-  int c;
-
-  // dump JPEG file
-  if (dumpJPEG && str->getKind() == strDCT) {
-
-    // open the image file
-    sprintf(fileName, "%s-%03d.jpg", fileRoot, imgNum);
-    ++imgNum;
-    if (!(f = fopen(fileName, "wb"))) {
-      error(-1, "Couldn't open image file '%s'", fileName);
-      return;
-    }
-
-    // initialize stream
-    str = ((DCTStream *)str)->getRawStream();
-    str->reset();
-
-    // copy the stream
-    while ((c = str->getChar()) != EOF)
-      fputc(c, f);
-
-    fclose(f);
-
-  // dump PPM file
-  } else {
-
-    // open the image file and write the PPM header
-    sprintf(fileName, "%s-%03d.ppm", fileRoot, imgNum);
-    ++imgNum;
-    if (!(f = fopen(fileName, "wb"))) {
-      error(-1, "Couldn't open image file '%s'", fileName);
-      return;
-    }
-    fprintf(f, "P6\n");
-    fprintf(f, "%d %d\n", width, height);
-    fprintf(f, "255\n");
-
-    // initialize stream
-    imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(),
-                            colorMap->getBits());
-    imgStr->reset();
-
-    // for each line...
-    for (y = 0; y < height; ++y) {
-
-      // write the line
-      for (x = 0; x < width; ++x) {
-       imgStr->getPixel(pixBuf);
-       colorMap->getColor(pixBuf, &color);
-       fputc((int)(color.getR() * 255 + 0.5), f);
-       fputc((int)(color.getG() * 255 + 0.5), f);
-       fputc((int)(color.getB() * 255 + 0.5), f);
-      }
-    }
-    delete imgStr;
-
-    fclose(f);
-  }
-}
diff --git a/pdftops/ImageOutputDev.h b/pdftops/ImageOutputDev.h
deleted file mode 100644 (file)
index 84766dd..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-//========================================================================
-//
-// ImageOutputDev.h
-//
-// Copyright 1998 Derek B. Noonburg
-//
-//========================================================================
-
-#ifndef IMAGEOUTPUTDEV_H
-#define IMAGEOUTPUTDEV_H
-
-#ifdef __GNUC__
-#pragma interface
-#endif
-
-#include <stdio.h>
-#include "gtypes.h"
-#include "OutputDev.h"
-
-class GfxState;
-
-//------------------------------------------------------------------------
-// ImageOutputDev
-//------------------------------------------------------------------------
-
-class ImageOutputDev: public OutputDev {
-public:
-
-  // Create an OutputDev which will write images to files named
-  // <fileRoot>-NNN.<type>.  Normally, all images are written as PBM
-  // (.pbm) or PPM (.ppm) files.  If <dumpJPEG> is set, JPEG images are
-  // written as JPEG (.jpg) files.
-  ImageOutputDev(char *fileRoot1, GBool dumpJPEG1);
-
-  // Destructor.
-  virtual ~ImageOutputDev();
-
-  // Check if file was successfully created.
-  virtual GBool isOk() { return ok; }
-
-  //---- get info about output device
-
-  // Does this device use upside-down coordinates?
-  // (Upside-down means (0,0) is the top left corner of the page.)
-  virtual GBool upsideDown() { return gTrue; }
-
-  // Does this device use drawChar() or drawString()?
-  virtual GBool useDrawChar() { return gFalse; }
-
-  //----- image drawing
-  virtual void drawImageMask(GfxState *state, Stream *str,
-                            int width, int height, GBool invert,
-                            GBool inlineImg);
-  virtual void drawImage(GfxState *state, Stream *str, int width,
-                        int height, GfxImageColorMap *colorMap,
-                        GBool inlineImg);
-
-private:
-
-  char *fileRoot;              // root of output file names
-  char *fileName;              // buffer for output file names
-  GBool dumpJPEG;              // set to dump native JPEG files
-  int imgNum;                  // current image number
-  GBool ok;                    // set up ok?
-};
-
-#endif
index 302a02487310a0eaa2a8b070e84b36f2d9156123..4ca8cfe9f51e323d3fa41fd16bf6a7fddbcb0f8f 100644 (file)
 
 //------------------------------------------------------------------------
 
-// A '1' in this array means the corresponding character ends a name
-// or command.
-static char endOfNameChars[128] = {
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0,   // 0x
+// A '1' in this array means the character is white space.  A '1' or
+// '2' means the character ends a name or command.
+static char specialChars[256] = {
+  1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0,   // 0x
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // 1x
-  1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1,   // 2x
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,   // 3x
+  1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2,   // 2x
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0,   // 3x
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // 4x
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0,   // 5x
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0,   // 5x
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // 6x
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0    // 7x
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0,   // 7x
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // 8x
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // 9x
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // ax
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // bx
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // cx
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // dx
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // ex
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0    // fx
 };
 
 //------------------------------------------------------------------------
@@ -66,10 +74,13 @@ Lexer::Lexer(Object *obj) {
 }
 
 Lexer::~Lexer() {
-  if (!curStr.isNone())
+  if (!curStr.isNone()) {
+    curStr.streamClose();
     curStr.free();
-  if (freeArray)
+  }
+  if (freeArray) {
     delete streams;
+  }
 }
 
 int Lexer::getChar() {
@@ -77,6 +88,7 @@ int Lexer::getChar() {
 
   c = EOF;
   while (!curStr.isNone() && (c = curStr.streamGetChar()) == EOF) {
+    curStr.streamClose();
     curStr.free();
     ++strPtr;
     if (strPtr < streams->getLength()) {
@@ -88,18 +100,10 @@ int Lexer::getChar() {
 }
 
 int Lexer::lookChar() {
-  int c;
-
-  c = EOF;
-  while (!curStr.isNone() && (c = curStr.streamLookChar()) == EOF) {
-    curStr.free();
-    ++strPtr;
-    if (strPtr < streams->getLength()) {
-      streams->get(strPtr, &curStr);
-      curStr.streamReset();
-    }
+  if (curStr.isNone()) {
+    return EOF;
   }
-  return c;
+  return curStr.streamLookChar();
 }
 
 Object *Lexer::getObj(Object *obj) {
@@ -115,14 +119,15 @@ Object *Lexer::getObj(Object *obj) {
   // skip whitespace and comments
   comment = gFalse;
   while (1) {
-    if ((c = getChar()) == EOF)
+    if ((c = getChar()) == EOF) {
       return obj->initEOF();
+    }
     if (comment) {
       if (c == '\r' || c == '\n')
        comment = gFalse;
     } else if (c == '%') {
       comment = gTrue;
-    } else if (!isspace(c)) {
+    } else if (specialChars[c] != 1) {
       break;
     }
   }
@@ -164,8 +169,9 @@ Object *Lexer::getObj(Object *obj) {
     scale = 0.1;
     while (1) {
       c = lookChar();
-      if (!isdigit(c))
+      if (!isdigit(c)) {
        break;
+      }
       getChar();
       xf = xf + scale * (c - '0');
       scale *= 0.1;
@@ -187,8 +193,11 @@ Object *Lexer::getObj(Object *obj) {
       switch (c = getChar()) {
 
       case EOF:
+#if 0
+      // This breaks some PDF files, e.g., ones from Photoshop.
       case '\r':
       case '\n':
+#endif
        error(getPos(), "Unterminated string");
        done = gTrue;
        break;
@@ -240,8 +249,9 @@ Object *Lexer::getObj(Object *obj) {
          break;
        case '\r':
          c = lookChar();
-         if (c == '\n')
+         if (c == '\n') {
            getChar();
+         }
          break;
        case '\n':
          break;
@@ -284,29 +294,31 @@ Object *Lexer::getObj(Object *obj) {
   case '/':
     p = tokBuf;
     n = 0;
-    while ((c = lookChar()) != EOF && !(c < 128 && endOfNameChars[c])) {
+    while ((c = lookChar()) != EOF && !specialChars[c]) {
       getChar();
       if (c == '#') {
        c2 = lookChar();
-       if (c2 >= '0' && c2 <= '9')
+       if (c2 >= '0' && c2 <= '9') {
          c = c2 - '0';
-       else if (c2 >= 'A' && c2 <= 'F')
+       } else if (c2 >= 'A' && c2 <= 'F') {
          c = c2 - 'A' + 10;
-       else if (c2 >= 'a' && c2 <= 'f')
+       } else if (c2 >= 'a' && c2 <= 'f') {
          c = c2 - 'a' + 10;
-       else
+       } else {
          goto notEscChar;
+       }
        getChar();
        c <<= 4;
        c2 = getChar();
-       if (c2 >= '0' && c2 <= '9')
+       if (c2 >= '0' && c2 <= '9') {
          c += c2 - '0';
-       else if (c2 >= 'A' && c2 <= 'F')
+       } else if (c2 >= 'A' && c2 <= 'F') {
          c += c2 - 'A' + 10;
-       else if (c2 >= 'a' && c2 <= 'f')
+       } else if (c2 >= 'a' && c2 <= 'f') {
          c += c2 - 'a' + 10;
-       else
+       } else {
          error(getPos(), "Illegal digit in hex char in name");
+       }
       }
      notEscChar:
       if (++n == tokBufSize) {
@@ -351,7 +363,7 @@ Object *Lexer::getObj(Object *obj) {
        } else if (c == EOF) {
          error(getPos(), "Unterminated hex string");
          break;
-       } else if (!isspace(c)) {
+       } else if (specialChars[c] != 1) {
          c2 = c2 << 4;
          if (c >= '0' && c <= '9')
            c2 += c - '0';
@@ -414,7 +426,7 @@ Object *Lexer::getObj(Object *obj) {
     p = tokBuf;
     *p++ = c;
     n = 1;
-    while ((c = lookChar()) != EOF && !(c < 128 && endOfNameChars[c])) {
+    while ((c = lookChar()) != EOF && !specialChars[c]) {
       getChar();
       if (++n == tokBufSize) {
        error(getPos(), "Command token too long");
@@ -423,14 +435,15 @@ Object *Lexer::getObj(Object *obj) {
       *p++ = c;
     }
     *p = '\0';
-    if (tokBuf[0] == 't' && !strcmp(tokBuf, "true"))
+    if (tokBuf[0] == 't' && !strcmp(tokBuf, "true")) {
       obj->initBool(gTrue);
-    else if (tokBuf[0] == 'f' && !strcmp(tokBuf, "false"))
+    } else if (tokBuf[0] == 'f' && !strcmp(tokBuf, "false")) {
       obj->initBool(gFalse);
-    else if (tokBuf[0] == 'n' && !strcmp(tokBuf, "null"))
+    } else if (tokBuf[0] == 'n' && !strcmp(tokBuf, "null")) {
       obj->initNull();
-    else
+    } else {
       obj->initCmd(tokBuf);
+    }
     break;
   }
 
@@ -442,11 +455,13 @@ void Lexer::skipToNextLine() {
 
   while (1) {
     c = getChar();
-    if (c == EOF || c == '\n')
+    if (c == EOF || c == '\n') {
       return;
+    }
     if (c == '\r') {
-      if ((c = lookChar()) == '\n')
+      if ((c = lookChar()) == '\n') {
        getChar();
+      }
       return;
     }
   }
index 837cc9b33d678a033e1ace745b97a52b3f8ec1db..a53e0990b870b633d89302f0575374d78e02c87d 100644 (file)
@@ -363,11 +363,28 @@ LinkURI::~LinkURI() {
     delete uri;
 }
 
+//------------------------------------------------------------------------
+// LinkNamed
+//------------------------------------------------------------------------
+
+LinkNamed::LinkNamed(Object *nameObj) {
+  name = NULL;
+  if (nameObj->isName()) {
+    name = new GString(nameObj->getName());
+  }
+}
+
+LinkNamed::~LinkNamed() {
+  if (name) {
+    delete name;
+  }
+}
+
 //------------------------------------------------------------------------
 // LinkUnknown
 //------------------------------------------------------------------------
 
-LinkUnknown::LinkUnknown(char *action1) {
+LinkUnknown::LinkUnknown(const char *action1) {
   action = new GString(action1);
 }
 
@@ -472,6 +489,12 @@ Link::Link(Dict *dict, GString *baseURI) {
        action = new LinkURI(&obj3, baseURI);
        obj3.free();
 
+      // Named action
+      } else if (obj2.isName("Named")) {
+       obj1.dictLookup("N", &obj3);
+       action = new LinkNamed(&obj3);
+       obj3.free();
+
       // unknown action
       } else if (obj2.isName()) {
        action = new LinkUnknown(obj2.getName());
index 71ad0c5cd1b03e549c2fb5fd91a09b7793c26a0b..a502763525db9e061cf9788b2ca75a20574b2947 100644 (file)
@@ -28,6 +28,7 @@ enum LinkActionKind {
   actionGoToR,                 // go to destination in new file
   actionLaunch,                        // launch app (or open document)
   actionURI,                   // URI
+  actionNamed,                 // named action
   actionUnknown                        // anything else
 };
 
@@ -218,6 +219,28 @@ private:
   GString *uri;                        // the URI
 };
 
+//------------------------------------------------------------------------
+// LinkNamed
+//------------------------------------------------------------------------
+
+class LinkNamed: public LinkAction {
+public:
+
+  // Build a LinkNamed given the action name.
+  LinkNamed(Object *nameObj);
+
+  virtual ~LinkNamed();
+
+  virtual GBool isOk() { return name != NULL; }
+
+  virtual LinkActionKind getKind() { return actionNamed; }
+  GString *getName() { return name; }
+
+private:
+
+  GString *name;
+};
+
 //------------------------------------------------------------------------
 // LinkUnknown
 //------------------------------------------------------------------------
@@ -226,7 +249,7 @@ class LinkUnknown: public LinkAction {
 public:
 
   // Build a LinkUnknown with the specified action type.
-  LinkUnknown(char *action1);
+  LinkUnknown(const char *action1);
 
   // Destructor.
   virtual ~LinkUnknown();
index f9c10674d8957aede9507c7aaefeace4afd71c98..b3ebe40f0e6cefd2326f723e6b5d1653d17315b0 100644 (file)
@@ -22,7 +22,7 @@
 // Object
 //------------------------------------------------------------------------
 
-char *objTypeNames[numObjTypes] = {
+const char *objTypeNames[numObjTypes] = {
   "boolean",
   "integer",
   "real",
@@ -103,7 +103,7 @@ void Object::free() {
     delete string;
     break;
   case objName:
-    gfree(name);
+    gfree((void *)name);
     break;
   case objArray:
     if (!array->decRef()) {
@@ -121,7 +121,7 @@ void Object::free() {
     }
     break;
   case objCmd:
-    gfree(cmd);
+    gfree((void *)cmd);
     break;
   default:
     break;
@@ -132,7 +132,7 @@ void Object::free() {
   type = objNone;
 }
 
-char *Object::getTypeName() {
+const char *Object::getTypeName() {
   return objTypeNames[type];
 }
 
@@ -216,5 +216,7 @@ void Object::memCheck(FILE *f) {
        fprintf(f, "  %-20s: %6d\n", objTypeNames[i], numAlloc[i]);
     }
   }
+#else
+  (void)f;
 #endif
 }
index f63f219dc95d3a076c55f7f69dbbd474ff66dfb8..d5132efa5aca19b1d79458fff1b94f293565aebb 100644 (file)
@@ -86,7 +86,7 @@ public:
     { initObj(objReal); real = real1; return this; }
   Object *initString(GString *string1)
     { initObj(objString); string = string1; return this; }
-  Object *initName(char *name1)
+  Object *initName(const char *name1)
     { initObj(objName); name = copyString(name1); return this; }
   Object *initNull()
     { initObj(objNull); return this; }
@@ -97,7 +97,7 @@ public:
   Object *initStream(Stream *stream1);
   Object *initRef(int num1, int gen1)
     { initObj(objRef); ref.num = num1; ref.gen = gen1; return this; }
-  Object *initCmd(char *cmd1)
+  Object *initCmd(const char *cmd1)
     { initObj(objCmd); cmd = copyString(cmd1); return this; }
   Object *initError()
     { initObj(objError); return this; }
@@ -133,11 +133,11 @@ public:
   GBool isNone() { return type == objNone; }
 
   // Special type checking.
-  GBool isName(char *name1)
+  GBool isName(const char *name1)
     { return type == objName && !strcmp(name, name1); }
-  GBool isDict(char *dictType);
-  GBool isStream(char *dictType);
-  GBool isCmd(char *cmd1)
+  GBool isDict(const char *dictType);
+  GBool isStream(const char *dictType);
+  GBool isCmd(const char *cmd1)
     { return type == objCmd && !strcmp(cmd, cmd1); }
 
   // Accessors.  NB: these assume object is of correct type.
@@ -146,7 +146,7 @@ public:
   double getReal() { return real; }
   double getNum() { return type == objInt ? (double)intg : real; }
   GString *getString() { return string; }
-  char *getName() { return name; }
+  const char *getName() { return name; }
   Array *getArray() { return array; }
   Dict *getDict() { return dict; }
   Stream *getStream() { return stream; }
@@ -162,17 +162,18 @@ public:
 
   // Dict accessors.
   int dictGetLength();
-  void dictAdd(char *key, Object *val);
-  GBool dictIs(char *dictType);
-  Object *dictLookup(char *key, Object *obj);
-  Object *dictLookupNF(char *key, Object *obj);
-  char *dictGetKey(int i);
+  void dictAdd(const char *key, Object *val);
+  GBool dictIs(const char *dictType);
+  Object *dictLookup(const char *key, Object *obj);
+  Object *dictLookupNF(const char *key, Object *obj);
+  const char *dictGetKey(int i);
   Object *dictGetVal(int i, Object *obj);
   Object *dictGetValNF(int i, Object *obj);
 
   // Stream accessors.
-  GBool streamIs(char *dictType);
+  GBool streamIs(const char *dictType);
   void streamReset();
+  void streamClose();
   int streamGetChar();
   int streamLookChar();
   char *streamGetLine(char *buf, int size);
@@ -181,7 +182,7 @@ public:
   Dict *streamGetDict();
 
   // Output.
-  char *getTypeName();
+  const char *getTypeName();
   void print(FILE *f = stdout);
 
   // Memory testing.
@@ -195,12 +196,12 @@ private:
     int intg;                  //   integer
     double real;               //   real
     GString *string;           //   string
-    char *name;                        //   name
+    const char *name;          //   name
     Array *array;              //   array
     Dict *dict;                        //   dictionary
     Stream *stream;            //   stream
     Ref ref;                   //   indirect reference
-    char *cmd;                 //   command
+    const char *cmd;           //   command
   };
 
 #ifdef DEBUG_MEM
@@ -236,22 +237,22 @@ inline Object *Object::arrayGetNF(int i, Object *obj)
 inline int Object::dictGetLength()
   { return dict->getLength(); }
 
-inline void Object::dictAdd(char *key, Object *val)
+inline void Object::dictAdd(const char *key, Object *val)
   { dict->add(key, val); }
 
-inline GBool Object::dictIs(char *dictType)
+inline GBool Object::dictIs(const char *dictType)
   { return dict->is(dictType); }
 
-inline GBool Object::isDict(char *dictType)
+inline GBool Object::isDict(const char *dictType)
   { return type == objDict && dictIs(dictType); }
 
-inline Object *Object::dictLookup(char *key, Object *obj)
+inline Object *Object::dictLookup(const char *key, Object *obj)
   { return dict->lookup(key, obj); }
 
-inline Object *Object::dictLookupNF(char *key, Object *obj)
+inline Object *Object::dictLookupNF(const char *key, Object *obj)
   { return dict->lookupNF(key, obj); }
 
-inline char *Object::dictGetKey(int i)
+inline const char *Object::dictGetKey(int i)
   { return dict->getKey(i); }
 
 inline Object *Object::dictGetVal(int i, Object *obj)
@@ -266,15 +267,18 @@ inline Object *Object::dictGetValNF(int i, Object *obj)
 
 #include "Stream.h"
 
-inline GBool Object::streamIs(char *dictType)
+inline GBool Object::streamIs(const char *dictType)
   { return stream->getDict()->is(dictType); }
 
-inline GBool Object::isStream(char *dictType)
+inline GBool Object::isStream(const char *dictType)
   { return type == objStream && streamIs(dictType); }
 
 inline void Object::streamReset()
   { stream->reset(); }
 
+inline void Object::streamClose()
+  { stream->close(); }
+
 inline int Object::streamGetChar()
   { return stream->getChar(); }
 
index 16e0ad96d946f6bf012aa322095c5f6445210981..b90636116b8f548fa8454c0c71cd5b1d51089128 100644 (file)
@@ -57,11 +57,14 @@ void OutputDev::updateAll(GfxState *state) {
   updateFont(state);
 }
 
-void OutputDev::drawImageMask(GfxState *state, Stream *str,
+void OutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
                              int width, int height, GBool invert,
                              GBool inlineImg) {
   int i, j;
 
+  (void)state;
+  (void)invert;
+
   if (inlineImg) {
     str->reset();
     j = height * ((width + 7) / 8);
@@ -70,11 +73,13 @@ void OutputDev::drawImageMask(GfxState *state, Stream *str,
   }
 }
 
-void OutputDev::drawImage(GfxState *state, Stream *str, int width,
-                         int height, GfxImageColorMap *colorMap,
+void OutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
+                         int width, int height, GfxImageColorMap *colorMap,
                          GBool inlineImg) {
   int i, j;
 
+  (void)state;
+
   if (inlineImg) {
     str->reset();
     j = height * ((width * colorMap->getNumPixelComps() *
index 6d11ae8e59276e38c8fc3f00380dd2211ff69d04..7128183faea808cc01a09ce9286b8147eb896a46 100644 (file)
@@ -51,7 +51,7 @@ public:
   virtual void setDefaultCTM(double *ctm1);
 
   // Start a page.
-  virtual void startPage(int pageNum, GfxState *state) {}
+  virtual void startPage(int, GfxState *) {}
 
   // End a page.
   virtual void endPage() {}
@@ -66,61 +66,63 @@ public:
   virtual void cvtUserToDev(double ux, double uy, int *dx, int *dy);
 
   //----- link borders
-  virtual void drawLink(Link *link, Catalog *catalog) {}
+  virtual void drawLink(Link *, Catalog *) {}
 
   //----- save/restore graphics state
-  virtual void saveState(GfxState *state) {}
-  virtual void restoreState(GfxState *state) {}
+  virtual void saveState(GfxState *) {}
+  virtual void restoreState(GfxState *) {}
 
   //----- update graphics state
   virtual void updateAll(GfxState *state);
-  virtual void updateCTM(GfxState *state, double m11, double m12,
-                        double m21, double m22, double m31, double m32) {}
-  virtual void updateLineDash(GfxState *state) {}
-  virtual void updateFlatness(GfxState *state) {}
-  virtual void updateLineJoin(GfxState *state) {}
-  virtual void updateLineCap(GfxState *state) {}
-  virtual void updateMiterLimit(GfxState *state) {}
-  virtual void updateLineWidth(GfxState *state) {}
-  virtual void updateFillColor(GfxState *state) {}
-  virtual void updateStrokeColor(GfxState *state) {}
-
-  //----- update text state
-  virtual void updateFont(GfxState *state) {}
-  virtual void updateTextMat(GfxState *state) {}
-  virtual void updateCharSpace(GfxState *state) {}
-  virtual void updateRender(GfxState *state) {}
-  virtual void updateRise(GfxState *state) {}
-  virtual void updateWordSpace(GfxState *state) {}
-  virtual void updateHorizScaling(GfxState *state) {}
-  virtual void updateTextPos(GfxState *state) {}
-  virtual void updateTextShift(GfxState *state, double shift) {}
+  virtual void updateCTM(GfxState *, double, double,
+                        double, double, double, double) {}
+  virtual void updateLineDash(GfxState *) {}
+  virtual void updateFlatness(GfxState *) {}
+  virtual void updateLineJoin(GfxState *) {}
+  virtual void updateLineCap(GfxState *) {}
+  virtual void updateMiterLimit(GfxState *) {}
+  virtual void updateLineWidth(GfxState *) {}
+  virtual void updateFillColor(GfxState *) {}
+  virtual void updateStrokeColor(GfxState *) {}
+  virtual void updateFillOpacity(GfxState *) {}
+  virtual void updateStrokeOpacity(GfxState *) {}
+
+  //----- update text 
+  virtual void updateFont(GfxState *) {}
+  virtual void updateTextMat(GfxState *) {}
+  virtual void updateCharSpace(GfxState *) {}
+  virtual void updateRender(GfxState *) {}
+  virtual void updateRise(GfxState *) {}
+  virtual void updateWordSpace(GfxState *) {}
+  virtual void updateHorizScaling(GfxState *) {}
+  virtual void updateTextPos(GfxState *) {}
+  virtual void updateTextShift(GfxState *, double) {}
 
   //----- path painting
-  virtual void stroke(GfxState *state) {}
-  virtual void fill(GfxState *state) {}
-  virtual void eoFill(GfxState *state) {}
+  virtual void stroke(GfxState *) {}
+  virtual void fill(GfxState *) {}
+  virtual void eoFill(GfxState *) {}
 
   //----- path clipping
-  virtual void clip(GfxState *state) {}
-  virtual void eoClip(GfxState *state) {}
+  virtual void clip(GfxState *) {}
+  virtual void eoClip(GfxState *) {}
 
   //----- text drawing
-  virtual void beginString(GfxState *state, GString *s) {}
-  virtual void endString(GfxState *state) {}
-  virtual void drawChar(GfxState *state, double x, double y,
-                       double dx, double dy, Guchar c) {}
-  virtual void drawChar16(GfxState *state, double x, double y,
-                         double dx, double dy, int c) {}
-  virtual void drawString(GfxState *state, GString *s) {}
-  virtual void drawString16(GfxState *state, GString *s) {}
+  virtual void beginString(GfxState *, GString *) {}
+  virtual void endString(GfxState *) {}
+  virtual void drawChar(GfxState *, double, double,
+                       double, double, Guchar) {}
+  virtual void drawChar16(GfxState *, double, double,
+                         double, double, int) {}
+  virtual void drawString(GfxState *, GString *) {}
+  virtual void drawString16(GfxState *, GString *) {}
 
   //----- image drawing
-  virtual void drawImageMask(GfxState *state, Stream *str,
+  virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
                             int width, int height, GBool invert,
                             GBool inlineImg);
-  virtual void drawImage(GfxState *state, Stream *str, int width,
-                        int height, GfxImageColorMap *colorMap,
+  virtual void drawImage(GfxState *state, Object *ref, Stream *str,
+                        int width, int height, GfxImageColorMap *colorMap,
                         GBool inlineImg);
 
 #if OPI_SUPPORT
index 8d62450d1a4ed2d6289bcd930ed85b9df25cf1cb..b10410e540689ebde8ffccca5df9adef76617dfe 100644 (file)
@@ -80,11 +80,11 @@ PDFDoc::PDFDoc(GString *fileName1, GString *userPassword) {
   ok = setup(userPassword);
 }
 
-PDFDoc::PDFDoc(BaseStream *str, GString *userPassword) {
+PDFDoc::PDFDoc(BaseStream *nstr, GString *userPassword) {
   ok = gFalse;
   fileName = NULL;
   file = NULL;
-  this->str = str;
+  str = nstr;
   xref = NULL;
   catalog = NULL;
   links = NULL;
@@ -168,8 +168,8 @@ void PDFDoc::checkHeader() {
   }
 }
 
-void PDFDoc::displayPage(OutputDev *out, int page, int zoom, int rotate,
-                        GBool doLinks) {
+void PDFDoc::displayPage(OutputDev *out, int page, double zoom,
+                        int rotate, GBool doLinks) {
   Page *p;
 
   if (printCommands) {
@@ -237,6 +237,7 @@ GBool PDFDoc::saveAs(GString *name) {
   while ((c = str->getChar()) != EOF) {
     fputc(c, f);
   }
+  str->close();
   fclose(f);
   return gTrue;
 }
index eb2c9581e6fa63ff5631b9dc819220a52486ce45..e679db9795edec920d234882c4ce902da48b732f 100644 (file)
@@ -61,8 +61,8 @@ public:
   int getNumPages() { return catalog->getNumPages(); }
 
   // Display a page.
-  void displayPage(OutputDev *out, int page, int zoom, int rotate,
-                  GBool doLinks);
+  void displayPage(OutputDev *out, int page, double zoom,
+                  int rotate, GBool doLinks);
 
   // Display a range of pages.
   void displayPages(OutputDev *out, int firstPage, int lastPage,
index 982f582b87a092ba3e68d453a1645b6f621468c2..84e8ca7c720d2ab98c40b7ea097084bc8a8f2b82 100644 (file)
@@ -11,6 +11,7 @@
 #endif
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <stddef.h>
 #include <stdarg.h>
 #include <signal.h>
@@ -44,6 +45,9 @@
 // Generate Level 1 PostScript?
 GBool psOutLevel1 = gFalse;
 
+// Generate Level 1 separable PostScript?
+GBool psOutLevel1Sep = gFalse;
+
 // Generate Encapsulated PostScript?
 GBool psOutEPS = gFalse;
 
@@ -52,18 +56,17 @@ GBool psOutEPS = gFalse;
 GBool psOutOPI = gFalse;
 #endif
 
-int paperWidth = 612;
-int paperHeight = 792;
+int paperWidth = defPaperWidth;
+int paperHeight = defPaperHeight;
 
 //------------------------------------------------------------------------
 // PostScript prolog and setup
 //------------------------------------------------------------------------
 
-static char *prolog[] = {
+static const char *prolog[] = {
   "/xpdf 75 dict def xpdf begin",
   "% PDF special state",
   "/pdfDictSize 14 def",
-#if 0 // Not used for CUPS - the pstops filter handles this...
   "/pdfSetup {",
   "  2 array astore",
   "  /setpagedevice where {",
@@ -76,7 +79,6 @@ static char *prolog[] = {
   "    pop",
   "  } ifelse",
   "} def",
-#endif // 0
   "/pdfStartPage {",
   "  pdfDictSize dict begin",
   "  /pdfFill [0] def",
@@ -92,16 +94,22 @@ static char *prolog[] = {
   "  /pdfHorizScaling 1 def",
   "} def",
   "/pdfEndPage { end } def",
-  "/sCol { pdfLastStroke not {",
-  "          pdfStroke aload length",
-  "          1 eq { setgray } { setrgbcolor} ifelse",
-  "          /pdfLastStroke true def /pdfLastFill false def",
-  "        } if } def",
-  "/fCol { pdfLastFill not {",
-  "          pdfFill aload length",
-  "          1 eq { setgray } { setrgbcolor } ifelse",
-  "          /pdfLastFill true def /pdfLastStroke false def",
-  "        } if } def",
+  "/sCol {",
+  "  pdfLastStroke not {",
+  "    pdfStroke aload length",
+  "    dup 1 eq { pop setgray }",
+  "      { 3 eq { setrgbcolor } { setcmykcolor } ifelse } ifelse",
+  "    /pdfLastStroke true def /pdfLastFill false def",
+  "  } if",
+  "} def",
+  "/fCol {",
+  "  pdfLastFill not {",
+  "    pdfFill aload length",
+  "    dup 1 eq { pop setgray }",
+  "      { 3 eq { setrgbcolor } { setcmykcolor } ifelse } ifelse",
+  "    /pdfLastFill true def /pdfLastStroke false def",
+  "  } if",
+  "} def",
   "% build a font",
   "/pdfMakeFont {",
   "  4 3 roll findfont",
@@ -126,12 +134,16 @@ static char *prolog[] = {
   "/w { setlinewidth } def",
   "% color operators",
   "/g { dup 1 array astore /pdfFill exch def setgray",
-  "    /pdfLastFill true def /pdfLastStroke false def } def",
+  "     /pdfLastFill true def /pdfLastStroke false def } def",
   "/G { dup 1 array astore /pdfStroke exch def setgray",
   "     /pdfLastStroke true def /pdfLastFill false def } def",
   "/rg { 3 copy 3 array astore /pdfFill exch def setrgbcolor",
-  "     /pdfLastFill true def /pdfLastStroke false def } def",
+  "      /pdfLastFill true def /pdfLastStroke false def } def",
   "/RG { 3 copy 3 array astore /pdfStroke exch def setrgbcolor",
+  "      /pdfLastStroke true def /pdfLastFill false def } def",
+  "/k { 4 copy 4 array astore /pdfFill exch def setcmykcolor",
+  "     /pdfLastFill true def /pdfLastStroke false def } def",
+  "/K { 4 copy 4 array astore /pdfStroke exch def setcmykcolor",
   "     /pdfLastStroke true def /pdfLastFill false def } def",
   "% path segment operators",
   "/m { moveto } def",
@@ -168,7 +180,11 @@ static char *prolog[] = {
   "      sub 1 index length dup 0 ne { div } { pop pop 0 } ifelse",
   "      pdfWordSpacing 0 pdfTextMat dtransform 32",
   "      4 3 roll pdfCharSpacing add 0 pdfTextMat dtransform",
+#if 0 /* temporary fix until we can figure out why the width is wrong */
   "      6 5 roll awidthshow",
+#else
+  "      6 5 roll show pop pop pop pop pop",
+#endif /* 0 */
   "      0 pdfTextRise neg pdfTextMat dtransform rmoveto } def",
   "/TJm { pdfFontSize 0.001 mul mul neg 0",
   "       pdfTextMat dtransform rmoveto } def",
@@ -177,6 +193,17 @@ static char *prolog[] = {
   "  /pdfImBuf1 4 index string def",
   "  { currentfile pdfImBuf1 readhexstring pop } image",
   "} def",
+  "/pdfIm1Sep {",
+  "  /pdfImBuf1 4 index string def",
+  "  /pdfImBuf2 4 index string def",
+  "  /pdfImBuf3 4 index string def",
+  "  /pdfImBuf4 4 index string def",
+  "  { currentfile pdfImBuf1 readhexstring pop }",
+  "  { currentfile pdfImBuf2 readhexstring pop }",
+  "  { currentfile pdfImBuf3 readhexstring pop }",
+  "  { currentfile pdfImBuf4 readhexstring pop }",
+  "  true 4 colorimage",
+  "} def",
   "/pdfImM1 {",
   "  /pdfImBuf1 4 index 7 add 8 idiv string def",
   "  { currentfile pdfImBuf1 readhexstring pop } imagemask",
@@ -204,12 +231,12 @@ static char *prolog[] = {
 //------------------------------------------------------------------------
 
 struct PSFont {
-  char *name;                  // PDF name
-  char *psName;                        // PostScript name
+  const char *name;            // PDF name
+  const char *psName;          // PostScript name
 };
 
 struct PSSubstFont {
-  char *psName;                        // PostScript name
+  const char *psName;          // PostScript name
   double mWidth;               // width of 'm' character
 };
 
@@ -250,13 +277,13 @@ static PSSubstFont psSubstFonts[] = {
 // PSOutputDev
 //------------------------------------------------------------------------
 
-PSOutputDev::PSOutputDev(char *fileName, Catalog *catalog,
+PSOutputDev::PSOutputDev(const char *fileName, Catalog *catalog,
                         int firstPage, int lastPage,
                         GBool embedType11, GBool doForm1) {
   Page *page;
   Dict *resDict;
   FormWidgets *formWidgets;
-  char **p;
+  const char **p;
   int pg;
   Object obj1, obj2;
   int i;
@@ -281,7 +308,7 @@ PSOutputDev::PSOutputDev(char *fileName, Catalog *catalog,
     fileType = psPipe;
 #ifdef HAVE_POPEN
 #ifndef WIN32
-    signal(SIGPIPE, (void (*)(int))SIG_IGN);
+    signal(SIGPIPE, SIG_IGN);
 #endif
     if (!(f = popen(fileName + 1, "w"))) {
       error(-1, "Couldn't run print command '%s'", fileName);
@@ -320,12 +347,27 @@ PSOutputDev::PSOutputDev(char *fileName, Catalog *catalog,
   if (doForm) {
     writePS("%%!PS-Adobe-3.0 Resource-Form\n");
     writePS("%%%%Creator: xpdf/pdftops %s\n", xpdfVersion);
-    writePS("%%%%LanguageLevel: %d\n", psOutLevel1 ? 1 : 2);
+    writePS("%%%%LanguageLevel: %d\n",
+           (psOutLevel1 || psOutLevel1Sep) ? 1 : 2);
+    if (psOutLevel1Sep) {
+      writePS("%%%%DocumentProcessColors: Cyan Magenta Yellow Black\n");
+    }
     writePS("%%%%EndComments\n");
+    page = catalog->getPage(firstPage);
+    writePS("32 dict dup begin\n");
+    writePS("/BBox [%d %d %d %d] def\n",
+           (int)page->getX1(), (int)page->getY1(),
+           (int)page->getX2(), (int)page->getY2());
+    writePS("/FormType 1 def\n");
+    writePS("/Matrix [1 0 0 1 0 0] def\n");
   } else if (psOutEPS) {
     writePS("%%!PS-Adobe-3.0 EPSF-3.0\n");
     writePS("%%%%Creator: xpdf/pdftops %s\n", xpdfVersion);
-    writePS("%%%%LanguageLevel: %d\n", psOutLevel1 ? 1 : 2);
+    writePS("%%%%LanguageLevel: %d\n",
+           (psOutLevel1 || psOutLevel1Sep) ? 1 : 2);
+    if (psOutLevel1Sep) {
+      writePS("%%%%DocumentProcessColors: Cyan Magenta Yellow Black\n");
+    }
     page = catalog->getPage(firstPage);
     writePS("%%%%BoundingBox: %d %d %d %d\n",
            (int)floor(page->getX1()), (int)floor(page->getY1()),
@@ -338,13 +380,16 @@ PSOutputDev::PSOutputDev(char *fileName, Catalog *catalog,
              page->getX1(), page->getY1(),
              page->getX2(), page->getY2());
     }
-    writePS("%%%%DocumentSuppliedResources:\n");
-    writePS("%%%%+ font: (atend)\n");
+    writePS("%%%%DocumentSuppliedResources: (atend)\n");
     writePS("%%%%EndComments\n");
   } else {
     writePS("%%!PS-Adobe-3.0\n");
     writePS("%%%%Creator: xpdf/pdftops %s\n", xpdfVersion);
-    writePS("%%%%LanguageLevel: %d\n", psOutLevel1 ? 1 : 2);
+    writePS("%%%%LanguageLevel: %d\n",
+           (psOutLevel1 || psOutLevel1Sep) ? 1 : 2);
+    if (psOutLevel1Sep) {
+      writePS("%%%%DocumentProcessColors: Cyan Magenta Yellow Black\n");
+    }
     writePS("%%%%DocumentMedia: plain %d %d 0 () ()\n",
            paperWidth, paperHeight);
     writePS("%%%%Pages: %d\n", lastPage - firstPage + 1);
@@ -355,23 +400,31 @@ PSOutputDev::PSOutputDev(char *fileName, Catalog *catalog,
   }
 
   // write prolog
-  if (!doForm)
+  if (!doForm) {
     writePS("%%%%BeginProlog\n");
-  writePS("%%%%BeginResource: xpdf %s\n", xpdfVersion);
-  for (p = prolog; *p; ++p)
+  }
+  writePS("%%%%BeginResource: procset xpdf %s 0\n", xpdfVersion);
+  for (p = prolog; *p; ++p) {
     writePS("%s\n", *p);
+  }
   writePS("%%%%EndResource\n");
-  if (!doForm)
+  if (!doForm) {
     writePS("%%%%EndProlog\n");
+  }
 
-  // set up fonts
-  if (!doForm)
+  // set up fonts and images
+  type3Warning = gFalse;
+  if (doForm) {
+    // swap the form and xpdf dicts
+    writePS("xpdf end begin dup begin\n");
+  } else {
     writePS("%%%%BeginSetup\n");
-  writePS("xpdf begin\n");
+    writePS("xpdf begin\n");
+  }
   for (pg = firstPage; pg <= lastPage; ++pg) {
     page = catalog->getPage(pg);
     if ((resDict = page->getResourceDict())) {
-      setupFonts(resDict);
+      setupResources(resDict);
     }
     formWidgets = new FormWidgets(page->getAnnots(&obj1));
     obj1.free();
@@ -379,7 +432,7 @@ PSOutputDev::PSOutputDev(char *fileName, Catalog *catalog,
       if (formWidgets->getWidget(i)->getAppearance(&obj1)->isStream()) {
        obj1.streamGetDict()->lookup("Resources", &obj2);
        if (obj2.isDict()) {
-         setupFonts(obj2.getDict());
+         setupResources(obj2.getDict());
        }
        obj2.free();
       }
@@ -387,32 +440,21 @@ PSOutputDev::PSOutputDev(char *fileName, Catalog *catalog,
     }
     delete formWidgets;
   }
-  if (doForm) {
-    writePS("end\n");
-  } else {
+  if (!doForm) {
 #if OPI_SUPPORT
     if (psOutOPI) {
       writePS("/opiMatrix matrix currentmatrix def\n");
     }
 #endif
     if (!psOutEPS) {
-// pdfSetup not used for CUPS filter...
-//      writePS("%d %d pdfSetup\n", paperWidth, paperHeight);
+      if (!getenv("PPD") || !getenv("SOFTWARE")) {
+        // pdfSetup not used for CUPS filter...
+        writePS("%d %d pdfSetup\n", paperWidth, paperHeight);
+      }
     }
     writePS("%%%%EndSetup\n");
   }
 
-  // write form header
-  if (doForm) {
-    page = catalog->getPage(firstPage);
-    writePS("4 dict dup begin\n");
-    writePS("/BBox [%d %d %d %d] def\n",
-           (int)page->getX1(), (int)page->getY1(),
-           (int)page->getX2(), (int)page->getY2());
-    writePS("/FormType 1 def\n");
-    writePS("/Matrix [1 0 0 1 0 0] def\n");
-  }
-
   // initialize sequential page number
   seqPage = 1;
 
@@ -428,7 +470,6 @@ PSOutputDev::~PSOutputDev() {
 
   if (f) {
     if (doForm) {
-      writePS("end\n");
       writePS("/Foo exch /Form defineresource pop\n");
     } else if (psOutEPS) {
       writePS("%%%%Trailer\n");
@@ -451,7 +492,7 @@ PSOutputDev::~PSOutputDev() {
     else if (fileType == psPipe) {
       pclose(f);
 #ifndef WIN32
-      signal(SIGPIPE, (void (*)(int))SIG_DFL);
+      signal(SIGPIPE, SIG_DFL);
 #endif
     }
 #endif
@@ -473,22 +514,12 @@ PSOutputDev::~PSOutputDev() {
   }
 }
 
-void PSOutputDev::setupFonts(Dict *resDict) {
-  Object fontDict, xObjDict, xObj, resObj;
-  GfxFontDict *gfxFontDict;
-  GfxFont *font;
+void PSOutputDev::setupResources(Dict *resDict) {
+  Object xObjDict, xObj, resObj;
   int i;
 
-  resDict->lookup("Font", &fontDict);
-  if (fontDict.isDict()) {
-    gfxFontDict = new GfxFontDict(fontDict.getDict());
-    for (i = 0; i < gfxFontDict->getNumFonts(); ++i) {
-      font = gfxFontDict->getFont(i);
-      setupFont(font);
-    }
-    delete gfxFontDict;
-  }
-  fontDict.free();
+  setupFonts(resDict);
+  setupImages(resDict);
 
   resDict->lookup("XObject", &xObjDict);
   if (xObjDict.isDict()) {
@@ -496,8 +527,9 @@ void PSOutputDev::setupFonts(Dict *resDict) {
       xObjDict.dictGetVal(i, &xObj);
       if (xObj.isStream()) {
        xObj.streamGetDict()->lookup("Resources", &resObj);
-       if (resObj.isDict())
-         setupFonts(resObj.getDict());
+       if (resObj.isDict()) {
+         setupResources(resObj.getDict());
+       }
        resObj.free();
       }
       xObj.free();
@@ -506,11 +538,29 @@ void PSOutputDev::setupFonts(Dict *resDict) {
   xObjDict.free();
 }
 
+void PSOutputDev::setupFonts(Dict *resDict) {
+  Object fontDict;
+  GfxFontDict *gfxFontDict;
+  GfxFont *font;
+  int i;
+
+  resDict->lookup("Font", &fontDict);
+  if (fontDict.isDict()) {
+    gfxFontDict = new GfxFontDict(fontDict.getDict());
+    for (i = 0; i < gfxFontDict->getNumFonts(); ++i) {
+      font = gfxFontDict->getFont(i);
+      setupFont(font);
+    }
+    delete gfxFontDict;
+  }
+  fontDict.free();
+}
+
 void PSOutputDev::setupFont(GfxFont *font) {
   Ref fontFileID;
   GString *name;
-  char *psName;
-  char *charName;
+  const char *psName;
+  const char *charName;
   double xs, ys;
   GBool do16Bit;
   int code;
@@ -560,6 +610,10 @@ void PSOutputDev::setupFont(GfxFont *font) {
 
   // do font substitution
   } else {
+    if (!type3Warning && font->getType() == fontType3) {
+      error(-1, "This document uses Type 3 fonts - some text may not be correctly printed");
+      type3Warning = gTrue;
+    }
     name = font->getName();
     psName = NULL;
     if (name) {
@@ -627,7 +681,7 @@ void PSOutputDev::setupFont(GfxFont *font) {
   }
 }
 
-void PSOutputDev::setupEmbeddedType1Font(Ref *id, char *psName) {
+void PSOutputDev::setupEmbeddedType1Font(Ref *id, const char *psName) {
   static char hexChar[17] = "0123456789abcdef";
   Object refObj, strObj, obj1, obj2;
   Dict *dict;
@@ -743,12 +797,13 @@ void PSOutputDev::setupEmbeddedType1Font(Ref *id, char *psName) {
   }
 
  err1:
+  strObj.streamClose();
   strObj.free();
 }
 
 //~ This doesn't handle .pfb files or binary eexec data (which only
 //~ happens in pfb files?).
-void PSOutputDev::setupEmbeddedType1Font(GString *fileName, char *psName) {
+void PSOutputDev::setupEmbeddedType1Font(GString *fileName, const char *psName) {
   FILE *fontFile;
   int c;
   int i;
@@ -792,8 +847,8 @@ void PSOutputDev::setupEmbeddedType1Font(GString *fileName, char *psName) {
 }
 
 void PSOutputDev::setupEmbeddedType1CFont(GfxFont *font, Ref *id,
-                                         char *psName) {
-  char *fontBuf;
+                                         const char *psName) {
+  const char *fontBuf;
   int fontLen;
   Type1CFontConverter *cvt;
   int i;
@@ -825,7 +880,7 @@ void PSOutputDev::setupEmbeddedType1CFont(GfxFont *font, Ref *id,
   cvt = new Type1CFontConverter(fontBuf, fontLen, f);
   cvt->convert();
   delete cvt;
-  gfree(fontBuf);
+  gfree((void *)fontBuf);
 
   // ending comment
   if (psOutEPS) {
@@ -833,6 +888,121 @@ void PSOutputDev::setupEmbeddedType1CFont(GfxFont *font, Ref *id,
   }
 }
 
+void PSOutputDev::setupImages(Dict *resDict) {
+  Object xObjDict, xObj, xObjRef, subtypeObj;
+  int i;
+
+  if (!doForm) {
+    return;
+  }
+
+  resDict->lookup("XObject", &xObjDict);
+  if (xObjDict.isDict()) {
+    for (i = 0; i < xObjDict.dictGetLength(); ++i) {
+      xObjDict.dictGetValNF(i, &xObjRef);
+      xObjDict.dictGetVal(i, &xObj);
+      if (xObj.isStream()) {
+       xObj.streamGetDict()->lookup("Subtype", &subtypeObj);
+       if (subtypeObj.isName("Image")) {
+         if (xObjRef.isRef()) {
+           setupImage(xObjRef.getRef(), xObj.getStream());
+         } else {
+           error(-1, "Image in resource dict is not an indirect reference");
+         }
+       }
+       subtypeObj.free();
+      }
+      xObj.free();
+      xObjRef.free();
+    }
+  }
+  xObjDict.free();
+}
+
+void PSOutputDev::setupImage(Ref id, Stream *str) {
+  int c;
+  int size, line, col, i;
+
+  // construct an encoder stream
+  str = new ASCII85Encoder(str);
+
+  // compute image data size
+  str->reset();
+  col = size = 0;
+  do {
+    do {
+      c = str->getChar();
+    } while (c == '\n' || c == '\r');
+    if (c == '~' || c == EOF) {
+      break;
+    }
+    if (c == 'z') {
+      ++col;
+    } else {
+      ++col;
+      for (i = 1; i <= 4; ++i) {
+       do {
+         c = str->getChar();
+       } while (c == '\n' || c == '\r');
+       if (c == '~' || c == EOF) {
+         break;
+       }
+       ++col;
+      }
+    }
+    if (col > 225) {
+      ++size;
+      col = 0;
+    }
+  } while (c != '~' && c != EOF);
+  ++size;
+  writePS("%d array dup /ImData_%d_%d exch def\n", size, id.num, id.gen);
+
+  // write the data into the array
+  str->reset();
+  line = col = 0;
+  writePS("dup 0 <~");
+  do {
+    do {
+      c = str->getChar();
+    } while (c == '\n' || c == '\r');
+    if (c == '~' || c == EOF) {
+      break;
+    }
+    if (c == 'z') {
+      fputc(c, f);
+      ++col;
+    } else {
+      fputc(c, f);
+      ++col;
+      for (i = 1; i <= 4; ++i) {
+       do {
+         c = str->getChar();
+       } while (c == '\n' || c == '\r');
+       if (c == '~' || c == EOF) {
+         break;
+       }
+       fputc(c, f);
+       ++col;
+      }
+    }
+    // each line is: "dup nnnnn <~...data...~> put<eol>"
+    // so max data length = 255 - 20 = 235
+    // chunks are 1 or 4 bytes each, so we have to stop at 232
+    // but make it 225 just to be safe
+    if (col > 225) {
+      writePS("~> put\n");
+      ++line;
+      writePS("dup %d <~", line);
+      col = 0;
+    }
+  } while (c != '~' && c != EOF);
+  writePS("~> put\n");
+  writePS("pop\n");
+
+  delete str;
+}
+
 void PSOutputDev::startPage(int pageNum, GfxState *state) {
   int x1, y1, x2, y2, width, height, t;
 
@@ -911,6 +1081,7 @@ void PSOutputDev::endPage() {
     writePS("pdfEndPage\n");
     writePS("end end\n");
     writePS("} def\n");
+    writePS("end end\n");
   } else {
     writePS("showpage\n");
     writePS("%%%%PageTrailer\n");
@@ -919,15 +1090,21 @@ void PSOutputDev::endPage() {
 }
 
 void PSOutputDev::saveState(GfxState *state) {
+  (void)state;
+
   writePS("q\n");
 }
 
 void PSOutputDev::restoreState(GfxState *state) {
+  (void)state;
+
   writePS("Q\n");
 }
 
 void PSOutputDev::updateCTM(GfxState *state, double m11, double m12,
                            double m21, double m22, double m31, double m32) {
+  (void)state;
+
   writePS("[%g %g %g %g %g %g] cm\n", m11, m12, m21, m22, m31, m32);
 }
 
@@ -964,31 +1141,37 @@ void PSOutputDev::updateLineWidth(GfxState *state) {
 }
 
 void PSOutputDev::updateFillColor(GfxState *state) {
-  GfxColor *color;
-  double r, g, b;
-
-  color = state->getFillColor();
-  r = color->getR();
-  g = color->getG();
-  b = color->getB();
-  if (r == g && g == b)
-    writePS("%g g\n", r);
-  else
-    writePS("%g %g %g rg\n", r, g, b);
+  GfxRGB rgb;
+  GfxCMYK cmyk;
+
+  if (psOutLevel1Sep) {
+    state->getFillCMYK(&cmyk);
+    writePS("%g %g %g %g k\n", cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+  } else {
+    state->getFillRGB(&rgb);
+    if (rgb.r == rgb.g && rgb.g == rgb.b) {
+      writePS("%g g\n", rgb.r);
+    } else {
+      writePS("%g %g %g rg\n", rgb.r, rgb.g, rgb.b);
+    }
+  }
 }
 
 void PSOutputDev::updateStrokeColor(GfxState *state) {
-  GfxColor *color;
-  double r, g, b;
-
-  color = state->getStrokeColor();
-  r = color->getR();
-  g = color->getG();
-  b = color->getB();
-  if (r == g && g == b)
-    writePS("%g G\n", r);
-  else
-    writePS("%g %g %g RG\n", r, g, b);
+  GfxRGB rgb;
+  GfxCMYK cmyk;
+
+  if (psOutLevel1Sep) {
+    state->getStrokeCMYK(&cmyk);
+    writePS("%g %g %g %g K\n", cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+  } else {
+    state->getStrokeRGB(&rgb);
+    if (rgb.r == rgb.g && rgb.g == rgb.b) {
+      writePS("%g G\n", rgb.r);
+    } else {
+      writePS("%g %g %g RG\n", rgb.r, rgb.g, rgb.b);
+    }
+  }
 }
 
 void PSOutputDev::updateFont(GfxState *state) {
@@ -1032,6 +1215,8 @@ void PSOutputDev::updateTextPos(GfxState *state) {
 }
 
 void PSOutputDev::updateTextShift(GfxState *state, double shift) {
+  (void)state;
+
   writePS("%g TJm\n", shift);
 }
 
@@ -1126,9 +1311,13 @@ void PSOutputDev::drawString(GfxState *state, GString *s) {
 }
 
 void PSOutputDev::drawString16(GfxState *state, GString *s) {
+#if defined(JAPANESE_SUPPORT) || defined(CHINESE_SUPPORT)
   int c1, c2;
   double w;
   int i;
+#else
+  (void)s;
+#endif /* JAPANESE_SUPPORT || CHINESE_SUPPORT */
 
   // check for invisible text -- this is used by Acrobat Capture
   if ((state->getRender() & 3) == 3)
@@ -1160,42 +1349,57 @@ void PSOutputDev::drawString16(GfxState *state, GString *s) {
 
   case font16AdobeGB12:
     break;
+
+  case font16AdobeCNS13:
+    break;
   }
 }
 
-void PSOutputDev::drawImageMask(GfxState *state, Stream *str,
+void PSOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
                                int width, int height, GBool invert,
                                GBool inlineImg) {
   int len;
 
+  (void)state;
+
   len = height * ((width + 7) / 8);
-  if (psOutLevel1)
+  if (psOutLevel1 || psOutLevel1Sep) {
     doImageL1(NULL, invert, inlineImg, str, width, height, len);
-  else
-    doImage(NULL, invert, inlineImg, str, width, height, len);
+  } else {
+    doImageL2(ref, NULL, invert, inlineImg, str, width, height, len);
+  }
 }
 
-void PSOutputDev::drawImage(GfxState *state, Stream *str, int width,
-                           int height, GfxImageColorMap *colorMap,
+void PSOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
+                           int width, int height, GfxImageColorMap *colorMap,
                            GBool inlineImg) {
   int len;
 
+  (void)state;
+
   len = height * ((width * colorMap->getNumPixelComps() *
                   colorMap->getBits() + 7) / 8);
-  if (psOutLevel1)
+  if (psOutLevel1) {
     doImageL1(colorMap, gFalse, inlineImg, str, width, height, len);
-  else
-    doImage(colorMap, gFalse, inlineImg, str, width, height, len);
+  } else if (psOutLevel1Sep) {
+    //~ handle indexed, separation, ... color spaces
+    doImageL1Sep(colorMap, gFalse, inlineImg, str, width, height, len);
+  } else {
+    doImageL2(ref, colorMap, gFalse, inlineImg, str, width, height, len);
+  }
 }
 
 void PSOutputDev::doImageL1(GfxImageColorMap *colorMap,
                            GBool invert, GBool inlineImg,
                            Stream *str, int width, int height, int len) {
   ImageStream *imgStr;
-  Guchar pixBuf[4];
-  GfxColor color;
+  Guchar pixBuf[gfxColorMaxComps];
+  double gray;
   int x, y, i;
 
+  (void)inlineImg;
+  (void)len;
+
   // width, height, matrix, bits per component
   if (colorMap) {
     writePS("%d %d 8 [%d 0 0 %d 0 %d] pdfIm1\n",
@@ -1222,8 +1426,8 @@ void PSOutputDev::doImageL1(GfxImageColorMap *colorMap,
       // write the line
       for (x = 0; x < width; ++x) {
        imgStr->getPixel(pixBuf);
-       colorMap->getColor(pixBuf, &color);
-       fprintf(f, "%02x", (int)(color.getGray() * 255 + 0.5));
+       colorMap->getGray(pixBuf, &gray);
+       fprintf(f, "%02x", (int)(gray * 255 + 0.5));
        if (++i == 32) {
          fputc('\n', f);
          i = 0;
@@ -1252,97 +1456,80 @@ void PSOutputDev::doImageL1(GfxImageColorMap *colorMap,
   }
 }
 
-void PSOutputDev::doImage(GfxImageColorMap *colorMap,
-                         GBool invert, GBool inlineImg,
-                         Stream *str, int width, int height, int len) {
-  GfxColorSpace *colorSpace;
-  LabParams *labParams;
+void PSOutputDev::doImageL1Sep(GfxImageColorMap *colorMap,
+                              GBool invert, GBool inlineImg,
+                              Stream *str, int width, int height, int len) {
+  ImageStream *imgStr;
+  Guchar *lineBuf;
+  Guchar pixBuf[gfxColorMaxComps];
+  GfxCMYK cmyk;
+  int x, y, i, comp;
+
+  // width, height, matrix, bits per component
+  writePS("%d %d 8 [%d 0 0 %d 0 %d] pdfIm1Sep\n",
+           width, height,
+           width, -height, height);
+
+  // allocate a line buffer
+  lineBuf = (Guchar *)gmalloc(4 * width);
+
+  // set up to process the data stream
+  imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(),
+                          colorMap->getBits());
+  imgStr->reset();
+
+  // process the data stream
+  i = 0;
+  for (y = 0; y < height; ++y) {
+
+    // read the line
+    for (x = 0; x < width; ++x) {
+      imgStr->getPixel(pixBuf);
+      colorMap->getCMYK(pixBuf, &cmyk);
+      lineBuf[4*x+0] = (int)(255 * cmyk.c + 0.5);
+      lineBuf[4*x+1] = (int)(255 * cmyk.m + 0.5);
+      lineBuf[4*x+2] = (int)(255 * cmyk.y + 0.5);
+      lineBuf[4*x+3] = (int)(255 * cmyk.k + 0.5);
+    }
+
+    // write one line of each color component
+    for (comp = 0; comp < 4; ++comp) {
+      for (x = 0; x < width; ++x) {
+       fprintf(f, "%02x", lineBuf[4*x + comp]);
+       if (++i == 32) {
+         fputc('\n', f);
+         i = 0;
+       }
+      }
+    }
+  }
+
+  if (i != 0) {
+    fputc('\n', f);
+  }
+
+  delete imgStr;
+  gfree(lineBuf);
+}
+
+void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
+                           GBool invert, GBool inlineImg,
+                           Stream *str, int width, int height, int len) {
   GString *s;
   int n, numComps;
-  Guchar *color;
-  Guchar x[4];
-  GfxColor rgb;
   GBool useRLE, useA85;
   int c;
-  int i, j, k;
+  int i;
 
   // color space
   if (colorMap) {
-    colorSpace = colorMap->getColorSpace();
-    if (colorSpace->isSeparation()) {
-      //~ this is a kludge -- the correct thing would be to output
-      //~ a separation color space
-      n = (1 << colorMap->getBits()) - 1;
-      writePS("[/Indexed /DeviceRGB %d <", n);
-      for (i = 0; i <= n; i += 8) {
-       writePS("  ");
-       for (j = i; j < i+8 && j <= n; ++j) {
-         x[0] = j;
-         colorMap->getColor(x, &rgb);
-         writePS("%02x%02x%02x",
-                 (int)(255 * rgb.getR() + 0.5),
-                 (int)(255 * rgb.getG() + 0.5),
-                 (int)(255 * rgb.getB() + 0.5));
-       }
-       writePS("\n");
-      }
-      writePS("> ] setcolorspace\n");
-    } else {
-      if (colorSpace->isIndexed()) {
-       writePS("[/Indexed ");
-      }
-      switch (colorSpace->getMode()) {
-      case colorGray:
-       writePS("/DeviceGray ");
-       break;
-      case colorCMYK:
-       writePS("/DeviceCMYK ");
-       break;
-      case colorRGB:
-       writePS("/DeviceRGB ");
-       break;
-      case colorLab:
-       labParams = colorSpace->getLabParams();
-       writePS("[/CIEBasedABC <<\n");
-       writePS(" /RangeABC [0 100 %g %g %g %g]\n",
-               labParams->aMin, labParams->aMax,
-               labParams->bMin, labParams->bMax);
-       writePS(" /DecodeABC [{16 add 116 div} bind {500 div} bind {200 div} bind]\n");
-       writePS(" /MatrixABC [1 1 1 1 0 0 0 0 -1]\n");
-       writePS(" /DecodeLMN\n");
-       writePS("   [{dup 6 29 div ge {dup dup mul mul}\n");
-       writePS("     {4 29 div sub 108 841 div mul } ifelse %g mul} bind\n",
-               labParams->whiteX);
-       writePS("    {dup 6 29 div ge {dup dup mul mul}\n");
-       writePS("     {4 29 div sub 108 841 div mul } ifelse %g mul} bind\n",
-               labParams->whiteY);
-       writePS("    {dup 6 29 div ge {dup dup mul mul}\n");
-       writePS("     {4 29 div sub 108 841 div mul } ifelse %g mul} bind]\n",
-               labParams->whiteZ);
-       writePS(" /WhitePoint [%g %g %g]\n",
-               labParams->whiteX, labParams->whiteY, labParams->whiteZ);
-       writePS(">>] ");
-       break;
-      }
-      if (colorSpace->isIndexed()) {
-       n = colorSpace->getIndexHigh();
-       numComps = colorSpace->getNumColorComps();
-       writePS("%d <\n", n);
-       for (i = 0; i <= n; i += 8) {
-         writePS("  ");
-         for (j = i; j < i+8 && j <= n; ++j) {
-           color = colorSpace->getLookupVal(j);
-           for (k = 0; k < numComps; ++k) {
-             writePS("%02x", color[k]);
-           }
-         }
-         writePS("\n");
-       }
-       writePS("> ] setcolorspace\n");
-      } else {
-       writePS("setcolorspace\n");
-      }
-    }
+    dumpColorSpaceL2(colorMap->getColorSpace());
+    writePS(" setcolorspace\n");
+  }
+
+  // set up to use the array created by setupImages()
+  if (doForm && !inlineImg) {
+    writePS("ImData_%d_%d 0\n", ref->getRefNum(), ref->getRefGen());
   }
 
   // image dictionary
@@ -1358,9 +1545,8 @@ void PSOutputDev::doImage(GfxImageColorMap *colorMap,
   // decode 
   if (colorMap) {
     writePS("  /Decode [");
-    if (colorMap->getColorSpace()->isSeparation()) {
-      //~ this is a kludge -- the correct thing would be to output
-      //~ a separation color space
+    if (colorMap->getColorSpace()->getMode() == csSeparation) {
+      //~ this is a kludge -- see comment in dumpColorSpaceL2
       n = (1 << colorMap->getBits()) - 1;
       writePS("%g %g", colorMap->getDecodeLow(0) * n,
              colorMap->getDecodeHigh(0) * n);
@@ -1381,23 +1567,33 @@ void PSOutputDev::doImage(GfxImageColorMap *colorMap,
 
   if (doForm) {
 
-    // data source
-    writePS("  /DataSource <~\n");
-
-    // write image data stream, using ASCII85 encode filter
     if (inlineImg) {
+
+      // data source
+      writePS("  /DataSource <~\n");
+
+      // write image data stream, using ASCII85 encode filter
       str = new FixedLengthEncoder(str, len);
+      str = new ASCII85Encoder(str);
+      str->reset();
+      while ((c = str->getChar()) != EOF) {
+       fputc(c, f);
+      }
+      fputc('\n', f);
+      delete str;
+
+    } else {
+      writePS("  /DataSource { 2 copy get exch 1 add exch }\n");
     }
-    str = new ASCII85Encoder(str);
-    str->reset();
-    while ((c = str->getChar()) != EOF)
-      fputc(c, f);
-    fputc('\n', f);
-    delete str;
 
     // end of image dictionary
     writePS(">>\n%s\n", colorMap ? "image" : "imagemask");
 
+    // get rid of the array and index
+    if (!inlineImg) {
+      writePS("pop pop\n");
+    }
+
   } else {
 
     // data source
@@ -1476,6 +1672,152 @@ void PSOutputDev::doImage(GfxImageColorMap *colorMap,
   }
 }
 
+void PSOutputDev::dumpColorSpaceL2(GfxColorSpace *colorSpace) {
+  GfxCalGrayColorSpace *calGrayCS;
+  GfxCalRGBColorSpace *calRGBCS;
+  GfxLabColorSpace *labCS;
+  GfxIndexedColorSpace *indexedCS;
+  GfxSeparationColorSpace *separationCS;
+  Guchar *lookup;
+  double x[1], y[gfxColorMaxComps];
+  int n, numComps;
+  int i, j, k;
+
+  switch (colorSpace->getMode()) {
+
+  case csDeviceGray:
+    writePS("/DeviceGray");
+    break;
+
+  case csCalGray:
+    calGrayCS = (GfxCalGrayColorSpace *)colorSpace;
+    writePS("[/CIEBasedA <<\n");
+    writePS(" /DecodeA {%g exp} bind\n", calGrayCS->getGamma());
+    writePS(" /MatrixA [%g %g %g]\n",
+           calGrayCS->getWhiteX(), calGrayCS->getWhiteY(),
+           calGrayCS->getWhiteZ());
+    writePS(" /WhitePoint [%g %g %g]\n",
+           calGrayCS->getWhiteX(), calGrayCS->getWhiteY(),
+           calGrayCS->getWhiteZ());
+    writePS(" /BlackPoint [%g %g %g]\n",
+           calGrayCS->getBlackX(), calGrayCS->getBlackY(),
+           calGrayCS->getBlackZ());
+    writePS(">>]");
+    break;
+
+  case csDeviceRGB:
+    writePS("/DeviceRGB");
+    break;
+
+  case csCalRGB:
+    calRGBCS = (GfxCalRGBColorSpace *)colorSpace;
+    writePS("[/CIEBasedABC <<\n");
+    writePS(" /DecodeABC [{%g exp} bind {%g exp} bind {%g exp} bind]\n",
+           calRGBCS->getGammaR(), calRGBCS->getGammaG(),
+           calRGBCS->getGammaB());
+    writePS(" /MatrixABC [%g %g %g %g %g %g %g %g %g]\n",
+           calRGBCS->getMatrix()[0], calRGBCS->getMatrix()[1],
+           calRGBCS->getMatrix()[2], calRGBCS->getMatrix()[3],
+           calRGBCS->getMatrix()[4], calRGBCS->getMatrix()[5],
+           calRGBCS->getMatrix()[6], calRGBCS->getMatrix()[7],
+           calRGBCS->getMatrix()[8]);
+    writePS(" /WhitePoint [%g %g %g]\n",
+           calRGBCS->getWhiteX(), calRGBCS->getWhiteY(),
+           calRGBCS->getWhiteZ());
+    writePS(" /BlackPoint [%g %g %g]\n",
+           calRGBCS->getBlackX(), calRGBCS->getBlackY(),
+           calRGBCS->getBlackZ());
+    writePS(">>]");
+    break;
+
+  case csDeviceCMYK:
+    writePS("/DeviceCMYK");
+    break;
+
+  case csLab:
+    labCS = (GfxLabColorSpace *)colorSpace;
+    writePS("[/CIEBasedABC <<\n");
+    writePS(" /RangeABC [0 100 %g %g %g %g]\n",
+           labCS->getAMin(), labCS->getAMax(),
+           labCS->getBMin(), labCS->getBMax());
+    writePS(" /DecodeABC [{16 add 116 div} bind {500 div} bind {200 div} bind]\n");
+    writePS(" /MatrixABC [1 1 1 1 0 0 0 0 -1]\n");
+    writePS(" /DecodeLMN\n");
+    writePS("   [{dup 6 29 div ge {dup dup mul mul}\n");
+    writePS("     {4 29 div sub 108 841 div mul } ifelse %g mul} bind\n",
+           labCS->getWhiteX());
+    writePS("    {dup 6 29 div ge {dup dup mul mul}\n");
+    writePS("     {4 29 div sub 108 841 div mul } ifelse %g mul} bind\n",
+           labCS->getWhiteY());
+    writePS("    {dup 6 29 div ge {dup dup mul mul}\n");
+    writePS("     {4 29 div sub 108 841 div mul } ifelse %g mul} bind]\n",
+           labCS->getWhiteZ());
+    writePS(" /WhitePoint [%g %g %g]\n",
+           labCS->getWhiteX(), labCS->getWhiteY(), labCS->getWhiteZ());
+    writePS(" /BlackPoint [%g %g %g]\n",
+           labCS->getBlackX(), labCS->getBlackY(), labCS->getBlackZ());
+    writePS(">>]");
+    break;
+
+  case csICCBased:
+    dumpColorSpaceL2(((GfxICCBasedColorSpace *)colorSpace)->getAlt());
+    break;
+
+  case csIndexed:
+    indexedCS = (GfxIndexedColorSpace *)colorSpace;
+    writePS("[/Indexed ");
+    dumpColorSpaceL2(indexedCS->getBase());
+    n = indexedCS->getIndexHigh();
+    numComps = indexedCS->getBase()->getNComps();
+    lookup = indexedCS->getLookup();
+    writePS(" %d <\n", n);
+    for (i = 0; i <= n; i += 8) {
+      writePS("  ");
+      for (j = i; j < i+8 && j <= n; ++j) {
+       for (k = 0; k < numComps; ++k) {
+         writePS("%02x", lookup[j * numComps + k]);
+       }
+      }
+      writePS("\n");
+    }
+    writePS(">]");
+    break;
+
+  case csSeparation:
+    //~ this is a kludge -- the correct thing would to ouput a
+    //~ separation color space, with the specified alternate color
+    //~ space and tint transform
+    separationCS = (GfxSeparationColorSpace *)colorSpace;
+    writePS(" [/Indexed ");
+    dumpColorSpaceL2(separationCS->getAlt());
+    writePS(" 255 <\n");
+    numComps = separationCS->getAlt()->getNComps();
+    for (i = 0; i <= 255; i += 8) {
+      writePS("  ");
+      for (j = i; j < i+8 && j <= 255; ++j) {
+       x[0] = (double)j / 255.0;
+       separationCS->getFunc()->transform(x, y);
+       for (k = 0; k < numComps; ++k) {
+         writePS("%02x", (int)(255 * y[k] + 0.5));
+       }
+      }
+      writePS("\n");
+    }
+    writePS(">]");
+    break;
+
+  case csDeviceN:
+    // DeviceN color spaces are a Level 3 PostScript feature.
+    dumpColorSpaceL2(((GfxDeviceNColorSpace *)colorSpace)->getAlt());
+    break;
+
+  case csPattern:
+    //~ unimplemented
+    break;
+
+  }
+}
+
 #if OPI_SUPPORT
 void PSOutputDev::opiBegin(GfxState *state, Dict *opiDict) {
   Object dict;
@@ -1796,7 +2138,7 @@ void PSOutputDev::opiBegin13(GfxState *state, Dict *dict) {
     obj1.arrayGet(1, &obj2);
     height = obj2.getInt();
     obj2.free();
-    writePS("%%ALDImageSize: %d %d\n", width, height);
+    writePS("%%ALDImageDimensions: %d %d\n", width, height);
   }
   obj1.free();
 
index 43d45ee0e352d677d86faaff3632f09bdb5d8eee..62dce661158784ed5f7230887a3abbda7c2a1df3 100644 (file)
@@ -20,6 +20,7 @@
 
 class GfxPath;
 class GfxFont;
+class GfxColorSpace;
 
 //------------------------------------------------------------------------
 // Parameters
@@ -28,6 +29,9 @@ class GfxFont;
 // Generate Level 1 PostScript?
 extern GBool psOutLevel1;
 
+// Generate Level 1 separable PostScript?
+extern GBool psOutLevel1Sep;
+
 // Generate Encapsulated PostScript?
 extern GBool psOutEPS;
 
@@ -54,7 +58,7 @@ class PSOutputDev: public OutputDev {
 public:
 
   // Open a PostScript output file, and write the prolog.
-  PSOutputDev(char *fileName, Catalog *catalog,
+  PSOutputDev(const char *fileName, Catalog *catalog,
              int firstPage, int lastPage,
              GBool embedType11, GBool doForm1);
 
@@ -122,11 +126,11 @@ public:
   virtual void drawString16(GfxState *state, GString *s);
 
   //----- image drawing
-  virtual void drawImageMask(GfxState *state, Stream *str,
+  virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
                             int width, int height, GBool invert,
                             GBool inlineImg);
-  virtual void drawImage(GfxState *state, Stream *str, int width,
-                        int height, GfxImageColorMap *colorMap,
+  virtual void drawImage(GfxState *state, Object *ref, Stream *str,
+                        int width, int height, GfxImageColorMap *colorMap,
                         GBool inlineImg);
 
 #if OPI_SUPPORT
@@ -137,18 +141,25 @@ public:
 
 private:
 
+  void setupResources(Dict *resDict);
   void setupFonts(Dict *resDict);
   void setupFont(GfxFont *font);
-  void setupEmbeddedType1Font(Ref *id, char *psName);
-  void setupEmbeddedType1Font(GString *fileName, char *psName);
-  void setupEmbeddedType1CFont(GfxFont *font, Ref *id, char *psName);
+  void setupEmbeddedType1Font(Ref *id, const char *psName);
+  void setupEmbeddedType1Font(GString *fileName, const char *psName);
+  void setupEmbeddedType1CFont(GfxFont *font, Ref *id, const char *psName);
+  void setupImages(Dict *resDict);
+  void setupImage(Ref id, Stream *str);
   void doPath(GfxPath *path);
   void doImageL1(GfxImageColorMap *colorMap,
                 GBool invert, GBool inlineImg,
                 Stream *str, int width, int height, int len);
-  void doImage(GfxImageColorMap *colorMap,
-              GBool invert, GBool inlineImg,
-              Stream *str, int width, int height, int len);
+  void doImageL1Sep(GfxImageColorMap *colorMap,
+                   GBool invert, GBool inlineImg,
+                   Stream *str, int width, int height, int len);
+  void doImageL2(Object *ref, GfxImageColorMap *colorMap,
+                GBool invert, GBool inlineImg,
+                Stream *str, int width, int height, int len);
+  void dumpColorSpaceL2(GfxColorSpace *colorSpace);
   void opiBegin20(GfxState *state, Dict *dict);
   void opiBegin13(GfxState *state, Dict *dict);
   void opiTransform(GfxState *state, double x0, double y0,
@@ -185,6 +196,8 @@ private:
   int opi20Nest;               // nesting level of OPI 2.0 objects
 #endif
 
+  GBool type3Warning;          // only show the Type 3 font warning once
+
   GBool ok;                    // set up ok?
 };
 
index 2f4d2796c76c2734df31790d83aea487c5bccd5e..c2ac6b190bdd2c1246d23ecb486ac8cf798dab72 100644 (file)
@@ -182,7 +182,7 @@ Page::~Page() {
   contents.free();
 }
 
-void Page::display(OutputDev *out, int dpi, int rotate,
+void Page::display(OutputDev *out, double dpi, int rotate,
                   Links *links, Catalog *catalog) {
 #ifndef PDF_PARSER_ONLY
   Gfx *gfx;
@@ -235,6 +235,9 @@ void Page::display(OutputDev *out, int dpi, int rotate,
   for (i = 0; i < formWidgets->getNumWidgets(); ++i) {
     formWidgets->getWidget(i)->draw(gfx);
   }
+  if (formWidgets->getNumWidgets() > 0) {
+    out->dump();
+  }
   delete formWidgets;
 
   delete gfx;
index 94f63daac67778f7c23464b93dfb38445db2e6ac..a144d2cfa7195f5cf3cf757d7257d20eecffa326 100644 (file)
@@ -99,7 +99,7 @@ public:
   Object *getContents(Object *obj) { return contents.fetch(obj); }
 
   // Display a page.
-  void display(OutputDev *out, int dpi, int rotate,
+  void display(OutputDev *out, double dpi, int rotate,
               Links *links, Catalog *catalog);
 
 private:
index 35adfdfe00ad4b1544e2e51c27acec60caaee6be..efed572435162f8238f474c9a9f3a62d4df5ddf1 100644 (file)
 #include "gfile.h"
 #include "Params.h"
 
-char **fontPath = NULL;
+const char **fontPath = NULL;
 static int fontPathLen, fontPathSize;
 
 DevFontMapEntry *devFontMap = NULL;
 static int devFontMapLen, devFontMapSize;
 
-void initParams(char *configFile) {
+void initParams(const char *configFile) {
   GString *fileName;
   FILE *f;
   char buf[256];
   char *p, *q;
 
   // initialize font path and font map
-  fontPath = (char **)gmalloc((fontPathSize = 8) * sizeof(char *));
+  fontPath = (const char **)gmalloc((fontPathSize = 8) * sizeof(const char *));
   fontPath[fontPathLen = 0] = NULL;
   devFontMap = (DevFontMapEntry *)gmalloc((devFontMapSize = 8) *
                                          sizeof(DevFontMapEntry));
@@ -43,8 +43,8 @@ void initParams(char *configFile) {
       p = strtok(buf, " \t\n\r");
       if (p && !strcmp(p, "fontpath")) {
        if (fontPathLen+1 >= fontPathSize)
-         fontPath = (char **)
-             grealloc(fontPath, (fontPathSize += 8) * sizeof(char *));
+         fontPath = (const char **)
+             grealloc(fontPath, (fontPathSize += 8) * sizeof(const char *));
        p = strtok(NULL, " \t\n\r");
        fontPath[fontPathLen++] = copyString(p);
       } else if (p && !strcmp(p, "fontmap")) {
@@ -74,14 +74,14 @@ void freeParams() {
 
   if (fontPath) {
     for (i = 0; i < fontPathLen; ++i)
-      gfree(fontPath[i]);
-    gfree(fontPath);
+      gfree((void *)fontPath[i]);
+    gfree((void *)fontPath);
   }
   if (devFontMap) {
     for (i = 0; i < devFontMapLen; ++i) {
-      gfree(devFontMap[i].pdfFont);
-      gfree(devFontMap[i].devFont);
+      gfree((void *)devFontMap[i].pdfFont);
+      gfree((void *)devFontMap[i].devFont);
     }
-    gfree(devFontMap);
+    gfree((void *)devFontMap);
   }
 }
index ea8536fa1eda543fb96add77a137e41f3482f58e..2c5936a3f4b28a3ceb98df863d621e038e7d02bd 100644 (file)
@@ -16,12 +16,12 @@ extern GBool printCommands;
 extern GBool errQuiet;
 
 // Font search path.
-extern char **fontPath;
+extern const char **fontPath;
 
 // Mapping from PDF font name to device font name.
 struct DevFontMapEntry {
-  char *pdfFont;
-  char *devFont;
+  const char *pdfFont;
+  const char *devFont;
 };
 extern DevFontMapEntry *devFontMap;
 
@@ -29,7 +29,7 @@ extern DevFontMapEntry *devFontMap;
 
 // Initialize font path and font map, and read configuration file,
 // if present.
-extern void initParams(char *configFile);
+extern void initParams(const char *configFile);
 
 // Free memory used for font path and font map.
 extern void freeParams();
index 9fce596e4f1d43691e95f97febf94815cc7a41c4..6ad0c5a7816afa4cb55fd565dfa3f6073669af76 100644 (file)
@@ -15,6 +15,7 @@
 #include "Array.h"
 #include "Dict.h"
 #include "Parser.h"
+#include "XRef.h"
 #include "Error.h"
 #ifndef NO_DECRYPTION
 #include "Decrypt.h"
@@ -150,7 +151,7 @@ Object *Parser::getObj(Object *obj) {
 Stream *Parser::makeStream(Object *dict) {
   Object obj;
   Stream *str;
-  int pos, length;
+  int pos, endPos, length;
 
   // get stream start position
   lexer->skipToNextLine();
@@ -167,6 +168,11 @@ Stream *Parser::makeStream(Object *dict) {
     return NULL;
   }
 
+  // check for length in damaged file
+  if ((endPos = xref->getStreamEnd(pos)) >= 0) {
+    length = endPos - pos;
+  }
+
   // make base stream
   str = lexer->getStream()->getBaseStream()->makeSubStream(pos, length, dict);
 
index 0db033f6bd59cf7339c932ff2839763b26c359d4..4b3e43539aa5954b04ef6c21a4b4c112061a0374 100644 (file)
@@ -16,7 +16,7 @@
 //------------------------------------------------------------------------
 
 #define type1StdEncodingSize 256
-static char *type1StdEncodingNames[type1StdEncodingSize] = {
+static const char *type1StdEncodingNames[type1StdEncodingSize] = {
   NULL,
   NULL,
   NULL,
@@ -282,7 +282,7 @@ static FontEncoding type1StdEncoding(type1StdEncodingNames,
 //------------------------------------------------------------------------
 
 #define type1ExpertEncodingSize 256
-static char *type1ExpertEncodingNames[type1ExpertEncodingSize] = {
+static const char *type1ExpertEncodingNames[type1ExpertEncodingSize] = {
   NULL,
   NULL,
   NULL,
index 5beaf98df07ad64860936996524edd648259ff35..5677dff9d9ce931814a8ad7dd88f339caa85ea9d 100644 (file)
@@ -59,6 +59,9 @@ Stream::Stream() {
 Stream::~Stream() {
 }
 
+void Stream::close() {
+}
+
 int Stream::getRawChar() {
   error(-1, "Internal: called getRawChar() on non-predictor stream");
   return EOF;
@@ -85,7 +88,9 @@ char *Stream::getLine(char *buf, int size) {
   return buf;
 }
 
-GString *Stream::getPSFilter(char *indent) {
+GString *Stream::getPSFilter(const char *indent) {
+  (void)indent;
+
   return new GString();
 }
 
@@ -133,7 +138,7 @@ Stream *Stream::addFilters(Object *dict) {
   return str;
 }
 
-Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
+Stream *Stream::makeFilter(const char *name, Stream *str, Object *params) {
   int pred;                    // parameters
   int colors;
   int bits;
@@ -262,8 +267,8 @@ Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
 // BaseStream
 //------------------------------------------------------------------------
 
-BaseStream::BaseStream(Object *dict) {
-  this->dict = *dict;
+BaseStream::BaseStream(Object *ndict) {
+  dict = *ndict;
 #ifndef NO_DECRYPTION
   decrypt = NULL;
 #endif
@@ -287,14 +292,20 @@ void BaseStream::doDecryption(Guchar *fileKey, int objNum, int objGen) {
 // FilterStream
 //------------------------------------------------------------------------
 
-FilterStream::FilterStream(Stream *str) {
-  this->str = str;
+FilterStream::FilterStream(Stream *nstr) {
+  str = nstr;
 }
 
 FilterStream::~FilterStream() {
 }
 
+void FilterStream::close() {
+  str->close();
+}
+
 void FilterStream::setPos(int pos) {
+  (void)pos;
+
   error(-1, "Internal: called setPos() on FilterStream");
 }
 
@@ -302,13 +313,13 @@ void FilterStream::setPos(int pos) {
 // ImageStream
 //------------------------------------------------------------------------
 
-ImageStream::ImageStream(Stream *str, int width, int nComps, int nBits) {
+ImageStream::ImageStream(Stream *nstr, int nwidth, int nnComps, int nnBits) {
   int imgLineSize;
 
-  this->str = str;
-  this->width = width;
-  this->nComps = nComps;
-  this->nBits = nBits;
+  str = nstr;
+  width = nwidth;
+  nComps = nnComps;
+  nBits = nnBits;
 
   nVals = width * nComps;
   if (nBits == 1) {
@@ -389,13 +400,13 @@ void ImageStream::skipLine() {
 // StreamPredictor
 //------------------------------------------------------------------------
 
-StreamPredictor::StreamPredictor(Stream *str, int predictor,
-                                int width, int nComps, int nBits) {
-  this->str = str;
-  this->predictor = predictor;
-  this->width = width;
-  this->nComps = nComps;
-  this->nBits = nBits;
+StreamPredictor::StreamPredictor(Stream *nstr, int npredictor,
+                                int nwidth, int nnComps, int nnBits) {
+  str = nstr;
+  predictor = npredictor;
+  width = nwidth;
+  nComps = nnComps;
+  nBits = nnBits;
 
   nVals = width * nComps;
   pixBytes = (nComps * nBits + 7) >> 3;
@@ -545,24 +556,22 @@ GBool StreamPredictor::getNextLine() {
 // FileStream
 //------------------------------------------------------------------------
 
-FileStream::FileStream(FILE *f, int start, int length, Object *dict):
+FileStream::FileStream(FILE *nf, int nstart, int nlength, Object *dict):
     BaseStream(dict) {
-  this->f = f;
-  this->start = start;
-  this->length = length;
+  f = nf;
+  start = nstart;
+  length = nlength;
   bufPtr = bufEnd = buf;
   bufPos = start;
   savePos = -1;
 }
 
 FileStream::~FileStream() {
-  if (savePos >= 0) {
-    fseek(f, savePos, SEEK_SET);
-  }
+  close();
 }
 
-Stream *FileStream::makeSubStream(int start, int length, Object *dict) {
-  return new FileStream(f, start, length, dict);
+Stream *FileStream::makeSubStream(int nstart, int nlength, Object *ndict) {
+  return new FileStream(f, nstart, nlength, ndict);
 }
 
 void FileStream::reset() {
@@ -576,6 +585,13 @@ void FileStream::reset() {
 #endif
 }
 
+void FileStream::close() {
+  if (savePos >= 0) {
+    fseek(f, savePos, SEEK_SET);
+    savePos = -1;
+  }
+}
+
 GBool FileStream::fillBuf() {
   int n;
 #ifndef NO_DECRYPTION
@@ -584,20 +600,24 @@ GBool FileStream::fillBuf() {
 
   bufPos += bufEnd - buf;
   bufPtr = bufEnd = buf;
-  if (length >= 0 && bufPos >= start + length)
+  if (length >= 0 && bufPos >= start + length) {
     return gFalse;
-  if (length >= 0 && bufPos + 256 > start + length)
+  }
+  if (length >= 0 && bufPos + fileStreamBufSize > start + length) {
     n = start + length - bufPos;
-  else
-    n = 256;
+  } else {
+    n = fileStreamBufSize;
+  }
   n = fread(buf, 1, n, f);
   bufEnd = buf + n;
-  if (bufPtr >= bufEnd)
+  if (bufPtr >= bufEnd) {
     return gFalse;
+  }
 #ifndef NO_DECRYPTION
   if (decrypt) {
-    for (p = buf; p < bufEnd; ++p)
+    for (p = buf; p < bufEnd; ++p) {
       *p = (char)decrypt->decryptByte((Guchar)*p);
+    }
   }
 #endif
   return gTrue;
@@ -630,20 +650,26 @@ void FileStream::moveStart(int delta) {
 // EmbedStream
 //------------------------------------------------------------------------
 
-EmbedStream::EmbedStream(Stream *str, Object *dict):
-    BaseStream(dict) {
-  this->str = str;
+EmbedStream::EmbedStream(Stream *nstr, Object *ndict):
+    BaseStream(ndict) {
+  str = nstr;
 }
 
 EmbedStream::~EmbedStream() {
 }
 
-Stream *EmbedStream::makeSubStream(int start, int length, Object *dict) {
+Stream *EmbedStream::makeSubStream(int start, int length, Object *ndict) {
+  (void)start;
+  (void)length;
+  (void)ndict;
+
   error(-1, "Internal: called makeSubStream() on EmbedStream");
   return NULL;
 }
 
 void EmbedStream::setPos(int pos) {
+  (void)pos;
+
   error(-1, "Internal: called setPos() on EmbedStream");
 }
 
@@ -653,6 +679,8 @@ int EmbedStream::getStart() {
 }
 
 void EmbedStream::moveStart(int start) {
+  (void)start;
+
   error(-1, "Internal: called moveStart() on EmbedStream");
 }
 
@@ -729,7 +757,7 @@ int ASCIIHexStream::lookChar() {
   return buf;
 }
 
-GString *ASCIIHexStream::getPSFilter(char *indent) {
+GString *ASCIIHexStream::getPSFilter(const char *indent) {
   GString *s;
 
   s = str->getPSFilter(indent);
@@ -738,6 +766,8 @@ GString *ASCIIHexStream::getPSFilter(char *indent) {
 }
 
 GBool ASCIIHexStream::isBinary(GBool last) {
+  (void)last;
+
   return str->isBinary(gFalse);
 }
 
@@ -805,7 +835,7 @@ int ASCII85Stream::lookChar() {
   return b[index];
 }
 
-GString *ASCII85Stream::getPSFilter(char *indent) {
+GString *ASCII85Stream::getPSFilter(const char *indent) {
   GString *s;
 
   s = str->getPSFilter(indent);
@@ -814,6 +844,8 @@ GString *ASCII85Stream::getPSFilter(char *indent) {
 }
 
 GBool ASCII85Stream::isBinary(GBool last) {
+  (void)last;
+
   return str->isBinary(gFalse);
 }
 
@@ -1117,7 +1149,7 @@ GBool LZWStream::fillBuf() {
   return n > 0;
 }
 
-GString *LZWStream::getPSFilter(char *indent) {
+GString *LZWStream::getPSFilter(const char *indent) {
   GString *s;
 
   if (pred) {
@@ -1129,6 +1161,8 @@ GString *LZWStream::getPSFilter(char *indent) {
 }
 
 GBool LZWStream::isBinary(GBool last) {
+  (void)last;
+
   return str->isBinary(gTrue);
 }
 
@@ -1152,7 +1186,7 @@ void RunLengthStream::reset() {
   eof = gFalse;
 }
 
-GString *RunLengthStream::getPSFilter(char *indent) {
+GString *RunLengthStream::getPSFilter(const char *indent) {
   GString *s;
 
   s = str->getPSFilter(indent);
@@ -1161,6 +1195,8 @@ GString *RunLengthStream::getPSFilter(char *indent) {
 }
 
 GBool RunLengthStream::isBinary(GBool last) {
+  (void)last;
+
   return str->isBinary(gTrue);
 }
 
@@ -1194,17 +1230,17 @@ GBool RunLengthStream::fillBuf() {
 // CCITTFaxStream
 //------------------------------------------------------------------------
 
-CCITTFaxStream::CCITTFaxStream(Stream *str, int encoding, GBool endOfLine,
-                              GBool byteAlign, int columns, int rows,
-                              GBool endOfBlock, GBool black):
+CCITTFaxStream::CCITTFaxStream(Stream *str, int nencoding, GBool nendOfLine,
+                              GBool nbyteAlign, int ncolumns, int nrows,
+                              GBool nendOfBlock, GBool nblack):
     FilterStream(str) {
-  this->encoding = encoding;
-  this->endOfLine = endOfLine;
-  this->byteAlign = byteAlign;
-  this->columns = columns;
-  this->rows = rows;
-  this->endOfBlock = endOfBlock;
-  this->black = black;
+  encoding = nencoding;
+  endOfLine = nendOfLine;
+  byteAlign = nbyteAlign;
+  columns = ncolumns;
+  rows = nrows;
+  endOfBlock = nendOfBlock;
+  black = nblack;
   refLine = (short *)gmalloc((columns + 3) * sizeof(short));
   codingLine = (short *)gmalloc((columns + 2) * sizeof(short));
 
@@ -1261,8 +1297,9 @@ int CCITTFaxStream::lookChar() {
 #if 0 //~
   GBool err;
 #endif
+  GBool gotEOL;
   int ret;
-  int bits, i, n;
+  int bits, i;
 
   // if at eof just return EOF
   if (eof && codingLine[a0] >= columns) {
@@ -1417,58 +1454,53 @@ int CCITTFaxStream::lookChar() {
       inputBits &= ~7;
     }
 
-    // check for end-of-line marker, end-of-block marker, and
-    // 2D encoding tag
-    if (endOfBlock) {
+    // check for end-of-line marker, skipping over any extra zero bits
+    gotEOL = gFalse;
+    if (!endOfBlock && row == rows - 1) {
+      eof = gTrue;
+    } else {
       code1 = lookBits(12);
-      if (code1 == EOF) {
+      while (code1 == 0) {
+       eatBits(1);
+       code1 = lookBits(12);
+      }
+      if (code1 == 0x001) {
+       eatBits(12);
+       gotEOL = gTrue;
+      } else if (code1 == EOF) {
        eof = gTrue;
-      } else if (code1 == 0x001) {
+      }
+    }
+
+    // get 2D encoding tag
+    if (!eof && encoding > 0) {
+      nextLine2D = !lookBits(1);
+      eatBits(1);
+    }
+
+    // check for end-of-block marker
+    if (endOfBlock && gotEOL) {
+      code1 = lookBits(12);
+      if (code1 == 0x001) {
        eatBits(12);
        if (encoding > 0) {
-         nextLine2D = !lookBits(1);
+         lookBits(1);
          eatBits(1);
        }
-       code1 = lookBits(12);
-       if (code1 == 0x001) {
-         eatBits(12);
-         if (encoding > 0) {
-           lookBits(1);
-           eatBits(1);
-         }
-         if (encoding >= 0) {
-           for (i = 0; i < 4; ++i) {
-             code1 = lookBits(12);
-             if (code1 != 0x001) {
-               error(getPos(), "Bad RTC code in CCITTFax stream");
-             }
-             eatBits(12);
-             if (encoding > 0) {
-               lookBits(1);
-               eatBits(1);
-             }
+       if (encoding >= 0) {
+         for (i = 0; i < 4; ++i) {
+           code1 = lookBits(12);
+           if (code1 != 0x001) {
+             error(getPos(), "Bad RTC code in CCITTFax stream");
+           }
+           eatBits(12);
+           if (encoding > 0) {
+             lookBits(1);
+             eatBits(1);
            }
          }
-         eof = gTrue;
-       }
-      } else {
-       if (encoding > 0) {
-         nextLine2D = !lookBits(1);
-         eatBits(1);
        }
-      }
-    } else {
-      if (row == rows - 1) {
        eof = gTrue;
-      } else {
-       for (n = 0; n < 11 && lookBits(n) == 0; ++n) ;
-       if (n == 11 && lookBits(12) == 0x001) {
-         eatBits(12);
-       }
-       if (encoding > 0) {
-         nextLine2D = !lookBits(1);
-         eatBits(1);
-       }
       }
     }
 
@@ -1581,10 +1613,11 @@ short CCITTFaxStream::getWhiteCode() {
   code = 0; // make gcc happy
   if (endOfBlock) {
     code = lookBits(12);
-    if ((code >> 5) == 0)
+    if ((code >> 5) == 0) {
       p = &whiteTab1[code];
-    else
+    } else {
       p = &whiteTab2[code >> 3];
+    }
     if (p->bits > 0) {
       eatBits(p->bits);
       return p->n;
@@ -1614,7 +1647,10 @@ short CCITTFaxStream::getWhiteCode() {
     }
   }
   error(getPos(), "Bad white code (%04x) in CCITTFax stream", code);
-  return EOF;
+  // eat a bit and return a positive number so that the caller doesn't
+  // go into an infinite loop
+  eatBits(1);
+  return 1;
 }
 
 short CCITTFaxStream::getBlackCode() {
@@ -1625,12 +1661,13 @@ short CCITTFaxStream::getBlackCode() {
   code = 0; // make gcc happy
   if (endOfBlock) {
     code = lookBits(13);
-    if ((code >> 7) == 0)
+    if ((code >> 7) == 0) {
       p = &blackTab1[code];
-    else if ((code >> 9) == 0)
+    } else if ((code >> 9) == 0) {
       p = &blackTab2[(code >> 1) - 64];
-    else
+    } else {
       p = &blackTab3[code >> 7];
+    }
     if (p->bits > 0) {
       eatBits(p->bits);
       return p->n;
@@ -1673,7 +1710,10 @@ short CCITTFaxStream::getBlackCode() {
     }
   }
   error(getPos(), "Bad black code (%04x) in CCITTFax stream", code);
-  return EOF;
+  // eat a bit and return a positive number so that the caller doesn't
+  // go into an infinite loop
+  eatBits(1);
+  return 1;
 }
 
 short CCITTFaxStream::lookBits(int n) {
@@ -1681,9 +1721,14 @@ short CCITTFaxStream::lookBits(int n) {
 
   while (inputBits < n) {
     if ((c = str->getChar()) == EOF) {
-      if (inputBits == 0)
+      if (inputBits == 0) {
        return EOF;
-      c = 0;
+      }
+      // near the end of the stream, the caller may ask for more bits
+      // than are available, but there may still be a valid code in
+      // however many bits are available -- we need to return correct
+      // data in this case
+      return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n));
     }
     inputBuf = (inputBuf << 8) + c;
     inputBits += 8;
@@ -1691,7 +1736,7 @@ short CCITTFaxStream::lookBits(int n) {
   return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
 }
 
-GString *CCITTFaxStream::getPSFilter(char *indent) {
+GString *CCITTFaxStream::getPSFilter(const char *indent) {
   GString *s;
   char s1[50];
 
@@ -1724,6 +1769,8 @@ GString *CCITTFaxStream::getPSFilter(char *indent) {
 }
 
 GBool CCITTFaxStream::isBinary(GBool last) {
+  (void)last;
+
   return str->isBinary(gTrue);
 }
 
@@ -2682,7 +2729,7 @@ int DCTStream::read16() {
   return (c1 << 8) + c2;
 }
 
-GString *DCTStream::getPSFilter(char *indent) {
+GString *DCTStream::getPSFilter(const char *indent) {
   GString *s;
 
   s = str->getPSFilter(indent);
@@ -2691,6 +2738,8 @@ GString *DCTStream::getPSFilter(char *indent) {
 }
 
 GBool DCTStream::isBinary(GBool last) {
+  (void)last;
+
   return str->isBinary(gTrue);
 }
 
@@ -2787,6 +2836,14 @@ FlateStream::~FlateStream() {
 void FlateStream::reset() {
   int cmf, flg;
 
+  index = 0;
+  remain = 0;
+  codeBuf = 0;
+  codeSize = 0;
+  compressedBlock = gFalse;
+  endOfBlock = gTrue;
+  eof = gTrue;
+
   str->reset();
 
   // read header
@@ -2809,13 +2866,6 @@ void FlateStream::reset() {
     return;
   }
 
-  // initialize
-  index = 0;
-  remain = 0;
-  codeBuf = 0;
-  codeSize = 0;
-  compressedBlock = gFalse;
-  endOfBlock = gTrue;
   eof = gFalse;
 }
 
@@ -2865,11 +2915,15 @@ int FlateStream::getRawChar() {
   return c;
 }
 
-GString *FlateStream::getPSFilter(char *indent) {
+GString *FlateStream::getPSFilter(const char *indent) {
+  (void)indent;
+
   return NULL;
 }
 
 GBool FlateStream::isBinary(GBool last) {
+  (void)last;
+
   return str->isBinary(gTrue);
 }
 
@@ -3226,6 +3280,9 @@ void FixedLengthEncoder::reset() {
   count = 0;
 }
 
+void FixedLengthEncoder::close() {
+}
+
 int FixedLengthEncoder::getChar() {
   if (length >= 0 && count >= length)
     return EOF;
@@ -3262,6 +3319,9 @@ void ASCII85Encoder::reset() {
   eof = gFalse;
 }
 
+void ASCII85Encoder::close() {
+}
+
 GBool ASCII85Encoder::fillBuf() {
   Gulong t;
   char buf1[5];
@@ -3329,6 +3389,9 @@ void RunLengthEncoder::reset() {
   eof = gFalse;
 }
 
+void RunLengthEncoder::close() {
+}
+
 //
 // When fillBuf finishes, buf[] looks like this:
 //   +-----+--------------+-----------------+--
index 6413b5bd8afcdcb91e730a209ba2e32bbf6c066b..f77bade5031496803cba99708e1f71d886a9d905 100644 (file)
@@ -59,6 +59,9 @@ public:
   // Reset stream to beginning.
   virtual void reset() = 0;
 
+  // Close down the stream.
+  virtual void close();
+
   // Get next char from stream.
   virtual int getChar() = 0;
 
@@ -79,7 +82,7 @@ public:
   virtual void setPos(int pos1) = 0;
 
   // Get PostScript command for the filter(s).
-  virtual GString *getPSFilter(char *indent);
+  virtual GString *getPSFilter(const char *indent);
 
   // Does this stream type potentially contain non-printable chars?
   virtual GBool isBinary(GBool last = gTrue) = 0;
@@ -99,7 +102,7 @@ public:
 
 private:
 
-  Stream *makeFilter(char *name, Stream *str, Object *params);
+  Stream *makeFilter(const char *name, Stream *str, Object *params);
 
   int ref;                     // reference count
 };
@@ -151,6 +154,7 @@ public:
 
   FilterStream(Stream *str);
   virtual ~FilterStream();
+  virtual void close();
   virtual int getPos() { return str->getPos(); }
   virtual void setPos(int pos);
   virtual BaseStream *getBaseStream() { return str->getBaseStream(); }
@@ -233,6 +237,8 @@ private:
 // FileStream
 //------------------------------------------------------------------------
 
+#define fileStreamBufSize 256
+
 class FileStream: public BaseStream {
 public:
 
@@ -241,6 +247,7 @@ public:
   virtual Stream *makeSubStream(int start, int length, Object *dict);
   virtual StreamKind getKind() { return strFile; }
   virtual void reset();
+  virtual void close();
   virtual int getChar()
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
   virtual int lookChar()
@@ -258,7 +265,7 @@ private:
   FILE *f;
   int start;
   int length;
-  char buf[256];
+  char buf[fileStreamBufSize];
   char *bufPtr;
   char *bufEnd;
   int bufPos;
@@ -310,7 +317,7 @@ public:
   virtual int getChar()
     { int c = lookChar(); buf = EOF; return c; }
   virtual int lookChar();
-  virtual GString *getPSFilter(char *indent);
+  virtual GString *getPSFilter(const char *indent);
   virtual GBool isBinary(GBool last = gTrue);
 
 private:
@@ -333,7 +340,7 @@ public:
   virtual int getChar()
     { int ch = lookChar(); ++index; return ch; }
   virtual int lookChar();
-  virtual GString *getPSFilter(char *indent);
+  virtual GString *getPSFilter(const char *indent);
   virtual GBool isBinary(GBool last = gTrue);
 
 private:
@@ -359,7 +366,7 @@ public:
   virtual int getChar();
   virtual int lookChar();
   virtual int getRawChar();
-  virtual GString *getPSFilter(char *indent);
+  virtual GString *getPSFilter(const char *indent);
   virtual GBool isBinary(GBool last = gTrue);
 
 private:
@@ -395,7 +402,7 @@ public:
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
   virtual int lookChar()
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
-  virtual GString *getPSFilter(char *indent);
+  virtual GString *getPSFilter(const char *indent);
   virtual GBool isBinary(GBool last = gTrue);
 
 private:
@@ -426,7 +433,7 @@ public:
   virtual int getChar()
     { int c = lookChar(); buf = EOF; return c; }
   virtual int lookChar();
-  virtual GString *getPSFilter(char *indent);
+  virtual GString *getPSFilter(const char *indent);
   virtual GBool isBinary(GBool last = gTrue);
 
 private:
@@ -488,7 +495,7 @@ public:
   virtual void reset();
   virtual int getChar();
   virtual int lookChar();
-  virtual GString *getPSFilter(char *indent);
+  virtual GString *getPSFilter(const char *indent);
   virtual GBool isBinary(GBool last = gTrue);
   Stream *getRawStream() { return str; }
 
@@ -574,7 +581,7 @@ public:
   virtual int getChar();
   virtual int lookChar();
   virtual int getRawChar();
-  virtual GString *getPSFilter(char *indent);
+  virtual GString *getPSFilter(const char *indent);
   virtual GBool isBinary(GBool last = gTrue);
 
 private:
@@ -623,8 +630,8 @@ public:
   virtual void reset() {}
   virtual int getChar() { return EOF; }
   virtual int lookChar() { return EOF; }
-  virtual GString *getPSFilter(char *indent)  { return NULL; }
-  virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
+  virtual GString *getPSFilter(const char *indent)  { (void)indent; return NULL; }
+  virtual GBool isBinary(GBool last = gTrue) { (void)last; return gFalse; }
 };
 
 //------------------------------------------------------------------------
@@ -638,10 +645,11 @@ public:
   ~FixedLengthEncoder();
   virtual StreamKind getKind() { return strWeird; }
   virtual void reset();
+  virtual void close();
   virtual int getChar();
   virtual int lookChar();
-  virtual GString *getPSFilter(char *indent) { return NULL; }
-  virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
+  virtual GString *getPSFilter(const char *indent) { (void)indent; return NULL; }
+  virtual GBool isBinary(GBool last = gTrue) { (void)last; return gFalse; }
   virtual GBool isEncoder() { return gTrue; }
 
 private:
@@ -661,12 +669,13 @@ public:
   virtual ~ASCII85Encoder();
   virtual StreamKind getKind() { return strWeird; }
   virtual void reset();
+  virtual void close();
   virtual int getChar()
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
   virtual int lookChar()
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
-  virtual GString *getPSFilter(char *indent) { return NULL; }
-  virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
+  virtual GString *getPSFilter(const char *indent) { (void)indent; return NULL; }
+  virtual GBool isBinary(GBool last = gTrue) { (void)last; return gFalse; }
   virtual GBool isEncoder() { return gTrue; }
 
 private:
@@ -691,12 +700,13 @@ public:
   virtual ~RunLengthEncoder();
   virtual StreamKind getKind() { return strWeird; }
   virtual void reset();
+  virtual void close();
   virtual int getChar()
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
   virtual int lookChar()
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
-  virtual GString *getPSFilter(char *indent) { return NULL; }
-  virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
+  virtual GString *getPSFilter(const char *indent) { (void)indent; return NULL; }
+  virtual GBool isBinary(GBool last = gTrue) { (void)last; return gFalse; }
   virtual GBool isEncoder() { return gTrue; }
 
 private:
index 2479818cdee72025810b5eb976685efe8886d55a..d70b9f2097c48e6ce37fb9c1f12617b533be8c6b 100644 (file)
@@ -61,6 +61,8 @@ XRef::XRef(BaseStream *str, GString *userPassword) {
   ok = gTrue;
   size = 0;
   entries = NULL;
+  streamEnds = NULL;
+  streamEndsLen = 0;
 
   // get rid of old xref (otherwise it will try to fetch the Root object
   // in the new document, using the old xref)
@@ -119,6 +121,9 @@ XRef::XRef(BaseStream *str, GString *userPassword) {
 XRef::~XRef() {
   gfree(entries);
   trailerDict.free();
+  if (streamEnds) {
+    gfree(streamEnds);
+  }
 }
 
 // Read startxref position, xref table size, and root.  Returns
@@ -324,25 +329,28 @@ GBool XRef::constructXRef() {
   int pos;
   int num, gen;
   int newSize;
+  int streamEndsSize;
   char *p;
   int i;
   GBool gotRoot;
 
   error(0, "PDF file is damaged - attempting to reconstruct xref table...");
   gotRoot = gFalse;
+  streamEndsLen = streamEndsSize = 0;
 
   str->reset();
   while (1) {
     pos = str->getPos();
-    if (!str->getLine(buf, 256))
+    if (!str->getLine(buf, 256)) {
       break;
+    }
     p = buf;
 
     // got trailer dictionary
     if (!strncmp(p, "trailer", 7)) {
       obj.initNull();
       parser = new Parser(new Lexer(
-                     str->makeSubStream(start + pos + 8, -1, &obj)));
+                     str->makeSubStream(start + pos + 7, -1, &obj)));
       if (!trailerDict.isNone())
        trailerDict.free();
       parser->getObj(&trailerDict);
@@ -398,6 +406,13 @@ GBool XRef::constructXRef() {
          }
        }
       }
+
+    } else if (!strncmp(p, "endstream", 9)) {
+      if (streamEndsLen == streamEndsSize) {
+       streamEndsSize += 64;
+       streamEnds = (int *)grealloc(streamEnds, streamEndsSize * sizeof(int));
+      }
+      streamEnds[streamEndsLen++] = pos;
     }
   }
 
@@ -553,3 +568,25 @@ Object *XRef::fetch(int num, int gen, Object *obj) {
 Object *XRef::getDocInfo(Object *obj) {
   return trailerDict.dictLookup("Info", obj);
 }
+
+int XRef::getStreamEnd(int start) {
+  int a, b, m;
+
+  if (streamEndsLen == 0 ||
+      start > streamEnds[streamEndsLen - 1]) {
+    return -1;
+  }
+
+  a = -1;
+  b = streamEndsLen - 1;
+  // invariant: streamEnds[a] < start <= streamEnds[b]
+  while (b - a > 1) {
+    m = (a + b) / 2;
+    if (start <= streamEnds[m]) {
+      b = m;
+    } else {
+      a = m;
+    }
+  }
+  return streamEnds[b];
+}
index 28ef66cf987a28bae48f1f179968f4a9bdeb70eb..e2260d0c33cf9ded044ac83ee41d9f18ab74172b 100644 (file)
@@ -73,6 +73,10 @@ public:
   int getRootNum() { return rootNum; }
   int getRootGen() { return rootGen; }
 
+  // Get end position for a stream in a damaged file.
+  // Returns -1 if unknown or file is not damaged.
+  int getStreamEnd(int start);
+
 private:
 
   BaseStream *str;             // input stream
@@ -84,6 +88,9 @@ private:
   GBool ok;                    // true if xref table is valid
   Object trailerDict;          // trailer dictionary
   int lastXRefPos;             // offset of last xref table
+  int *streamEnds;             // 'endstream' positions - only used in
+                               //   damaged files
+  int streamEndsLen;           // number of valid entries in streamEnds
 #ifndef NO_DECRYPTION
   GBool encrypted;             // true if file is encrypted
   int permFlags;               // permission bits
index 051bb069715f24b0543a719e04629ff191aa17da..ff79d1f88928ac6a8661973e2a0247e31abd9f7a 100644 (file)
@@ -9,26 +9,51 @@
 #ifndef CONFIG_H
 #define CONFIG_H
 
+#include <config.h>
+#define HAVE_LIBCUPS
+
 //------------------------------------------------------------------------
 // general constants
 //------------------------------------------------------------------------
 
 // xpdf version
-#define xpdfVersion "0.91"
+#define xpdfVersion "0.92"
 
 // supported PDF version
 #define supportedPDFVersionStr "1.3"
 #define supportedPDFVersionNum 1.3
-  
+
 // copyright notice
-#define xpdfCopyright "Copyright 1996-2001 Derek B. Noonburg"
+#define xpdfCopyright "Copyright 1996-2000 Derek B. Noonburg"
+
+// default paper size (in points) for PostScript output
+#ifdef A4_PAPER
+#define defPaperWidth  595    // ISO A4 (210x297 mm)
+#define defPaperHeight 842
+#else
+#define defPaperWidth  612    // American letter (8.5x11")
+#define defPaperHeight 792
+#endif
+
+// config file name
+#if defined(VMS)
+#define xpdfConfigFile "xpdfrc"
+#else
+#define xpdfConfigFile ".xpdfrc"
+#endif
 
 //------------------------------------------------------------------------
-// uncompress program
+// X-related constants
 //------------------------------------------------------------------------
 
-#define HAVE_POPEN
-#define uncompressCmd "uncompress -c"
+// default maximum size of color cube to allocate
+#define defaultRGBCube 5
+
+// number of X server fonts to cache
+#define serverFontCacheSize 16
+
+// number of Type 1 (t1lib) fonts to cache
+#define t1FontCacheSize 32
 
 // number of TrueType (FreeType) fonts to cache
 #define ttFontCacheSize 32
 #define POPEN_READ_MODE "r"
 #endif
 
+//------------------------------------------------------------------------
+// uncompress program
+//------------------------------------------------------------------------
+
+#ifdef HAVE_POPEN
+
+// command to uncompress to stdout
+#  ifdef USE_GZIP
+#    define uncompressCmd "gzip -d -c -q"
+#  else
+#    ifdef __EMX__
+#      define uncompressCmd "compress -d -c"
+#    else
+#      define uncompressCmd "uncompress -c"
+#    endif // __EMX__
+#  endif // USE_GZIP
+
+#else // HAVE_POPEN
+
+// command to uncompress a file
+#  ifdef USE_GZIP
+#    define uncompressCmd "gzip -d -q"
+#  else
+#    define uncompressCmd "uncompress"
+#  endif // USE_GZIP
+
+#endif // HAVE_POPEN
+
 //------------------------------------------------------------------------
 // Win32 stuff
 //------------------------------------------------------------------------
index 7a34ed94debf9b9073d0c4c6330244a169fb6cc2..5e3781793edc37b257c27a334b872873c7e189a6 100644 (file)
 #endif // WIN32
 #include "GString.h"
 #include "gfile.h"
-#include <cups/cups.h>
+
+#ifdef HAVE_LIBCUPS
+#  include <cups/cups.h>
+#endif // HAVE_LIBCUPS
 
 // Some systems don't define this, so just make it something reasonably
 // large.
@@ -75,6 +78,10 @@ GString *getHomeDir() {
 
   if ((s = getenv("HOME"))) {
     ret = new GString(s);
+#  ifdef HAVE_LIBCUPS
+  } else if ((s = getenv("CUPS_SERVERROOT"))) {
+    ret = new GString(s);
+#  endif // HAVE_LIBCUPS
   } else {
     if ((s = getenv("USER")))
       pw = getpwnam(s);
@@ -107,7 +114,7 @@ GString *getCurrentDir() {
   return new GString();
 }
 
-GString *appendToPath(GString *path, char *fileName) {
+GString *appendToPath(GString *path, const char *fileName) {
 #if defined(VMS)
   //---------- VMS ----------
   //~ this should handle everything necessary for file
@@ -273,10 +280,10 @@ GString *appendToPath(GString *path, char *fileName) {
 #endif
 }
 
-GString *grabPath(char *fileName) {
+GString *grabPath(const char *fileName) {
 #ifdef VMS
   //---------- VMS ----------
-  char *p;
+  const char *p;
 
   if ((p = strrchr(fileName, ']')))
     return new GString(fileName, p + 1 - fileName);
@@ -286,7 +293,7 @@ GString *grabPath(char *fileName) {
 
 #elif defined(__EMX__) || defined(WIN32)
   //---------- OS/2+EMX and Win32 ----------
-  char *p;
+  const char *p;
 
   if ((p = strrchr(fileName, '/')))
     return new GString(fileName, p - fileName);
@@ -298,7 +305,7 @@ GString *grabPath(char *fileName) {
 
 #elif defined(ACORN)
   //---------- RISCOS ----------
-  char *p;
+  const char *p;
 
   if ((p = strrchr(fileName, '.')))
     return new GString(fileName, p - fileName);
@@ -306,7 +313,7 @@ GString *grabPath(char *fileName) {
 
 #elif defined(MACOS)
   //---------- MacOS ----------
-  char *p;
+  const char *p;
 
   if ((p = strrchr(fileName, ':')))
     return new GString(fileName, p - fileName);
@@ -314,7 +321,7 @@ GString *grabPath(char *fileName) {
 
 #else
   //---------- Unix ----------
-  char *p;
+  const char *p;
 
   if ((p = strrchr(fileName, '/')))
     return new GString(fileName, p - fileName);
@@ -322,7 +329,7 @@ GString *grabPath(char *fileName) {
 #endif
 }
 
-GBool isAbsolutePath(char *path) {
+GBool isAbsolutePath(const char *path) {
 #ifdef VMS
   //---------- VMS ----------
   return strchr(path, ':') ||
@@ -428,7 +435,7 @@ GString *makePathAbsolute(GString *path) {
 #endif
 }
 
-time_t getModTime(char *fileName) {
+time_t getModTime(const char *fileName) {
 #ifdef WIN32
   //~ should implement this, but it's (currently) only used in xpdf
   return 0;
@@ -442,11 +449,14 @@ time_t getModTime(char *fileName) {
 #endif
 }
 
-GBool openTempFile(GString **name, FILE **f, char *mode, char *ext) {
+GBool openTempFile(GString **name, FILE **f, const char *mode, const char *ext) {
+#ifdef HAVE_LIBCUPS
   char filename[1024]; // Name of temporary file...
   int  fd;             // File descriptor...
 
 
+  (void)ext;
+
   // Use the CUPS temporary file function on all platforms...
   if ((fd = cupsTempFd(filename, sizeof(filename))) < 0)
     return (gFalse);
@@ -456,13 +466,72 @@ GBool openTempFile(GString **name, FILE **f, char *mode, char *ext) {
   *name = new GString(filename);
 
   return (gTrue);
+#elif defined(VMS) || defined(__EMX__) || defined(WIN32) || defined(ACORN) || defined(MACOS)
+  //---------- non-Unix ----------
+  char *s;
+
+  // There is a security hole here: an attacker can create a symlink
+  // with this file name after the tmpnam call and before the fopen
+  // call.  I will happily accept fixes to this function for non-Unix
+  // OSs.
+  if (!(s = tmpnam(NULL))) {
+    return gFalse;
+  }
+  *name = new GString(s);
+  if (ext) {
+    (*name)->append(ext);
+  }
+  if (!(*f = fopen((*name)->getCString(), mode))) {
+    delete (*name);
+    return gFalse;
+  }
+  return gTrue;
+#else
+  //---------- Unix ----------
+  char *s, *p;
+  int fd;
+
+  if (ext) {
+    if (!(s = tmpnam(NULL))) {
+      return gFalse;
+    }
+    *name = new GString(s);
+    s = (*name)->getCString();
+    if ((p = strrchr(s, '.'))) {
+      (*name)->del(p - s, (*name)->getLength() - (p - s));
+    }
+    (*name)->append(ext);
+    fd = open((*name)->getCString(), O_WRONLY | O_CREAT | O_EXCL, 0600);
+  } else {
+#  if HAVE_MKSTEMP
+    if ((s = getenv("TMPDIR"))) {
+      *name = new GString(s);
+    } else {
+      *name = new GString("/tmp");
+    }
+    (*name)->append("/XXXXXX");
+    fd = mkstemp((*name)->getCString());
+#  else // HAVE_MKSTEMP
+    if (!(s = tmpnam(NULL))) {
+      return gFalse;
+    }
+    *name = new GString(s);
+    fd = open((*name)->getCString(), O_WRONLY | O_CREAT | O_EXCL, 0600);
+#  endif // HAVE_MKSTEMP
+  }
+  if (fd < 0 || !(*f = fdopen(fd, mode))) {
+    delete *name;
+    return gFalse;
+  }
+  return gTrue;
+#endif
 }
 
 //------------------------------------------------------------------------
 // GDir and GDirEntry
 //------------------------------------------------------------------------
 
-GDirEntry::GDirEntry(char *dirPath, char *name1, GBool doStat) {
+GDirEntry::GDirEntry(const char *dirPath, const char *name1, GBool doStat) {
 #ifdef VMS
   char *p;
 #elif defined(WIN32)
@@ -501,7 +570,7 @@ GDirEntry::~GDirEntry() {
   delete name;
 }
 
-GDir::GDir(char *name, GBool doStat1) {
+GDir::GDir(const char *name, GBool doStat1) {
   path = new GString(name);
   doStat = doStat1;
 #if defined(WIN32)
index b7bd3c200f61b9d5ecb5c259f7d9552510f8ceb7..49c6888ca60b360457cbb6a5512d6340cd7ee18c 100644 (file)
@@ -24,6 +24,7 @@
 #  endif
 #elif defined(ACORN)
 #elif defined(MACOS)
+#  include <ctime.h>
 #else
 #  include <unistd.h>
 #  include <sys/types.h>
@@ -60,14 +61,14 @@ extern GString *getCurrentDir();
 
 // Append a file name to a path string.  <path> may be an empty
 // string, denoting the current directory).  Returns <path>.
-extern GString *appendToPath(GString *path, char *fileName);
+extern GString *appendToPath(GString *path, const char *fileName);
 
 // Grab the path from the front of the file name.  If there is no
 // directory component in <fileName>, returns an empty string.
-extern GString *grabPath(char *fileName);
+extern GString *grabPath(const char *fileName);
 
 // Is this an absolute path or file name?
-extern GBool isAbsolutePath(char *path);
+extern GBool isAbsolutePath(const char *path);
 
 // Make this path absolute by prepending current directory (if path is
 // relative) or prepending user's directory (if path starts with '~').
@@ -75,7 +76,7 @@ GString *makePathAbsolute(GString *path);
 
 // Get the modification time for <fileName>.  Returns 0 if there is an
 // error.
-time_t getModTime(char *fileName);
+time_t getModTime(const char *fileName);
 
 // Create a temporary file and open it for writing.  If <ext> is not
 // NULL, it will be used as the file name extension.  Returns both the
@@ -83,7 +84,7 @@ time_t getModTime(char *fileName);
 // should be done to the returned file pointer; the file may be
 // reopened later for reading, but not for writing.  The <mode> string
 // should be "w" or "wb".  Returns true on success.
-GBool openTempFile(GString **name, FILE **f, char *mode, char *ext);
+GBool openTempFile(GString **name, FILE **f, const char *mode, const char *ext);
 
 //------------------------------------------------------------------------
 // GDir and GDirEntry
@@ -92,7 +93,7 @@ GBool openTempFile(GString **name, FILE **f, char *mode, char *ext);
 class GDirEntry {
 public:
 
-  GDirEntry(char *dirPath, char *name1, GBool doStat);
+  GDirEntry(const char *dirPath, const char *name1, GBool doStat);
   ~GDirEntry();
   GString *getName() { return name; }
   GBool isDir() { return dir; }
@@ -106,7 +107,7 @@ private:
 class GDir {
 public:
 
-  GDir(char *name, GBool doStat1 = gTrue);
+  GDir(const char *name, GBool doStat1 = gTrue);
   ~GDir();
   GDirEntry *getNextEntry();
   void rewind();
index cac386bc8aab161c555d87dfacd523efe6e7e92f..5b3743db362956fcbccd5bc803481ed111a35f8c 100644 (file)
@@ -194,7 +194,7 @@ void gMemReport(FILE *f) {
 }
 #endif
 
-char *copyString(char *s) {
+char *copyString(const char *s) {
   char *s1;
 
   s1 = (char *)gmalloc(strlen(s) + 1);
index 7ab5ddbeb873b0321cd9f1a3ec0e0098243fb621..8c8ca1f4aec6957886d45761ea3f39612265799b 100644 (file)
@@ -44,7 +44,7 @@ extern void gMemReport(FILE *f);
 /*
  * Allocate memory and copy a string into it.
  */
-extern char *copyString(char *s);
+extern char *copyString(const char *s);
 
 #ifdef __cplusplus
 }
index 6593267414401e2275708f51b4f5cb229ad51fd3..7a34876630dc1400cbf603717d4ae4fb9672223b 100644 (file)
@@ -9,6 +9,8 @@
 #ifndef GTYPES_H
 #define GTYPES_H
 
+#define HAVE_LIBCUPS
+
 /*
  * These have stupid names to avoid conflicts with some (but not all)
  * C++ compilers which define them.
index e9fdbfb71f407b8107a879483960e27cb40bddfc..7002302a69de491cb15ecda635333d657981d00f 100644 (file)
@@ -10,7 +10,6 @@
 #include <stdlib.h>
 #include <stddef.h>
 #include <string.h>
-#include <config.h>
 #include "parseargs.h"
 #include "GString.h"
 #include "gmem.h"
 #include "Params.h"
 #include "Error.h"
 #include "config.h"
-#include <cups/cups.h>
 
+#ifdef HAVE_LIBCUPS
+#  include <cups/cups.h>
+#endif /* HAVE_LIBCUPS */
+
+static int firstPage = 1;
+static int lastPage = 0;
+static GBool noEmbedFonts = gFalse;
+static GBool doForm = gFalse;
+static char userPassword[33] = "";
+static GBool printVersion = gFalse;
+static GBool printHelp = gFalse;
+
+static ArgDesc argDesc[] = {
+  {"-f",      argInt,      &firstPage,      0,
+   "first page to print"},
+  {"-l",      argInt,      &lastPage,       0,
+   "last page to print"},
+  {"-paperw", argInt,      &paperWidth,     0,
+   "paper width, in points"},
+  {"-paperh", argInt,      &paperHeight,    0,
+   "paper height, in points"},
+  {"-level1", argFlag,     &psOutLevel1,    0,
+   "generate Level 1 PostScript"},
+  {"-level1sep", argFlag,  &psOutLevel1Sep, 0,
+   "generate Level 1 separable PostScript"},
+  {"-eps",    argFlag,     &psOutEPS,       0,
+   "generate Encapsulated PostScript (EPS)"},
+#if OPI_SUPPORT
+  {"-opi",    argFlag,     &psOutOPI,       0,
+   "generate OPI comments"},
+#endif
+  {"-noemb",  argFlag,     &noEmbedFonts,   0,
+   "don't embed Type 1 fonts"},
+  {"-form",   argFlag,     &doForm,         0,
+   "generate a PostScript form"},
+  {"-upw",    argString,   userPassword,    sizeof(userPassword),
+   "user password (for encrypted files)"},
+  {"-q",      argFlag,     &errQuiet,       0,
+   "don't print any messages or errors"},
+  {"-v",      argFlag,     &printVersion,   0,
+   "print copyright and version info"},
+  {"-h",      argFlag,     &printHelp,      0,
+   "print usage information"},
+  {"-help",   argFlag,     &printHelp,      0,
+   "print usage information"},
+  {NULL}
+};
 
 int main(int argc, char *argv[]) {
-  PDFDoc       *doc;
-  GString      *fileName;
-  PSOutputDev  *psOut;
+  PDFDoc *doc;
+  GString *fileName;
+  GString *psFileName;
+  GString *userPW;
+  PSOutputDev *psOut;
+  GBool ok;
+  char *p;
+#ifdef HAVE_LIBCUPS
   int          num_options;
   cups_option_t        *options;
   ppd_file_t   *ppd;
   ppd_size_t   *size;
   FILE         *fp;
+  const char   *server_root;
   char         tempfile[1024];
   char         buffer[8192];
   int          bytes;
 
 
-  // Make sure status messages are not buffered...
-  setbuf(stderr, NULL);
+  // See if we are being run as a filter...
+  if (getenv("PPD") && getenv("SOFTWARE")) {
+    // Yes, make sure status messages are not buffered...
+    setbuf(stderr, NULL);
 
-  // Make sure we have the right number of arguments for CUPS!
-  if (argc < 6 || argc > 7)
-  {
-    fputs("Usage: pdftops job user title copies options [filename]\n", stderr);
-    return (1);
-  }
+    // Send all error messages...
+    errQuiet = 0;
 
-  // Copy stdin if needed...
-  if (argc == 6)
-  {
-    if ((fp = fopen(cupsTempFile(tempfile, sizeof(tempfile)), "w")) == NULL)
-    {
-      perror("ERROR: Unable to copy PDF file");
+    // Make sure we have the right number of arguments for CUPS!
+    if (argc < 6 || argc > 7) {
+      fputs("Usage: pdftops job user title copies options [filename]\n", stderr);
       return (1);
     }
 
-    fprintf(stderr, "DEBUG: pdftops - copying to temp print file \"%s\"\n",
-            tempfile);
+    // Copy stdin if needed...
+    if (argc == 6) {
+      if ((fp = fopen(cupsTempFile(tempfile, sizeof(tempfile)), "w")) == NULL) {
+       perror("ERROR: Unable to copy PDF file");
+       return (1);
+      }
 
-    while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0)
-      fwrite(buffer, 1, bytes, fp);
-    fclose(fp);
+      fprintf(stderr, "DEBUG: pdftops - copying to temp print file \"%s\"\n",
+              tempfile);
 
-    fileName = new GString(tempfile);
-  }
-  else
-  {
-    fileName = new GString(argv[6]);
+      while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0)
+       fwrite(buffer, 1, bytes, fp);
+      fclose(fp);
+
+      fileName = new GString(tempfile);
+    } else {
+      fileName = new GString(argv[6]);
+      tempfile[0] = '\0';
+    }
+  } else {
     tempfile[0] = '\0';
+#endif // HAVE_LIBCUPS
+  // parse args
+  ok = parseArgs(argDesc, &argc, argv);
+  if (!ok || argc < 2 || argc > 3 || printVersion || printHelp) {
+    fprintf(stderr, "pdftops version %s\n", xpdfVersion);
+    fprintf(stderr, "%s\n", xpdfCopyright);
+    if (!printVersion) {
+      printUsage("pdftops", "<PDF-file> [<PS-file>]", argDesc);
+    }
+    exit(1);
+  }
+  if (psOutLevel1 && psOutLevel1Sep) {
+    fprintf(stderr, "Error: use -level1 or -level1sep, not both.\n");
+    exit(1);
+  }
+  if (doForm && (psOutLevel1 || psOutLevel1Sep)) {
+    fprintf(stderr, "Error: forms are only available with Level 2 output.\n");
+    exit(1);
+  }
+  fileName = new GString(argv[1]);
+#ifdef HAVE_LIBCUPS
   }
 
   // Get PPD and initialize options as needed...
-  if ((ppd = ppdOpenFile(getenv("PPD"))) != NULL)
-  {
+  if ((ppd = ppdOpenFile(getenv("PPD"))) != NULL) {
     fprintf(stderr, "DEBUG: pdftops - opened PPD file \"%s\"...\n", getenv("PPD"));
 
     ppdMarkDefaults(ppd);
@@ -87,8 +161,7 @@ int main(int argc, char *argv[]) {
     cupsMarkOptions(ppd, num_options, options);
     cupsFreeOptions(num_options, options);
 
-    if ((size = ppdPageSize(ppd, NULL)) != NULL)
-    {
+    if ((size = ppdPageSize(ppd, NULL)) != NULL) {
       paperWidth  = (int)size->width;
       paperHeight = (int)size->length;
     }
@@ -100,16 +173,31 @@ int main(int argc, char *argv[]) {
 
     ppdClose(ppd);
   }
+#endif // HAVE_LIBCUPS
 
   // init error file
   errorInit();
 
   // read config file
-  initParams(CUPS_SERVERROOT "/xpdf.conf");
+#ifdef HAVE_LIBCUPS
+  if ((server_root = getenv("CUPS_SERVERROOT")) != NULL) {
+    sprintf(tempfile, "%s/pdftops.conf", server_root);
+    initParams(tempfile);
+  } else
+#endif /* HAVE_LIBCUPS */
+  initParams(xpdfConfigFile);
 
   // open PDF file
   xref = NULL;
-  doc = new PDFDoc(fileName, NULL);
+  if (userPassword[0]) {
+    userPW = new GString(userPassword);
+  } else {
+    userPW = NULL;
+  }
+  doc = new PDFDoc(fileName, userPW);
+  if (userPW) {
+    delete userPW;
+  }
   if (!doc->isOk()) {
     goto err1;
   }
@@ -120,25 +208,68 @@ int main(int argc, char *argv[]) {
     goto err1;
   }
 
+#ifdef HAVE_LIBCUPS
+  if (getenv("PPD") && getenv("SOFTWARE")) {
+    // CUPS always needs every page and writes to stdout...
+    psFileName = new GString("-");
+    firstPage  = 1;
+    lastPage   = doc->getNumPages();
+  } else {
+#endif // HAVE_LIBCUPS
+
+  // construct PostScript file name
+  if (argc == 3) {
+    psFileName = new GString(argv[2]);
+  } else {
+    p = fileName->getCString() + fileName->getLength() - 4;
+    if (!strcmp(p, ".pdf") || !strcmp(p, ".PDF"))
+      psFileName = new GString(fileName->getCString(),
+                              fileName->getLength() - 4);
+    else
+      psFileName = fileName->copy();
+    psFileName->append(psOutEPS ? ".eps" : ".ps");
+  }
+
+  // get page range
+  if (firstPage < 1)
+    firstPage = 1;
+  if (lastPage < 1 || lastPage > doc->getNumPages())
+    lastPage = doc->getNumPages();
+  if (doForm)
+    lastPage = firstPage;
+
+  // check for multi-page EPS
+  if (psOutEPS && firstPage != lastPage) {
+    error(-1, "EPS files can only contain one page.");
+    goto err2;
+  }
+#ifdef HAVE_LIBCUPS
+  }
+#endif // HAVE_LIBCUPS
+
   // write PostScript file
-  psOut = new PSOutputDev("-", doc->getCatalog(), 1, doc->getNumPages(), 1, 0);
+  psOut = new PSOutputDev(psFileName->getCString(), doc->getCatalog(),
+                         firstPage, lastPage, !noEmbedFonts, doForm);
   if (psOut->isOk())
-    doc->displayPages(psOut, 1, doc->getNumPages(), 72, 0, gFalse);
-
+    doc->displayPages(psOut, firstPage, lastPage, 72, 0, gFalse);
   delete psOut;
 
   // clean up
-  delete doc;
+ err2:
+  delete psFileName;
  err1:
+  delete doc;
   freeParams();
 
   // check for memory leaks
   Object::memCheck(stderr);
   gMemReport(stderr);
 
+#ifdef HAVE_LIBCUPS
   // Remove temp file if needed...
   if (tempfile[0])
     unlink(tempfile);
+#endif /* HAVE_LIBCUPS */
 
   return 0;
 }
index 0fcdeaeda61abab7424d54ec96ef51ef81bf9bd6..117df28abb642771a77946fe2da6902c23eb48d0 100644 (file)
@@ -1,5 +1,5 @@
 #
-# "$Id: Makefile,v 1.8 2001/01/22 15:03:53 mike Exp $"
+# "$Id: Makefile,v 1.8.2.1 2001/05/13 18:38:30 mike Exp $"
 #
 #   PPD file makefile for the Common UNIX Printing System (CUPS).
 #
@@ -28,21 +28,24 @@ include ../Makedefs
 # PPD files...
 #
 
-FILES  =       deskjet.ppd epson9.ppd epson24.ppd laserjet.ppd \
+FILES  =       deskjet.ppd deskjet2.ppd epson9.ppd epson24.ppd laserjet.ppd \
                okidata9.ppd okidat24.ppd stcolor.ppd stphoto.ppd
 
+
 #
 # Make everything...
 #
 
 all:
 
+
 #
 # Clean all config and object files...
 #
 
 clean:
 
+
 #
 # Install files...
 #
@@ -52,6 +55,7 @@ install:
        $(CHMOD) ugo+rx $(DATADIR)/model
        $(INSTALL_DATA) $(FILES) $(DATADIR)/model
 
+
 #
-# End of "$Id: Makefile,v 1.8 2001/01/22 15:03:53 mike Exp $".
+# End of "$Id: Makefile,v 1.8.2.1 2001/05/13 18:38:30 mike Exp $".
 #
index 81fc2b3f1ae83035f4fb1e0f9a0390895add1094..7caea4dc4f276a6e108ceddf97a95a99006af541 100644 (file)
@@ -1,6 +1,6 @@
 *PPD-Adobe: "4.3"
 *%
-*% "$Id: deskjet.ppd,v 1.9 2001/02/22 16:48:12 mike Exp $"
+*% "$Id: deskjet.ppd,v 1.9.2.1 2001/05/13 18:38:30 mike Exp $"
 *%
 *%   Sample HP DeskJet driver PPD file for the Common UNIX Printing
 *%   System (CUPS).
@@ -33,6 +33,7 @@
 *cupsVersion:  1.1
 *cupsManualCopies: True
 *cupsFilter:   "application/vnd.cups-raster 0 rastertohp"
+*cupsModelNumber: 1
 *ModelName:     "HP DeskJet Series"
 *ShortNickName: "HP DeskJet Series"
 *NickName:      "HP DeskJet Series CUPS v1.1"
 *Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM
 *Font ZapfDingbats: Special "(001.004S)" Standard ROM
 *%
-*% End of "$Id: deskjet.ppd,v 1.9 2001/02/22 16:48:12 mike Exp $".
+*% End of "$Id: deskjet.ppd,v 1.9.2.1 2001/05/13 18:38:30 mike Exp $".
 *%
index 84cff6a186835b424c1b1f9b8f5c7952880e6927..d6f487b9ddabe87baa32277b60b4a62de99bfbff 100644 (file)
@@ -1,6 +1,6 @@
 *PPD-Adobe: "4.3"
 *%
-*% "$Id: deskjet2.ppd,v 1.1 2001/04/23 19:52:31 mike Exp $"
+*% "$Id: deskjet2.ppd,v 1.1.2.1 2001/05/13 18:38:30 mike Exp $"
 *%
 *%   Second sample HP DeskJet driver PPD file for the Common UNIX Printing
 *%   System (CUPS).
 *Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM
 *Font ZapfDingbats: Special "(001.004S)" Standard ROM
 *%
-*% End of "$Id: deskjet2.ppd,v 1.1 2001/04/23 19:52:31 mike Exp $".
+*% End of "$Id: deskjet2.ppd,v 1.1.2.1 2001/05/13 18:38:30 mike Exp $".
 *%
index 6e0b68832d6b36172dc2ee52e8e972c9234cfd84..ef1b5575df57ed161cc50d56d2099e1dbe5cf7ba 100644 (file)
@@ -1,6 +1,6 @@
 *PPD-Adobe: "4.3"
 *%
-*% "$Id: laserjet.ppd,v 1.7 2001/02/22 16:48:12 mike Exp $"
+*% "$Id: laserjet.ppd,v 1.7.2.1 2001/05/13 18:38:30 mike Exp $"
 *%
 *%   Sample HP LaserJet driver PPD file for the Common UNIX Printing
 *%   System (CUPS).
@@ -33,6 +33,7 @@
 *cupsVersion:  1.1
 *cupsManualCopies: False
 *cupsFilter:   "application/vnd.cups-raster 0 rastertohp"
+*cupsModelNumber: 0
 *ModelName:     "HP LaserJet Series"
 *ShortNickName: "HP LaserJet Series"
 *NickName:      "HP LaserJet Series CUPS v1.1"
 *Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM
 *Font ZapfDingbats: Special "(001.004S)" Standard ROM
 *%
-*% End of "$Id: laserjet.ppd,v 1.7 2001/02/22 16:48:12 mike Exp $".
+*% End of "$Id: laserjet.ppd,v 1.7.2.1 2001/05/13 18:38:30 mike Exp $".
 *%
index 829949d810d9018796fe126239c054dd429ed395..b3bffac57d1a41fcef61adb4737e8773891424c7 100644 (file)
@@ -1,5 +1,5 @@
 #
-# "$Id: Makefile,v 1.31 2001/02/02 16:37:45 mike Exp $"
+# "$Id: Makefile,v 1.31.2.1 2001/05/13 18:38:31 mike Exp $"
 #
 #   GNU Ghostscript makefile for the Common UNIX Printing System (CUPS).
 #
 include ../Makedefs
 
 
-#
-# Updated rules for Ghostscript, which can't use the same level of
-# optimization on many platforms...
-#
-
-.c.o:
-       echo Compiling $<...
-       $(CC) $(GSOPTIM) $(CFLAGS) -c $<
-
-
 #
 # Object files...
 #
@@ -418,9 +408,6 @@ libgs.a:    $(LIBOBJS) ../Makedefs
        $(AR) $(ARFLAGS) $@ $(LIBOBJS)
        $(RANLIB) $@
 
-gdevcups.o:    ../filter/raster.h
-$(LIBOBJS):    arch.h ../config.h ../Makedefs
-
 
 #
 # pstoraster - PostScript RIP filter.
@@ -430,9 +417,30 @@ pstoraster:        pstoraster.o libgs.a ../Makedefs ../cups/$(LIBCUPS)
        echo Linking $@...
        $(CC) $(LDFLAGS) -o pstoraster pstoraster.o libgs.a \
                $(LINKCUPSIMAGE) $(IMGLIBS) $(DSOLIBS) $(LIBS) -lm
-pstoraster.o:  arch.h ../config.h ../Makedefs
 
 
 #
-# End of "$Id: Makefile,v 1.31 2001/02/02 16:37:45 mike Exp $".
+# Generate dependencies for Ghostscript source files...
+#
+
+depend:
+       rm -f Dependencies
+       touch Dependencies
+       for file in $(OBJS:.o=.c); do \
+               echo $$file; \
+               makedepend -a -fDependencies -I.. -Y $$file >/dev/null 2>&1; \
+       done
+
+
+#
+# Dependencies...
+#
+
+$(OBJS):       ../Makedefs
+
+include Dependencies
+
+
+#
+# End of "$Id: Makefile,v 1.31.2.1 2001/05/13 18:38:31 mike Exp $".
 #
index 4e2333118682757aa3e08ba98f300f022a942ad7..da9e6dbfef18fdae28be7db65361dbfdeabdb158 100644 (file)
@@ -22,7 +22,7 @@
   GNU software to build or run it.
 */
 
-/*$Id: gdevm1.c,v 1.2 2000/03/08 23:14:23 mike Exp $ */
+/*$Id: gdevm1.c,v 1.2.2.1 2001/05/13 18:38:31 mike Exp $ */
 /* Monobit "memory" (stored bitmap) device */
 #include "memory_.h"
 #include "gx.h"
@@ -191,16 +191,16 @@ typedef struct {
  * The indexing is (transparent, 0, 1, unused). */
 private const copy_mode copy_modes[16] =
 {
-    {~0, COPY_FUNNY},          /* NN */
-    {~0, COPY_AND},            /* N0 */
+    {~0UL, COPY_FUNNY},                /* NN */
+    {~0UL, COPY_AND},          /* N0 */
     {0, COPY_OR},              /* N1 */
     {0, 0},                    /* unused */
     {0, COPY_AND},             /* 0N */
     {0, COPY_FUNNY},           /* 00 */
     {0, COPY_STORE},           /* 01 */
     {0, 0},                    /* unused */
-    {~0, COPY_OR},             /* 1N */
-    {~0, COPY_STORE},          /* 10 */
+    {~0UL, COPY_OR},           /* 1N */
+    {~0UL, COPY_STORE},                /* 10 */
     {0, COPY_FUNNY},           /* 11 */
     {0, 0},                    /* unused */
     {0, 0},                    /* unused */
index beac6349ba26403db67071dc914efcf228e0382c..99664d904cbf0f06fb3e0d6e93fb467cfca82268 100644 (file)
@@ -21,7 +21,7 @@
 % Ghostscript, as distributed by Aladdin Enterprises, does not require any
 % GNU software to build or run it.
 
-% $Id: gs_fonts.ps,v 1.2 2000/03/08 23:14:29 mike Exp $
+% $Id: gs_fonts.ps,v 1.2.2.1 2001/05/13 18:38:31 mike Exp $
 % Font initialization and management code.
 
 % Define the default font.
@@ -281,7 +281,7 @@ FONTPATH length 0 eq { (%END FONTPATH) .skipeof } if
                { pop pop
                }
                { exch copystring exch
-                 DEBUG { ( ) print dup =only flush } if
+                 DEBUG { dup =only (\n) print flush } if
                  1 index .definefontmap
                  .splitfilename pop true .scanfontdict 3 1 roll .growput
                        % Increment fontcount.
index 9801894b1fa2669f6f1ca6b9c017eb2411a77ea3..a3ad9167e49efed772d5e129480c709b71277e2e 100644 (file)
@@ -1,4 +1,6 @@
-/* Copyright (C) 1996, 1997, 1998 Aladdin Enterprises.  All rights reserved.
+/*
+  Copyright 2001 by Easy Software Products
+  Copyright 1996, 1997, 1998 Aladdin Enterprises.  All rights reserved.
   
   This file is part of GNU Ghostscript.
   
@@ -22,7 +24,7 @@
   GNU software to build or run it.
 */
 
-/*$Id: gstype2.c,v 1.1 2000/03/08 23:14:49 mike Exp $ */
+/*$Id: gstype2.c,v 1.1.2.1 2001/05/13 18:38:31 mike Exp $ */
 /* Adobe Type 2 charstring interpreter */
 #include "math_.h"
 #include "memory_.h"
@@ -259,7 +261,12 @@ gs_type2_charstring_interpret(gs_type1_state * pcis,
                goto vstem;
            case cx_vmoveto:
                check_first_operator(csp > cstack);
-               accum_y(*csp);
+                /*** MRS: This is the first of many macro invocations;
+                 ***      Since these are encased in {} (previously an
+                 ***      empty do while(0) loop), we don't need the
+                 ***      trailing semicolon...
+                 ***/
+               accum_y(*csp)
              move:if ((pcis->hint_next != 0 || path_is_drawing(sppath)))
                    apply_path_hints(pcis, true);
                code = gx_path_add_point(sppath, ptx, pty);
@@ -283,9 +290,9 @@ gs_type2_charstring_interpret(gs_type1_state * pcis,
                vertical = true;
              hvl:for (ap = cstack; ap <= csp; vertical = !vertical, ++ap) {
                    if (vertical)
-                       accum_y(*ap);
+                       accum_y(*ap)
                    else
-                       accum_x(*ap);
+                       accum_x(*ap)
                    code = gx_path_add_line(sppath, ptx, pty);
                    if (code < 0)
                        return code;
@@ -343,7 +350,7 @@ gs_type2_charstring_interpret(gs_type1_state * pcis,
                goto move;
            case cx_hmoveto:
                check_first_operator(csp > cstack);
-               accum_x(*csp);
+               accum_x(*csp)
                goto move;
            case cx_vhcurveto:
                vertical = true;
@@ -356,9 +363,9 @@ gs_type2_charstring_interpret(gs_type1_state * pcis,
                    fixed ay0 = sppath->position.y - pty;
 
                    if (vertical)
-                       accum_y(ap[0]);
+                       accum_y(ap[0])
                    else
-                       accum_x(ap[0]);
+                       accum_x(ap[0])
                    pt1.x = ptx + ax0, pt1.y = pty + ay0;
                    accum_xy(ap[1], ap[2]);
                    pt2.x = ptx, pt2.y = pty;
@@ -366,12 +373,12 @@ gs_type2_charstring_interpret(gs_type1_state * pcis,
                        if (ap + 4 == csp)
                            accum_xy(ap[3], ap[4]);
                        else
-                           accum_x(ap[3]);
+                           accum_x(ap[3])
                    } else {
                        if (ap + 4 == csp)
                            accum_xy(ap[4], ap[3]);
                        else
-                           accum_y(ap[3]);
+                           accum_y(ap[3])
                    }
                    code = gx_path_add_curve(sppath, pt1.x, pt1.y,
                                             pt2.x, pt2.y, ptx, pty);
index df1a1210bb5c53eaaad864d80b01df9c42ec5ad2..9b35d967672c9f4efd0c11dac17b057a642e31f5 100644 (file)
@@ -1,4 +1,6 @@
-/* Copyright (C) 1998 Aladdin Enterprises.  All rights reserved.
+/*
+  Copyright 2001 by Easy Software Products.
+  Copyright 1998 Aladdin Enterprises.  All rights reserved.
   
   This file is part of GNU Ghostscript.
   
@@ -22,7 +24,7 @@
   GNU software to build or run it.
 */
 
-/*$Id: gxclrast.c,v 1.1 2000/03/08 23:14:54 mike Exp $ */
+/*$Id: gxclrast.c,v 1.1.2.1 2001/05/13 18:38:32 mike Exp $ */
 /* Command list interpreter/rasterizer */
 #include "memory_.h"
 #include "gx.h"
@@ -419,7 +421,7 @@ in:                         /* Initialize for a new page. */
                                    break;
                                case cmd_set_misc_data_x >> 6:
                                    if (cb & 0x20)
-                                       cmd_getw(data_x, cbp);
+                                       cmd_getw(data_x, cbp) /* MRS: No trailing ; */
                                    else
                                        data_x = 0;
                                    data_x = (data_x << 5) + (cb & 0x1f);
@@ -1506,7 +1508,7 @@ read_set_tile_size(command_buf_t *pcb, tile_slot *bits)
        bits->height = rep_height;
     }
     if (bd & 0x80)
-       cmd_getw(bits->rep_shift, cbp);
+       cmd_getw(bits->rep_shift, cbp) /* MRS: No trailing ; */
     else
        bits->rep_shift = 0;
     if_debug6('L', " depth=%d size=(%d,%d), rep_size=(%d,%d), rep_shift=%d\n",
index 407313f8266c05df0dec7b8b1510a17b5ca7fd76..69b9cb5f298787f1575ef98ef408dba1df8634cc 100644 (file)
@@ -22,7 +22,7 @@
   GNU software to build or run it.
 */
 
-/*$Id: iparam.c,v 1.2 2000/03/08 23:15:14 mike Exp $ */
+/*$Id: iparam.c,v 1.2.2.1 2001/05/13 18:38:32 mike Exp $ */
 /* Interpreter implementations of parameter dictionaries */
 #include "memory_.h"
 #include "string_.h"
@@ -251,7 +251,7 @@ ref_param_write_typed(gs_param_list * plist, gs_param_name pkey,
        case gs_param_type_array:
            return ref_param_begin_write_collection(plist, pkey,
                                                    &pvalue->value.d,
-                                        pvalue->type - gs_param_type_dict);
+                                        (gs_param_collection_type_t)(pvalue->type - gs_param_type_dict));
        default:
            return_error(e_typecheck);
     }
index c773f2b2cee260f77b97c66e2d43aa8089392ec1..df1306993ea9e18cbfa3a5f5aeb90fabf3042fd0 100644 (file)
@@ -1,4 +1,6 @@
-/* Copyright (C) 1993, 1994, 1996, 1997, 1998 Aladdin Enterprises.  All rights reserved.
+/*
+  Copyright 2001 by Easy Software Products.
+  Copyright 1993, 1994, 1996, 1997, 1998 Aladdin Enterprises.  All rights reserved.
   
   This file is part of GNU Ghostscript.
   
@@ -22,7 +24,7 @@
   GNU software to build or run it.
 */
 
-/*$Id: stdpre.h,v 1.2 2000/03/08 23:15:29 mike Exp $ */
+/*$Id: stdpre.h,v 1.2.2.1 2001/05/13 18:38:32 mike Exp $ */
 /* Standard definitions for Aladdin Enterprises code not needing arch.h */
 
 #ifndef stdpre_INCLUDED
@@ -303,15 +305,22 @@ typedef double floatp;
  *        ...statements...
  *      END
  */
-#define BEGIN  do {
-#define END    } while (0)
+/*** MRS: If you didn't treat C like a macro language, maybe this wouldn't
+ ***      be a problem; changed to { and } (which do work) to avoid
+ ***      needless compiler warnings...
+ ***/
+#define BEGIN  {
+#define END    }
 
 /*
  * Define a handy macro for a statement that does nothing.
  * We can't just use an empty statement, since this upsets some compilers.
  */
+/*** MRS: Fix DO_NOTHING to use a void statement.  Again, not using
+ ***      macros makes life easier...
+ ***/
 #ifndef DO_NOTHING
-#  define DO_NOTHING BEGIN END
+#  define DO_NOTHING (void)stdout
 #endif
 
 /*
index fb2cf4c13002c74a3aa47529a9fc163b7537e7a8..8bfae01c661ba90a1c2b199e40c980308ca9e7bf 100644 (file)
@@ -1,4 +1,6 @@
-/* Copyright (C) 1997, 1998 Aladdin Enterprises.  All rights reserved.
+/*
+  Copyright 2001 by Easy Software Products.
+  Copyright 1997, 1998 Aladdin Enterprises.  All rights reserved.
   
   This file is part of GNU Ghostscript.
   
@@ -22,7 +24,7 @@
   GNU software to build or run it.
 */
 
-/*$Id: zfunc.c,v 1.1 2000/03/08 23:15:38 mike Exp $ */
+/*$Id: zfunc.c,v 1.1.2.1 2001/05/13 18:38:33 mike Exp $ */
 /* Generic PostScript language interface to Functions */
 #include "memory_.h"
 #include "ghost.h"
@@ -124,7 +126,7 @@ zexecfunction(os_ptr op)
                DO_NOTHING;
            else {
                if (diff > 0)
-                   push(diff); /* can't fail */
+                   push(diff)  /* can't fail */ /* MRS: No trailing ; */
                else if (diff < 0) {
                    pop(-diff);
                    op = osp;
index a1879f824d293976146f23049fed4c127517f07d..fc0e2d809c8423b1d71e8577f8faa9acafddabdc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: auth.c,v 1.41.2.1 2001/04/02 19:51:46 mike Exp $"
+ * "$Id: auth.c,v 1.41.2.2 2001/05/13 18:38:33 mike Exp $"
  *
  *   Authorization routines for the Common UNIX Printing System (CUPS).
  *
@@ -62,6 +62,9 @@
 #if HAVE_LIBPAM
 #  include <security/pam_appl.h>
 #endif /* HAVE_LIBPAM */
+#ifdef HAVE_USERSEC_H
+#  include <usersec.h>
+#endif /* HAVE_USERSEC_H */
 
 
 /*
@@ -78,6 +81,15 @@ static int           pam_func(int, const struct pam_message **,
 #endif /* HAVE_LIBPAM */
 
 
+/*
+ * Local globals...
+ */
+
+#ifdef __hpux
+static client_t                *auth_client;   /* Current client being authenticated */
+#endif /* __hpux */
+
+
 /*
  * 'AddLocation()' - Add a location for authorization.
  */
@@ -539,7 +551,8 @@ FindBest(client_t *con)             /* I - Connection */
 
   for (i = NumLocations, loc = Locations; i > 0; i --, loc ++)
   {
-    DEBUG_printf(("Location %s Limit %x\n", loc->location, loc->limit));
+    LogMessage(L_DEBUG2, "FindBest: Location %s Limit %x",
+               loc->location, loc->limit);
 
     if (loc->length > bestlen &&
         strncmp(con->uri, loc->location, loc->length) == 0 &&
@@ -555,6 +568,8 @@ FindBest(client_t *con)             /* I - Connection */
   * Return the match, if any...
   */
 
+  LogMessage(L_DEBUG2, "FindBest: best = %s", best ? best->location : "NONE");
+
   return (best);
 }
 
@@ -602,6 +617,10 @@ IsAuthorized(client_t *con)        /* I - Connection */
   pam_handle_t *pamh;          /* PAM authentication handle */
   int          pamerr;         /* PAM error code */
   struct pam_conv pamdata;     /* PAM conversation data */
+#elif defined(HAVE_USERSEC_H)
+  char         *authmsg;       /* Authentication message */
+  char         *loginmsg;      /* Login message */
+  int          reenter;        /* ??? */
 #else
   char         *pass;          /* Encrypted password */
 #  ifdef HAVE_SHADOW_H
@@ -627,18 +646,15 @@ IsAuthorized(client_t *con)       /* I - Connection */
                };
 
 
+  LogMessage(L_DEBUG2, "IsAuthorized: URI = %s", con->uri);
+
  /*
   * Find a matching location; if there is no match then access is
   * not authorized...
   */
 
   if ((best = FindBest(con)) == NULL)
-  {
-    DEBUG_printf(("FindBest(%s, %s) failed!\n", states[con->http.state],
-                  con->uri));
-
     return (HTTP_FORBIDDEN);
-  }
 
  /*
   * Check host/ip-based accesses...
@@ -724,6 +740,9 @@ IsAuthorized(client_t *con) /* I - Connection */
     }
   }
 
+  LogMessage(L_DEBUG2, "IsAuthorized: auth = %d, satisfy=%d...",
+             auth, best->satisfy);
+
   if (auth == AUTH_DENY && best->satisfy == AUTH_SATISFY_ALL)
     return (HTTP_FORBIDDEN);
 
@@ -733,7 +752,10 @@ IsAuthorized(client_t *con)        /* I - Connection */
   */
 
   if (best->encryption >= HTTP_ENCRYPT_REQUIRED && !con->http.tls)
+  {
+    LogMessage(L_DEBUG2, "IsAuthorized: Need upgrade to TLS...");
     return (HTTP_UPGRADE_REQUIRED);
+  }
 #endif /* HAVE_LIBSSL */
 
  /*
@@ -743,6 +765,8 @@ IsAuthorized(client_t *con) /* I - Connection */
   if (best->level == AUTH_ANON)                /* Anonymous access - allow it */
     return (HTTP_OK);
 
+  LogMessage(L_DEBUG2, "IsAuthorized: username = \"%s\" password = %d chars",
+            con->username, strlen(con->password));
   DEBUG_printf(("IsAuthorized: username = \"%s\", password = \"%s\"\n",
                con->username, con->password));
 
@@ -768,8 +792,8 @@ IsAuthorized(client_t *con) /* I - Connection */
     return (HTTP_UNAUTHORIZED);
   }
 
-  DEBUG_printf(("IsAuthorized: Checking \"%s\", address = %08x, hostname = \"%s\"\n",
-                con->username, address, con->http.hostname));
+  LogMessage(L_DEBUG2, "IsAuthorized: Checking \"%s\", address = %08x, hostname = \"%s\"",
+             con->username, address, con->http.hostname);
 
   if (strcasecmp(con->http.hostname, "localhost") != 0 ||
       strncmp(con->http.fields[HTTP_FIELD_AUTHORIZATION], "Local", 5) != 0)
@@ -796,6 +820,17 @@ IsAuthorized(client_t *con)        /* I - Connection */
       pamdata.conv        = pam_func;
       pamdata.appdata_ptr = con;
 
+#  ifdef __hpux
+     /*
+      * Workaround for HP-UX bug in pam_unix; see pam_conv() below for
+      * more info...
+      */
+
+      auth_client = con;
+#  endif /* __hpux */
+
+      DEBUG_printf(("IsAuthorized: Setting appdata_ptr = %p\n", con));
+
       pamerr = pam_start("cups", con->username, &pamdata, &pamh);
       if (pamerr != PAM_SUCCESS)
       {
@@ -824,6 +859,21 @@ IsAuthorized(client_t *con)        /* I - Connection */
       }
 
       pam_end(pamh, PAM_SUCCESS);
+#elif defined(HAVE_USERSEC_H)
+     /*
+      * Use AIX authentication interface...
+      */
+
+      LogMessage(L_DEBUG, "IsAuthorized: AIX authenticate of username \"%s\"",
+                 con->username);
+
+      reenter = 1;
+      if (authenticate(con->username, con->password, &reenter, &authmsg) != 0)
+      {
+       LogMessage(L_DEBUG, "IsAuthorized: Unable to authenticate username \"%s\": %s",
+                  con->username, strerror(errno));
+       return (HTTP_UNAUTHORIZED);
+      }
 #else
 #  ifdef HAVE_SHADOW_H
       spw = getspnam(con->username);
@@ -857,8 +907,8 @@ IsAuthorized(client_t *con) /* I - Connection */
       * OK, the password isn't blank, so compare with what came from the client...
       */
 
-      DEBUG_printf(("IsAuthorized: pw_passwd = %s, crypt = %s\n",
-                   pw->pw_passwd, crypt(con->password, pw->pw_passwd)));
+      LogMessage(L_DEBUG2, "IsAuthorized: pw_passwd = %s, crypt = %s",
+                pw->pw_passwd, crypt(con->password, pw->pw_passwd));
 
       pass = crypt(con->password, pw->pw_passwd);
 
@@ -868,8 +918,8 @@ IsAuthorized(client_t *con) /* I - Connection */
 #  ifdef HAVE_SHADOW_H
        if (spw != NULL)
        {
-         DEBUG_printf(("IsAuthorized: sp_pwdp = %s, crypt = %s\n",
-                       spw->sp_pwdp, crypt(con->password, spw->sp_pwdp)));
+         LogMessage(L_DEBUG2, "IsAuthorized: sp_pwdp = %s, crypt = %s",
+                    spw->sp_pwdp, crypt(con->password, spw->sp_pwdp));
 
          pass = crypt(con->password, spw->sp_pwdp);
 
@@ -938,6 +988,8 @@ IsAuthorized(client_t *con) /* I - Connection */
     * any valid user is OK...
     */
 
+    LogMessage(L_DEBUG2, "IsAuthorized: Checking user membership...");
+
     if (best->num_names == 0)
       return (HTTP_OK);
 
@@ -957,6 +1009,8 @@ IsAuthorized(client_t *con)        /* I - Connection */
   * Check to see if this user is in any of the named groups...
   */
 
+  LogMessage(L_DEBUG2, "IsAuthorized: Checking group membership...");
+
   for (i = 0; i < best->num_names; i ++)
   {
     grp = getgrnam(best->names[i]);
@@ -985,7 +1039,7 @@ IsAuthorized(client_t *con)        /* I - Connection */
   * The user isn't part of the specified group, so deny access...
   */
 
-  DEBUG_puts("IsAuthorized: user not in group!");
+  LogMessage(L_DEBUG2, "IsAuthorized: user not in group!");
 
   return (HTTP_UNAUTHORIZED);
 }
@@ -1148,31 +1202,59 @@ pam_func(int                      num_msg,      /* I - Number of messages */
   * Answer all of the messages...
   */
 
+  DEBUG_printf(("pam_func: appdata_ptr = %p\n", appdata_ptr));
+
+#ifdef __hpux
+ /*
+  * Apparently some versions of HP-UX 11 have a broken pam_unix security
+  * module.  This is a workaround...
+  */
+
+  client = auth_client;
+  (void)appdata_ptr;
+#else
   client = (client_t *)appdata_ptr;
+#endif /* __hpux */
 
   for (i = 0; i < num_msg; i ++)
+  {
+    DEBUG_printf(("pam_func: Message = \"%s\"\n", msg[i]->msg));
+
     switch (msg[i]->msg_style)
     {
       case PAM_PROMPT_ECHO_ON:
+          DEBUG_printf(("pam_func: PAM_PROMPT_ECHO_ON, returning \"%s\"...\n",
+                       client->username));
           replies[i].resp_retcode = PAM_SUCCESS;
           replies[i].resp         = strdup(client->username);
           break;
 
       case PAM_PROMPT_ECHO_OFF:
+          DEBUG_printf(("pam_func: PAM_PROMPT_ECHO_OFF, returning \"%s\"...\n",
+                       client->password));
           replies[i].resp_retcode = PAM_SUCCESS;
           replies[i].resp         = strdup(client->password);
           break;
 
       case PAM_TEXT_INFO:
+          DEBUG_puts("pam_func: PAM_TEXT_INFO...");
+          replies[i].resp_retcode = PAM_SUCCESS;
+          replies[i].resp         = NULL;
+          break;
+
       case PAM_ERROR_MSG:
+          DEBUG_puts("pam_func: PAM_ERROR_MSG...");
           replies[i].resp_retcode = PAM_SUCCESS;
           replies[i].resp         = NULL;
           break;
 
       default:
+          DEBUG_printf(("pam_func: Unknown PAM message %d...\n",
+                       msg[i]->msg_style));
           free(replies);
           return (PAM_CONV_ERR);
     }
+  }
 
  /*
   * Return the responses back to PAM...
@@ -1186,5 +1268,5 @@ pam_func(int                      num_msg,        /* I - Number of messages */
 
 
 /*
- * End of "$Id: auth.c,v 1.41.2.1 2001/04/02 19:51:46 mike Exp $".
+ * End of "$Id: auth.c,v 1.41.2.2 2001/05/13 18:38:33 mike Exp $".
  */
index 1fbe8502e15059a4a404db346a4a72b7f4e7b0ab..325fb1d813c24d4328dabe677286cf5a0df0897f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: cert.c,v 1.7 2001/03/06 14:23:15 mike Exp $"
+ * "$Id: cert.c,v 1.7.2.1 2001/05/13 18:38:34 mike Exp $"
  *
  *   Authentication certificate routines for the Common UNIX
  *   Printing System (CUPS).
@@ -96,9 +96,9 @@ AddCert(int        pid,                       /* I - Process ID */
     fchmod(fileno(fp), 0440);
 
     if ((grp = getgrnam(SystemGroup)) == NULL)
-      fchown(fileno(fp), 0, 0);
+      fchown(fileno(fp), getuid(), 0);
     else
-      fchown(fileno(fp), 0, grp->gr_gid);
+      fchown(fileno(fp), getuid(), grp->gr_gid);
 
     endgrent();
 
@@ -271,5 +271,5 @@ InitCerts(void)
 
 
 /*
- * End of "$Id: cert.c,v 1.7 2001/03/06 14:23:15 mike Exp $".
+ * End of "$Id: cert.c,v 1.7.2.1 2001/05/13 18:38:34 mike Exp $".
  */
index 49d4354a88ca285c59efddac442ac8392bc46043..5301067fa0510b1bb955325d6ef25a38dce64c88 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: client.c,v 1.91.2.1 2001/04/02 19:51:47 mike Exp $"
+ * "$Id: client.c,v 1.91.2.2 2001/05/13 18:38:34 mike Exp $"
  *
  *   Client routines for the Common UNIX Printing System (CUPS) scheduler.
  *
@@ -634,8 +634,7 @@ ReadClient(client_t *con)   /* I - Client to read from */
        }
       }
 
-      if ((strcasecmp(con->http.fields[HTTP_FIELD_CONNECTION], "Upgrade") == 0 ||
-           (best != NULL && best->encryption == HTTP_ENCRYPT_ALWAYS)) &&
+      if (strcasecmp(con->http.fields[HTTP_FIELD_CONNECTION], "Upgrade") == 0 &&
          con->http.tls == NULL)
       {
 #ifdef HAVE_LIBSSL
@@ -650,7 +649,7 @@ ReadClient(client_t *con)   /* I - Client to read from */
        }
 
        httpPrintf(HTTP(con), "Connection: Upgrade\r\n");
-       httpPrintf(HTTP(con), "Upgrade: TLS/1.0,SSL/2.0,SSL/3.0\r\n");
+       httpPrintf(HTTP(con), "Upgrade: TLS/1.0,HTTP/1.1\r\n");
        httpPrintf(HTTP(con), "Content-Length: 0\r\n");
        httpPrintf(HTTP(con), "\r\n");
 
@@ -700,7 +699,8 @@ ReadClient(client_t *con)   /* I - Client to read from */
     }
     else
     {
-      if ((status = IsAuthorized(con)) == HTTP_UPGRADE_REQUIRED)
+      if (strcasecmp(con->http.fields[HTTP_FIELD_CONNECTION], "Upgrade") == 0 &&
+         con->http.tls == NULL)
       {
 #ifdef HAVE_LIBSSL
        /*
@@ -714,7 +714,7 @@ ReadClient(client_t *con)   /* I - Client to read from */
        }
 
        httpPrintf(HTTP(con), "Connection: Upgrade\r\n");
-       httpPrintf(HTTP(con), "Upgrade: TLS/1.0,SSL/2.0,SSL/3.0\r\n");
+       httpPrintf(HTTP(con), "Upgrade: TLS/1.0,HTTP/1.1\r\n");
        httpPrintf(HTTP(con), "Content-Length: 0\r\n");
        httpPrintf(HTTP(con), "\r\n");
 
@@ -727,7 +727,8 @@ ReadClient(client_t *con)   /* I - Client to read from */
        }
 #endif /* HAVE_LIBSSL */
       }
-      else if (status != HTTP_OK)
+
+      if ((status = IsAuthorized(con)) != HTTP_OK)
       {
        SendError(con, status);
        CloseClient(con);
@@ -1250,8 +1251,9 @@ SendCommand(client_t      *con,
 
   close(fd);
 
-  LogMessage(L_DEBUG, "SendCommand() %d command=\"%s\" file=%d pipe_pid=%d",
-             con->http.fd, command, con->file, con->pipe_pid);
+  LogMessage(L_INFO, "Started \"%s\" (pid=%d)", command, con->pipe_pid);
+
+  LogMessage(L_DEBUG, "SendCommand() %d file=%d", con->http.fd, con->file);
 
   if (con->pipe_pid == 0)
     return (0);
@@ -1321,13 +1323,11 @@ SendError(client_t      *con,   /* I - Connection */
 
 #ifdef HAVE_LIBSSL
   if (code == HTTP_UPGRADE_REQUIRED)
-  {
     if (httpPrintf(HTTP(con), "Connection: Upgrade\r\n") < 0)
       return (0);
 
-    if (httpPrintf(HTTP(con), "Upgrade: TLS/1.0,SSL/2.0,SSL/3.0\r\n") < 0)
-      return (0);
-  }
+  if (httpPrintf(HTTP(con), "Upgrade: TLS/1.0,HTTP/1.1\r\n") < 0)
+    return (0);
 #endif /* HAVE_LIBSSL */
 
   if (con->http.version >= HTTP_1_1 && !con->http.keep_alive)
@@ -2132,5 +2132,5 @@ pipe_command(client_t *con,       /* I - Client connection */
 
 
 /*
- * End of "$Id: client.c,v 1.91.2.1 2001/04/02 19:51:47 mike Exp $".
+ * End of "$Id: client.c,v 1.91.2.2 2001/05/13 18:38:34 mike Exp $".
  */
index 1bf788ed2ad52bc34a4a05f3d93776b9d4c5e6e4..7d6a8e0464b61957e1309b44f3e473c7b219e82d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: cups-lpd.c,v 1.24.2.1 2001/04/02 19:51:48 mike Exp $"
+ * "$Id: cups-lpd.c,v 1.24.2.2 2001/05/13 18:38:34 mike Exp $"
  *
  *   Line Printer Daemon interface for the Common UNIX Printing System (CUPS).
  *
@@ -299,7 +299,8 @@ print_file(const char    *name,             /* I - Printer or class name */
   * Setup a connection and request data...
   */
 
-  if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+  if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
+                                 cupsEncryption())) == NULL)
   {
     syslog(LOG_ERR, "Unable to connect to server: %s", strerror(errno));
     return (0);
@@ -762,7 +763,8 @@ remove_jobs(const char *dest,               /* I - Destination */
   * Try connecting to the local server...
   */
 
-  if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+  if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
+                                 cupsEncryption())) == NULL)
     return (1);
 
   language = cupsLangDefault();
@@ -915,7 +917,8 @@ send_state(const char *dest,                /* I - Destination */
   * Try connecting to the local server...
   */
 
-  if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+  if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
+                                 cupsEncryption())) == NULL)
     return (1);
 
  /*
@@ -1235,5 +1238,5 @@ smart_gets(char *s,       /* I - Pointer to line buffer */
 
 
 /*
- * End of "$Id: cups-lpd.c,v 1.24.2.1 2001/04/02 19:51:48 mike Exp $".
+ * End of "$Id: cups-lpd.c,v 1.24.2.2 2001/05/13 18:38:34 mike Exp $".
  */
index 5c1fc059ee31d2daac9cff6aebbd9c86f0d24887..6cbac566878131bb0b9454421a15146167ae60de 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: cups-polld.c,v 1.5 2001/01/22 15:03:59 mike Exp $"
+ * "$Id: cups-polld.c,v 1.5.2.1 2001/05/13 18:38:35 mike Exp $"
  *
  *   Polling daemon for the Common UNIX Printing System (CUPS).
  *
@@ -78,7 +78,8 @@ main(int  argc,                               /* I - Number of command-line arguments */
   * Open a connection to the server...
   */
 
-  if ((http = httpConnect(argv[1], atoi(argv[2]))) == NULL)
+  if ((http = httpConnectEncrypt(argv[1], atoi(argv[2]),
+                                 cupsEncryption())) == NULL)
   {
     perror("cups-polld");
     return (1);
@@ -304,5 +305,5 @@ poll_server(http_t      *http,              /* I - HTTP connection */
 
 
 /*
- * End of "$Id: cups-polld.c,v 1.5 2001/01/22 15:03:59 mike Exp $".
+ * End of "$Id: cups-polld.c,v 1.5.2.1 2001/05/13 18:38:35 mike Exp $".
  */
index ea249def129dab74dc66eef06809c79cacdb41fd..a3dc19fe7416107f8c989f69c2437ef46111836c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: dirsvc.c,v 1.73.2.1 2001/04/02 19:51:48 mike Exp $"
+ * "$Id: dirsvc.c,v 1.73.2.2 2001/05/13 18:38:35 mike Exp $"
  *
  *   Directory services routines for the Common UNIX Printing System (CUPS).
  *
@@ -182,7 +182,8 @@ UpdateBrowseList(void)
                *sptr;                  /* Pointer into ServerName */
   printer_t    *p,                     /* Printer information */
                *pclass,                /* Printer class */
-               *first;                 /* First printer in class */
+               *first,                 /* First printer in class */
+               *next;                  /* Next printer in list */
 
 
  /*
@@ -675,8 +676,14 @@ UpdateBrowseList(void)
 
     for (p = Printers, len = 0, offset = 0, first = NULL;
          p != NULL;
-        p = p->next)
+        p = next)
     {
+     /*
+      * Get next printer in list...
+      */
+
+      next = p->next;
+
      /*
       * Skip classes...
       */
@@ -953,5 +960,5 @@ StopPolling(void)
 
 
 /*
- * End of "$Id: dirsvc.c,v 1.73.2.1 2001/04/02 19:51:48 mike Exp $".
+ * End of "$Id: dirsvc.c,v 1.73.2.2 2001/05/13 18:38:35 mike Exp $".
  */
index f221b0f385c05d6851cbc1b50a05d6aed2f78b68..cecd041b2cc4febdac6f08ca16720f7dfd1ab8ce 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: ipp.c,v 1.127.2.1 2001/04/02 19:51:48 mike Exp $"
+ * "$Id: ipp.c,v 1.127.2.2 2001/05/13 18:38:35 mike Exp $"
  *
  *   IPP routines for the Common UNIX Printing System (CUPS) scheduler.
  *
@@ -391,10 +391,12 @@ ProcessIPPRequest(client_t *con)  /* I - Client connection */
               break;
 
          case CUPS_ACCEPT_JOBS :
+         case IPP_ENABLE_PRINTER :
               accept_jobs(con, uri);
               break;
 
          case CUPS_REJECT_JOBS :
+         case IPP_DISABLE_PRINTER :
               reject_jobs(con, uri);
               break;
 
@@ -1386,15 +1388,12 @@ static void
 add_queued_job_count(client_t  *con,   /* I - Client connection */
                      printer_t *p)     /* I - Printer or class */
 {
-  cups_ptype_t dtype;                  /* Destination type */
   int          count;                  /* Number of jobs on destination */
 
 
   LogMessage(L_DEBUG2, "add_queued_job_count(%d, %s)\n", con->http.fd,
              p->name);
 
-  dtype = p->type & CUPS_PRINTER_CLASS;
-
   count = GetPrinterJobCount(p->name);
 
   ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
@@ -1825,7 +1824,8 @@ copy_attribute(ipp_t           *to,       /* O - Destination request/response */
   ipp_attribute_t      *toattr;        /* Destination attribute */
 
 
-  LogMessage(L_DEBUG2, "copy_attribute(%p, %s)\n", to, attr->name);
+  LogMessage(L_DEBUG2, "copy_attribute(%p, %s)\n", to,
+             attr->name ? attr->name : "(null)");
 
   switch (attr->value_tag)
   {
@@ -1860,7 +1860,7 @@ copy_attribute(ipp_t           *to,       /* O - Destination request/response */
     case IPP_TAG_LANGUAGE :
     case IPP_TAG_MIMETYPE :
         toattr = ippAddStrings(to, attr->group_tag,
-                              attr->value_tag | IPP_TAG_COPY,
+                              (ipp_tag_t)(attr->value_tag | IPP_TAG_COPY),
                               attr->name, attr->num_values, NULL,
                               NULL);
 
@@ -1900,7 +1900,7 @@ copy_attribute(ipp_t           *to,       /* O - Destination request/response */
     case IPP_TAG_TEXTLANG :
     case IPP_TAG_NAMELANG :
         toattr = ippAddStrings(to, attr->group_tag,
-                              attr->value_tag | IPP_TAG_COPY,
+                              (ipp_tag_t)(attr->value_tag | IPP_TAG_COPY),
                               attr->name, attr->num_values, NULL, NULL);
 
         for (i = 0; i < attr->num_values; i ++)
@@ -2225,6 +2225,8 @@ create_job(client_t        *con,  /* I - Client connection */
       attr->values[1].string.text = strdup(printer->job_sheets[1]);
     }
 
+    job->job_sheets = attr;
+
    /*
     * Enforce classification level if set...
     */
@@ -3891,6 +3893,8 @@ print_job(client_t        *con,           /* I - Client connection */
       attr->values[1].string.text = strdup(printer->job_sheets[1]);
     }
 
+    job->job_sheets = attr;
+
    /*
     * Enforce classification level if set...
     */
@@ -5424,5 +5428,5 @@ validate_user(client_t   *con,            /* I - Client connection */
 
 
 /*
- * End of "$Id: ipp.c,v 1.127.2.1 2001/04/02 19:51:48 mike Exp $".
+ * End of "$Id: ipp.c,v 1.127.2.2 2001/05/13 18:38:35 mike Exp $".
  */
index 277d8920b5a0b4afc79f6f4032a4d139962b6772..e485662ff228b3b4269ae68c7942f6a1c9fba86a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: job.c,v 1.124.2.1 2001/04/02 19:51:49 mike Exp $"
+ * "$Id: job.c,v 1.124.2.2 2001/05/13 18:38:36 mike Exp $"
  *
  *   Job management routines for the Common UNIX Printing System (CUPS).
  *
@@ -275,7 +275,16 @@ CheckJobs(void)
     if (current->state->values[0].integer == IPP_JOB_PENDING)
     {
       if ((pclass = FindClass(current->dest)) != NULL)
-        printer = FindAvailablePrinter(current->dest);
+      {
+       /*
+        * If the class is remote, just pass it to the remote server...
+       */
+
+        if (pclass->type & CUPS_PRINTER_REMOTE)
+         printer = pclass;
+       else
+         printer = FindAvailablePrinter(current->dest);
+      }
       else
         printer = FindPrinter(current->dest);
 
@@ -1048,6 +1057,7 @@ StartJob(int       id,            /* I - Job ID */
                *optptr;        /* Pointer to options */
   ipp_attribute_t *attr;       /* Current attribute */
   int          pid;            /* Process ID of new filter process */
+  int          banner_page;    /* 1 if banner page, 0 otherwise */
   int          statusfds[2],   /* Pipes used between the filters and scheduler */
                filterfds[2][2];/* Pipes used between the filters */
   char         *argv[8],       /* Filter command-line arguments */
@@ -1084,8 +1094,8 @@ StartJob(int       id,            /* I - Job ID */
   if (current == NULL)
     return;
 
-  LogMessage(L_DEBUG, "StartJob() id = %d, file = %d", id,
-             current->current_file);
+  LogMessage(L_DEBUG, "StartJob() id = %d, file = %d/%d", id,
+             current->current_file, current->num_files);
 
   if (current->num_files == 0)
   {
@@ -1173,6 +1183,36 @@ StartJob(int       id,           /* I - Job ID */
   if (current->current_file == 0)
     set_time(current, "time-at-processing");
 
+ /*
+  * Determine if we are printing a banner page or not...
+  */
+
+  if (current->job_sheets == NULL)
+    LogMessage(L_DEBUG, "No job-sheets attribute.");
+  else if (current->job_sheets->num_values == 1)
+    LogMessage(L_DEBUG, "job-sheets=%s",
+               current->job_sheets->values[0].string.text);
+  else
+    LogMessage(L_DEBUG, "job-sheets=%s,%s",
+               current->job_sheets->values[0].string.text,
+               current->job_sheets->values[1].string.text);
+
+  if (printer->type & CUPS_PRINTER_REMOTE)
+    banner_page = 0;
+  else if (current->job_sheets == NULL)
+    banner_page = 0;
+  else if (strcasecmp(current->job_sheets->values[0].string.text, "none") != 0 &&
+          current->current_file == 0)
+    banner_page = 1;
+  else if (current->job_sheets->num_values > 1 &&
+          strcasecmp(current->job_sheets->values[1].string.text, "none") != 0 &&
+          current->current_file == (current->num_files - 1))
+    banner_page = 1;
+  else
+    banner_page = 0;
+
+  LogMessage(L_DEBUG, "banner_page = %d", banner_page);
+
  /*
   * Building the options string is harder than it needs to be, but
   * for the moment we need to pass strings for command-line args and
@@ -1194,13 +1234,7 @@ StartJob(int       id,           /* I - Job ID */
       * Don't use the # copies attribute if we are printing the job sheets...
       */
 
-      if ((printer->type & CUPS_PRINTER_REMOTE) ||
-          current->job_sheets == NULL ||
-          ((strcasecmp(current->job_sheets->values[0].string.text, "none") == 0 ||
-           current->current_file != 0) &&
-           (current->job_sheets->num_values == 1 ||
-           strcasecmp(current->job_sheets->values[1].string.text, "none") == 0 ||
-           current->current_file != (current->num_files - 1))))
+      if (!banner_page)
         sprintf(copies, "%d", attr->values[0].integer);
     }
     else if (strcmp(attr->name, "job-name") == 0 &&
@@ -1237,6 +1271,10 @@ StartJob(int       id,           /* I - Job ID */
          strcmp(attr->name, "job-priority") != 0)
        continue;
 
+      if (strcmp(attr->name, "page-label") == 0 &&
+         banner_page)
+        continue;
+
      /*
       * Otherwise add them to the list...
       */
@@ -1382,7 +1420,7 @@ StartJob(int       id,            /* I - Job ID */
   snprintf(tmpdir, sizeof(tmpdir), "TMPDIR=%s", TempDir);
   snprintf(datadir, sizeof(datadir), "CUPS_DATADIR=%s", DataDir);
   snprintf(fontpath, sizeof(fontpath), "CUPS_FONTPATH=%s", FontPath);
-  if (Classification[0])
+  if (Classification[0] && !banner_page)
     snprintf(classification, sizeof(classification), "CLASSIFICATION=%s",
              Classification);
   else
@@ -1620,7 +1658,7 @@ StopJob(int id)                   /* I - Job ID */
 
         if (current->status < 0)
          SetPrinterState(current->printer, IPP_PRINTER_STOPPED);
-       else
+       else if (current->printer->state != IPP_PRINTER_STOPPED)
          SetPrinterState(current->printer, IPP_PRINTER_IDLE);
 
         LogMessage(L_DEBUG, "StopJob: printer state is %d", current->printer->state);
@@ -1696,27 +1734,22 @@ UpdateJob(job_t *job)           /* I - Job to check */
     * Figure out the logging level...
     */
 
-    if (strncmp(buffer, "ERROR:", 6) == 0)
-    {
-      loglevel = L_ERROR;
-      message  = buffer + 6;
-    }
     if (strncmp(buffer, "EMERG:", 6) == 0)
     {
       loglevel = L_EMERG;
       message  = buffer + 6;
     }
-    if (strncmp(buffer, "ALERT:", 6) == 0)
+    else if (strncmp(buffer, "ALERT:", 6) == 0)
     {
       loglevel = L_ALERT;
       message  = buffer + 6;
     }
-    if (strncmp(buffer, "CRIT:", 5) == 0)
+    else if (strncmp(buffer, "CRIT:", 5) == 0)
     {
       loglevel = L_CRIT;
       message  = buffer + 5;
     }
-    if (strncmp(buffer, "ERROR:", 6) == 0)
+    else if (strncmp(buffer, "ERROR:", 6) == 0)
     {
       loglevel = L_ERROR;
       message  = buffer + 6;
@@ -1726,7 +1759,7 @@ UpdateJob(job_t *job)             /* I - Job to check */
       loglevel = L_WARN;
       message  = buffer + 8;
     }
-    if (strncmp(buffer, "NOTICE:", 6) == 0)
+    else if (strncmp(buffer, "NOTICE:", 6) == 0)
     {
       loglevel = L_NOTICE;
       message  = buffer + 6;
@@ -2016,5 +2049,5 @@ start_process(const char *command,        /* I - Full path to command */
 
 
 /*
- * End of "$Id: job.c,v 1.124.2.1 2001/04/02 19:51:49 mike Exp $".
+ * End of "$Id: job.c,v 1.124.2.2 2001/05/13 18:38:36 mike Exp $".
  */
index 508ef6777902f9150dfdab658437f127443b86b0..494a4b780532e7029bde98705d75aa674c572462 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: main.c,v 1.57 2001/03/14 22:02:18 mike Exp $"
+ * "$Id: main.c,v 1.57.2.1 2001/05/13 18:38:37 mike Exp $"
  *
  *   Scheduler main loop for the Common UNIX Printing System (CUPS).
  *
@@ -335,7 +335,7 @@ main(int  argc,                     /* I - Number of command-line arguments */
       * Log all sorts of debug info to help track down the problem.
       */
 
-      LogMessage(L_ERROR, "select() failed - %s!", strerror(errno));
+      LogMessage(L_EMERG, "select() failed - %s!", strerror(errno));
 
       strcpy(s, "InputSet =");
       slen = 9;
@@ -345,7 +345,7 @@ main(int  argc,                     /* I - Number of command-line arguments */
         if (FD_ISSET(i, &InputSet))
           snprintf(sptr, sizeof(s) - slen, " %d", i);
 
-      LogMessage(L_ERROR, s);
+      LogMessage(L_EMERG, s);
 
       strcpy(s, "OutputSet =");
       slen = 10;
@@ -355,19 +355,19 @@ main(int  argc,                   /* I - Number of command-line arguments */
         if (FD_ISSET(i, &OutputSet))
           snprintf(sptr, sizeof(s) - slen, " %d", i);
 
-      LogMessage(L_ERROR, s);
+      LogMessage(L_EMERG, s);
 
       for (i = 0, con = Clients; i < NumClients; i ++, con ++)
-        LogMessage(L_ERROR, "Clients[%d] = %d, file = %d, state = %d",
+        LogMessage(L_EMERG, "Clients[%d] = %d, file = %d, state = %d",
                   i, con->http.fd, con->file, con->http.state);
 
       for (i = 0, lis = Listeners; i < NumListeners; i ++, lis ++)
-        LogMessage(L_ERROR, "Listeners[%d] = %d", i, lis->fd);
+        LogMessage(L_EMERG, "Listeners[%d] = %d", i, lis->fd);
 
-      LogMessage(L_ERROR, "BrowseSocket = %d", BrowseSocket);
+      LogMessage(L_EMERG, "BrowseSocket = %d", BrowseSocket);
 
       for (job = Jobs; job != NULL; job = job->next)
-        LogMessage(L_ERROR, "Jobs[%d] = %d", job->id, job->pipe);
+        LogMessage(L_EMERG, "Jobs[%d] = %d", job->id, job->pipe);
 
       break;
     }
@@ -423,7 +423,20 @@ main(int  argc,                    /* I - Number of command-line arguments */
       next = job->next;
 
       if (job->pipe && FD_ISSET(job->pipe, &input))
+      {
+       /*
+        * Clear the input bit to avoid updating the next job
+       * using the same status pipe file descriptor...
+       */
+
+        FD_CLR(job->pipe, &input);
+
+       /*
+        * Read any status messages from the filters...
+       */
+
         UpdateJob(job);
+      }
     }
 
    /*
@@ -727,5 +740,5 @@ usage(void)
 
 
 /*
- * End of "$Id: main.c,v 1.57 2001/03/14 22:02:18 mike Exp $".
+ * End of "$Id: main.c,v 1.57.2.1 2001/05/13 18:38:37 mike Exp $".
  */
index 32310c08e8a7f710dadb141678c73a862bc2b8f2..578d5b610243a38fabd9cd4459d66087a9419f97 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: ppds.c,v 1.14 2001/01/22 15:04:01 mike Exp $"
+ * "$Id: ppds.c,v 1.14.2.1 2001/05/13 18:38:38 mike Exp $"
  *
  *   PPD scanning routines for the Common UNIX Printing System (CUPS).
  *
@@ -568,8 +568,6 @@ load_ppds(const char *d,            /* I - Actual directory */
        *ptr = '\0';
       else if (strncasecmp(manufacturer, "agfa", 4) == 0)
        strcpy(manufacturer, "AGFA");
-      else if (strncasecmp(manufacturer, "ps-ipu", 6) == 0)
-       strcpy(manufacturer, "Canon");
       else if (strncasecmp(manufacturer, "herk", 4) == 0)
        strcpy(manufacturer, "Linotype");
       else
@@ -589,8 +587,13 @@ load_ppds(const char *d,           /* I - Actual directory */
        strcpy(manufacturer, "Seiko");
       else if (strcasecmp(manufacturer, "fiery") == 0)
        strcpy(manufacturer, "EFI");
+      else if (strcasecmp(manufacturer, "ps") == 0 ||
+               strcasecmp(manufacturer, "colorpass") == 0)
+       strcpy(manufacturer, "Canon");
       else if (strncasecmp(manufacturer, "primera", 7) == 0)
        strcpy(manufacturer, "Fargo");
+      else if (strcasecmp(manufacturer, "designjet") == 0)
+       strcpy(manufacturer, "HP");
     }
 
    /*
@@ -658,5 +661,5 @@ load_ppds(const char *d,            /* I - Actual directory */
 
 
 /*
- * End of "$Id: ppds.c,v 1.14 2001/01/22 15:04:01 mike Exp $".
+ * End of "$Id: ppds.c,v 1.14.2.1 2001/05/13 18:38:38 mike Exp $".
  */
index 1e0a3850c21374f353be41990c24183b4211159d..f2b34a6cffd12dcf1e5db2ede7a9884b85d4c459 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: printers.c,v 1.93.2.2 2001/04/11 00:24:14 mike Exp $"
+ * "$Id: printers.c,v 1.93.2.3 2001/05/13 18:38:38 mike Exp $"
  *
  *   Printer routines for the Common UNIX Printing System (CUPS).
  *
@@ -852,6 +852,8 @@ SetPrinterAttrs(printer_t *p)               /* I - Printer to setup */
                  IPP_RESUME_PRINTER,
                  IPP_PURGE_JOBS,
                  IPP_SET_JOB_ATTRIBUTES,
+                 IPP_ENABLE_PRINTER,
+                 IPP_DISABLE_PRINTER,
                  CUPS_GET_DEFAULT,
                  CUPS_GET_PRINTERS,
                  CUPS_ADD_PRINTER,
@@ -1540,9 +1542,13 @@ SortPrinters(void)
        next          = current->next;
        current->next = next->next;
        next->next    = current;
+       prev          = next;
       }
       else
+      {
+        prev    = current;
        current = current->next;
+      }
   }
   while (did_swap);
 }
@@ -1787,5 +1793,5 @@ write_printcap(void)
 
 
 /*
- * End of "$Id: printers.c,v 1.93.2.2 2001/04/11 00:24:14 mike Exp $".
+ * End of "$Id: printers.c,v 1.93.2.3 2001/05/13 18:38:38 mike Exp $".
  */
index e2515e5df455c1dfa0a1e18ceb633049d8b1c48c..272098c15ca98fe6bfb675b122352a452e205dbf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: accept.c,v 1.11 2001/01/23 17:36:22 mike Exp $"
+ * "$Id: accept.c,v 1.11.2.1 2001/05/13 18:38:40 mike Exp $"
  *
  *   "accept", "disable", "enable", and "reject" commands for the Common
  *   UNIX Printing System (CUPS).
@@ -123,7 +123,7 @@ main(int  argc,                     /* I - Number of command-line arguments */
              httpClose(http);
 
            if (argv[i][2] != '\0')
-             http = httpConnect(argv[i] + 2, ippPort());
+             http = httpConnectEncrypt(argv[i] + 2, ippPort(), encryption);
            else
            {
              i ++;
@@ -134,7 +134,7 @@ main(int  argc,                     /* I - Number of command-line arguments */
                return (1);
              }
 
-             http = httpConnect(argv[i], ippPort());
+             http = httpConnectEncrypt(argv[i], ippPort(), encryption);
            }
 
            if (http == NULL)
@@ -182,7 +182,7 @@ main(int  argc,                     /* I - Number of command-line arguments */
       }
 
       if (http == NULL)
-        http = httpConnect(hostname, ippPort());
+        http = httpConnectEncrypt(hostname, ippPort(), encryption);
 
       if (http == NULL)
       {
@@ -226,8 +226,6 @@ main(int  argc,                     /* I - Number of command-line arguments */
       * Do the request and get back a response...
       */
 
-      httpEncryption(http, encryption);
-
       if ((response = cupsDoRequest(http, request, "/admin/")) != NULL)
       {
         if (response->request.status.status_code > IPP_OK_CONFLICT)
@@ -306,5 +304,5 @@ main(int  argc,                     /* I - Number of command-line arguments */
 
 
 /*
- * End of "$Id: accept.c,v 1.11 2001/01/23 17:36:22 mike Exp $".
+ * End of "$Id: accept.c,v 1.11.2.1 2001/05/13 18:38:40 mike Exp $".
  */
index c8eda40ba336f8744d695e949f231e09dda53000..72a4702986d682bab493141df39c02c60d19f2ba 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: cancel.c,v 1.19 2001/03/02 17:35:04 mike Exp $"
+ * "$Id: cancel.c,v 1.19.2.1 2001/05/13 18:38:40 mike Exp $"
  *
  *   "cancel" command for the Common UNIX Printing System (CUPS).
  *
@@ -101,7 +101,7 @@ main(int  argc,                     /* I - Number of command-line arguments */
              httpClose(http);
 
            if (argv[i][2] != '\0')
-             http = httpConnect(argv[i] + 2, ippPort());
+             http = httpConnectEncrypt(argv[i] + 2, ippPort(), encryption);
            else
            {
              i ++;
@@ -112,7 +112,7 @@ main(int  argc,                     /* I - Number of command-line arguments */
                return (1);
               }
              else
-               http = httpConnect(argv[i], ippPort());
+               http = httpConnectEncrypt(argv[i], ippPort(), encryption);
            }
 
            if (http == NULL)
@@ -189,7 +189,7 @@ main(int  argc,                     /* I - Number of command-line arguments */
 
          *host++ = '\0';
 
-         if ((http = httpConnect(host, ippPort())) == NULL)
+         if ((http = httpConnectEncrypt(host, ippPort(), encryption)) == NULL)
          {
            perror("cancel: Unable to connect to server");
            return (1);
@@ -202,7 +202,8 @@ main(int  argc,                     /* I - Number of command-line arguments */
       */
 
       if (http == NULL)
-       if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+       if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
+                                      encryption)) == NULL)
        {
          fputs("cancel: Unable to contact server!\n", stderr);
          return (1);
@@ -253,8 +254,6 @@ main(int  argc,                     /* I - Number of command-line arguments */
       * Do the request and get back a response...
       */
 
-      httpEncryption(http, encryption);
-
       if (op == IPP_PURGE_JOBS)
         response = cupsDoRequest(http, request, "/admin/");
       else
@@ -282,5 +281,5 @@ main(int  argc,                     /* I - Number of command-line arguments */
 
 
 /*
- * End of "$Id: cancel.c,v 1.19 2001/03/02 17:35:04 mike Exp $".
+ * End of "$Id: cancel.c,v 1.19.2.1 2001/05/13 18:38:40 mike Exp $".
  */
index dc185a67ba01e74fa564fd7f7c0188cc3ae2ae99..902c0c1254b5139a8304fe5bec8feb73cc4e99bf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: lp.c,v 1.29 2001/03/09 14:26:54 mike Exp $"
+ * "$Id: lp.c,v 1.29.2.1 2001/05/13 18:38:40 mike Exp $"
  *
  *   "lp" command for the Common UNIX Printing System (CUPS).
  *
@@ -579,7 +579,7 @@ set_job_attrs(int           job_id, /* I - Job ID */
   char         uri[HTTP_MAX_URI];      /* URI for job */
 
 
-  http = httpConnect(cupsServer(), ippPort());
+  http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
 
   language = cupsLangDefault();
 
@@ -650,5 +650,5 @@ sighandler(int s)   /* I - Signal number */
 
 
 /*
- * End of "$Id: lp.c,v 1.29 2001/03/09 14:26:54 mike Exp $".
+ * End of "$Id: lp.c,v 1.29.2.1 2001/05/13 18:38:40 mike Exp $".
  */
index 5ccb24a81f2a4fac9a6a38bc5e30ef40994d1b08..11ae41aed592822960b4d79dc846557fa6d6b8ea 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: lpadmin.c,v 1.22 2001/02/07 00:33:55 mike Exp $"
+ * "$Id: lpadmin.c,v 1.22.2.1 2001/05/13 18:38:41 mike Exp $"
  *
  *   "lpadmin" command for the Common UNIX Printing System (CUPS).
  *
@@ -109,15 +109,13 @@ main(int  argc,                   /* I - Number of command-line arguments */
         case 'c' : /* Add printer to class */
            if (!http)
            {
-              http = httpConnect(cupsServer(), ippPort());
+              http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
 
              if (http == NULL)
              {
                perror("lpadmin: Unable to connect to server");
                return (1);
              }
-
-              httpEncryption(http, encryption);
             }
 
            if (printer == NULL)
@@ -154,15 +152,13 @@ main(int  argc,                   /* I - Number of command-line arguments */
         case 'd' : /* Set as default destination */
            if (!http)
            {
-              http = httpConnect(cupsServer(), ippPort());
+              http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
 
              if (http == NULL)
              {
                perror("lpadmin: Unable to connect to server");
                return (1);
              }
-
-              httpEncryption(http, encryption);
             }
 
            if (argv[i][2])
@@ -195,7 +191,7 @@ main(int  argc,                     /* I - Number of command-line arguments */
              httpClose(http);
 
            if (argv[i][2] != '\0')
-             http = httpConnect(argv[i] + 2, ippPort());
+             http = httpConnectEncrypt(argv[i] + 2, ippPort(), encryption);
            else
            {
              i ++;
@@ -206,7 +202,7 @@ main(int  argc,                     /* I - Number of command-line arguments */
                return (1);
               }
              else
-               http = httpConnect(argv[i], ippPort());
+               http = httpConnectEncrypt(argv[i], ippPort(), encryption);
            }
 
            if (http == NULL)
@@ -215,24 +211,19 @@ main(int  argc,                   /* I - Number of command-line arguments */
              return (1);
            }
            else
-           {
-              httpEncryption(http, encryption);
              cupsSetServer(http->hostname);
-           }
            break;
 
         case 'i' : /* Use the specified interface script */
            if (!http)
            {
-              http = httpConnect(cupsServer(), ippPort());
+              http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
 
              if (http == NULL)
              {
                perror("lpadmin: Unable to connect to server");
                return (1);
              }
-
-              httpEncryption(http, encryption);
             }
 
            if (printer == NULL)
@@ -275,15 +266,13 @@ main(int  argc,                   /* I - Number of command-line arguments */
 
            if (!http)
            {
-              http = httpConnect(cupsServer(), ippPort());
+              http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
 
              if (http == NULL)
              {
                perror("lpadmin: Unable to connect to server");
                return (1);
              }
-
-              httpEncryption(http, encryption);
             }
 
             enable_printer(http, printer);
@@ -292,15 +281,13 @@ main(int  argc,                   /* I - Number of command-line arguments */
         case 'm' : /* Use the specified standard script/PPD file */
            if (!http)
            {
-              http = httpConnect(cupsServer(), ippPort());
+              http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
 
              if (http == NULL)
              {
                perror("lpadmin: Unable to connect to server");
                return (1);
              }
-
-              httpEncryption(http, encryption);
             }
 
            if (printer == NULL)
@@ -350,15 +337,13 @@ main(int  argc,                   /* I - Number of command-line arguments */
         case 'p' : /* Add/modify a printer */
            if (!http)
            {
-              http = httpConnect(cupsServer(), ippPort());
+              http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
 
              if (http == NULL)
              {
                perror("lpadmin: Unable to connect to server");
                return (1);
              }
-
-              httpEncryption(http, encryption);
             }
 
            if (argv[i][2])
@@ -391,28 +376,24 @@ main(int  argc,                   /* I - Number of command-line arguments */
              httpClose(http);
 
               *host++ = '\0';
-              if ((http = httpConnect(host, ippPort())) == NULL)
+              if ((http = httpConnectEncrypt(host, ippPort(), encryption)) == NULL)
              {
                perror("lpadmin: Unable to connect to server");
                return (1);
              }
-
-              httpEncryption(http, encryption);
            }
            break;
 
         case 'r' : /* Remove printer from class */
            if (!http)
            {
-              http = httpConnect(cupsServer(), ippPort());
+              http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
 
              if (http == NULL)
              {
                perror("lpadmin: Unable to connect to server");
                return (1);
              }
-
-              httpEncryption(http, encryption);
             }
 
            if (printer == NULL)
@@ -479,15 +460,13 @@ main(int  argc,                   /* I - Number of command-line arguments */
         case 'v' : /* Set the device-uri attribute */
            if (!http)
            {
-              http = httpConnect(cupsServer(), ippPort());
+              http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
 
              if (http == NULL)
              {
                perror("lpadmin: Unable to connect to server");
                return (1);
              }
-
-              httpEncryption(http, encryption);
             }
 
            if (printer == NULL)
@@ -516,15 +495,13 @@ main(int  argc,                   /* I - Number of command-line arguments */
         case 'x' : /* Delete a printer */
            if (!http)
            {
-              http = httpConnect(cupsServer(), ippPort());
+              http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
 
              if (http == NULL)
              {
                perror("lpadmin: Unable to connect to server");
                return (1);
              }
-
-              httpEncryption(http, encryption);
             }
 
            if (argv[i][2])
@@ -557,7 +534,7 @@ main(int  argc,                     /* I - Number of command-line arguments */
              httpClose(http);
 
               *host++ = '\0';
-              if ((http = httpConnect(host, ippPort())) == NULL)
+              if ((http = httpConnectEncrypt(host, ippPort(), encryption)) == NULL)
              {
                perror("lpadmin: Unable to connect to server");
                return (1);
@@ -571,15 +548,13 @@ main(int  argc,                   /* I - Number of command-line arguments */
         case 'D' : /* Set the printer-info attribute */
            if (!http)
            {
-              http = httpConnect(cupsServer(), ippPort());
+              http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
 
              if (http == NULL)
              {
                perror("lpadmin: Unable to connect to server");
                return (1);
              }
-
-              httpEncryption(http, encryption);
             }
 
            if (printer == NULL)
@@ -608,15 +583,13 @@ main(int  argc,                   /* I - Number of command-line arguments */
         case 'L' : /* Set the printer-location attribute */
            if (!http)
            {
-              http = httpConnect(cupsServer(), ippPort());
+              http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
 
              if (http == NULL)
              {
                perror("lpadmin: Unable to connect to server");
                return (1);
              }
-
-              httpEncryption(http, encryption);
             }
 
            if (printer == NULL)
@@ -645,15 +618,13 @@ main(int  argc,                   /* I - Number of command-line arguments */
         case 'P' : /* Use the specified PPD file */
            if (!http)
            {
-              http = httpConnect(cupsServer(), ippPort());
+              http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
 
              if (http == NULL)
              {
                perror("lpadmin: Unable to connect to server");
                return (1);
              }
-
-              httpEncryption(http, encryption);
             }
 
            if (printer == NULL)
@@ -697,15 +668,13 @@ main(int  argc,                   /* I - Number of command-line arguments */
   {
     if (!http)
     {
-      http = httpConnect(cupsServer(), ippPort());
+      http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
 
       if (http == NULL)
       {
        perror("lpadmin: Unable to connect to server");
        return (1);
       }
-
-      httpEncryption(http, encryption);
     }
 
     if (printer == NULL)
@@ -1801,5 +1770,5 @@ validate_name(const char *name)   /* I - Name to check */
 
 
 /*
- * End of "$Id: lpadmin.c,v 1.22 2001/02/07 00:33:55 mike Exp $".
+ * End of "$Id: lpadmin.c,v 1.22.2.1 2001/05/13 18:38:41 mike Exp $".
  */
index c8cbc92cc1e7a5b02205f5c95984a6adbcc6604c..c2e88bf6d3570142c22cdbad9d424fdb0e894481 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: lpinfo.c,v 1.3 2001/01/23 17:36:23 mike Exp $"
+ * "$Id: lpinfo.c,v 1.3.2.1 2001/05/13 18:38:41 mike Exp $"
  *
  *   "lpinfo" command for the Common UNIX Printing System (CUPS).
  *
@@ -90,15 +90,13 @@ main(int  argc,                     /* I - Number of command-line arguments */
         case 'm' : /* Show models */
            if (!http)
            {
-              http = httpConnect(cupsServer(), ippPort());
+              http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
 
              if (http == NULL)
              {
                perror("lpinfo: Unable to connect to server");
                return (1);
              }
-
-             httpEncryption(http, encryption);
             }
 
             show_models(http, long_status);
@@ -107,15 +105,13 @@ main(int  argc,                   /* I - Number of command-line arguments */
         case 'v' : /* Show available devices */
            if (!http)
            {
-              http = httpConnect(cupsServer(), ippPort());
+              http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
 
              if (http == NULL)
              {
                perror("lpinfo: Unable to connect to server");
                return (1);
              }
-
-             httpEncryption(http, encryption);
             }
 
             show_devices(http, long_status);
@@ -126,7 +122,7 @@ main(int  argc,                     /* I - Number of command-line arguments */
              httpClose(http);
 
            if (argv[i][2] != '\0')
-             http = httpConnect(argv[i] + 2, ippPort());
+             http = httpConnectEncrypt(argv[i] + 2, ippPort(), encryption);
            else
            {
              i ++;
@@ -137,7 +133,7 @@ main(int  argc,                     /* I - Number of command-line arguments */
                return (1);
               }
 
-             http = httpConnect(argv[i], ippPort());
+             http = httpConnectEncrypt(argv[i], ippPort(), encryption);
            }
 
            if (http == NULL)
@@ -145,8 +141,6 @@ main(int  argc,                     /* I - Number of command-line arguments */
              perror("lpinfo: Unable to connect to server");
              return (1);
            }
-
-           httpEncryption(http, encryption);
            break;
 
        default :
@@ -446,5 +440,5 @@ show_models(http_t *http,   /* I - HTTP connection to server */
 
 
 /*
- * End of "$Id: lpinfo.c,v 1.3 2001/01/23 17:36:23 mike Exp $".
+ * End of "$Id: lpinfo.c,v 1.3.2.1 2001/05/13 18:38:41 mike Exp $".
  */
index 8294f60a5f9fea3623c730e747cf30077256be74..f9edabd77d9fb4b29d9277f1b5904ec38e3eb47d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: lpmove.c,v 1.5 2001/01/23 17:36:24 mike Exp $"
+ * "$Id: lpmove.c,v 1.5.2.1 2001/05/13 18:38:41 mike Exp $"
  *
  *   "lpmove" command for the Common UNIX Printing System (CUPS).
  *
@@ -88,7 +88,7 @@ main(int  argc,                       /* I - Number of command-line arguments */
              httpClose(http);
 
            if (argv[i][2] != '\0')
-             http = httpConnect(argv[i] + 2, ippPort());
+             http = httpConnectEncrypt(argv[i] + 2, ippPort(), encryption);
            else
            {
              i ++;
@@ -99,7 +99,7 @@ main(int  argc,                       /* I - Number of command-line arguments */
                return (1);
               }
 
-             http = httpConnect(argv[i], ippPort());
+             http = httpConnectEncrypt(argv[i], ippPort(), encryption);
            }
 
            if (http == NULL)
@@ -107,8 +107,6 @@ main(int  argc,                     /* I - Number of command-line arguments */
              perror("lpmove: Unable to connect to server");
              return (1);
            }
-
-           httpEncryption(http, encryption);
            break;
 
        default :
@@ -138,15 +136,13 @@ main(int  argc,                   /* I - Number of command-line arguments */
 
   if (!http)
   {
-    http = httpConnect(cupsServer(), ippPort());
+    http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
 
     if (http == NULL)
     {
       perror("lpmove: Unable to connect to server");
       return (1);
     }
-
-    httpEncryption(http, encryption);
   }
 
   move_job(http, atoi(job), dest);
@@ -232,5 +228,5 @@ move_job(http_t     *http,  /* I - HTTP connection to server */
 
 
 /*
- * End of "$Id: lpmove.c,v 1.5 2001/01/23 17:36:24 mike Exp $".
+ * End of "$Id: lpmove.c,v 1.5.2.1 2001/05/13 18:38:41 mike Exp $".
  */
index 05605159622391ba1eda50b0919bda44cd78d45a..68680ec1cda8c5a158745d6e3ff7e9873ae9c04e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: lpstat.c,v 1.37 2001/01/26 15:29:59 mike Exp $"
+ * "$Id: lpstat.c,v 1.37.2.1 2001/05/13 18:38:41 mike Exp $"
  *
  *   "lpstat" command for the Common UNIX Printing System (CUPS).
  *
@@ -69,7 +69,6 @@ main(int  argc,                       /* I - Number of command-line arguments */
 {
   int          i;              /* Looping var */
   http_t       *http;          /* Connection to server */
-  char         server[1024];   /* CUPS_SERVER environment variable */
   int          num_dests;      /* Number of user destinations */
   cups_dest_t  *dests;         /* User destinations */
   int          long_status;    /* Long status report? */
@@ -119,15 +118,13 @@ main(int  argc,                   /* I - Number of command-line arguments */
         case 'a' : /* Show acceptance status */
            if (!http)
            {
-              http = httpConnect(cupsServer(), ippPort());
+              http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
 
              if (http == NULL)
              {
                perror("lpstat: Unable to connect to server");
                return (1);
              }
-
-             httpEncryption(http, encryption);
             }
 
             if (num_dests == 0)
@@ -147,15 +144,13 @@ main(int  argc,                   /* I - Number of command-line arguments */
         case 'c' : /* Show classes and members */
            if (!http)
            {
-              http = httpConnect(cupsServer(), ippPort());
+              http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
 
              if (http == NULL)
              {
                perror("lpstat: Unable to connect to server");
                return (1);
              }
-
-             httpEncryption(http, encryption);
             }
 
            if (argv[i][2] != '\0')
@@ -187,8 +182,8 @@ main(int  argc,                     /* I - Number of command-line arguments */
 
            if (argv[i][2] != '\0')
            {
-             http = httpConnect(argv[i] + 2, ippPort());
-             snprintf(server, sizeof(server), "CUPS_SERVER=%s", argv[i] + 2);
+             http = httpConnectEncrypt(argv[i] + 2, ippPort(), encryption);
+             cupsSetServer(argv[i] + 2);
            }
            else
            {
@@ -200,18 +195,15 @@ main(int  argc,                   /* I - Number of command-line arguments */
                return (1);
               }
 
-             http = httpConnect(argv[i], ippPort());
-             snprintf(server, sizeof(server), "CUPS_SERVER=%s", argv[i] + 2);
+             http = httpConnectEncrypt(argv[i], ippPort(), encryption);
+             cupsSetServer(argv[i]);
            }
 
-            putenv(server);
            if (http == NULL)
            {
              perror("lpstat: Unable to connect to server");
              return (1);
            }
-
-           httpEncryption(http, encryption);
            break;
 
         case 'l' : /* Long status */
@@ -221,15 +213,13 @@ main(int  argc,                   /* I - Number of command-line arguments */
         case 'o' : /* Show jobs by destination */
            if (!http)
            {
-              http = httpConnect(cupsServer(), ippPort());
+              http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
 
              if (http == NULL)
              {
                perror("lpstat: Unable to connect to server");
                return (1);
              }
-
-             httpEncryption(http, encryption);
             }
 
            if (argv[i][2] != '\0')
@@ -246,15 +236,13 @@ main(int  argc,                   /* I - Number of command-line arguments */
         case 'p' : /* Show printers */
            if (!http)
            {
-              http = httpConnect(cupsServer(), ippPort());
+              http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
 
              if (http == NULL)
              {
                perror("lpstat: Unable to connect to server");
                return (1);
              }
-
-             httpEncryption(http, encryption);
             }
 
             if (num_dests == 0)
@@ -274,15 +262,13 @@ main(int  argc,                   /* I - Number of command-line arguments */
         case 'r' : /* Show scheduler status */
            if (!http)
            {
-              http = httpConnect(cupsServer(), ippPort());
+              http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
 
              if (http == NULL)
              {
                perror("lpstat: Unable to connect to server");
                return (1);
              }
-
-             httpEncryption(http, encryption);
             }
 
            show_scheduler(http);
@@ -291,15 +277,13 @@ main(int  argc,                   /* I - Number of command-line arguments */
         case 's' : /* Show summary */
            if (!http)
            {
-              http = httpConnect(cupsServer(), ippPort());
+              http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
 
              if (http == NULL)
              {
                perror("lpstat: Unable to connect to server");
                return (1);
              }
-
-             httpEncryption(http, encryption);
             }
 
             if (num_dests == 0)
@@ -313,15 +297,13 @@ main(int  argc,                   /* I - Number of command-line arguments */
         case 't' : /* Show all info */
            if (!http)
            {
-              http = httpConnect(cupsServer(), ippPort());
+              http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
 
              if (http == NULL)
              {
                perror("lpstat: Unable to connect to server");
                return (1);
              }
-
-             httpEncryption(http, encryption);
             }
 
             if (num_dests == 0)
@@ -339,15 +321,13 @@ main(int  argc,                   /* I - Number of command-line arguments */
         case 'u' : /* Show jobs by user */
            if (!http)
            {
-              http = httpConnect(cupsServer(), ippPort());
+              http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
 
              if (http == NULL)
              {
                perror("lpstat: Unable to connect to server");
                return (1);
              }
-
-             httpEncryption(http, encryption);
             }
 
            if (argv[i][2] != '\0')
@@ -364,15 +344,13 @@ main(int  argc,                   /* I - Number of command-line arguments */
         case 'v' : /* Show printer devices */
            if (!http)
            {
-              http = httpConnect(cupsServer(), ippPort());
+              http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
 
              if (http == NULL)
              {
                perror("lpstat: Unable to connect to server");
                return (1);
              }
-
-             httpEncryption(http, encryption);
             }
 
             if (num_dests == 0)
@@ -398,15 +376,13 @@ main(int  argc,                   /* I - Number of command-line arguments */
     {
       if (!http)
       {
-       http = httpConnect(cupsServer(), ippPort());
+       http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
 
        if (http == NULL)
        {
          perror("lpstat: Unable to connect to server");
          return (1);
        }
-
-       httpEncryption(http, encryption);
       }
 
       show_jobs(http, argv[i], NULL, long_status, ranking);
@@ -416,15 +392,13 @@ main(int  argc,                   /* I - Number of command-line arguments */
   {
     if (!http)
     {
-      http = httpConnect(cupsServer(), ippPort());
+      http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
 
       if (http == NULL)
       {
        perror("lpstat: Unable to connect to server");
        return (1);
       }
-
-      httpEncryption(http, encryption);
     }
 
     show_jobs(http, NULL, cupsUser(), long_status, ranking);
@@ -791,7 +765,7 @@ show_classes(http_t     *http,      /* I - HTTP connection to server */
       {
         httpSeparate(printer_uri, method, username, server, &port, resource);
 
-        if ((http2 = httpConnect(server, port)) != NULL)
+        if ((http2 = httpConnectEncrypt(server, port, cupsEncryption())) != NULL)
        {
         /*
          * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the
@@ -1871,5 +1845,5 @@ show_scheduler(http_t *http)      /* I - HTTP connection to server */
 
 
 /*
- * End of "$Id: lpstat.c,v 1.37 2001/01/26 15:29:59 mike Exp $".
+ * End of "$Id: lpstat.c,v 1.37.2.1 2001/05/13 18:38:41 mike Exp $".
  */
index 1cf02c2da8c0638b6e9189b0d8b8913f2b08fb82..35b241b06bbe2eac8c79bd0ca900b461734a237e 100644 (file)
        ATTR uri job-uri $uri
 
        # What statuses are OK?
-       STATUS ok
-       STATUS ok-subst
+       #STATUS ok
+       #STATUS ok-subst
 
        # What attributes do we expect?
        EXPECT job-uri
        EXPECT job-state
+       EXPECT bogus-attribute
 }