X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/halibut/blobdiff_plain/9057a0a8b88a40b9e842ea583a71a49eff306f63..3e030063e831da0af7bdb8d12f2f25a5224ba0be:/bk_whlp.c diff --git a/bk_whlp.c b/bk_whlp.c index 690bb7c..d11fd22 100644 --- a/bk_whlp.c +++ b/bk_whlp.c @@ -1,12 +1,10 @@ /* * Windows Help backend for Halibut - * - * TODO: - * - allow user to specify section contexts. */ #include #include +#include #include #include "halibut.h" @@ -45,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,13 +58,9 @@ void whlp_backend(paragraph *sourceform, keywordlist *keywords, 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; @@ -92,8 +91,10 @@ void whlp_backend(paragraph *sourceform, keywordlist *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) { @@ -103,11 +104,39 @@ void whlp_backend(paragraph *sourceform, keywordlist *keywords, /* 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. */ @@ -449,6 +478,9 @@ void whlp_backend(paragraph *sourceform, keywordlist *keywords, 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, @@ -573,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); @@ -616,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); @@ -644,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; }