2 * keywords.c: keep track of all cross-reference keywords
10 static int kwcmp(void *av
, void *bv
)
12 const keyword
*a
= (const keyword
*)av
;
13 const keyword
*b
= (const keyword
*)bv
;
14 return ustrcmp(a
->key
, b
->key
);
17 static int kwfind(void *av
, void *bv
)
19 wchar_t *a
= (wchar_t *)av
;
20 const keyword
*b
= (const keyword
*)bv
;
21 return ustrcmp(a
, b
->key
);
24 keyword
*kw_lookup(keywordlist
*kl
, wchar_t *str
) {
25 return find234(kl
->keys
, str
, kwfind
);
29 * This function reads through source form and collects the
30 * keywords. They get collected in a heap, sorted by Unicode
31 * collation, last at the top (so that we can Heapsort them when we
34 keywordlist
*get_keywords(paragraph
*source
) {
36 keywordlist
*kl
= mknew(keywordlist
);
37 numberstate
*n
= number_init();
38 int prevpara
= para_NotParaType
;
40 number_cfg(n
, source
);
43 kl
->keys
= newtree234(kwcmp
);
44 kl
->nlooseends
= kl
->looseendssize
= 0;
46 for (; source
; source
= source
->next
) {
48 p
= q
= source
->keyword
;
51 * Look for the section type override (`example',
52 * `question' or whatever - to replace `chapter' or
53 * `section' on a per-section basis).
56 q
= uadv(q
); /* point q at the word beyond */
61 * Number the chapter / section / list-item / whatever.
62 * This also sets up the `parent', `child' and `sibling'
65 source
->kwtext
= number_mktext(n
, source
, q
, &prevpara
, &errors
);
68 if (source
->kwtext
|| source
->type
== para_Biblio
) {
73 kw
->text
= source
->kwtext
;
75 ret
= add234(kl
->keys
, kw
);
77 error(err_multikw
, &source
->fpos
, &ret
->para
->fpos
, p
);
79 /* FIXME: what happens to kw->text? Does it leak? */
83 if (kl
->nlooseends
>= kl
->looseendssize
) {
84 kl
->looseendssize
= kl
->nlooseends
+ 32;
85 kl
->looseends
= resize(kl
->looseends
, kl
->looseendssize
);
87 kl
->looseends
[kl
->nlooseends
++] = source
->kwtext
;
101 void free_keywords(keywordlist
*kl
) {
103 while (kl
->nlooseends
)
104 free_word_list(kl
->looseends
[--kl
->nlooseends
]);
105 sfree(kl
->looseends
);
106 while ( (kw
= index234(kl
->keys
, 0)) != NULL
) {
107 delpos234(kl
->keys
, 0);
108 free_word_list(kw
->text
);
111 freetree234(kl
->keys
);
115 void subst_keywords(paragraph
*source
, keywordlist
*kl
) {
116 for (; source
; source
= source
->next
) {
118 for (ptr
= source
->words
; ptr
; ptr
= ptr
->next
) {
119 if (ptr
->type
== word_UpperXref
||
120 ptr
->type
== word_LowerXref
) {
122 word
**endptr
, *close
, *subst
;
124 kw
= kw_lookup(kl
, ptr
->text
);
126 error(err_nosuchkw
, &ptr
->fpos
, ptr
->text
);
129 subst
= dup_word_list(kw
->text
);
131 if (subst
&& ptr
->type
== word_LowerXref
&&
132 kw
->para
->type
!= para_Biblio
&&
133 kw
->para
->type
!= para_BiblioCited
)
134 ustrlow(subst
->text
);
139 close
->type
= word_XrefEnd
;
140 close
->fpos
= ptr
->fpos
;
142 close
->next
= ptr
->next
;
145 for (endptr
= &ptr
->next
; *endptr
; endptr
= &(*endptr
)->next
)
146 (*endptr
)->fpos
= ptr
->fpos
;