Support, in the winhelp module only, for adding pictures to .HLP
[sgt/halibut] / bk_ps.c
diff --git a/bk_ps.c b/bk_ps.c
index f66420a..41b70d2 100644 (file)
--- a/bk_ps.c
+++ b/bk_ps.c
@@ -7,6 +7,7 @@
 #include "paper.h"
 
 static void ps_comment(FILE *fp, char const *leader, word *words);
+static void ps_string_len(FILE *fp, char const *str, int len);
 static void ps_string(FILE *fp, char const *str);
 
 paragraph *ps_config_filename(char *filename)
@@ -24,6 +25,9 @@ void ps_backend(paragraph *sourceform, keywordlist *keywords,
     FILE *fp;
     char *filename;
     paragraph *p;
+    outline_element *oe;
+    int noe;
+
 
     IGNORE(keywords);
     IGNORE(idx);
@@ -46,7 +50,7 @@ void ps_backend(paragraph *sourceform, keywordlist *keywords,
 
     fprintf(fp, "%%!PS-Adobe-3.0\n");
     fprintf(fp, "%%%%Creator: Halibut, %s\n", version);
-    fprintf(fp, "%%%%DocumentData: Clean8Bit\n");
+    fprintf(fp, "%%%%DocumentData: Clean7Bit\n");
     fprintf(fp, "%%%%LanguageLevel: 1\n");
     for (pageno = 0, page = doc->pages; page; page = page->next)
        pageno++;
@@ -104,13 +108,15 @@ void ps_backend(paragraph *sourceform, keywordlist *keywords,
            "/pdfmark where { pop\n"
            "  /p { [ /Dest 3 -1 roll /View [ /XYZ null null null ]\n"
            "       /DEST pdfmark } bind def\n"
-           "  /x { [ /Dest 3 -1 roll /Rect 5 -1 roll /Border [0 0 0 0]\n"
+           "  /x { [ /Dest 3 -1 roll /Rect 5 -1 roll /Border [0 0 0]\n"
            "       /Subtype /Link /ANN pdfmark } bind def\n"
            "  /u { 2 dict dup /Subtype /URI put dup /URI 4 -1 roll put\n"
-           "       [ /Action 3 -1 roll /Rect 5 -1 roll /Border [0 0 0 0]\n"
+           "       [ /Action 3 -1 roll /Rect 5 -1 roll /Border [0 0 0]\n"
            "       /Subtype /Link /ANN pdfmark } bind def\n"
            "} {\n"
-           "  [/p /x /u] { null cvx def } forall\n"
+           "  /p { pop } bind def\n"
+           "  /x { pop pop } bind def\n"
+           "  /u /x load def\n"
            "} ifelse\n");
 
     fprintf(fp, "%%%%EndResource\n");
@@ -119,6 +125,18 @@ void ps_backend(paragraph *sourceform, keywordlist *keywords,
     fprintf(fp, "%%%%BeginSetup\n");
 
     /*
+     * Assign a destination name to each page for pdfmark purposes.
+     */
+    pageno = 0;
+    for (page = doc->pages; page; page = page->next) {
+       char *buf;
+       pageno++;
+       buf = snewn(12, char);
+       sprintf(buf, "/p%d", pageno);
+       page->spare = buf;
+    }
+
+    /*
      * This is as good a place as any to put version IDs.
      */
     for (p = sourceform; p; p = p->next)
@@ -137,11 +155,29 @@ void ps_backend(paragraph *sourceform, keywordlist *keywords,
            doc->paper_height / FUNITS_PER_PT);
     fprintf(fp, "} if\n");
 
-    /* Request outline view if the document is converted to PDF. */
-    fprintf(fp,
-           "/pdfmark where {\n"
-           "  pop [ /PageMode /UseOutlines /DOCVIEW pdfmark\n"
-           "} if\n");
+    /* Outline etc, only if pdfmark is supported */
+    fprintf(fp, "/pdfmark where { pop %% if\n");
+    fprintf(fp, "  [/PageMode/UseOutlines/DOCVIEW pdfmark\n");
+    noe = doc->n_outline_elements;
+    for (oe = doc->outline_elements; noe; oe++, noe--) {
+       char *title;
+       int titlelen, count, i;
+
+       title = pdf_outline_convert(oe->pdata->outline_title, &titlelen);
+
+       count = 0;
+       for (i = 1; i < noe && oe[i].level > oe->level; i++)
+           if (oe[i].level == oe->level + 1)
+               count++;
+       if (oe->level > 0) count = -count;
+
+       fprintf(fp, "  [/Title");
+       ps_string_len(fp, title, titlelen);
+       sfree(title);
+       fprintf(fp, "/Dest%s/Count %d/OUT pdfmark\n",
+               (char *)oe->pdata->first->page->spare, count);
+    }
+    fprintf(fp, "} if\n");
 
     for (fe = doc->fonts->head; fe; fe = fe->next) {
        /* XXX This may request the same font multiple times. */
@@ -187,18 +223,6 @@ void ps_backend(paragraph *sourceform, keywordlist *keywords,
     fprintf(fp, "%%%%EndSetup\n");
 
     /*
-     * Assign a destination name to each page for pdfmark purposes.
-     */
-    pageno = 0;
-    for (page = doc->pages; page; page = page->next) {
-       char *buf;
-       pageno++;
-       buf = snewn(12, char);
-       sprintf(buf, "/p%d", pageno);
-       page->spare = buf;
-    }
-
-    /*
      * Output the text and graphics.
      */
     pageno = 0;
@@ -310,14 +334,39 @@ static void ps_comment(FILE *fp, char const *leader, word *words)
     fprintf(fp, "\n");
 }
 
-static void ps_string(FILE *fp, char const *str) {
+static void ps_string_len(FILE *fp, char const *str, int len) {
     char const *c;
-
-    fprintf(fp, "(");
-    for (c = str; *c; c++) {
-       if (*c == '(' || *c == ')' || *c == '\\')
-           fputc('\\', fp);
-       fputc(*c, fp);
+    int score = 0;
+
+    for (c = str; c < str+len; c++) {
+       if (*c < ' ' || *c > '~')
+           score += 2;
+       else if (*c == '(' || *c == ')' || *c == '\\')
+           score += 0;
+       else
+           score -= 1;
     }
-    fprintf(fp, ")");
+    if (score > 0) {
+       fprintf(fp, "<");
+       for (c = str; c < str+len; c++) {
+           fprintf(fp, "%02X", 0xFF & (int)*c);
+       }
+       fprintf(fp, ">");
+    } else {
+       fprintf(fp, "(");
+       for (c = str; c < str+len; c++) {
+           if (*c < ' ' || *c > '~') {
+               fprintf(fp, "\\%03o", 0xFF & (int)*c);
+           } else {
+               if (*c == '(' || *c == ')' || *c == '\\')
+                   fputc('\\', fp);
+               fputc(*c, fp);
+           }
+       }
+       fprintf(fp, ")");
+    }
+}
+
+static void ps_string(FILE *fp, char const *str) {
+    ps_string_len(fp, str, strlen(str));
 }