]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - filter/rastertolabel.c
Remove all of the Subversion keywords from various source files.
[thirdparty/cups.git] / filter / rastertolabel.c
index d5f4031825c9285a3b07a38868f9c31d749dcb08..a082831a318c85c61d983d52b8dda2781ffb94a9 100644 (file)
@@ -1,37 +1,16 @@
 /*
- * "$Id: rastertolabel.c 5665 2006-06-16 00:59:10Z mike $"
+ * Label printer filter for CUPS.
  *
- *   Label printer filter for the Common UNIX Printing System (CUPS).
+ * Copyright 2007-2015 by Apple Inc.
+ * Copyright 2001-2007 by Easy Software Products.
  *
- *   Copyright 2001-2006 by Easy Software Products.
+ * These coded instructions, statements, and computer programs are the
+ * property of Apple Inc. and are protected by Federal copyright
+ * law.  Distribution and use rights are outlined in the file "LICENSE.txt"
+ * which should have been included with this file.  If this file is
+ * file is missing or damaged, see the license at "http://www.cups.org/".
  *
- *   These coded instructions, statements, and computer programs are the
- *   property of Easy Software Products and are protected by Federal
- *   copyright law.  Distribution and use rights are outlined in the file
- *   "LICENSE.txt" which should have been included with this file.  If this
- *   file is missing or damaged please contact Easy Software Products
- *   at:
- *
- *       Attn: CUPS Licensing Information
- *       Easy Software Products
- *       44141 Airport View Drive, Suite 204
- *       Hollywood, Maryland 20636 USA
- *
- *       Voice: (301) 373-9600
- *       EMail: cups-info@cups.org
- *         WWW: http://www.cups.org
- *
- *   This file is subject to the Apple OS-Developed Software exception.
- *
- * Contents:
- *
- *   Setup()        - Prepare the printer for printing.
- *   StartPage()    - Start a page of graphics.
- *   EndPage()      - Finish a page of graphics.
- *   CancelJob()    - Cancel the current job...
- *   OutputLine()   - Output a line of graphics.
- *   ZPLCompress()  - Output a run-length compression sequence.
- *   main()         - Main entry and processing of driver.
+ * This file is subject to the Apple OS-Developed Software exception.
  */
 
 /*
  */
 
 #include <cups/cups.h>
-#include <cups/string.h>
-#include "raster.h"
-#include <stdlib.h>
+#include <cups/ppd.h>
+#include <cups/string-private.h>
+#include <cups/language-private.h>
+#include <cups/raster.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <signal.h>
 
 
 /*
- * This driver filter currently supports Dymo and Zebra label printers.
+ * This driver filter currently supports Dymo, Intellitech, and Zebra
+ * label printers.
  *
  * The Dymo portion of the driver has been tested with the 300, 330,
- * and 330 Turbo label printers; it may also work with older models.
+ * and 330 Turbo label printers; it may also work with other models.
  * The Dymo printers support printing at 136, 203, and 300 DPI.
  *
- * The Zebra portion of the driver has been tested with the LP-2844Z label
- * printer; it may also work with other models.  The driver supports EPL
- * line mode, EPL page mode, ZPL, and CPCL as defined in Zebra's on-line
- * developer documentation.
+ * The Intellitech portion of the driver has been tested with the
+ * Intellibar 408, 412, and 808 and supports their PCL variant.
+ *
+ * The Zebra portion of the driver has been tested with the LP-2844,
+ * LP-2844Z, QL-320, and QL-420 label printers; it may also work with
+ * other models.  The driver supports EPL line mode, EPL page mode,
+ * ZPL, and CPCL as defined in Zebra's online developer documentation.
  */
 
 /*
 #define ZEBRA_ZPL      0x12            /* Zebra ZPL-based printers */
 #define ZEBRA_CPCL     0x13            /* Zebra CPCL-based printers */
 
+#define INTELLITECH_PCL        0x20            /* Intellitech PCL-based printers */
+
 
 /*
  * Globals...
  */
 
 unsigned char  *Buffer;                /* Output buffer */
-char           *CompBuffer;            /* Compression buffer */
+unsigned char  *CompBuffer;            /* Compression buffer */
 unsigned char  *LastBuffer;            /* Last buffer */
