/*
* Windows Help backend for Halibut
- *
- * TODO:
- * - allow user to specify section contexts.
*/
#include <stdio.h>
#include <stdlib.h>
+#include <ctype.h>
#include <assert.h>
#include "halibut.h"
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;
int i;
int nesting;
indexentry *ie;
- int done_contents_topic;
-
- filename = "output.hlp"; /* FIXME: configurability */
- cntname = "output.cnt"; /* corresponding contents file */
+ int done_contents_topic = FALSE;
- state.cntfp = fopen(cntname, "wb");
- state.cnt_last_level = -1; state.cnt_workaround = 0;
+ IGNORE(unused);
h = state.h = whlp_new();
state.keywords = keywords;
/*
* Loop over the source form finding out whether the user has
- * specified particular help topic names for anything.
+ * specified particular help topic names for anything. Also
+ * pick out the output file name at this stage.
*/
+ filename = dupstr("output.hlp");
for (p = sourceform; p; p = p->next) {
p->private_data = NULL;
if (p->type == para_Config && p->parent) {
/* Store the topic name in the private_data field of the
* containing section. */
p->parent->private_data = topicname;
+ } else if (!ustricmp(p->keyword, L"winhelp-filename")) {
+ sfree(filename);
+ filename = dupstr(adv(p->origkeyword));
}
}
}
/*
+ * Ensure the output file name has a .hlp extension. This is
+ * required since we must create the .cnt file in parallel with
+ * it.
+ */
+ {
+ int len = strlen(filename);
+ if (len < 4 || filename[len-4] != '.' ||
+ tolower(filename[len-3] != 'h') ||
+ tolower(filename[len-2] != 'l') ||
+ tolower(filename[len-1] != 'p')) {
+ char *newf;
+ newf = mknewa(char, len + 5);
+ sprintf(newf, "%s.hlp", filename);
+ sfree(filename);
+ filename = newf;
+ len = strlen(newf);
+ }
+ cntname = mknewa(char, len+1);
+ sprintf(cntname, "%.*s.cnt", len-4, filename);
+ }
+
+ state.cntfp = fopen(cntname, "wb");
+ state.cnt_last_level = -1; state.cnt_workaround = 0;
+
+ /*
* Loop over the source form registering WHLP_TOPICs for
* everything.
*/
for (i = 0; (ie = index234(idx->entries, i)) != NULL; i++) {
sfree(ie->backend_data);
}
+
+ sfree(filename);
+ sfree(cntname);
}
static void whlp_contents_write(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);
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);
*/
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;
}