/*
* 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"
FONT_NORMAL,
FONT_EMPH,
FONT_CODE,
+ FONT_ITAL_CODE,
+ FONT_BOLD_CODE,
FONT_TITLE,
FONT_TITLE_EMPH,
FONT_TITLE_CODE,
};
static void whlp_rdaddwc(rdstringc *rs, word *text);
-static int whlp_convert(wchar_t *s, char **result, int hard_spaces);
+static int whlp_convert(wchar_t *s, int maxlen,
+ char **result, int hard_spaces);
static void whlp_mkparagraph(struct bk_whlp_state *state,
int font, word *text, int subsidiary);
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)
+{
+ paragraph *p;
+ wchar_t *ufilename, *up;
+ int len;
+
+ p = mknew(paragraph);
+ memset(p, 0, sizeof(*p));
+ p->type = para_Config;
+ p->next = NULL;
+ p->fpos.filename = "<command line>";
+ p->fpos.line = p->fpos.col = -1;
+
+ ufilename = ufroma_dup(filename);
+ len = ustrlen(ufilename) + 2 + lenof(L"winhelp-filename");
+ p->keyword = mknewa(wchar_t, len);
+ up = p->keyword;
+ ustrcpy(up, L"winhelp-filename");
+ up = uadv(up);
+ ustrcpy(up, ufilename);
+ up = uadv(up);
+ *up = L'\0';
+ assert(up - p->keyword < len);
+ sfree(ufilename);
+
+ return p;
+}
+
void whlp_backend(paragraph *sourceform, keywordlist *keywords,
indexdata *idx) {
WHLP h;
int i;
int nesting;
indexentry *ie;
-
- filename = "output.hlp"; /* FIXME: configurability */
- cntname = "output.cnt"; /* corresponding contents file */
-
- state.cntfp = fopen(cntname, "wb");
- state.cnt_last_level = -1; state.cnt_workaround = 0;
+ int done_contents_topic = FALSE;
h = state.h = whlp_new();
state.keywords = keywords;
WHLP_FONT_ITALIC, 0, 0, 0);
whlp_create_font(h, "Courier New", WHLP_FONTFAM_FIXED, 24,
0, 0, 0, 0);
+ whlp_create_font(h, "Courier New", WHLP_FONTFAM_FIXED, 24,
+ WHLP_FONT_ITALIC, 0, 0, 0);
+ whlp_create_font(h, "Courier New", WHLP_FONTFAM_FIXED, 24,
+ WHLP_FONT_BOLD, 0, 0, 0);
whlp_create_font(h, "Arial", WHLP_FONTFAM_SERIF, 30,
WHLP_FONT_BOLD, 0, 0, 0);
whlp_create_font(h, "Arial", WHLP_FONTFAM_SERIF, 30,
/*
* 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) {
if (!ustricmp(p->keyword, L"winhelp-topic")) {
char *topicname;
- whlp_convert(uadv(p->keyword), &topicname, 0);
+ whlp_convert(uadv(p->keyword), 0, &topicname, 0);
/* 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 = utoa_dup(uadv(p->keyword));
}
}
}
/*
+ * 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);
+ 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.
*/
whlp_prepare(h);
/* ------------------------------------------------------------------
- * Do the contents page, containing title, preamble and
- * copyright.
+ * Begin the contents page.
*/
whlp_begin_topic(h, contents_topic, "Contents", "DB(\"btn_up\")", NULL);
}
/*
- * Next comes the preamble, which just goes into the ordinary
- * scrolling region.
- */
- for (p = sourceform; p; p = p->next) {
- if (p->type == para_Preamble) {
- whlp_para_attr(h, WHLP_PARA_SPACEBELOW, 12);
- whlp_begin_para(h, WHLP_PARA_SCROLL);
- whlp_mkparagraph(&state, FONT_NORMAL, p->words, FALSE);
- whlp_end_para(h);
- }
- }
-
- /*
- * The copyright goes to two places, again: into the contents
- * page and also into the system section.
+ * Put the copyright into the system section.
*/
{
rdstringc rs = {0, 0, NULL};
for (p = sourceform; p; p = p->next) {
- if (p->type == para_Copyright) {
- whlp_para_attr(h, WHLP_PARA_SPACEBELOW, 12);
- whlp_begin_para(h, WHLP_PARA_SCROLL);
- whlp_mkparagraph(&state, FONT_NORMAL, p->words, FALSE);
- whlp_end_para(h);
+ if (p->type == para_Copyright)
whlp_rdaddwc(&rs, p->words);
- }
}
if (rs.text) {
whlp_copyright(h, rs.text);
}
}
- /*
- * Now do the primary navigation menu.
- */
- for (p = sourceform; p; p = p->next) {
- if (p->type == para_Chapter ||
- p->type == para_Appendix ||
- p->type == para_UnnumberedChapter)
- whlp_navmenu(&state, p);
- }
-
- state.curr_topic = contents_topic;
lastsect = NULL;
/* ------------------------------------------------------------------
case para_BR:
case para_Biblio: /* only touch BiblioCited */
case para_VersionID:
- case para_Copyright:
- case para_Preamble:
case para_NoCite:
case para_Title:
break;
case para_LcontPush:
+ case para_QuotePush:
nesting++;
break;
case para_LcontPop:
+ case para_QuotePop:
assert(nesting > 0);
nesting--;
break;
case para_UnnumberedChapter:
case para_Heading:
case para_Subsect:
+
+ if (!done_contents_topic) {
+ paragraph *p;
+
+ /*
+ * If this is the first section title we've seen, then
+ * we're currently still in the contents topic. We
+ * should therefore finish up the contents page by
+ * writing a nav menu.
+ */
+ for (p = sourceform; p; p = p->next) {
+ if (p->type == para_Chapter ||
+ p->type == para_Appendix ||
+ p->type == para_UnnumberedChapter)
+ whlp_navmenu(&state, p);
+ }
+
+ state.curr_topic = contents_topic;
+
+ done_contents_topic = TRUE;
+ }
+
if (lastsect && lastsect->child) {
paragraph *q;
/*
break;
case para_Normal:
+ case para_Copyright:
case para_DescribedThing:
case para_Description:
case para_BiblioCited:
*/
{
word *w;
+ wchar_t *t, *e;
char *c;
- for (w = p->words; w; w = w->next) {
+
+ for (w = p->words; w; w = w->next) if (w->type == word_WeakCode) {
+ t = w->text;
+ if (w->next && w->next->type == word_Emph) {
+ w = w->next;
+ e = w->text;
+ } else
+ e = NULL;
+
if (!w->next)
whlp_para_attr(h, WHLP_PARA_SPACEBELOW, 12);
+
whlp_para_attr(h, WHLP_PARA_LEFTINDENT, 72*nesting);
whlp_begin_para(h, WHLP_PARA_SCROLL);
+ while (e && *e && *t) {
+ int n;
+ int ec = *e;
+
+ for (n = 0; t[n] && e[n] && e[n] == ec; n++);
+ if (ec == 'i')
+ whlp_set_font(h, FONT_ITAL_CODE);
+ else if (ec == 'b')
+ whlp_set_font(h, FONT_BOLD_CODE);
+ else
+ whlp_set_font(h, FONT_CODE);
+ whlp_convert(t, n, &c, FALSE);
+ whlp_text(h, c);
+ sfree(c);
+ t += n;
+ e += n;
+ }
whlp_set_font(h, FONT_CODE);
- whlp_convert(w->text, &c, FALSE);
+ whlp_convert(t, 0, &c, FALSE);
whlp_text(h, c);
sfree(c);
whlp_end_para(h);
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, &c, TRUE))
+ if (whlp_convert(text->text, 0, &c, TRUE))
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, &c, FALSE))
+ if (whlp_convert(text->text, 0, &c, FALSE))
rdaddsc(rs, c);
else
whlp_rdaddwc(rs, text->alt);
* characters are OK but `result' is non-NULL, a result _will_
* still be generated!
*/
-static int whlp_convert(wchar_t *s, char **result, int hard_spaces) {
+static int whlp_convert(wchar_t *s, int maxlen,
+ char **result, int hard_spaces) {
/*
* FIXME. Currently this is ISO8859-1 only.
*/
char *p = NULL;
int plen = 0, psize = 0;
- for (; *s; s++) {
+ if (maxlen <= 0)
+ maxlen = -1;
+
+ for (; *s && maxlen != 0; s++, maxlen--) {
wchar_t c = *s;
char outc;