+unsigned       Feed;                   /* Number of lines to skip */
 int            LastSet;                /* Number of repeat characters */
 int            ModelNumber,            /* cupsModelNumber attribute */
                Page,                   /* Current page */
-               Feed,                   /* Number of lines to skip */
                Canceled;               /* Non-zero if job is canceled */
 
 
@@ -91,11 +77,12 @@ int         ModelNumber,            /* cupsModelNumber attribute */
  */
 
 void   Setup(ppd_file_t *ppd);
-void   StartPage(ppd_file_t *ppd, cups_page_header_t *header);
-void   EndPage(ppd_file_t *ppd, cups_page_header_t *header);
+void   StartPage(ppd_file_t *ppd, cups_page_header2_t *header);
+void   EndPage(ppd_file_t *ppd, cups_page_header2_t *header);
 void   CancelJob(int sig);
-void   OutputLine(ppd_file_t *ppd, cups_page_header_t *header, int y);
-void   ZPLCompress(char repeat_char, int repeat_count);
+void   OutputLine(ppd_file_t *ppd, cups_page_header2_t *header, unsigned y);
+void   PCLCompress(unsigned char *line, unsigned length);
+void   ZPLCompress(unsigned char repeat_char, unsigned repeat_count);
 
 
 /*
@@ -147,6 +134,15 @@ Setup(ppd_file_t *ppd)                     /* I - PPD file */
 
     case ZEBRA_CPCL :
         break;
+
+    case INTELLITECH_PCL :
+       /*
+       * Send a PCL reset sequence.
+       */
+
+       putchar(0x1b);
+       putchar('E');
+        break;
   }
 }
 
