]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - filter/texttops.c
Save work on localization changes - prep for new bundle-based localizations,
[thirdparty/cups.git] / filter / texttops.c
index 699f42a5af2009ee1823dcdb8f48890b0238595e..970964e418c1fc8fceb1a414cdde0f0deba801e4 100644 (file)
@@ -1,25 +1,18 @@
 /*
- * "$Id: texttops.c,v 1.25 2000/04/09 23:09:06 mike Exp $"
+ * "$Id$"
  *
- *   Text to PostScript filter for the Common UNIX Printing System (CUPS).
+ *   Text to PostScript filter for CUPS.
  *
- *   Copyright 1993-2000 by Easy Software Products.
+ *   Copyright 2007-2010 by Apple Inc.
+ *   Copyright 1993-2007 by Easy Software Products.
  *
  *   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:
+ *   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/".
  *
- *       Attn: CUPS Licensing Information
- *       Easy Software Products
- *       44141 Airport View Drive, Suite 204
- *       Hollywood, Maryland 20636-3111 USA
- *
- *       Voice: (301) 373-9603
- *       EMail: cups-info@cups.org
- *         WWW: http://www.cups.org
+ *   This file is subject to the Apple OS-Developed Software exception.
  *
  * Contents:
  *
@@ -36,6 +29,7 @@
  */
 
 #include "textcommon.h"
