summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Tatham <anakin@pobox.com>2001-12-04 21:12:40 +0000
committerSimon Tatham <anakin@pobox.com>2001-12-04 21:12:40 +0000
commit5e3a21913b6a47e78d3e4edd4238d028b90827b7 (patch)
treecfb3f25b5643cb957014f64aa831c27cf9a308eb
parent087e9915b987f1cd6eb679521f87fa3e5b2b9d96 (diff)
downloadhalibut-5e3a21913b6a47e78d3e4edd4238d028b90827b7.zip
halibut-5e3a21913b6a47e78d3e4edd4238d028b90827b7.tar.gz
halibut-5e3a21913b6a47e78d3e4edd4238d028b90827b7.tar.bz2
halibut-5e3a21913b6a47e78d3e4edd4238d028b90827b7.tar.xz
This update should bring the Windows Help back end up to
near-complete functionality. All that's missing now is indexing and horizontal rules. [originally from svn r1449]
-rw-r--r--bk_text.c3
-rw-r--r--bk_whlp.c84
-rw-r--r--bk_xhtml.c5
-rw-r--r--buttress.h31
-rw-r--r--contents.c47
-rw-r--r--index.c12
-rw-r--r--input.c4
-rw-r--r--keywords.c6
-rw-r--r--main.c2
-rw-r--r--malloc.c10
-rw-r--r--winhelp.c13
11 files changed, 154 insertions, 63 deletions
diff --git a/bk_text.c b/bk_text.c
index 3bec969..18a6af7 100644
--- a/bk_text.c
+++ b/bk_text.c
@@ -154,7 +154,8 @@ static textconfig text_configure(paragraph *source) {
return ret;
}
-void text_backend(paragraph *sourceform, keywordlist *keywords, index *idx) {
+void text_backend(paragraph *sourceform, keywordlist *keywords,
+ indexdata *idx) {
paragraph *p;
textconfig conf;
word *prefix, *body, *wp;
diff --git a/bk_whlp.c b/bk_whlp.c
index f049585..a9975c9 100644
--- a/bk_whlp.c
+++ b/bk_whlp.c
@@ -4,10 +4,6 @@
* TODO:
*
* - rules
- * - work out whether we can make an xref to a biblio entry jump
- * to the topic containing the citation itself?
- * - section macros are broken (can't do Up)
- * - need menus at the bottom of every non-leaf section.
* - indexing
* - allow user to specify section contexts.
*/
@@ -29,11 +25,13 @@ static void whlp_rdaddwc(rdstringc *rs, word *text);
static int whlp_convert(wchar_t *s, char **result, int hard_spaces);
static void whlp_mkparagraph(struct bk_whlp_state *state,
int font, word *text);
-
-void whlp_backend(paragraph *sourceform, keywordlist *keywords, index *idx) {
+static void whlp_navmenu(struct bk_whlp_state *state, paragraph *p);
+
+void whlp_backend(paragraph *sourceform, keywordlist *keywords,
+ indexdata *idx) {
WHLP h;
char *filename;
- paragraph *p;
+ paragraph *p, *lastsect;
struct bk_whlp_state state;
WHLP_TOPIC contents_topic, curr_topic;
@@ -47,8 +45,10 @@ void whlp_backend(paragraph *sourceform, keywordlist *keywords, index *idx) {
whlp_start_macro(h, "BrowseButtons()");
/*
- * Register topics for everything.
+ * Loop over the source form registering WHLP_TOPICs for
+ * everything.
*/
+
contents_topic = whlp_register_topic(h, "Top", NULL);
whlp_primary_topic(h, contents_topic);
for (p = sourceform; p; p = p->next) {
@@ -124,7 +124,18 @@ void whlp_backend(paragraph *sourceform, keywordlist *keywords, index *idx) {
}
}
+ /*
+ * 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);
+ }
+
curr_topic = contents_topic;
+ lastsect = NULL;
/* ------------------------------------------------------------------
* Now we've done the contents page, we're ready to go through
@@ -153,9 +164,19 @@ void whlp_backend(paragraph *sourceform, keywordlist *keywords, index *idx) {
case para_UnnumberedChapter:
case para_Heading:
case para_Subsect:
+ if (lastsect && lastsect->child) {
+ paragraph *q;
+ /*
+ * Do a navigation menu for the previous section we
+ * were in.
+ */
+ for (q = lastsect->child; q; q = q->sibling)
+ whlp_navmenu(&state, q);
+ }
{
rdstringc rs = {0, 0, NULL};
- WHLP_TOPIC new_topic;
+ WHLP_TOPIC new_topic, parent_topic;
+ char *macro, *topicid;
new_topic = p->private_data;
whlp_browse_link(h, curr_topic, new_topic);
@@ -166,9 +187,19 @@ void whlp_backend(paragraph *sourceform, keywordlist *keywords, index *idx) {
rdaddsc(&rs, ": "); /* FIXME: configurability */
}
whlp_rdaddwc(&rs, p->words);
- /* FIXME: change the macro to point at the parent topic. */
- /* FIXME: check if rs.text is NULL */
- whlp_begin_topic(h, new_topic, rs.text, "DB(\"btn_up\")", NULL);
+ if (p->parent == NULL)
+ parent_topic = contents_topic;
+ else
+ parent_topic = (WHLP_TOPIC)p->parent->private_data;
+ topicid = whlp_topic_id(parent_topic);
+ macro = smalloc(100+strlen(topicid));
+ sprintf(macro,
+ "CBB(\"btn_up\",\"JI(`',`%s')\");EB(\"btn_up\")",
+ topicid);
+ whlp_begin_topic(h, new_topic,
+ rs.text ? rs.text : "",
+ macro, NULL);
+ sfree(macro);
sfree(rs.text);
whlp_begin_para(h, WHLP_PARA_NONSCROLL);
@@ -179,6 +210,8 @@ void whlp_backend(paragraph *sourceform, keywordlist *keywords, index *idx) {
}
whlp_mkparagraph(&state, WHLP_FONT_TITLE, p->words);
whlp_end_para(h);
+
+ lastsect = p;
}
break;
@@ -243,6 +276,21 @@ void whlp_backend(paragraph *sourceform, keywordlist *keywords, index *idx) {
whlp_close(h, filename);
}
+static void whlp_navmenu(struct bk_whlp_state *state, paragraph *p) {
+ whlp_begin_para(state->h, WHLP_PARA_NONSCROLL);
+ /* FIXME: mkparagraph will need a way to disable all hyperlinks */
+ whlp_start_hyperlink(state->h, (WHLP_TOPIC)p->private_data);
+ if (p->kwtext) {
+ whlp_mkparagraph(state, WHLP_FONT_NORMAL, p->kwtext);
+ whlp_set_font(state->h, WHLP_FONT_NORMAL);
+ whlp_text(state->h, ": "); /* FIXME: configurability */
+ }
+ whlp_mkparagraph(state, WHLP_FONT_NORMAL, p->words);
+ whlp_end_hyperlink(state->h);
+ whlp_end_para(state->h);
+
+}
+
static void whlp_mkparagraph(struct bk_whlp_state *state,
int font, word *text) {
keyword *kwl;
@@ -265,10 +313,14 @@ static void whlp_mkparagraph(struct bk_whlp_state *state,
if (kwl->para->type == para_NumberedList) {
break; /* don't xref to numbered list items */
} else if (kwl->para->type == para_BiblioCited) {
- /* Bibliography items: perhaps we should xref them to the
- * Bibliography section they're in? Can we even do
- * this? FIXME: for the moment we leave them out. */
- break;
+ /*
+ * An xref to a bibliography item jumps to the section
+ * containing it.
+ */
+ if (kwl->para->parent)
+ xref_target = kwl->para->parent;
+ else
+ break;
} else {
xref_target = kwl->para;
}
diff --git a/bk_xhtml.c b/bk_xhtml.c
index 5bc52cf..4f6de4e 100644
--- a/bk_xhtml.c
+++ b/bk_xhtml.c
@@ -98,7 +98,7 @@ static void xhtml_heading(FILE *, paragraph *);
*/
static xhtmlconfig conf;
static keywordlist *keywords;
-static index *idx;
+static indexdata *idx;
static xhtmlfile *topfile;
static xhtmlsection *topsection;
static paragraph *sourceparas;
@@ -563,7 +563,8 @@ static void xhtml_free_file(xhtmlfile* xfile)
/*
* Main function.
*/
-void xhtml_backend(paragraph *sourceform, keywordlist *in_keywords, index *in_idx)
+void xhtml_backend(paragraph *sourceform, keywordlist *in_keywords,
+ indexdata *in_idx)
{
/* int i;*/
indexentry *ientry;
diff --git a/buttress.h b/buttress.h
index a233bdb..5b274d5 100644
--- a/buttress.h
+++ b/buttress.h
@@ -34,7 +34,7 @@ typedef struct keywordlist_Tag keywordlist;
typedef struct keyword_Tag keyword;
typedef struct userstyle_Tag userstyle;
typedef struct numberstate_Tag numberstate;
-typedef struct index_Tag index;
+typedef struct indexdata_Tag indexdata;
typedef struct indextag_Tag indextag;
typedef struct indexentry_Tag indexentry;
typedef struct macrostack_Tag macrostack;
@@ -83,6 +83,8 @@ struct paragraph_Tag {
word *kwtext2; /* numeric-only form of kwtext */
filepos fpos;
+ paragraph *parent, *child, *sibling; /* for hierarchy navigation */
+
void *private_data; /* for temp use in backends */
};
enum {
@@ -224,6 +226,7 @@ void sfree(void *p);
void free_word_list(word *w);
void free_para_list(paragraph *p);
word *dup_word_list(word *w);
+char *dupstr(char *s);
#define mknew(type) ( (type *) smalloc (sizeof (type)) )
#define mknewa(type, number) ( (type *) smalloc ((number) * sizeof (type)) )
@@ -309,7 +312,7 @@ void wrap_free(wrappedline *);
/*
* input.c
*/
-paragraph *read_input(input *in, index *idx);
+paragraph *read_input(input *in, indexdata *idx);
/*
* keywords.c
@@ -340,7 +343,7 @@ void subst_keywords(paragraph *, keywordlist *);
/*
* Data structure to hold both sides of the index.
*/
-struct index_Tag {
+struct indexdata_Tag {
tree234 *tags; /* holds type `indextag' */
tree234 *entries; /* holds type `indexentry' */
};
@@ -365,21 +368,20 @@ struct indexentry_Tag {
void *backend_data; /* private to back end */
};
-index *make_index(void);
-void cleanup_index(index *);
+indexdata *make_index(void);
+void cleanup_index(indexdata *);
/* index_merge takes responsibility for freeing arg 3 iff implicit; never
* takes responsibility for arg 2 */
-void index_merge(index *, int is_explicit, wchar_t *, word *);
-void build_index(index *);
-void index_debug(index *);
+void index_merge(indexdata *, int is_explicit, wchar_t *, word *);
+void build_index(indexdata *);
+void index_debug(indexdata *);
/*
* contents.c
*/
numberstate *number_init(void);
void number_cfg(numberstate *, paragraph *);
-word *number_mktext(numberstate *, int, int, wchar_t *,
- int, word **, filepos, int *);
+word *number_mktext(numberstate *, paragraph *, wchar_t *, int , int *);
void number_free(numberstate *);
/*
@@ -396,11 +398,16 @@ struct userstyle_Tag {
/*
* bk_text.c
*/
-void text_backend(paragraph *, keywordlist *, index *);
+void text_backend(paragraph *, keywordlist *, indexdata *);
/*
* bk_xhtml.c
*/
-void xhtml_backend(paragraph *, keywordlist *, index *);
+void xhtml_backend(paragraph *, keywordlist *, indexdata *);
+
+/*
+ * bk_whlp.c
+ */
+void whlp_backend(paragraph *, keywordlist *, indexdata *);
#endif
diff --git a/contents.c b/contents.c
index dae0d8d..85d230b 100644
--- a/contents.c
+++ b/contents.c
@@ -13,6 +13,8 @@ struct numberstate_Tag {
int appendixnum;
int ischapter;
int *sectionlevels;
+ paragraph **currentsects;
+ paragraph *lastsect;
int oklevel;
int maxsectlevel;
int listitem;
@@ -29,12 +31,16 @@ numberstate *number_init(void) {
ret->oklevel = -1; /* not even in a chapter yet */
ret->maxsectlevel = 32;
ret->sectionlevels = mknewa(int, ret->maxsectlevel);
+ ret->currentsects = mknewa(paragraph *, ret->maxsectlevel+1);
+ memset(ret->currentsects, 0, (ret->maxsectlevel+1)*sizeof(paragraph *));
+ ret->lastsect = NULL;
ret->listitem = -1;
return ret;
}
void number_free(numberstate *state) {
sfree(state->sectionlevels);
+ sfree(state->currentsects);
sfree(state);
}
@@ -115,14 +121,15 @@ void number_cfg(numberstate *state, paragraph *source) {
}
}
-word *number_mktext(numberstate *state, int para, int aux, wchar_t *category,
- int prev, word **auxret, filepos fpos, int *errflag) {
+word *number_mktext(numberstate *state, paragraph *p, wchar_t *category,
+ int prev, int *errflag) {
word *ret = NULL;
word **ret2 = &ret;
word **pret = &ret;
int i, level;
- switch (para) {
+ level = -2; /* default for non-section-heading */
+ switch (p->type) {
case para_Chapter:
state->chapternum++;
for (i = 0; i < state->maxsectlevel; i++)
@@ -133,14 +140,16 @@ word *number_mktext(numberstate *state, int para, int aux, wchar_t *category,
donumber(&pret, state->chapternum);
state->ischapter = 1;
state->oklevel = 0;
+ level = -1;
break;
case para_Heading:
case para_Subsect:
- level = (para == para_Heading ? 0 : aux);
+ level = (p->type == para_Heading ? 0 : p->aux);
if (level > state->oklevel) {
- error(err_sectjump, &fpos);
+ error(err_sectjump, &p->fpos);
*errflag = TRUE;
- return NULL;
+ ret = NULL;
+ break;
}
state->oklevel = level+1;
if (state->maxsectlevel <= level) {
@@ -175,6 +184,10 @@ word *number_mktext(numberstate *state, int para, int aux, wchar_t *category,
doanumber(&pret, state->appendixnum);
state->ischapter = 0;
state->oklevel = 0;
+ level = -1;
+ break;
+ case para_UnnumberedChapter:
+ level = -1;
break;
case para_NumberedList:
ret2 = pret;
@@ -185,7 +198,25 @@ word *number_mktext(numberstate *state, int para, int aux, wchar_t *category,
break;
}
- if (auxret)
- *auxret = *ret2;
+ /*
+ * Now set up parent, child and sibling links.
+ */
+ p->parent = p->child = p->sibling = NULL;
+ if (level != -2) {
+ if (state->currentsects[level+1])
+ state->currentsects[level+1]->sibling = p;
+ if (level >= 0 && state->currentsects[level]) {
+ p->parent = state->currentsects[level];
+ if (!state->currentsects[level]->child)
+ state->currentsects[level]->child = p;
+ }
+ state->currentsects[level+1] = state->lastsect = p;
+ for (i = level+2; i < state->maxsectlevel+1; i++)
+ state->currentsects[i] = NULL;
+ } else {
+ p->parent = state->lastsect;
+ }
+
+ p->kwtext2 = *ret2;
return ret;
}
diff --git a/index.c b/index.c
index 89cebb5..3fb45a1 100644
--- a/index.c
+++ b/index.c
@@ -9,8 +9,8 @@
static int compare_tags(void *av, void *bv);
static int compare_entries(void *av, void *bv);
-index *make_index(void) {
- index *ret = mknew(index);
+indexdata *make_index(void) {
+ indexdata *ret = mknew(indexdata);
ret->tags = newtree234(compare_tags);
ret->entries = newtree234(compare_entries);
return ret;
@@ -44,7 +44,7 @@ static int compare_entries(void *av, void *bv) {
* Guarantee on calling sequence: all implicit merges are given
* before the explicit ones.
*/
-void index_merge(index *idx, int is_explicit, wchar_t *tags, word *text) {
+void index_merge(indexdata *idx, int is_explicit, wchar_t *tags, word *text) {
indextag *t, *existing;
/*
@@ -113,7 +113,7 @@ void index_merge(index *idx, int is_explicit, wchar_t *tags, word *text) {
* entries in the original 2-3 tree with pointers to the RHS
* entries.
*/
-void build_index(index *i) {
+void build_index(indexdata *i) {
indextag *t;
word **ta;
int ti;
@@ -140,7 +140,7 @@ void build_index(index *i) {
}
}
-void cleanup_index(index *i) {
+void cleanup_index(indexdata *i) {
indextag *t;
indexentry *ent;
int ti;
@@ -163,7 +163,7 @@ void cleanup_index(index *i) {
static void dbg_prtwordlist(int level, word *w);
static void dbg_prtmerge(int is_explicit, wchar_t *tag, word *text);
-void index_debug(index *i) {
+void index_debug(indexdata *i) {
indextag *t;
indexentry *y;
int ti;
diff --git a/input.c b/input.c
index 90085bf..4fd8017 100644
--- a/input.c
+++ b/input.c
@@ -493,7 +493,7 @@ static paragraph *addpara(paragraph newpara, paragraph ***hptrptr) {
/*
* Reads a single file (ie until get() returns EOF)
*/
-static void read_file(paragraph ***ret, input *in, index *idx) {
+static void read_file(paragraph ***ret, input *in, indexdata *idx) {
token t;
paragraph par;
word wd, **whptr, **idximplicit;
@@ -1144,7 +1144,7 @@ static void read_file(paragraph ***ret, input *in, index *idx) {
macrocleanup(macros);
}
-paragraph *read_input(input *in, index *idx) {
+paragraph *read_input(input *in, indexdata *idx) {
paragraph *head = NULL;
paragraph **hptr = &head;
diff --git a/keywords.c b/keywords.c
index 26580f8..638ff29 100644
--- a/keywords.c
+++ b/keywords.c
@@ -114,10 +114,10 @@ keywordlist *get_keywords(paragraph *source) {
/*
* Number the chapter / section / list-item / whatever.
+ * This also sets up the `parent', `child' and `sibling'
+ * links.
*/
- source->kwtext = number_mktext(n, source->type, source->aux, q,
- prevpara, &source->kwtext2,
- source->fpos, &errors);
+ source->kwtext = number_mktext(n, source, q, prevpara, &errors);
prevpara = source->type;
if (p && *p) {
diff --git a/main.c b/main.c
index 96bbefd..8202bca 100644
--- a/main.c
+++ b/main.c
@@ -172,7 +172,7 @@ int main(int argc, char **argv) {
{
input in;
paragraph *sourceform, *p;
- index *idx;
+ indexdata *idx;
keywordlist *keywords;
in.filenames = infiles;
diff --git a/malloc.c b/malloc.c
index 0f42bde..e9f54d6 100644
--- a/malloc.c
+++ b/malloc.c
@@ -88,6 +88,16 @@ void *(srealloc)(LOGPARAMS void *p, int size) {
}
/*
+ * dupstr is like strdup, but with the never-return-NULL property
+ * of smalloc (and also reliably defined in all environments :-)
+ */
+char *dupstr(char *s) {
+ char *r = smalloc(1+strlen(s));
+ strcpy(r,s);
+ return r;
+}
+
+/*
* Duplicate a linked list of words
*/
word *dup_word_list(word *w) {
diff --git a/winhelp.c b/winhelp.c
index ffbd5cd..95f0939 100644
--- a/winhelp.c
+++ b/winhelp.c
@@ -76,22 +76,11 @@
#include <time.h>
#include <stdarg.h>
+#include "buttress.h"
#include "winhelp.h"
#include "tree234.h"
-/* ----------------------------------------------------------------------
- * FIXME: remove this whole section when we integrate to Buttress.
- */
-#define smalloc malloc
-#define srealloc realloc
-#define sfree free
-#define mknew(type) ( (type *) smalloc (sizeof (type)) )
-#define mknewa(type, number) ( (type *) smalloc ((number) * sizeof (type)) )
-#define resize(array, len) ( srealloc ((array), (len) * sizeof (*(array))) )
-#define lenof(array) ( sizeof(array) / sizeof(*(array)) )
-char *dupstr(char *s) { char *r = mknewa(char, 1+strlen(s)); strcpy(r,s); return r; }
#define UNUSEDARG(x) ( (x) = (x) )
-/* ------------------------------------------------------------------- */
#define GET_32BIT_LSB_FIRST(cp) \
(((unsigned long)(unsigned char)(cp)[0]) | \