Enhance the text backend to support configurable quote characters,
[sgt/halibut] / bk_whlp.c
index 6eee4d4..d11fd22 100644 (file)
--- a/bk_whlp.c
+++ b/bk_whlp.c
@@ -43,8 +43,13 @@ static void whlp_navmenu(struct bk_whlp_state *state, paragraph *p);
 static void whlp_contents_write(struct bk_whlp_state *state,
                                int level, char *text, WHLP_TOPIC topic);
     
+paragraph *whlp_config_filename(char *filename)
+{
+    return cmdline_cfg_simple("winhelp-filename", filename, NULL);
+}
+
 void whlp_backend(paragraph *sourceform, keywordlist *keywords,
-                 indexdata *idx) {
+                 indexdata *idx, void *unused) {
     WHLP h;
     char *filename, *cntname;
     paragraph *p, *lastsect;
@@ -55,6 +60,8 @@ void whlp_backend(paragraph *sourceform, keywordlist *keywords,
     indexentry *ie;
     int done_contents_topic = FALSE;
 
+    IGNORE(unused);
+
     h = state.h = whlp_new();
     state.keywords = keywords;
     state.idx = idx;
@@ -99,7 +106,7 @@ void whlp_backend(paragraph *sourceform, keywordlist *keywords,
                p->parent->private_data = topicname;
            } else if (!ustricmp(p->keyword, L"winhelp-filename")) {
                sfree(filename);
-               filename = utoa_dup(uadv(p->keyword));
+               filename = dupstr(adv(p->origkeyword));
            }
        }
     }
@@ -122,7 +129,7 @@ void whlp_backend(paragraph *sourceform, keywordlist *keywords,
            filename = newf;
            len = strlen(newf);
        }
-       cntname = mknewa(char, len);
+       cntname = mknewa(char, len+1);
        sprintf(cntname, "%.*s.cnt", len-4, filename);
     }
 
@@ -598,7 +605,7 @@ static void whlp_mkparagraph(struct bk_whlp_state *state,
            whlp_set_font(state->h, newfont);
        }
        if (removeattr(text->type) == word_Normal) {
-           if (whlp_convert(text->text, 0, &c, TRUE))
+           if (whlp_convert(text->text, 0, &c, TRUE) || !text->alt)
                whlp_text(state->h, c);
            else
                whlp_mkparagraph(state, deffont, text->alt, FALSE);
@@ -641,7 +648,7 @@ static void whlp_rdaddwc(rdstringc *rs, word *text) {
        assert(text->type != word_CodeQuote &&
               text->type != word_WkCodeQuote);
        if (removeattr(text->type) == word_Normal) {
-           if (whlp_convert(text->text, 0, &c, FALSE))
+           if (whlp_convert(text->text, 0, &c, FALSE) || !text->alt)
                rdaddsc(rs, c);
            else
                whlp_rdaddwc(rs, text->alt);
@@ -669,45 +676,49 @@ static void whlp_rdaddwc(rdstringc *rs, word *text) {
  */
 static int whlp_convert(wchar_t *s, int maxlen,
                        char **result, int hard_spaces) {
+    wchar_t *s2;
+    char *ret;
+    int ok;
+
     /*
-     * FIXME. Currently this is ISO8859-1 only.
+     * Enforce maxlen.
      */
-    int doing = (result != 0);
-    int ok = TRUE;
-    char *p = NULL;
-    int plen = 0, psize = 0;
-
-    if (maxlen <= 0)
-       maxlen = -1;
-
-    for (; *s && maxlen != 0; s++, maxlen--) {
-       wchar_t c = *s;
-       char outc;
-
-       if ((c >= 32 && c <= 126) ||
-           (c >= 160 && c <= 255)) {
-           /* Char is OK. */
-           if (c == 32 && hard_spaces)
-               outc = '\240';
-           else
-               outc = (char)c;
-       } else {
-           /* Char is not OK. */
-           ok = FALSE;
-           outc = 0xBF;               /* approximate the good old DEC `uh?' */
-       }
-       if (doing) {
-           if (plen >= psize) {
-               psize = plen + 256;
-               p = resize(p, psize);
-           }
-           p[plen++] = outc;
-       }
-    }
-    if (doing) {
-       p = resize(p, plen+1);
-       p[plen] = '\0';
-       *result = p;
+    if (maxlen > 0 && ustrlen(s) > maxlen) {
+       s2 = mknewa(wchar_t, maxlen+1);
+       memcpy(s2, s, maxlen * sizeof(wchar_t));
+       s2[maxlen] = L'\0';
+       s = s2;
+    } else
+       s2 = NULL;
+
+    /*
+     * We currently only support Win1252 in Windows Help files,
+     * because I don't know how to fiddle the character set
+     * designation in the |SYSTEM file to indicate anything else.
+     */
+
+    ret = utoa_careful_dup(s, CS_CP1252);
+    if (!ret) {
+       ok = FALSE;
+       ret = utoa_dup(s, CS_CP1252);
+    } else
+       ok = TRUE;
+
+    /*
+     * Enforce hard_spaces.
+     */
+    if (hard_spaces) {
+       char *p;
+
+       for (p = ret; *p; p++)
+           if (*p == ' ')
+               *p = '\240';
     }
+
+    if (s2)
+       sfree(s2);
+
+    *result = ret;
+
     return ok;
 }