diff options
| author | Simon Tatham <anakin@pobox.com> | 2001-12-04 21:12:40 +0000 |
|---|---|---|
| committer | Simon Tatham <anakin@pobox.com> | 2001-12-04 21:12:40 +0000 |
| commit | 5e3a21913b6a47e78d3e4edd4238d028b90827b7 (patch) | |
| tree | cfb3f25b5643cb957014f64aa831c27cf9a308eb | |
| parent | 087e9915b987f1cd6eb679521f87fa3e5b2b9d96 (diff) | |
| download | halibut-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.c | 3 | ||||
| -rw-r--r-- | bk_whlp.c | 84 | ||||
| -rw-r--r-- | bk_xhtml.c | 5 | ||||
| -rw-r--r-- | buttress.h | 31 | ||||
| -rw-r--r-- | contents.c | 47 | ||||
| -rw-r--r-- | index.c | 12 | ||||
| -rw-r--r-- | input.c | 4 | ||||
| -rw-r--r-- | keywords.c | 6 | ||||
| -rw-r--r-- | main.c | 2 | ||||
| -rw-r--r-- | malloc.c | 10 | ||||
| -rw-r--r-- | winhelp.c | 13 |
11 files changed, 154 insertions, 63 deletions
@@ -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; @@ -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; } @@ -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; @@ -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 @@ -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; } @@ -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; @@ -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; @@ -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) { @@ -172,7 +172,7 @@ int main(int argc, char **argv) { { input in; paragraph *sourceform, *p; - index *idx; + indexdata *idx; keywordlist *keywords; in.filenames = infiles; @@ -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) { @@ -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]) | \ |