+#include <cups/language-private.h>
 
 
 /*
@@ -57,7 +51,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);
 
 
 /*
@@ -79,7 +73,7 @@ main(int  argc,               /* I - Number of command-line arguments */
 void
 WriteEpilogue(void)
 {
-  puts("%%BeginTrailer");
+  puts("%%Trailer");
   printf("%%%%Pages: %d\n", NumPages);
   puts("%%EOF");
 
@@ -121,14 +115,17 @@ 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 */
   char         filename[1024]; /* Glyph filenames */
   FILE         *fp;            /* Glyph files */
+  const char   *datadir;       /* CUPS_DATADIR environment variable */
   char         line[1024],     /* Line from file */
                *lineptr,       /* Pointer into line */
                *valptr;        /* Pointer to value in line */
@@ -148,6 +145,27 @@ WriteProlog(char       *title,     /* I - Title of job */
                };
 
 
+ /*
+  * Get the data directory...
+  */
+
+  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...
   */
@@ -155,8 +173,31 @@ WriteProlog(char       *title,     /* I - Title of job */
   SizeColumns = (PageRight - PageLeft) / 72.0 * CharsPerInch;
   SizeLines   = (PageTop - PageBottom) / 72.0 * LinesPerInch;
 
-  Page    = calloc(sizeof(lchar_t *), SizeLines);
-  Page[0] = calloc(sizeof(lchar_t), SizeColumns * SizeLines);
+  if (SizeColumns <= 0 || SizeColumns > 32767 ||
+      SizeLines <= 0 || SizeLines > 32767)
+  {
+    _cupsLangPrintFilter(stderr, "ERROR",
+                         _("Unable to print %dx%d text page.\n"),
+                         SizeColumns, SizeLines);
+    exit(1);
+  }
+
+  if ((Page = calloc(sizeof(lchar_t *), SizeLines)) == NULL)
+  {
+    _cupsLangPrintFilter(stderr, "ERROR",
+                         _("Unable to print %dx%d text page.\n"),
+                         SizeColumns, SizeLines);
+    exit(1);
+  }
+
+  if ((Page[0] = calloc(sizeof(lchar_t), SizeColumns * SizeLines)) == NULL)
+  {
+    _cupsLangPrintFilter(stderr, "ERROR",
+                         _("Unable to print %dx%d text page.\n"),
+                         SizeColumns, SizeLines);
+    exit(1);
+  }
+
   for (i = 1; i < SizeLines; i ++)
     Page[i] = Page[0] + i * SizeColumns;
 
@@ -169,6 +210,13 @@ WriteProlog(char       *title,     /* I - Title of job */
   else
     ColumnWidth = SizeColumns;
 
+  if (ColumnWidth <= 0)
+  {
+    _cupsLangPrintFilter(stderr, "ERROR",
+                         _("Unable to print %d text columns.\n"), PageColumns);
+    exit(1);
+  }
+
  /*
   * Output the DSC header...
   */
@@ -178,15 +226,12 @@ WriteProlog(char       *title,    /* I - Title of job */
   strftime(curdate, sizeof(curdate), "%c", curtm);
 
   puts("%!PS-Adobe-3.0");
-  printf("%%%%BoundingBox: %.0f %.0f %.0f %.0f\n", PageLeft, PageBottom,
-         PageRight, PageTop);
-  if (Orientation & 1)
-    puts("%%Orientation: Landscape");
+  printf("%%%%BoundingBox: 0 0 %.0f %.0f\n", PageWidth, PageLength);
+  printf("%%cupsRotation: %d\n", (Orientation & 3) * 90);
   puts("%%Creator: texttops/" CUPS_SVERSION);
   printf("%%%%CreationDate: %s\n", curdate);
-  printf("%%%%Title: %s\n", title);
-  printf("%%%%For: %s\n", user);
-  puts("%%DocumentSuppliedResources: procset texttops 1.1 0");
+  WriteTextComment("Title", title);
+  WriteTextComment("For", user);
   puts("%%Pages: (atend)");
 
  /*
@@ -204,7 +249,9 @@ WriteProlog(char       *title,      /* I - Title of job */
   * set definition...
   */
 
-  if ((fp = fopen(CUPS_DATADIR "/data/psglyphs", "r")) != NULL)
+  snprintf(filename, sizeof(filename), "%s/data/psglyphs", datadir);
+
+  if ((fp = fopen(filename, "r")) != NULL)
   {
     while (fscanf(fp, "%x%63s", &unicode, glyph) == 2)
       Glyphs[unicode] = strdup(glyph);
@@ -213,7 +260,8 @@ WriteProlog(char       *title,      /* I - Title of job */
   }
   else
   {
-    perror("ERROR: Unable to open " CUPS_DATADIR "/data/psglyphs");
+    fprintf(stderr, _("ERROR: Unable to open \"%s\" - %s\n"), filename,
+            strerror(errno));
     exit(1);
   }
 
@@ -224,7 +272,7 @@ WriteProlog(char       *title,      /* I - Title of job */
   charset = getenv("CHARSET");
   if (charset != NULL && strcmp(charset, "us-ascii") != 0)
   {
-    snprintf(filename, sizeof(filename), CUPS_DATADIR "/charsets/%s", charset);
+    snprintf(filename, sizeof(filename), "%s/charsets/%s", datadir, charset);
 
     if ((fp = fopen(filename, "r")) == NULL)
     {
@@ -232,7 +280,7 @@ WriteProlog(char       *title,      /* I - Title of job */
       * Can't open charset file!
       */
 
-      fprintf(stderr, "ERROR: Unable to open %s: %s\n", filename,
+      fprintf(stderr, _("ERROR: Unable to open %s: %s\n"), filename,
               strerror(errno));
       exit(1);
     }
@@ -248,7 +296,7 @@ WriteProlog(char       *title,      /* I - Title of job */
       */
 
       fclose(fp);
-      fprintf(stderr, "ERROR: Bad/empty charset file %s\n", filename);
+      fprintf(stderr, _("ERROR: Bad charset file %s\n"), filename);
       exit(1);
     }
 
@@ -259,7 +307,7 @@ WriteProlog(char       *title,      /* I - Title of job */
       */
 
       fclose(fp);
-      fprintf(stderr, "ERROR: Bad charset file %s\n", filename);
+      fprintf(stderr, _("ERROR: Bad charset file %s\n"), filename);
       exit(1);
     }
 
@@ -268,186 +316,14 @@ WriteProlog(char       *title,   /* I - Title of job */
     */
 
     line[strlen(line) - 1] = '\0'; /* Drop \n */
-    for (lineptr = line + 7; isspace(*lineptr); lineptr ++); /* Skip whitespace */
-
-    if (strcmp(lineptr, "8bit") == 0)
-    {
-     /*
-      * 8-bit text...
-      */
-
-      UTF8     = 0;
-      NumFonts = 0;
-
-     /*
-      * Read the font description(s)...
-      */
-
-      while (fgets(line, sizeof(line), fp) != NULL)
-      {
-       /*
-        * Skip comment and blank lines...
-       */
-
-        if (line[0] == '#' || line[0] == '\n')
-         continue;
-
-       /*
-       * Read the font descriptions that should look like:
-       *
-       *   first last direction width normal [bold italic bold-italic]
-       */
-
-       lineptr = line;
-
-        start = strtol(lineptr, &lineptr, 16);
-       end   = strtol(lineptr, &lineptr, 16);
-
-       while (isspace(*lineptr))
-         lineptr ++;
-
-        if (!*lineptr)
-         break;        // Must be font mapping
-
-       valptr = lineptr;
-
-       while (!isspace(*lineptr) && *lineptr)
-         lineptr ++;
-
-       if (!*lineptr)
-       {
-        /*
-         * Can't have a font without all required values...
-         */
-
-         fprintf(stderr, "ERROR: bad font description line: %s\n", valptr);
-         fclose(fp);
-         exit(1);
-       }
-
-       *lineptr++ = '\0';
-
-       if (strcmp(valptr, "ltor") == 0)
-         Directions[NumFonts] = 1;
-       else if (strcmp(valptr, "rtol") == 0)
-         Directions[NumFonts] = -1;
-       else
-       {
-         fprintf(stderr, "ERROR: Bad text direction %s\n", valptr);
-         fclose(fp);
-         exit(1);
-       }
-
-       /*
-       * Got the direction, now get the width...
-       */
-
-       while (isspace(*lineptr))
-         lineptr ++;
-
-       valptr = lineptr;
-
-       while (!isspace(*lineptr) && *lineptr)
-         lineptr ++;
-
-       if (!*lineptr)
-       {
-        /*
-         * Can't have a font without all required values...
-         */
-
-         fprintf(stderr, "ERROR: bad font description line: %s\n", valptr);
-         fclose(fp);
-         exit(1);
-       }
-
-       *lineptr++ = '\0';
-
-       if (strcmp(valptr, "single") == 0)
-          Widths[NumFonts] = 1;
-       else if (strcmp(valptr, "double") == 0)
-          Widths[NumFonts] = 2;
-       else 
-       {
-         fprintf(stderr, "ERROR: Bad text width %s\n", valptr);
-         fclose(fp);
-         exit(1);
-       }
+    for (lineptr = line + 7; isspace(*lineptr & 255); lineptr ++); /* Skip whitespace */
 
-       /*
-       * Get the fonts...
-       */
-
-       for (i = 0; *lineptr && i < 4; i ++)
-       {
-         while (isspace(*lineptr))
-           lineptr ++;
-
-         valptr = lineptr;
-
-         while (!isspace(*lineptr) && *lineptr)
-           lineptr ++;
-
-          if (*lineptr)
-           *lineptr++ = '\0';
-
-          if (lineptr > valptr)
-           Fonts[NumFonts][i] = strdup(valptr);
-       }
-
-       /*
-       * Fill in remaining fonts as needed...
-       */
-
-       for (j = i; j < 4; j ++)
-         Fonts[NumFonts][j] = strdup(Fonts[NumFonts][0]);
-
-       /*
-        * Define the character mappings...
-       */
-
-       for (i = start, j = NumFonts * 256; i <= end; i ++, j ++)
-         Chars[i] = j;
-
-        NumFonts ++;
-      }
-
-     /*
-      * Read encoding lines...
-      */
-
-      do
-      {
-       /*
-        * Skip comment and blank lines...
-       */
-
-        if (line[0] == '#' || line[0] == '\n')
-         continue;
-
-       /*
-        * Grab the character and unicode glyph number.
-       */
-
-       if (sscanf(line, "%x%x", &ch, &unicode) == 2 && ch < 256)
-          Codes[Chars[ch]] = unicode;
-      }
-      while (fgets(line, sizeof(line), fp) != NULL);
-
-      fclose(fp);
-    }
-    else if (strcmp(lineptr, "utf8") == 0)
+    if (strcmp(lineptr, "utf8") == 0)
     {
      /*
       * UTF-8 (Unicode) text...
       */
 
-      UTF8 = 1;
-
-     /*
-      * Read the font descriptions...
-      */
-
       NumFonts = 0;
 
       while (fgets(line, sizeof(line), fp) != NULL)
@@ -470,12 +346,12 @@ WriteProlog(char       *title,    /* I - Title of job */
         start = strtol(lineptr, &lineptr, 16);
        end   = strtol(lineptr, &lineptr, 16);
 
-       while (isspace(*lineptr))
+       while (isspace(*lineptr & 255))
          lineptr ++;
 
        valptr = lineptr;
 
-       while (!isspace(*lineptr) && *lineptr)
+       while (!isspace(*lineptr & 255) && *lineptr)
          lineptr ++;
 
        if (!*lineptr)
@@ -484,7 +360,7 @@ WriteProlog(char       *title,      /* I - Title of job */
          * Can't have a font without all required values...
          */
 
-         fprintf(stderr, "ERROR: bad font description line: %s\n", valptr);
+         fprintf(stderr, _("ERROR: Bad font description line: %s\n"), valptr);
          fclose(fp);
          exit(1);
        }
@@ -497,7 +373,7 @@ WriteProlog(char       *title,      /* I - Title of job */
          Directions[NumFonts] = -1;
        else
        {
-         fprintf(stderr, "ERROR: Bad text direction %s\n", valptr);
+         fprintf(stderr, _("ERROR: Bad text direction %s\n"), valptr);
          fclose(fp);
          exit(1);
        }
@@ -506,12 +382,12 @@ WriteProlog(char       *title,    /* I - Title of job */
        * Got the direction, now get the width...
        */
 
-       while (isspace(*lineptr))
+       while (isspace(*lineptr & 255))
          lineptr ++;
 
        valptr = lineptr;
 
-       while (!isspace(*lineptr) && *lineptr)
+       while (!isspace(*lineptr & 255) && *lineptr)
          lineptr ++;
 
        if (!*lineptr)
@@ -520,7 +396,7 @@ WriteProlog(char       *title,      /* I - Title of job */
          * Can't have a font without all required values...
          */
 
-         fprintf(stderr, "ERROR: bad font description line: %s\n", valptr);
+         fprintf(stderr, _("ERROR: Bad font description line: %s\n"), valptr);
          fclose(fp);
          exit(1);
        }
@@ -533,7 +409,7 @@ WriteProlog(char       *title,      /* I - Title of job */
           Widths[NumFonts] = 2;
        else 
        {
-         fprintf(stderr, "ERROR: Bad text width %s\n", valptr);
+         fprintf(stderr, _("ERROR: Bad text width %s\n"), valptr);
          fclose(fp);
          exit(1);
        }
@@ -544,12 +420,12 @@ WriteProlog(char       *title,    /* I - Title of job */
 
        for (i = 0; *lineptr && i < 4; i ++)
        {
-         while (isspace(*lineptr))
+         while (isspace(*lineptr & 255))
            lineptr ++;
 
          valptr = lineptr;
 
-         while (!isspace(*lineptr) && *lineptr)
+         while (!isspace(*lineptr & 255) && *lineptr)
            lineptr ++;
 
           if (*lineptr)
@@ -589,7 +465,7 @@ WriteProlog(char       *title,      /* I - Title of job */
     }
     else
     {
-      fprintf(stderr, "ERROR: Bad charset type %s\n", lineptr);
+      fprintf(stderr, _("ERROR: Bad charset type %s\n"), lineptr);
       fclose(fp);
       exit(1);
     }
@@ -627,7 +503,7 @@ WriteProlog(char       *title,      /* I - Title of job */
   */
 
   for (i = 0, num_fonts = 0; i < NumFonts; i ++)
-    for (j = 1 + PrettyPrint; j >= 0; j --)
+    for (j = PrettyPrint ? 2 : 1; j >= 0; j --)
     {
       for (k = 0; k < num_fonts; k ++)
         if (strcmp(Fonts[i][j], fonts[k]) == 0)
@@ -650,14 +526,85 @@ WriteProlog(char       *title,    /* I - Title of job */
 
   for (i = 0; i < num_fonts; i ++)
     if (i == 0)
-      printf("%%DocumentNeededResources: font %s\n", fonts[i]);
+      printf("%%%%DocumentNeededResources: font %s\n", fonts[i]);
+    else
+      printf("%%%%+ font %s\n", fonts[i]);
+
+  puts("%%DocumentSuppliedResources: procset texttops 1.1 0");
+
+  for (i = 0; i < num_fonts; i ++)
+  {
+    if (ppd != NULL)
+    {
+      fprintf(stderr, "DEBUG: ppd->num_fonts = %d\n", ppd->num_fonts);
+
+      for (j = 0; j < ppd->num_fonts; j ++)
+      {
+        fprintf(stderr, "DEBUG: ppd->fonts[%d] = %s\n", j, ppd->fonts[j]);
+
+       if (strcmp(fonts[i], ppd->fonts[j]) == 0)
+          break;
+      }
+    }
     else
-      printf("%%+ font %s\n", fonts[i]);
+      j = 0;
+
+    if ((ppd != NULL && j >= ppd->num_fonts) ||
+        strncmp(fonts[i], "Courier", 7) == 0 ||
+       strcmp(fonts[i], "Symbol") == 0)
+    {
+     /*
+      * Need to embed this font...
+      */
+
+      printf("%%%%+ font %s\n", fonts[i]);
+    }
+  }
 
   puts("%%EndComments");
 
   puts("%%BeginProlog");
 
+ /*
+  * Download any missing fonts...
+  */
+
+  for (i = 0; i < num_fonts; i ++)
+  {
+    if (ppd != NULL)
+    {
+      for (j = 0; j < ppd->num_fonts; j ++)
+       if (strcmp(fonts[i], ppd->fonts[j]) == 0)
+          break;
+    }
+    else
+      j = 0;
+
+    if ((ppd != NULL && j >= ppd->num_fonts) ||
+        strncmp(fonts[i], "Courier", 7) == 0 ||
+       strcmp(fonts[i], "Symbol") == 0)
+    {
+     /*
+      * Need to embed this font...
+      */
+
+      printf("%%%%BeginResource: font %s\n", fonts[i]);
+
+      /**** MRS: Need to use CUPS_FONTPATH env var! ****/
+      /**** Also look for Fontmap file or name.pfa, name.pfb... ****/
+      snprintf(filename, sizeof(filename), "%s/fonts/%s", datadir, fonts[i]);
+      if ((fp = fopen(filename, "rb")) != NULL)
+      {
+        while ((j = fread(line, 1, sizeof(line), fp)) > 0)
+         fwrite(line, 1, j, stdout);
+
+       fclose(fp);
+      }
+
+      puts("\n%%EndResource");
+    }
+  }
+
  /*
   * Write the encoding array(s)...
   */
@@ -672,6 +619,8 @@ WriteProlog(char       *title,      /* I - Title of job */
     {
       if (Glyphs[Codes[i * 256 + ch]])
        printf("/%s", Glyphs[Codes[i * 256 + ch]]);
+      else if (Codes[i * 256 + ch] > 255)
+        printf("/uni%04X", Codes[i * 256 + ch]);
       else
        printf("/.notdef");
 
@@ -694,7 +643,7 @@ WriteProlog(char       *title,      /* I - Title of job */
 
     puts("% Reencode fonts");
 
-    for (i = 1 + PrettyPrint; i >= 0; i --)
+    for (i = PrettyPrint ? 2 : 1; i >= 0; i --)
     {
       printf("/%s findfont\n", Fonts[0][i]);
       puts("dup length 1 add dict begin\n"
@@ -713,7 +662,7 @@ WriteProlog(char       *title,      /* I - Title of job */
 
     puts("% Reencode base fonts");
 
-    for (i = 1 + PrettyPrint; i >= 0; i --)
+    for (i = PrettyPrint ? 2 : 1; i >= 0; i --)
       for (j = 0; j < NumFonts; j ++)
       {
        printf("/%s findfont\n", Fonts[j][i]);
@@ -732,7 +681,7 @@ WriteProlog(char       *title,      /* I - Title of job */
 
     puts("% Create composite fonts...");
 
-    for (i = 1 + PrettyPrint; i >= 0; i --)
+    for (i = PrettyPrint ? 2 : 1; i >= 0; i --)
     {
       puts("8 dict begin");
       puts("/FontType 0 def/FontMatrix[1.0 0 0 1.0 0 0]def/FMapType 2 def/Encoding[");
@@ -764,19 +713,19 @@ WriteProlog(char       *title,    /* I - Title of job */
 
   puts("% Define fonts");
 
-  printf("/FN /cupsNormal findfont [%.1f 0 0 %.1f 0 0] makefont def\n",
+  printf("/FN /cupsNormal findfont [%.3f 0 0 %.3f 0 0] makefont def\n",
          120.0 / CharsPerInch, 68.0 / LinesPerInch);
-  printf("/FB /cupsBold findfont [%.1f 0 0 %.1f 0 0] makefont def\n",
+  printf("/FB /cupsBold findfont [%.3f 0 0 %.3f 0 0] makefont def\n",
          120.0 / CharsPerInch, 68.0 / LinesPerInch);
   if (PrettyPrint)
-    printf("/FI /cupsItalic findfont [%.1f 0 0 %.1f 0 0] makefont def\n",
+    printf("/FI /cupsItalic findfont [%.3f 0 0 %.3f 0 0] makefont def\n",
            120.0 / CharsPerInch, 68.0 / LinesPerInch);
 
   puts("% Common procedures");
 
   puts("/N { FN setfont moveto } bind def");
   puts("/B { FB setfont moveto } bind def");
-  printf("/U { gsave 0.5 setlinewidth 0 %.2f rmoveto "
+  printf("/U { gsave 0.5 setlinewidth 0 %.3f rmoveto "
          "0 rlineto stroke grestore } bind def\n", -6.8 / LinesPerInch);
 
   if (PrettyPrint)
@@ -800,17 +749,24 @@ WriteProlog(char       *title,    /* I - Title of job */
 
     puts("/n {");
     puts("\t20 string cvs % convert page number to string");
-    puts("\tdup length % get length");
-    puts("\tdup 2 mul string /P exch def % P = string twice as long");
-    puts("\t0 1 2 index 1 sub { % loop through each character in the page number");
-    puts("\t\tdup 3 index exch get % get character N from the page number");
-    puts("\t\texch 2 mul dup % compute offset in P");
-    puts("\t\tP exch 0 put % font 0");
-    puts("\t\t1 add P exch 2 index put % character");
-    puts("\t\tpop % discard character");
-    puts("\t} for % do for loop");
-    puts("\tpop pop % discard string and length");
-    puts("\tP % put string on stack");
+    if (NumFonts > 1)
+    {
+     /*
+      * Convert a number to double-byte chars...
+      */
+
+      puts("\tdup length % get length");
+      puts("\tdup 2 mul string /P exch def % P = string twice as long");
+      puts("\t0 1 2 index 1 sub { % loop through each character in the page number");
+      puts("\t\tdup 3 index exch get % get character N from the page number");
+      puts("\t\texch 2 mul dup % compute offset in P");
+      puts("\t\tP exch 0 put % font 0");
+      puts("\t\t1 add P exch 2 index put % character");
+      puts("\t\tpop % discard character");
+      puts("\t} for % do for loop");
+      puts("\tpop pop % discard string and length");
+      puts("\tP % put string on stack");
+    }
     puts("} bind def");
 
     printf("/T");
@@ -822,22 +778,22 @@ WriteProlog(char       *title,    /* I - Title of job */
     puts("def");
 
     puts("/H {");
-    puts("gsave");
+    puts("\tgsave");
     puts("\t0.9 setgray");
 
     if (Duplex)
     {
       puts("\tdup 2 mod 0 eq {");
-      printf("\t\t%.1f %.1f translate } {\n",
+      printf("\t\t%.3f %.3f translate } {\n",
              PageWidth - PageRight, PageTop + 72.0f / LinesPerInch);
-      printf("\t\t%.1f %.1f translate } ifelse\n",
+      printf("\t\t%.3f %.3f translate } ifelse\n",
              PageLeft, PageTop + 72.0f / LinesPerInch);
     }
     else
-      printf("\t%.1f %.1f translate\n",
+      printf("\t%.3f %.3f translate\n",
              PageLeft, PageTop + 72.0f / LinesPerInch);
 
-    printf("\t0 0 %.1f %.1f rectfill\n", PageRight - PageLeft,
+    printf("\t0 0 %.3f %.3f rectfill\n", PageRight - PageLeft,
           144.0f / LinesPerInch);
 
     puts("\tFB setfont");
@@ -846,19 +802,19 @@ WriteProlog(char       *title,    /* I - Title of job */
     if (Duplex)
     {
       puts("\tdup 2 mod 0 eq {");
-      printf("\t\tT stringwidth pop neg %.1f add %.1f } {\n",
+      printf("\t\tT stringwidth pop neg %.3f add %.3f } {\n",
              PageRight - PageLeft - 36.0f / LinesPerInch,
             (0.5f + 0.157f) * 72.0f / LinesPerInch);
-      printf("\t\t%.1f %.1f } ifelse\n", 36.0f / LinesPerInch,
+      printf("\t\t%.3f %.3f } ifelse\n", 36.0f / LinesPerInch,
             (0.5f + 0.157f) * 72.0f / LinesPerInch);
     }
     else
-      printf("\t%.1f %.1f\n", 36.0f / LinesPerInch,
+      printf("\t%.3f %.3f\n", 36.0f / LinesPerInch,
             (0.5f + 0.157f) * 72.0f / LinesPerInch);
 
     puts("\tmoveto T show");
 
-    printf("\tD dup stringwidth pop neg 2 div %.1f add %.1f\n",
+    printf("\tD dup stringwidth pop neg 2 div %.3f add %.3f\n",
            (PageRight - PageLeft) * 0.5,
            (0.5f + 0.157f) * 72.0f / LinesPerInch);
     puts("\tmoveto show");
@@ -866,14 +822,14 @@ WriteProlog(char       *title,    /* I - Title of job */
     if (Duplex)
     {
       puts("\tdup n exch 2 mod 0 eq {");
-      printf("\t\t%.1f %.1f } {\n", 36.0f / LinesPerInch,
+      printf("\t\t%.3f %.3f } {\n", 36.0f / LinesPerInch,
             (0.5f + 0.157f) * 72.0f / LinesPerInch);
-      printf("\t\tdup stringwidth pop neg %.1f add %.1f } ifelse\n",
+      printf("\t\tdup stringwidth pop neg %.3f add %.3f } ifelse\n",
              PageRight - PageLeft - 36.0f / LinesPerInch,
             (0.5f + 0.157f) * 72.0f / LinesPerInch);
     }
     else
-      printf("\tn dup stringwidth pop neg %.1f add %.1f\n",
+      printf("\tn dup stringwidth pop neg %.3f add %.3f\n",
              PageRight - PageLeft - 36.0f / LinesPerInch,
             (0.5f + 0.157f) * 72.0f / LinesPerInch);
 
@@ -902,11 +858,12 @@ write_line(int     row,           /* I - Row number (0 to N) */
   int          col;            /* Current column */
   int          attr;           /* Current attribute */
   int          font,           /* Font to use */
+               lastfont,       /* Last font */
                mono;           /* Monospaced? */
   lchar_t      *start;         /* First character in sequence */
 
 
-  for (col = 0, start = line; col < SizeColumns;)
+  for (col = 0; col < SizeColumns;)
   {
     while (col < SizeColumns && (line->ch == ' ' || line->ch == 0))
     {
@@ -940,10 +897,10 @@ write_line(int     row,           /* I - Row number (0 to N) */
       * Multiple fonts; break up based on the font...
       */
 
-      attr  = line->attr;
-      start = line;
-      font  = Chars[line->ch] / 256;
-      mono  = strncmp(Fonts[font][0], "Courier", 7) == 0;
+      attr     = line->attr;
+      start    = line;
+      lastfont = Chars[line->ch] / 256;
+      mono     = strncmp(Fonts[lastfont][0], "Courier", 7) == 0;
       col ++;
       line ++;
 
@@ -952,7 +909,8 @@ write_line(int     row,             /* I - Row number (0 to N) */
        while (col < SizeColumns && line->ch != 0 && attr == line->attr)
        {
           font = Chars[line->ch] / 256;
-          if (strncmp(Fonts[font][0], "Courier", 7) != 0)
+          if (strncmp(Fonts[font][0], "Courier", 7) != 0 ||
+             font != lastfont)
            break;
 
          col ++;
@@ -960,7 +918,7 @@ write_line(int     row,             /* I - Row number (0 to N) */
        }
       }
 
-      if (Directions[font] > 0)
+      if (Directions[lastfont] > 0)
         write_string(col - (line - start), row, line - start, start);
       else
       {
@@ -971,15 +929,15 @@ write_line(int     row,           /* I - Row number (0 to N) */
        while (col < SizeColumns && line->ch != 0 && attr == line->attr)
        {
           if (Directions[Chars[line->ch] / 256] > 0 &&
-             !ispunct(line->ch) && !isspace(line->ch))
+             !ispunct(line->ch & 255) && !isspace(line->ch & 255))
            break;
 
          col ++;
          line ++;
        }
 
-        for (i = 1; start < line; start ++)
-         if (!isspace(start->ch))
+        for (i = 1; start < line; i ++, start ++)
+         if (!isspace(start->ch & 255))
            write_string(col - i, row, 1, start);
       }
     }
@@ -1030,12 +988,12 @@ write_string(int     col,        /* I - Start column */
   if (x == (int)x)
     printf("%.0f ", x);
   else
-    printf("%.1f ", x);
+    printf("%.3f ", x);
 
   if (y == (int)y)
     printf("%.0f ", y);
   else
-    printf("%.1f ", y);
+    printf("%.3f ", y);
 
   if (attr & ATTR_BOLD)
     putchar('B');
@@ -1045,7 +1003,7 @@ write_string(int     col, /* I - Start column */
     putchar('N');
 
   if (attr & ATTR_UNDERLINE)
-    printf(" %.1f U", (float)len * 72.0 / (float)CharsPerInch);
+    printf(" %.3f U", (float)len * 72.0 / (float)CharsPerInch);
 
   if (NumFonts > 1)
   {
@@ -1125,10 +1083,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)
@@ -1139,11 +1097,11 @@ write_text(char *s)     /* I - String to write */
 
     putchar('<');
 
-    utf8 = (unsigned char *)s;
+    utf8 = (const unsigned char *)s;
 
     while (*utf8)
     {
-      if (*utf8 < 0xc0 || !UTF8)
+      if (*utf8 < 0xc0)
         ch = *utf8 ++;
       else if ((*utf8 & 0xe0) == 0xc0)
       {
@@ -1199,5 +1157,5 @@ write_text(char *s)       /* I - String to write */
 
 
 /*
- * End of "$Id: texttops.c,v 1.25 2000/04/09 23:09:06 mike Exp $".
+ * End of "$Id$".
  */