@@ -157,13 +153,10 @@ Setup(ppd_file_t *ppd)                    /* I - PPD file */
 
 void
 StartPage(ppd_file_t         *ppd,     /* I - PPD file */
-          cups_page_header_t *header)  /* I - Page header */
+          cups_page_header2_t *header) /* I - Page header */
 {
   ppd_choice_t *choice;                /* Marked choice */
-  int          length;                 /* Actual label length */
-#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
-  struct sigaction action;             /* Actions for POSIX signals */
-#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+  unsigned     length;                 /* Actual label length */
 
 
  /*
@@ -171,39 +164,15 @@ StartPage(ppd_file_t         *ppd,        /* I - PPD file */
   */
 
   fprintf(stderr, "DEBUG: StartPage...\n");
-  fprintf(stderr, "DEBUG: MediaClass = \"%s\"\n", header->MediaClass);
-  fprintf(stderr, "DEBUG: MediaColor = \"%s\"\n", header->MediaColor);
-  fprintf(stderr, "DEBUG: MediaType = \"%s\"\n", header->MediaType);
-  fprintf(stderr, "DEBUG: OutputType = \"%s\"\n", header->OutputType);
-
-  fprintf(stderr, "DEBUG: AdvanceDistance = %d\n", header->AdvanceDistance);
-  fprintf(stderr, "DEBUG: AdvanceMedia = %d\n", header->AdvanceMedia);
-  fprintf(stderr, "DEBUG: Collate = %d\n", header->Collate);
-  fprintf(stderr, "DEBUG: CutMedia = %d\n", header->CutMedia);
   fprintf(stderr, "DEBUG: Duplex = %d\n", header->Duplex);
-  fprintf(stderr, "DEBUG: HWResolution = [ %d %d ]\n", header->HWResolution[0],
-          header->HWResolution[1]);
-  fprintf(stderr, "DEBUG: ImagingBoundingBox = [ %d %d %d %d ]\n",
-          header->ImagingBoundingBox[0], header->ImagingBoundingBox[1],
-          header->ImagingBoundingBox[2], header->ImagingBoundingBox[3]);
-  fprintf(stderr, "DEBUG: InsertSheet = %d\n", header->InsertSheet);
-  fprintf(stderr, "DEBUG: Jog = %d\n", header->Jog);
-  fprintf(stderr, "DEBUG: LeadingEdge = %d\n", header->LeadingEdge);
-  fprintf(stderr, "DEBUG: Margins = [ %d %d ]\n", header->Margins[0],
-          header->Margins[1]);
+  fprintf(stderr, "DEBUG: HWResolution = [ %d %d ]\n", header->HWResolution[0], header->HWResolution[1]);
+  fprintf(stderr, "DEBUG: ImagingBoundingBox = [ %d %d %d %d ]\n", header->ImagingBoundingBox[0], header->ImagingBoundingBox[1], header->ImagingBoundingBox[2], header->ImagingBoundingBox[3]);
+  fprintf(stderr, "DEBUG: Margins = [ %d %d ]\n", header->Margins[0], header->Margins[1]);
   fprintf(stderr, "DEBUG: ManualFeed = %d\n", header->ManualFeed);
   fprintf(stderr, "DEBUG: MediaPosition = %d\n", header->MediaPosition);
-  fprintf(stderr, "DEBUG: MediaWeight = %d\n", header->MediaWeight);
-  fprintf(stderr, "DEBUG: MirrorPrint = %d\n", header->MirrorPrint);
-  fprintf(stderr, "DEBUG: NegativePrint = %d\n", header->NegativePrint);
   fprintf(stderr, "DEBUG: NumCopies = %d\n", header->NumCopies);
   fprintf(stderr, "DEBUG: Orientation = %d\n", header->Orientation);
-  fprintf(stderr, "DEBUG: OutputFaceUp = %d\n", header->OutputFaceUp);
-  fprintf(stderr, "DEBUG: PageSize = [ %d %d ]\n", header->PageSize[0],
-          header->PageSize[1]);
-  fprintf(stderr, "DEBUG: Separations = %d\n", header->Separations);
-  fprintf(stderr, "DEBUG: TraySwitch = %d\n", header->TraySwitch);
-  fprintf(stderr, "DEBUG: Tumble = %d\n", header->Tumble);
+  fprintf(stderr, "DEBUG: PageSize = [ %d %d ]\n", header->PageSize[0], header->PageSize[1]);
   fprintf(stderr, "DEBUG: cupsWidth = %d\n", header->cupsWidth);
   fprintf(stderr, "DEBUG: cupsHeight = %d\n", header->cupsHeight);
   fprintf(stderr, "DEBUG: cupsMediaType = %d\n", header->cupsMediaType);
@@ -214,23 +183,6 @@ StartPage(ppd_file_t         *ppd, /* I - PPD file */
   fprintf(stderr, "DEBUG: cupsColorSpace = %d\n", header->cupsColorSpace);
   fprintf(stderr, "DEBUG: cupsCompression = %d\n", header->cupsCompression);
 
- /*
-  * Register a signal handler to eject the current page if the
-  * job is canceled.
-  */
-
-#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
-  sigset(SIGTERM, CancelJob);
-#elif defined(HAVE_SIGACTION)
-  memset(&action, 0, sizeof(action));
-
-  sigemptyset(&action.sa_mask);
-  action.sa_handler = CancelJob;
-  sigaction(SIGTERM, &action, NULL);
-#else
-  signal(SIGTERM, CancelJob);
-#endif /* HAVE_SIGSET */
-
   switch (ModelNumber)
   {
     case DYMO_3x0 :
@@ -297,7 +249,7 @@ StartPage(ppd_file_t         *ppd,  /* I - PPD file */
        if ((choice = ppdFindMarkedChoice(ppd, "zePrintRate")) != NULL &&
            strcmp(choice->choice, "Default"))
        {
-         float val = atof(choice->choice);
+         double val = atof(choice->choice);
 
          if (val >= 3.0)
            printf("S%.0f\n", val);
@@ -310,13 +262,13 @@ StartPage(ppd_file_t         *ppd,        /* I - PPD file */
        */
 
         if (header->cupsCompression > 0 && header->cupsCompression <= 100)
-         printf("D%d\n", 15 * header->cupsCompression / 100);
+         printf("D%u\n", 15 * header->cupsCompression / 100);
 
        /*
         * Set label size...
        */
 
-        printf("q%d\n", header->cupsWidth);
+        printf("q%u\n", (header->cupsWidth + 7) & ~7U);
         break;
 
     case ZEBRA_ZPL :
@@ -325,13 +277,13 @@ StartPage(ppd_file_t         *ppd,        /* I - PPD file */
        */
 
         if (header->cupsCompression > 0 && header->cupsCompression <= 100)
-         printf("~SD%02d\n", 30 * header->cupsCompression / 100);
+         printf("~SD%02u\n", 30 * header->cupsCompression / 100);
 
        /*
         * Start bitmap graphics...
        */
 
-        printf("~DGR:CUPS.GRF,%d,%d,\n",
+        printf("~DGR:CUPS.GRF,%u,%u,\n",
               header->cupsHeight * header->cupsBytesPerLine,
               header->cupsBytesPerLine);
 
@@ -352,6 +304,123 @@ StartPage(ppd_file_t         *ppd,        /* I - PPD file */
         printf("! 0 %u %u %u %u\r\n", header->HWResolution[0],
               header->HWResolution[1], header->cupsHeight,
               header->NumCopies);
+       printf("PAGE-WIDTH %u\r\n", header->cupsWidth);
+       printf("PAGE-HEIGHT %u\r\n", header->cupsWidth);
+        break;
+
+    case INTELLITECH_PCL :
+       /*
+        * Set the media size...
+       */
+
+       printf("\033&l6D\033&k12H");    /* Set 6 LPI, 10 CPI */
+       printf("\033&l0O");             /* Set portrait orientation */
+
+       switch (header->PageSize[1])
+       {
+         case 540 : /* Monarch Envelope */
+              printf("\033&l80A");     /* Set page size */
+             break;
+
+         case 624 : /* DL Envelope */
+              printf("\033&l90A");     /* Set page size */
+             break;
+
+         case 649 : /* C5 Envelope */
+              printf("\033&l91A");     /* Set page size */
+             break;
+
+         case 684 : /* COM-10 Envelope */
+              printf("\033&l81A");     /* Set page size */
+             break;
+
+         case 756 : /* Executive */
+              printf("\033&l1A");      /* Set page size */
+             break;
+
+         case 792 : /* Letter */
+              printf("\033&l2A");      /* Set page size */
+             break;
+
+         case 842 : /* A4 */
+              printf("\033&l26A");     /* Set page size */
+             break;
+
+         case 1008 : /* Legal */
+              printf("\033&l3A");      /* Set page size */
+             break;
+
+          default : /* Custom size */
+             printf("\033!f%uZ", header->PageSize[1] * 300 / 72);
+             break;
+       }
+
+       printf("\033&l%uP",             /* Set page length */
+               header->PageSize[1] / 12);
+       printf("\033&l0E");             /* Set top margin to 0 */
+        if (header->NumCopies)
+         printf("\033&l%uX", header->NumCopies);
+                                       /* Set number copies */
+        printf("\033&l0L");            /* Turn off perforation skip */
+
+       /*
+        * Print settings...
+       */
+
+       if (Page == 1)
+       {
+          if (header->cupsRowFeed)     /* inPrintRate */
+           printf("\033!p%uS", header->cupsRowFeed);
+
+          if (header->cupsCompression != ~0U)
+                                       /* inPrintDensity */
+           printf("\033&d%uA", 30 * header->cupsCompression / 100 - 15);
+
+         if ((choice = ppdFindMarkedChoice(ppd, "inPrintMode")) != NULL)
+         {
+           if (!strcmp(choice->choice, "Standard"))
+             fputs("\033!p0M", stdout);
+           else if (!strcmp(choice->choice, "Tear"))
+           {
+             fputs("\033!p1M", stdout);
+
+              if (header->cupsRowCount)        /* inTearInterval */
+               printf("\033!n%uT", header->cupsRowCount);
+            }
+           else
+           {
+             fputs("\033!p2M", stdout);
+
+              if (header->cupsRowStep) /* inCutInterval */
+               printf("\033!n%uC", header->cupsRowStep);
+            }
+         }
+        }
+
+       /*
+       * Setup graphics...
+       */
+
+       printf("\033*t%uR", header->HWResolution[0]);
+                                       /* Set resolution */
+
+       printf("\033*r%uS", header->cupsWidth);
+                                       /* Set width */
+       printf("\033*r%uT", header->cupsHeight);
+                                       /* Set height */
+
+       printf("\033&a0H");             /* Set horizontal position */
+       printf("\033&a0V");             /* Set vertical position */
+        printf("\033*r1A");            /* Start graphics */
+        printf("\033*b3M");            /* Set compression */
+
+       /*
+        * Allocate compression buffers...
+       */
+
+       CompBuffer = malloc(2 * header->cupsBytesPerLine + 1);
+       LastBuffer = malloc(header->cupsBytesPerLine);
+       LastSet    = 0;
         break;
   }
 
@@ -370,13 +439,10 @@ StartPage(ppd_file_t         *ppd,        /* I - PPD file */
 
 void
 EndPage(ppd_file_t *ppd,               /* I - PPD file */
-        cups_page_header_t *header)    /* I - Page header */
+        cups_page_header2_t *header)   /* I - Page header */
 {
   int          val;                    /* Option value */
   ppd_choice_t *choice;                /* Marked choice */
-#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
-  struct sigaction action;             /* Actions for POSIX signals */
-#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
 
 
   switch (ModelNumber)
@@ -403,6 +469,13 @@ EndPage(ppd_file_t *ppd,           /* I - PPD file */
        */
 
         puts("P1");
+
+       /*
+        * Cut the label as needed...
+        */
+
+       if (header->CutMedia)
+         puts("C");
        break;
 
     case ZEBRA_ZPL :
@@ -462,7 +535,7 @@ EndPage(ppd_file_t *ppd,            /* I - PPD file */
        */
 
        if (header->cupsRowStep != 200)
-         printf("^LT%u\n", header->cupsRowStep);
+         printf("^LT%d\n", header->cupsRowStep);
 
        /*
         * Set media type...
@@ -532,14 +605,15 @@ EndPage(ppd_file_t *ppd,          /* I - PPD file */
         * End the label and eject...
        */
 
-        puts("^XZ");
+        puts("^IDR:CUPS.GRF^FS");
+       puts("^XZ");
 
        /*
-        * Free compression buffers...
-       */
+        * Cut the label as needed...
+        */
 
-       free(CompBuffer);
-       free(LastBuffer);
+       if (header->CutMedia)
+         puts("^CN1");
         break;
 
     case ZEBRA_CPCL :
@@ -588,34 +662,38 @@ EndPage(ppd_file_t *ppd,          /* I - PPD file */
         * Print the label...
        */
 
-        puts("FORM\r");
+       if ((choice = ppdFindMarkedChoice(ppd, "zeMediaTracking")) == NULL ||
+           strcmp(choice->choice, "Continuous"))
+          puts("FORM\r");
+
        puts("PRINT\r");
        break;
+
+    case INTELLITECH_PCL :
+        printf("\033*rB");             /* End GFX */
+        printf("\014");                        /* Eject current page */
+        break;
   }
 
   fflush(stdout);
 
- /*
-  * Unregister the signal handler...
-  */
-
-#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
-  sigset(SIGTERM, SIG_IGN);
-#elif defined(HAVE_SIGACTION)
-  memset(&action, 0, sizeof(action));
-
-  sigemptyset(&action.sa_mask);
-  action.sa_handler = SIG_IGN;
-  sigaction(SIGTERM, &action, NULL);
-#else
-  signal(SIGTERM, SIG_IGN);
-#endif /* HAVE_SIGSET */
-
  /*
   * Free memory...
   */
 
   free(Buffer);
+
+  if (CompBuffer)
+  {
+    free(CompBuffer);
+    CompBuffer = NULL;
+  }
+
+  if (LastBuffer)
+  {
+    free(LastBuffer);
+    LastBuffer = NULL;
+  }
 }
 
 
@@ -642,18 +720,20 @@ CancelJob(int sig)                        /* I - Signal */
 
 void
 OutputLine(ppd_file_t         *ppd,    /* I - PPD file */
-           cups_page_header_t *header, /* I - Page header */
-           int                y)       /* I - Line number */
+           cups_page_header2_t *header,        /* I - Page header */
+           unsigned           y)       /* I - Line number */
 {
-  int          i;                      /* Looping var */
+  unsigned     i;                      /* Looping var */
   unsigned char        *ptr;                   /* Pointer into buffer */
   unsigned char        *compptr;               /* Pointer into compression buffer */
-  char         repeat_char;            /* Repeated character */
-  int          repeat_count;           /* Number of repeated characters */
-  static const char *hex = "0123456789ABCDEF";
+  unsigned char        repeat_char;            /* Repeated character */
+  unsigned     repeat_count;           /* Number of repeated characters */
+  static const unsigned char *hex = (const unsigned char *)"0123456789ABCDEF";
                                        /* Hex digits */
 
 
+  (void)ppd;
+
   switch (ModelNumber)
   {
     case DYMO_3x0 :
@@ -679,17 +759,6 @@ OutputLine(ppd_file_t         *ppd,        /* I - PPD file */
           putchar(0x16);
          fwrite(Buffer, header->cupsBytesPerLine, 1, stdout);
          fflush(stdout);
-
-#ifdef __sgi
-        /*
-          * This hack works around a bug in the IRIX serial port driver when
-         * run at high baud rates (e.g. 115200 baud)...  This results in
-         * slightly slower label printing, but at least the labels come
-         * out properly.
-         */
-
-         sginap(1);
-#endif /* __sgi */
        }
        else
           Feed ++;
@@ -745,7 +814,7 @@ OutputLine(ppd_file_t         *ppd, /* I - PPD file */
         * Run-length compress the graphics...
        */
 
-       for (compptr = CompBuffer, repeat_char = CompBuffer[0], repeat_count = 1;
+       for (compptr = CompBuffer + 1, repeat_char = CompBuffer[0], repeat_count = 1;
             *compptr;
             compptr ++)
          if (*compptr == repeat_char)
@@ -764,13 +833,19 @@ OutputLine(ppd_file_t         *ppd,       /* I - PPD file */
          */
 
          if (repeat_count & 1)
+         {
+           repeat_count --;
            putchar('0');
+         }
 
-         putchar(',');
+          if (repeat_count > 0)
+           putchar(',');
        }
        else
          ZPLCompress(repeat_char, repeat_count);
 
+       fflush(stdout);
+
        /*
         * Save this line for the next round...
        */
@@ -788,24 +863,174 @@ OutputLine(ppd_file_t         *ppd,      /* I - PPD file */
          fflush(stdout);
        }
        break;
+
+    case INTELLITECH_PCL :
+       if (Buffer[0] ||
+            memcmp(Buffer, Buffer + 1, header->cupsBytesPerLine - 1))
+        {
+         if (Feed)
+         {
+           printf("\033*b%dY", Feed);
+           Feed    = 0;
+           LastSet = 0;
+         }
+
+          PCLCompress(Buffer, header->cupsBytesPerLine);
+       }
+       else
+         Feed ++;
+        break;
   }
 }
 
 
+/*
+ * 'PCLCompress()' - Output a PCL (mode 3) compressed line.
+ */
+
+void
+PCLCompress(unsigned char *line,       /* I - Line to compress */
+            unsigned      length)      /* I - Length of line */
+{
+  unsigned char        *line_ptr,              /* Current byte pointer */
+               *line_end,              /* End-of-line byte pointer */
+               *comp_ptr,              /* Pointer into compression buffer */
+               *start,                 /* Start of compression sequence */
+               *seed;                  /* Seed buffer pointer */
+  unsigned     count,                  /* Count of bytes for output */
+               offset;                 /* Offset of bytes for output */
+
+
+ /*
+  * Do delta-row compression...
+  */
+
+  line_ptr = line;
+  line_end = line + length;
+
+  comp_ptr = CompBuffer;
+  seed     = LastBuffer;
+
+  while (line_ptr < line_end)
+  {
+   /*
+    * Find the next non-matching sequence...
+    */
+
+    start = line_ptr;
+
+    if (!LastSet)
+    {
+     /*
+      * The seed buffer is invalid, so do the next 8 bytes, max...
+      */
+
+      offset = 0;
+
+      if ((count = (unsigned)(line_end - line_ptr)) > 8)
+       count = 8;
+
+      line_ptr += count;
+    }
+    else
+    {
+     /*
+      * The seed buffer is valid, so compare against it...
+      */
+
+      while (*line_ptr == *seed &&
+             line_ptr < line_end)
+      {
+        line_ptr ++;
+        seed ++;
+      }
+
+      if (line_ptr == line_end)
+        break;
+
+      offset = (unsigned)(line_ptr - start);
+
+     /*
+      * Find up to 8 non-matching bytes...
+      */
+
+      start = line_ptr;
+      count = 0;
+      while (*line_ptr != *seed &&
+             line_ptr < line_end &&
+             count < 8)
+      {
+        line_ptr ++;
+        seed ++;
+        count ++;
+      }
+    }
+
+   /*
+    * Place mode 3 compression data in the buffer; see HP manuals
+    * for details...
+    */
+
+    if (offset >= 31)
+    {
+     /*
+      * Output multi-byte offset...
+      */
+
+      *comp_ptr++ = (unsigned char)(((count - 1) << 5) | 31);
+
+      offset -= 31;
+      while (offset >= 255)
+      {
+        *comp_ptr++ = 255;
+        offset    -= 255;
+      }
+
+      *comp_ptr++ = (unsigned char)offset;
+    }
+    else
+    {
+     /*
+      * Output single-byte offset...
+      */
+
+      *comp_ptr++ = (unsigned char)(((count - 1) << 5) | offset);
+    }
+
+    memcpy(comp_ptr, start, count);
+    comp_ptr += count;
+  }
+
+ /*
+  * Set the length of the data and write it...
+  */
+
+  printf("\033*b%dW", (int)(comp_ptr - CompBuffer));
+  fwrite(CompBuffer, (size_t)(comp_ptr - CompBuffer), 1, stdout);
+
+ /*
+  * Save this line as a "seed" buffer for the next...
+  */
+
+  memcpy(LastBuffer, line, length);
+  LastSet = 1;
+}
+
+
 /*
  * 'ZPLCompress()' - Output a run-length compression sequence.
  */
 
 void
-ZPLCompress(char repeat_char,          /* I - Character to repeat */
-           int  repeat_count)          /* I - Number of repeated characters */
+ZPLCompress(unsigned char repeat_char, /* I - Character to repeat */
+           unsigned      repeat_count) /* I - Number of repeated characters */
 {
   if (repeat_count > 1)
   {
    /*
     * Print as many z's as possible - they are the largest denomination
-    * representing 400 characters (zC stands for 400 adjacent C's)     
-    */ 
+    * representing 400 characters (zC stands for 400 adjacent C's)
+    */
 
     while (repeat_count >= 400)
     {
@@ -819,7 +1044,7 @@ ZPLCompress(char repeat_char,              /* I - Character to repeat */
 
     if (repeat_count >= 20)
     {
-      putchar('f' + repeat_count / 20);
+      putchar((int)('f' + repeat_count / 20));
       repeat_count %= 20;
     }
 
@@ -828,14 +1053,14 @@ ZPLCompress(char repeat_char,            /* I - Character to repeat */
     */
 
     if (repeat_count > 0)
-      putchar('F' + repeat_count);
+      putchar((int)('F' + repeat_count));
   }
 
  /*
   * Then the character to be repeated...
   */
 
-  putchar(repeat_char);
+  putchar((int)repeat_char);
 }
 
 
@@ -849,11 +1074,14 @@ main(int  argc,                          /* I - Number of command-line arguments */
 {
   int                  fd;             /* File descriptor */
   cups_raster_t                *ras;           /* Raster stream for printing */
-  cups_page_header_t   header;         /* Page header from file */
-  int                  y;              /* Current line */
+  cups_page_header2_t  header;         /* Page header from file */
+  unsigned             y;              /* Current line */
   ppd_file_t           *ppd;           /* PPD file */
   int                  num_options;    /* Number of options */
   cups_option_t                *options;       /* Options */
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+  struct sigaction action;             /* Actions for POSIX signals */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
 
 
  /*
@@ -873,7 +1101,9 @@ main(int  argc,                            /* I - Number of command-line arguments */
     * and return.
     */
 
-    fputs("ERROR: rastertodymo job-id user title copies options [file]\n", stderr);
+    _cupsLangPrintFilter(stderr, "ERROR",
+                         _("%s job-id user title copies options [file]"),
+                        "rastertolabel");
     return (1);
   }
 
@@ -885,7 +1115,7 @@ main(int  argc,                            /* I - Number of command-line arguments */
   {
     if ((fd = open(argv[6], O_RDONLY)) == -1)
     {
-      perror("ERROR: Unable to open raster file - ");
+      _cupsLangPrintError("ERROR", _("Unable to open raster file"));
       sleep(1);
       return (1);
     }
@@ -895,18 +1125,50 @@ main(int  argc,                          /* I - Number of command-line arguments */
 
   ras = cupsRasterOpen(fd, CUPS_RASTER_READ);
 
+ /*
+  * Register a signal handler to eject the current page if the
+  * job is cancelled.
+  */
+
+  Canceled = 0;
+
+#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
+  sigset(SIGTERM, CancelJob);
+#elif defined(HAVE_SIGACTION)
+  memset(&action, 0, sizeof(action));
+
+  sigemptyset(&action.sa_mask);
+  action.sa_handler = CancelJob;
+  sigaction(SIGTERM, &action, NULL);
+#else
+  signal(SIGTERM, CancelJob);
+#endif /* HAVE_SIGSET */
+
  /*
   * Open the PPD file and apply options...
   */
 
   num_options = cupsParseOptions(argv[5], 0, &options);
 
-  if ((ppd = ppdOpenFile(getenv("PPD"))) != NULL)
+  ppd = ppdOpenFile(getenv("PPD"));
+  if (!ppd)
   {
-    ppdMarkDefaults(ppd);
-    cupsMarkOptions(ppd, num_options, options);
+    ppd_status_t       status;         /* PPD error */
+    int                        linenum;        /* Line number */
+
+    _cupsLangPrintFilter(stderr, "ERROR",
+                         _("The PPD file could not be opened."));
+
+    status = ppdLastError(&linenum);
+
+    fprintf(stderr, "DEBUG: %s on line %d.\n", ppdErrorString(status), linenum);
+
+    return (1);
   }
 
+  ppdMarkDefaults(ppd);
+  cupsMarkOptions(ppd, num_options, options);
+
  /*
   * Initialize the print device...
   */
@@ -917,18 +1179,21 @@ main(int  argc,                          /* I - Number of command-line arguments */
   * Process pages as needed...
   */
 
-  Page      = 0;
-  Canceled = 0;
+  Page = 0;
 
-  while (cupsRasterReadHeader(ras, &header))
+  while (cupsRasterReadHeader2(ras, &header))
   {
    /*
     * Write a status message with the page number and number of copies.
     */
 
+    if (Canceled)
+      break;
+
     Page ++;
 
     fprintf(stderr, "PAGE: %d 1\n", Page);
+    _cupsLangPrintFilter(stderr, "INFO", _("Starting page %d."), Page);
 
    /*
     * Start the page...
@@ -946,9 +1211,17 @@ main(int  argc,                           /* I - Number of command-line arguments */
       * Let the user know how far we have progressed...
       */
 
+      if (Canceled)
+       break;
+
       if ((y & 15) == 0)
-        fprintf(stderr, "INFO: Printing page %d, %d%% complete...\n", Page,
-               100 * y / header.cupsHeight);
+      {
+        _cupsLangPrintFilter(stderr, "INFO",
+                            _("Printing page %d, %u%% complete."),
+                            Page, 100 * y / header.cupsHeight);
+        fprintf(stderr, "ATTR: job-media-progress=%u\n",
+               100 * y / header.cupsHeight);
+      }
 
      /*
       * Read a line of graphics...
@@ -968,6 +1241,8 @@ main(int  argc,                            /* I - Number of command-line arguments */
     * Eject the page...
     */
 
+    _cupsLangPrintFilter(stderr, "INFO", _("Finished page %d."), Page);
+
     EndPage(ppd, &header);
 
     if (Canceled)
@@ -994,14 +1269,10 @@ main(int  argc,                          /* I - Number of command-line arguments */
   */
 
   if (Page == 0)
-    fputs("ERROR: No pages found!\n", stderr);
+  {
+    _cupsLangPrintFilter(stderr, "ERROR", _("No pages were found."));
+    return (1);
+  }
   else
-    fputs("INFO: Ready to print.\n", stderr);
-
-  return (Page == 0);
+    return (0);
 }
-
-
-/*
- * End of "$Id: rastertolabel.c 5665 2006-06-16 00:59:10Z mike $".
- */