removed text and help file backends; added some usage crap and removed the help command line optin(who needs that)

git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@1542 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
rainwater 2002-11-01 21:52:36 +00:00
parent ef17957fff
commit 048c27836c
23 changed files with 7533 additions and 10037 deletions

Binary file not shown.

View file

@ -1,5 +1,7 @@
Halibut is copyright (c) 1999-2001 Simon Tatham and James Aylett. Halibut is copyright (c) 1999-2001 Simon Tatham and James Aylett.
Note: This version is modified by Robert Rainwater and Amir Szekely
Permission is hereby granted, free of charge, to any person Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files obtaining a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction, (the "Software"), to deal in the Software without restriction,

View file

@ -5,38 +5,33 @@
#include <assert.h> #include <assert.h>
#include "halibut.h" #include "halibut.h"
static wchar_t * static wchar_t *gentext(int num)
gentext (int num)
{ {
wchar_t text[22]; wchar_t text[22];
wchar_t *p = text + sizeof (text); wchar_t *p = text + sizeof(text);
*--p = L'\0'; *--p = L'\0';
*--p = L']'; *--p = L']';
while (num != 0) while (num != 0) {
{ assert(p > text);
assert (p > text);
*--p = L"0123456789"[num % 10]; *--p = L"0123456789"[num % 10];
num /= 10; num /= 10;
} }
assert (p > text); assert(p > text);
*--p = L'['; *--p = L'[';
return ustrdup (p); return ustrdup(p);
} }
static void static void cite_biblio(keywordlist * kl, wchar_t * key, filepos fpos)
cite_biblio (keywordlist * kl, wchar_t * key, filepos fpos)
{ {
keyword *kw = kw_lookup (kl, key); keyword *kw = kw_lookup(kl, key);
if (!kw) if (!kw)
error (err_nosuchkw, &fpos, key); error(err_nosuchkw, &fpos, key);
else else {
{
/* /*
* We've found a \k reference. If it's a * We've found a \k reference. If it's a
* bibliography entry ... * bibliography entry ...
*/ */
if (kw->para->type == para_Biblio) if (kw->para->type == para_Biblio) {
{
/* /*
* ... then mark the paragraph as cited. * ... then mark the paragraph as cited.
*/ */
@ -51,52 +46,40 @@ cite_biblio (keywordlist * kl, wchar_t * key, filepos fpos)
* entries are actually cited (or \nocite-ed). * entries are actually cited (or \nocite-ed).
*/ */
void void gen_citations(paragraph * source, keywordlist * kl)
gen_citations (paragraph * source, keywordlist * kl)
{ {
paragraph *para; paragraph *para;
int bibnum = 0; int bibnum = 0;
for (para = source; para; para = para->next) for (para = source; para; para = para->next) {
{
word *ptr; word *ptr;
/* /*
* \BR and \nocite paragraphs get special processing here. * \BR and \nocite paragraphs get special processing here.
*/ */
if (para->type == para_BR) if (para->type == para_BR) {
{ keyword *kw = kw_lookup(kl, para->keyword);
keyword *kw = kw_lookup (kl, para->keyword); if (!kw) {
if (!kw) error(err_nosuchkw, &para->fpos, para->keyword);
{ } else if (kw->text) {
error (err_nosuchkw, &para->fpos, para->keyword); error(err_multiBR, &para->fpos, para->keyword);
} else {
kw->text = dup_word_list(para->words);
} }
else if (kw->text) } else if (para->type == para_NoCite) {
{
error (err_multiBR, &para->fpos, para->keyword);
}
else
{
kw->text = dup_word_list (para->words);
}
}
else if (para->type == para_NoCite)
{
wchar_t *wp = para->keyword; wchar_t *wp = para->keyword;
while (*wp) while (*wp) {
{ cite_biblio(kl, wp, para->fpos);
cite_biblio (kl, wp, para->fpos); wp = uadv(wp);
wp = uadv (wp);
} }
} }
/* /*
* Scan for keyword references. * Scan for keyword references.
*/ */
for (ptr = para->words; ptr; ptr = ptr->next) for (ptr = para->words; ptr; ptr = ptr->next) {
{
if (ptr->type == word_UpperXref || ptr->type == word_LowerXref) if (ptr->type == word_UpperXref || ptr->type == word_LowerXref)
cite_biblio (kl, ptr->text, ptr->fpos); cite_biblio(kl, ptr->text, ptr->fpos);
} }
} }
@ -106,16 +89,13 @@ gen_citations (paragraph * source, keywordlist * kl)
* texts for the ones that don't already have explicitly * texts for the ones that don't already have explicitly
* provided \BR text. * provided \BR text.
*/ */
for (para = source; para; para = para->next) for (para = source; para; para = para->next) {
{ if (para->type == para_BiblioCited) {
if (para->type == para_BiblioCited) keyword *kw = kw_lookup(kl, para->keyword);
{ assert(kw != NULL);
keyword *kw = kw_lookup (kl, para->keyword); if (!kw->text) {
assert (kw != NULL); word *wd = smalloc(sizeof(word));
if (!kw->text) wd->text = gentext(++bibnum);
{
word *wd = smalloc (sizeof (word));
wd->text = gentext (++bibnum);
wd->type = word_Normal; wd->type = word_Normal;
wd->alt = NULL; wd->alt = NULL;
wd->next = NULL; wd->next = NULL;

View file

@ -1,751 +0,0 @@
/*
* text backend for Halibut
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "halibut.h"
typedef enum
{ LEFT, LEFTPLUS, CENTRE }
alignment;
typedef struct
{
alignment align;
int just_numbers;
wchar_t underline;
wchar_t *number_suffix;
}
alignstruct;
typedef struct
{
int indent, indent_code;
int listindentbefore, listindentafter;
int width;
alignstruct atitle, achapter, *asect;
int nasect;
int include_version_id;
int indent_preambles;
word bullet;
}
textconfig;
static int text_convert (wchar_t *, char **);
static void text_heading (FILE *, word *, word *, word *, alignstruct, int,
int);
static void text_rule (FILE *, int, int);
static void text_para (FILE *, word *, char *, word *, int, int, int);
static void text_codepara (FILE *, word *, int, int);
static void text_versionid (FILE *, word *);
static alignment
utoalign (wchar_t * p)
{
if (!ustricmp (p, L"centre") || !ustricmp (p, L"center"))
return CENTRE;
if (!ustricmp (p, L"leftplus"))
return LEFTPLUS;
return LEFT;
}
static textconfig
text_configure (paragraph * source)
{
textconfig ret;
/*
* Non-negotiables.
*/
ret.bullet.next = NULL;
ret.bullet.alt = NULL;
ret.bullet.type = word_Normal;
ret.atitle.just_numbers = FALSE; /* ignored */
/*
* Defaults.
*/
ret.indent = 7;
ret.indent_code = 2;
ret.listindentbefore = 1;
ret.listindentafter = 3;
ret.width = 68;
ret.atitle.align = CENTRE;
ret.atitle.underline = L'=';
ret.achapter.align = LEFT;
ret.achapter.just_numbers = FALSE;
ret.achapter.number_suffix = ustrdup (L": ");
ret.achapter.underline = L'-';
ret.nasect = 1;
ret.asect = mknewa (alignstruct, ret.nasect);
ret.asect[0].align = LEFTPLUS;
ret.asect[0].just_numbers = TRUE;
ret.asect[0].number_suffix = ustrdup (L" ");
ret.asect[0].underline = L'\0';
ret.include_version_id = TRUE;
ret.indent_preambles = FALSE;
ret.bullet.text = ustrdup (L"-");
for (; source; source = source->next)
{
if (source->type == para_Config)
{
if (!ustricmp (source->keyword, L"text-indent"))
{
ret.indent = utoi (uadv (source->keyword));
}
else if (!ustricmp (source->keyword, L"text-indent-code"))
{
ret.indent_code = utoi (uadv (source->keyword));
}
else if (!ustricmp (source->keyword, L"text-width"))
{
ret.width = utoi (uadv (source->keyword));
}
else if (!ustricmp (source->keyword, L"text-list-indent"))
{
ret.listindentbefore = utoi (uadv (source->keyword));
}
else if (!ustricmp (source->keyword, L"text-listitem-indent"))
{
ret.listindentafter = utoi (uadv (source->keyword));
}
else if (!ustricmp (source->keyword, L"text-chapter-align"))
{
ret.achapter.align = utoalign (uadv (source->keyword));
}
else if (!ustricmp (source->keyword, L"text-chapter-underline"))
{
ret.achapter.underline = *uadv (source->keyword);
}
else if (!ustricmp (source->keyword, L"text-chapter-numeric"))
{
ret.achapter.just_numbers = utob (uadv (source->keyword));
}
else if (!ustricmp (source->keyword, L"text-chapter-suffix"))
{
ret.achapter.number_suffix = ustrdup (uadv (source->keyword));
}
else if (!ustricmp (source->keyword, L"text-section-align"))
{
wchar_t *p = uadv (source->keyword);
int n = 0;
if (uisdigit (*p))
{
n = utoi (p);
p = uadv (p);
}
if (n >= ret.nasect)
{
int i;
ret.asect = resize (ret.asect, n + 1);
for (i = ret.nasect; i <= n; i++)
ret.asect[i] = ret.asect[ret.nasect - 1];
ret.nasect = n + 1;
}
ret.asect[n].align = utoalign (p);
}
else if (!ustricmp (source->keyword, L"text-section-underline"))
{
wchar_t *p = uadv (source->keyword);
int n = 0;
if (uisdigit (*p))
{
n = utoi (p);
p = uadv (p);
}
if (n >= ret.nasect)
{
int i;
ret.asect = resize (ret.asect, n + 1);
for (i = ret.nasect; i <= n; i++)
ret.asect[i] = ret.asect[ret.nasect - 1];
ret.nasect = n + 1;
}
ret.asect[n].underline = *p;
}
else if (!ustricmp (source->keyword, L"text-section-numeric"))
{
wchar_t *p = uadv (source->keyword);
int n = 0;
if (uisdigit (*p))
{
n = utoi (p);
p = uadv (p);
}
if (n >= ret.nasect)
{
int i;
ret.asect = resize (ret.asect, n + 1);
for (i = ret.nasect; i <= n; i++)
ret.asect[i] = ret.asect[ret.nasect - 1];
ret.nasect = n + 1;
}
ret.asect[n].just_numbers = utob (p);
}
else if (!ustricmp (source->keyword, L"text-section-suffix"))
{
wchar_t *p = uadv (source->keyword);
int n = 0;
if (uisdigit (*p))
{
n = utoi (p);
p = uadv (p);
}
if (n >= ret.nasect)
{
int i;
ret.asect = resize (ret.asect, n + 1);
for (i = ret.nasect; i <= n; i++)
ret.asect[i] = ret.asect[ret.nasect - 1];
ret.nasect = n + 1;
}
ret.asect[n].number_suffix = ustrdup (p);
}
else if (!ustricmp (source->keyword, L"text-title-align"))
{
ret.atitle.align = utoalign (uadv (source->keyword));
}
else if (!ustricmp (source->keyword, L"text-title-underline"))
{
ret.atitle.underline = *uadv (source->keyword);
}
else if (!ustricmp (source->keyword, L"text-versionid"))
{
ret.include_version_id = utob (uadv (source->keyword));
}
else if (!ustricmp (source->keyword, L"text-indent-preamble"))
{
ret.indent_preambles = utob (uadv (source->keyword));
}
else if (!ustricmp (source->keyword, L"text-bullet"))
{
ret.bullet.text = uadv (source->keyword);
}
}
}
return ret;
}
void
text_backend (paragraph * sourceform, keywordlist * keywords, indexdata * idx)
{
paragraph *p;
textconfig conf;
word *prefix, *body, *wp;
word spaceword;
FILE *fp;
char *prefixextra;
int indentb, indenta;
IGNORE (keywords); /* we don't happen to need this */
IGNORE (idx); /* or this */
conf = text_configure (sourceform);
/*
* Determine the output file name, and open the output file
*
* FIXME: want configurable output file names here. For the
* moment, we'll just call it `output.txt'.
*/
fp = fopen ("output.txt", "w");
if (!fp)
{
error (err_cantopenw, "output.txt");
return;
}
/* Do the title */
for (p = sourceform; p; p = p->next)
if (p->type == para_Title)
text_heading (fp, NULL, NULL, p->words,
conf.atitle, conf.indent, conf.width);
/* Do the preamble and copyright */
for (p = sourceform; p; p = p->next)
if (p->type == para_Preamble)
text_para (fp, NULL, NULL, p->words,
conf.indent_preambles ? conf.indent : 0, 0,
conf.width + (conf.indent_preambles ? 0 : conf.indent));
for (p = sourceform; p; p = p->next)
if (p->type == para_Copyright)
text_para (fp, NULL, NULL, p->words,
conf.indent_preambles ? conf.indent : 0, 0,
conf.width + (conf.indent_preambles ? 0 : conf.indent));
/* Do the main document */
for (p = sourceform; p; p = p->next)
switch (p->type)
{
/*
* Things we ignore because we've already processed them or
* aren't going to touch them in this pass.
*/
case para_IM:
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;
/*
* Chapter titles.
*/
case para_Chapter:
case para_Appendix:
case para_UnnumberedChapter:
text_heading (fp, p->kwtext, p->kwtext2, p->words,
conf.achapter, conf.indent, conf.width);
break;
case para_Heading:
case para_Subsect:
text_heading (fp, p->kwtext, p->kwtext2, p->words,
conf.asect[p->aux >=
conf.nasect ? conf.nasect - 1 : p->aux],
conf.indent, conf.width);
break;
case para_Rule:
text_rule (fp, conf.indent, conf.width);
break;
case para_Normal:
case para_BiblioCited:
case para_Bullet:
case para_NumberedList:
if (p->type == para_Bullet)
{
prefix = &conf.bullet;
prefixextra = NULL;
indentb = conf.listindentbefore;
indenta = conf.listindentafter;
}
else if (p->type == para_NumberedList)
{
prefix = p->kwtext;
prefixextra = "."; /* FIXME: configurability */
indentb = conf.listindentbefore;
indenta = conf.listindentafter;
}
else
{
prefix = NULL;
prefixextra = NULL;
indentb = indenta = 0;
}
if (p->type == para_BiblioCited)
{
body = dup_word_list (p->kwtext);
for (wp = body; wp->next; wp = wp->next);
wp->next = &spaceword;
spaceword.next = p->words;
spaceword.alt = NULL;
spaceword.type = word_WhiteSpace;
spaceword.text = NULL;
}
else
{
wp = NULL;
body = p->words;
}
text_para (fp, prefix, prefixextra, body,
conf.indent + indentb, indenta,
conf.width - indentb - indenta);
if (wp)
{
wp->next = NULL;
free_word_list (body);
}
break;
case para_Code:
text_codepara (fp, p->words, conf.indent + conf.indent_code,
conf.width - 2 * conf.indent_code);
break;
}
/* Do the version ID */
if (conf.include_version_id)
{
for (p = sourceform; p; p = p->next)
if (p->type == para_VersionID)
text_versionid (fp, p->words);
}
/*
* Tidy up
*/
fclose (fp);
{
int i;
sfree (conf.achapter.number_suffix);
for (i = 0; i < conf.nasect; i++)
sfree (conf.asect[i].number_suffix);
sfree (conf.asect);
sfree (conf.bullet.text);
}
}
/*
* Convert a wide string into a string of chars. If `result' is
* non-NULL, mallocs the resulting string and stores a pointer to
* it in `*result'. If `result' is NULL, merely checks whether all
* characters in the string are feasible for the output character
* set.
*
* Return is nonzero if all characters are OK. If not all
* characters are OK but `result' is non-NULL, a result _will_
* still be generated!
*/
static int
text_convert (wchar_t * s, char **result)
{
/*
* FIXME. Currently this is ISO8859-1 only.
*/
int doing = (result != 0);
int ok = TRUE;
char *p = NULL;
int plen = 0, psize = 0;
for (; *s; s++)
{
wchar_t c = *s;
char outc;
if ((c >= 32 && c <= 126) || (c >= 160 && c <= 255))
{
/* Char is OK. */
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;
}
return ok;
}
static void
text_rdaddwc (rdstringc * rs, word * text, word * end)
{
char *c;
for (; text && text != end; text = text->next)
switch (text->type)
{
case word_HyperLink:
case word_HyperEnd:
case word_UpperXref:
case word_LowerXref:
case word_XrefEnd:
case word_IndexRef:
break;
case word_Normal:
case word_Emph:
case word_Code:
case word_WeakCode:
case word_WhiteSpace:
case word_EmphSpace:
case word_CodeSpace:
case word_WkCodeSpace:
case word_Quote:
case word_EmphQuote:
case word_CodeQuote:
case word_WkCodeQuote:
assert (text->type != word_CodeQuote &&
text->type != word_WkCodeQuote);
if (towordstyle (text->type) == word_Emph &&
(attraux (text->aux) == attr_First ||
attraux (text->aux) == attr_Only))
rdaddc (rs, '_'); /* FIXME: configurability */
else if (towordstyle (text->type) == word_Code &&
(attraux (text->aux) == attr_First ||
attraux (text->aux) == attr_Only))
rdaddc (rs, '`'); /* FIXME: configurability */
if (removeattr (text->type) == word_Normal)
{
if (text_convert (text->text, &c))
rdaddsc (rs, c);
else
text_rdaddwc (rs, text->alt, NULL);
sfree (c);
}
else if (removeattr (text->type) == word_WhiteSpace)
{
rdaddc (rs, ' ');
}
else if (removeattr (text->type) == word_Quote)
{
rdaddc (rs, quoteaux (text->aux) == quote_Open ? '`' : '\'');
/* FIXME: configurability */
}
if (towordstyle (text->type) == word_Emph &&
(attraux (text->aux) == attr_Last ||
attraux (text->aux) == attr_Only))
rdaddc (rs, '_'); /* FIXME: configurability */
else if (towordstyle (text->type) == word_Code &&
(attraux (text->aux) == attr_Last ||
attraux (text->aux) == attr_Only))
rdaddc (rs, '\''); /* FIXME: configurability */
break;
}
}
static int text_width (word *);
static int
text_width_list (word * text)
{
int w = 0;
while (text)
{
w += text_width (text);
text = text->next;
}
return w;
}
static int
text_width (word * text)
{
switch (text->type)
{
case word_HyperLink:
case word_HyperEnd:
case word_UpperXref:
case word_LowerXref:
case word_XrefEnd:
case word_IndexRef:
return 0;
case word_Normal:
case word_Emph:
case word_Code:
case word_WeakCode:
return (((text->type == word_Emph ||
text->type == word_Code)
? (attraux (text->aux) == attr_Only ? 2 :
attraux (text->aux) == attr_Always ? 0 : 1)
: 0) +
(text_convert (text->text, NULL) ?
ustrlen (text->text) : text_width_list (text->alt)));
case word_WhiteSpace:
case word_EmphSpace:
case word_CodeSpace:
case word_WkCodeSpace:
case word_Quote:
case word_EmphQuote:
case word_CodeQuote:
case word_WkCodeQuote:
assert (text->type != word_CodeQuote && text->type != word_WkCodeQuote);
return (((towordstyle (text->type) == word_Emph ||
towordstyle (text->type) == word_Code)
? (attraux (text->aux) == attr_Only ? 2 :
attraux (text->aux) == attr_Always ? 0 : 1) : 0) + 1);
}
return 0; /* should never happen */
}
static void
text_heading (FILE * fp, word * tprefix, word * nprefix, word * text,
alignstruct align, int indent, int width)
{
rdstringc t = { 0, 0, NULL };
int margin, length;
int firstlinewidth, wrapwidth;
wrappedline *wrapping, *p;
if (align.just_numbers && nprefix)
{
char *c;
text_rdaddwc (&t, nprefix, NULL);
if (text_convert (align.number_suffix, &c))
{
rdaddsc (&t, c);
sfree (c);
}
}
else if (!align.just_numbers && tprefix)
{
char *c;
text_rdaddwc (&t, tprefix, NULL);
if (text_convert (align.number_suffix, &c))
{
rdaddsc (&t, c);
sfree (c);
}
}
margin = length = (t.text ? strlen (t.text) : 0);
if (align.align == LEFTPLUS)
{
margin = indent - margin;
if (margin < 0)
margin = 0;
firstlinewidth = indent + width - margin - length;
wrapwidth = width;
}
else if (align.align == LEFT || align.align == CENTRE)
{
margin = 0;
firstlinewidth = indent + width - length;
wrapwidth = indent + width;
}
wrapping = wrap_para (text, firstlinewidth, wrapwidth, text_width);
for (p = wrapping; p; p = p->next)
{
text_rdaddwc (&t, p->begin, p->end);
length = (t.text ? strlen (t.text) : 0);
if (align.align == CENTRE)
{
margin = (indent + width - length) / 2;
if (margin < 0)
margin = 0;
}
fprintf (fp, "%*s%s\n", margin, "", t.text);
if (align.underline != L'\0')
{
char *u, uc;
wchar_t uw[2];
uw[0] = align.underline;
uw[1] = L'\0';
text_convert (uw, &u);
uc = u[0];
sfree (u);
fprintf (fp, "%*s", margin, "");
while (length--)
putc (uc, fp);
putc ('\n', fp);
}
if (align.align == LEFTPLUS)
margin = indent;
else
margin = 0;
sfree (t.text);
t = empty_rdstringc;
}
wrap_free (wrapping);
putc ('\n', fp);
sfree (t.text);
}
static void
text_rule (FILE * fp, int indent, int width)
{
while (indent--)
putc (' ', fp);
while (width--)
putc ('-', fp); /* FIXME: configurability! */
putc ('\n', fp);
putc ('\n', fp);
}
static void
text_para (FILE * fp, word * prefix, char *prefixextra, word * text,
int indent, int extraindent, int width)
{
wrappedline *wrapping, *p;
rdstringc pfx = { 0, 0, NULL };
int e;
int firstlinewidth = width;
if (prefix)
{
text_rdaddwc (&pfx, prefix, NULL);
if (prefixextra)
rdaddsc (&pfx, prefixextra);
fprintf (fp, "%*s%s", indent, "", pfx.text);
/* If the prefix is too long, shorten the first line to fit. */
e = extraindent - strlen (pfx.text);
if (e < 0)
{
firstlinewidth += e; /* this decreases it, since e < 0 */
if (firstlinewidth < 0)
{
e = indent + extraindent;
firstlinewidth = width;
fprintf (fp, "\n");
}
else
e = 0;
}
sfree (pfx.text);
}
else
e = indent + extraindent;
wrapping = wrap_para (text, firstlinewidth, width, text_width);
for (p = wrapping; p; p = p->next)
{
rdstringc t = { 0, 0, NULL };
text_rdaddwc (&t, p->begin, p->end);
fprintf (fp, "%*s%s\n", e, "", t.text);
e = indent + extraindent;
sfree (t.text);
}
wrap_free (wrapping);
putc ('\n', fp);
}
static void
text_codepara (FILE * fp, word * text, int indent, int width)
{
for (; text; text = text->next)
if (text->type == word_WeakCode)
{
char *c;
text_convert (text->text, &c);
if (strlen (c) > (size_t) width)
{
/* FIXME: warn */
}
fprintf (fp, "%*s%s\n", indent, "", c);
sfree (c);
}
putc ('\n', fp);
}
static void
text_versionid (FILE * fp, word * text)
{
rdstringc t = { 0, 0, NULL };
rdaddc (&t, '['); /* FIXME: configurability */
text_rdaddwc (&t, text, NULL);
rdaddc (&t, ']'); /* FIXME: configurability */
fprintf (fp, "%s\n", t.text);
sfree (t.text);
}

View file

@ -1,711 +0,0 @@
/*
* Windows Help backend for Halibut
*
* TODO:
* - allow user to specify section contexts.
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "halibut.h"
#include "winhelp.h"
struct bk_whlp_state
{
WHLP h;
indexdata *idx;
keywordlist *keywords;
WHLP_TOPIC curr_topic;
FILE *cntfp;
int cnt_last_level, cnt_workaround;
};
/*
* Indexes of fonts in our standard font descriptor set.
*/
enum
{
FONT_NORMAL,
FONT_EMPH,
FONT_CODE,
FONT_TITLE,
FONT_TITLE_EMPH,
FONT_TITLE_CODE,
FONT_RULE
};
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, 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);
void
whlp_backend (paragraph * sourceform, keywordlist * keywords, indexdata * idx)
{
WHLP h;
char *filename, *cntname;
paragraph *p, *lastsect;
struct bk_whlp_state state;
WHLP_TOPIC contents_topic;
int i;
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;
h = state.h = whlp_new ();
state.keywords = keywords;
state.idx = idx;
whlp_start_macro (h, "CB(\"btn_about\",\"&About\",\"About()\")");
whlp_start_macro (h, "CB(\"btn_up\",\"&Up\",\"Contents()\")");
whlp_start_macro (h, "BrowseButtons()");
whlp_create_font (h, "Times New Roman", WHLP_FONTFAM_SERIF, 24, 0, 0, 0, 0);
whlp_create_font (h, "Times New Roman", WHLP_FONTFAM_SERIF, 24,
WHLP_FONT_ITALIC, 0, 0, 0);
whlp_create_font (h, "Courier New", WHLP_FONTFAM_FIXED, 24, 0, 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,
WHLP_FONT_BOLD | WHLP_FONT_ITALIC, 0, 0, 0);
whlp_create_font (h, "Courier New", WHLP_FONTFAM_FIXED, 30,
WHLP_FONT_BOLD, 0, 0, 0);
whlp_create_font (h, "Courier New", WHLP_FONTFAM_SANS, 18,
WHLP_FONT_STRIKEOUT, 0, 0, 0);
/*
* Loop over the source form finding out whether the user has
* specified particular help topic names for anything.
*/
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);
/* Store the topic name in the private_data field of the
* containing section. */
p->parent->private_data = topicname;
}
}
}
/*
* 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)
{
if (p->type == para_Chapter ||
p->type == para_Appendix ||
p->type == para_UnnumberedChapter ||
p->type == para_Heading || p->type == para_Subsect)
{
char *topicid = p->private_data;
char *errstr;
p->private_data = whlp_register_topic (h, topicid, &errstr);
if (!p->private_data)
{
p->private_data = whlp_register_topic (h, NULL, NULL);
error (err_winhelp_ctxclash, &p->fpos, topicid, errstr);
}
sfree (topicid);
}
}
/*
* Loop over the index entries, preparing final text forms for
* each one.
*/
for (i = 0; (ie = index234 (idx->entries, i)) != NULL; i++)
{
rdstringc rs = { 0, 0, NULL };
whlp_rdaddwc (&rs, ie->text);
ie->backend_data = rs.text;
}
whlp_prepare (h);
/* ------------------------------------------------------------------
* Do the contents page, containing title, preamble and
* copyright.
*/
whlp_begin_topic (h, contents_topic, "Contents", "DB(\"btn_up\")", NULL);
/*
* The manual title goes in the non-scroll region, and also
* goes into the system title slot.
*/
{
rdstringc rs = { 0, 0, NULL };
for (p = sourceform; p; p = p->next)
{
if (p->type == para_Title)
{
whlp_begin_para (h, WHLP_PARA_NONSCROLL);
whlp_mkparagraph (&state, FONT_TITLE, p->words, FALSE);
whlp_rdaddwc (&rs, p->words);
whlp_end_para (h);
}
}
if (rs.text)
{
whlp_title (h, rs.text);
fprintf (state.cntfp, ":Title %s\r\n", rs.text);
sfree (rs.text);
}
whlp_contents_write (&state, 1, "Title page", contents_topic);
/* FIXME: configurability in that string */
}
/*
* 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.
*/
{
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);
whlp_rdaddwc (&rs, p->words);
}
}
if (rs.text)
{
whlp_copyright (h, rs.text);
sfree (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;
/* ------------------------------------------------------------------
* Now we've done the contents page, we're ready to go through
* and do the main manual text. Ooh.
*/
for (p = sourceform; p; p = p->next)
switch (p->type)
{
/*
* Things we ignore because we've already processed them or
* aren't going to touch them in this pass.
*/
case para_IM:
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;
/*
* Chapter and section titles: start a new Help topic.
*/
case para_Chapter:
case para_Appendix:
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, parent_topic;
char *macro, *topicid;
new_topic = p->private_data;
whlp_browse_link (h, state.curr_topic, new_topic);
state.curr_topic = new_topic;
if (p->kwtext)
{
whlp_rdaddwc (&rs, p->kwtext);
rdaddsc (&rs, ": "); /* FIXME: configurability */
}
whlp_rdaddwc (&rs, p->words);
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);
{
/*
* Output the .cnt entry.
*
* WinHelp has a bug involving having an internal
* node followed by a leaf at the same level: the
* leaf is output at the wrong level. We can mostly
* work around this by modifying the leaf level
* itself (see whlp_contents_write), but this
* doesn't work for top-level sections since we
* can't turn a level-1 leaf into a level-0 one. So
* for top-level leaf sections (Bibliography
* springs to mind), we output an internal node
* containing only the leaf for that section.
*/
int i;
paragraph *q;
/* Count up the level. */
i = 1;
for (q = p; q->parent; q = q->parent)
i++;
if (p->child || !p->parent)
{
/*
* If p has children then it needs to be a
* folder; if it has no parent then it needs to
* be a folder to work around the bug.
*/
whlp_contents_write (&state, i, rs.text, NULL);
i++;
}
whlp_contents_write (&state, i, rs.text, new_topic);
}
sfree (rs.text);
whlp_begin_para (h, WHLP_PARA_NONSCROLL);
if (p->kwtext)
{
whlp_mkparagraph (&state, FONT_TITLE, p->kwtext, FALSE);
whlp_set_font (h, FONT_TITLE);
whlp_text (h, ": "); /* FIXME: configurability */
}
whlp_mkparagraph (&state, FONT_TITLE, p->words, FALSE);
whlp_end_para (h);
lastsect = p;
}
break;
case para_Rule:
whlp_para_attr (h, WHLP_PARA_SPACEBELOW, 12);
whlp_para_attr (h, WHLP_PARA_ALIGNMENT, WHLP_ALIGN_CENTRE);
whlp_begin_para (h, WHLP_PARA_SCROLL);
whlp_set_font (h, FONT_RULE);
#define TEN "\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0"
#define TWENTY TEN TEN
#define FORTY TWENTY TWENTY
#define EIGHTY FORTY FORTY
whlp_text (h, EIGHTY);
#undef TEN
#undef TWENTY
#undef FORTY
#undef EIGHTY
whlp_end_para (h);
break;
case para_Normal:
case para_BiblioCited:
case para_Bullet:
case para_NumberedList:
whlp_para_attr (h, WHLP_PARA_SPACEBELOW, 12);
if (p->type == para_Bullet || p->type == para_NumberedList)
{
whlp_para_attr (h, WHLP_PARA_LEFTINDENT, 72);
whlp_para_attr (h, WHLP_PARA_FIRSTLINEINDENT, -36);
whlp_set_tabstop (h, 72, WHLP_ALIGN_LEFT);
whlp_begin_para (h, WHLP_PARA_SCROLL);
whlp_set_font (h, FONT_NORMAL);
if (p->type == para_Bullet)
{
whlp_text (h, "\x95");
}
else
{
whlp_mkparagraph (&state, FONT_NORMAL, p->kwtext, FALSE);
whlp_text (h, ".");
}
whlp_tab (h);
}
else
{
whlp_begin_para (h, WHLP_PARA_SCROLL);
}
if (p->type == para_BiblioCited)
{
whlp_mkparagraph (&state, FONT_NORMAL, p->kwtext, FALSE);
whlp_text (h, " ");
}
whlp_mkparagraph (&state, FONT_NORMAL, p->words, FALSE);
whlp_end_para (h);
break;
case para_Code:
/*
* In a code paragraph, each individual word is a line. For
* Help files, we will have to output this as a set of
* paragraphs, all but the last of which don't set
* SPACEBELOW.
*/
{
word *w;
char *c;
for (w = p->words; w; w = w->next)
{
if (!w->next)
whlp_para_attr (h, WHLP_PARA_SPACEBELOW, 12);
whlp_begin_para (h, WHLP_PARA_SCROLL);
whlp_set_font (h, FONT_CODE);
whlp_convert (w->text, &c, FALSE);
whlp_text (h, c);
sfree (c);
whlp_end_para (h);
}
}
break;
}
fclose (state.cntfp);
whlp_close (h, filename);
/*
* Loop over the index entries, cleaning up our final text
* forms.
*/
for (i = 0; (ie = index234 (idx->entries, i)) != NULL; i++)
{
sfree (ie->backend_data);
}
}
static void
whlp_contents_write (struct bk_whlp_state *state,
int level, char *text, WHLP_TOPIC topic)
{
/*
* Horrifying bug in WinHelp. When dropping a section level or
* more without using a folder-type entry, WinHelp accidentally
* adds one to the section level. So we correct for that here.
*/
if (state->cnt_last_level > level && topic)
state->cnt_workaround = -1;
else if (!topic)
state->cnt_workaround = 0;
state->cnt_last_level = level;
fprintf (state->cntfp, "%d ", level + state->cnt_workaround);
while (*text)
{
if (*text == '=')
fputc ('\\', state->cntfp);
fputc (*text, state->cntfp);
text++;
}
if (topic)
fprintf (state->cntfp, "=%s", whlp_topic_id (topic));
fputc ('\n', state->cntfp);
}
static void
whlp_navmenu (struct bk_whlp_state *state, paragraph * p)
{
whlp_begin_para (state->h, WHLP_PARA_NONSCROLL);
whlp_start_hyperlink (state->h, (WHLP_TOPIC) p->private_data);
if (p->kwtext)
{
whlp_mkparagraph (state, FONT_NORMAL, p->kwtext, TRUE);
whlp_set_font (state->h, FONT_NORMAL);
whlp_text (state->h, ": "); /* FIXME: configurability */
}
whlp_mkparagraph (state, FONT_NORMAL, p->words, TRUE);
whlp_end_hyperlink (state->h);
whlp_end_para (state->h);
}
static void
whlp_mkparagraph (struct bk_whlp_state *state,
int font, word * text, int subsidiary)
{
keyword *kwl;
int deffont = font;
int currfont = -1;
int newfont;
char *c;
paragraph *xref_target = NULL;
for (; text; text = text->next)
switch (text->type)
{
case word_HyperLink:
case word_HyperEnd:
break;
case word_IndexRef:
if (subsidiary)
break; /* disabled in subsidiary bits */
{
indextag *tag = index_findtag (state->idx, text->text);
int i;
if (!tag)
break;
for (i = 0; i < tag->nrefs; i++)
whlp_index_term (state->h, tag->refs[i]->backend_data,
state->curr_topic);
}
break;
case word_UpperXref:
case word_LowerXref:
if (subsidiary)
break; /* disabled in subsidiary bits */
kwl = kw_lookup (state->keywords, text->text);
assert (xref_target == NULL);
if (kwl->para->type == para_NumberedList)
{
break; /* don't xref to numbered list items */
}
else if (kwl->para->type == para_BiblioCited)
{
/*
* 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;
}
whlp_start_hyperlink (state->h,
(WHLP_TOPIC) xref_target->private_data);
break;
case word_XrefEnd:
if (subsidiary)
break; /* disabled in subsidiary bits */
if (xref_target)
whlp_end_hyperlink (state->h);
xref_target = NULL;
break;
case word_Normal:
case word_Emph:
case word_Code:
case word_WeakCode:
case word_WhiteSpace:
case word_EmphSpace:
case word_CodeSpace:
case word_WkCodeSpace:
case word_Quote:
case word_EmphQuote:
case word_CodeQuote:
case word_WkCodeQuote:
if (towordstyle (text->type) == word_Emph)
newfont = deffont + FONT_EMPH;
else if (towordstyle (text->type) == word_Code ||
towordstyle (text->type) == word_WeakCode)
newfont = deffont + FONT_CODE;
else
newfont = deffont;
if (newfont != currfont)
{
currfont = newfont;
whlp_set_font (state->h, newfont);
}
if (removeattr (text->type) == word_Normal)
{
if (whlp_convert (text->text, &c, TRUE))
whlp_text (state->h, c);
else
whlp_mkparagraph (state, deffont, text->alt, FALSE);
sfree (c);
}
else if (removeattr (text->type) == word_WhiteSpace)
{
whlp_text (state->h, " ");
}
else if (removeattr (text->type) == word_Quote)
{
whlp_text (state->h,
quoteaux (text->aux) == quote_Open ? "\x91" : "\x92");
/* FIXME: configurability */
}
break;
}
}
static void
whlp_rdaddwc (rdstringc * rs, word * text)
{
char *c;
for (; text; text = text->next)
switch (text->type)
{
case word_HyperLink:
case word_HyperEnd:
case word_UpperXref:
case word_LowerXref:
case word_XrefEnd:
case word_IndexRef:
break;
case word_Normal:
case word_Emph:
case word_Code:
case word_WeakCode:
case word_WhiteSpace:
case word_EmphSpace:
case word_CodeSpace:
case word_WkCodeSpace:
case word_Quote:
case word_EmphQuote:
case word_CodeQuote:
case word_WkCodeQuote:
assert (text->type != word_CodeQuote &&
text->type != word_WkCodeQuote);
if (removeattr (text->type) == word_Normal)
{
if (whlp_convert (text->text, &c, FALSE))
rdaddsc (rs, c);
else
whlp_rdaddwc (rs, text->alt);
sfree (c);
}
else if (removeattr (text->type) == word_WhiteSpace)
{
rdaddc (rs, ' ');
}
else if (removeattr (text->type) == word_Quote)
{
rdaddc (rs, quoteaux (text->aux) == quote_Open ? '\x91' : '\x92');
/* FIXME: configurability */
}
break;
}
}
/*
* Convert a wide string into a string of chars. If `result' is
* non-NULL, mallocs the resulting string and stores a pointer to
* it in `*result'. If `result' is NULL, merely checks whether all
* characters in the string are feasible for the output character
* set.
*
* Return is nonzero if all characters are OK. If not all
* 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)
{
/*
* FIXME. Currently this is ISO8859-1 only.
*/
int doing = (result != 0);
int ok = TRUE;
char *p = NULL;
int plen = 0, psize = 0;
for (; *s; s++)
{
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;
}
return ok;
}

File diff suppressed because it is too large Load diff

View file

@ -8,8 +8,7 @@
#include <limits.h> #include <limits.h>
#include "halibut.h" #include "halibut.h"
struct numberstate_Tag struct numberstate_Tag {
{
int chapternum; int chapternum;
int appendixnum; int appendixnum;
int ischapter; int ischapter;
@ -24,37 +23,34 @@ struct numberstate_Tag
wchar_t *apptext; /* the word for an appendix */ wchar_t *apptext; /* the word for an appendix */
}; };
numberstate * numberstate *number_init(void)
number_init (void)
{ {
numberstate *ret = mknew (numberstate); numberstate *ret = mknew(numberstate);
ret->chapternum = 0; ret->chapternum = 0;
ret->appendixnum = -1; ret->appendixnum = -1;
ret->ischapter = 1; ret->ischapter = 1;
ret->oklevel = -1; /* not even in a chapter yet */ ret->oklevel = -1; /* not even in a chapter yet */
ret->maxsectlevel = 32; ret->maxsectlevel = 32;
ret->sectionlevels = mknewa (int, ret->maxsectlevel); ret->sectionlevels = mknewa(int, ret->maxsectlevel);
ret->currentsects = mknewa (paragraph *, ret->maxsectlevel + 1); ret->currentsects = mknewa(paragraph *, ret->maxsectlevel + 1);
memset (ret->currentsects, 0, memset(ret->currentsects, 0,
(ret->maxsectlevel + 1) * sizeof (paragraph *)); (ret->maxsectlevel + 1) * sizeof(paragraph *));
ret->lastsect = NULL; ret->lastsect = NULL;
ret->listitem = -1; ret->listitem = -1;
return ret; return ret;
} }
void void number_free(numberstate * state)
number_free (numberstate * state)
{ {
sfree (state->sectionlevels); sfree(state->sectionlevels);
sfree (state->currentsects); sfree(state->currentsects);
sfree (state); sfree(state);
} }
static void static void dotext(word *** wret, wchar_t * text)
dotext (word *** wret, wchar_t * text)
{ {
word *mnewword = mknew (word); word *mnewword = mknew(word);
mnewword->text = ustrdup (text); mnewword->text = ustrdup(text);
mnewword->type = word_Normal; mnewword->type = word_Normal;
mnewword->alt = NULL; mnewword->alt = NULL;
mnewword->next = NULL; mnewword->next = NULL;
@ -62,10 +58,9 @@ dotext (word *** wret, wchar_t * text)
*wret = &mnewword->next; *wret = &mnewword->next;
} }
static void static void dospace(word *** wret)
dospace (word *** wret)
{ {
word *mnewword = mknew (word); word *mnewword = mknew(word);
mnewword->text = NULL; mnewword->text = NULL;
mnewword->type = word_WhiteSpace; mnewword->type = word_WhiteSpace;
mnewword->alt = NULL; mnewword->alt = NULL;
@ -74,31 +69,27 @@ dospace (word *** wret)
*wret = &mnewword->next; *wret = &mnewword->next;
} }
static void static void donumber(word *** wret, int num)
donumber (word *** wret, int num)
{ {
wchar_t text[20]; wchar_t text[20];
wchar_t *p = text + sizeof (text); wchar_t *p = text + sizeof(text);
*--p = L'\0'; *--p = L'\0';
while (num != 0) while (num != 0) {
{ assert(p > text);
assert (p > text);
*--p = L"0123456789"[num % 10]; *--p = L"0123456789"[num % 10];
num /= 10; num /= 10;
} }
dotext (wret, p); dotext(wret, p);
} }
static void static void doanumber(word *** wret, int num)
doanumber (word *** wret, int num)
{ {
wchar_t text[20]; wchar_t text[20];
wchar_t *p; wchar_t *p;
int nletters, aton; int nletters, aton;
nletters = 1; nletters = 1;
aton = 25; aton = 25;
while (num > aton) while (num > aton) {
{
nletters++; nletters++;
num -= aton + 1; num -= aton + 1;
if (aton < INT_MAX / 26) if (aton < INT_MAX / 26)
@ -106,19 +97,17 @@ doanumber (word *** wret, int num)
else else
aton = INT_MAX; aton = INT_MAX;
} }
p = text + sizeof (text); p = text + sizeof(text);
*--p = L'\0'; *--p = L'\0';
while (nletters--) while (nletters--) {
{ assert(p > text);
assert (p > text);
*--p = L"ABCDEFGHIJKLMNOPQRSTUVWXYZ"[num % 26]; *--p = L"ABCDEFGHIJKLMNOPQRSTUVWXYZ"[num % 26];
num /= 26; num /= 26;
} }
dotext (wret, p); dotext(wret, p);
} }
void void number_cfg(numberstate * state, paragraph * source)
number_cfg (numberstate * state, paragraph * source)
{ {
/* /*
* Defaults * Defaults
@ -127,28 +116,20 @@ number_cfg (numberstate * state, paragraph * source)
state->sectiontext = L"Section"; state->sectiontext = L"Section";
state->apptext = L"Appendix"; state->apptext = L"Appendix";
for (; source; source = source->next) for (; source; source = source->next) {
{ if (source->type == para_Config) {
if (source->type == para_Config) if (!ustricmp(source->keyword, L"chapter")) {
{ state->chaptertext = uadv(source->keyword);
if (!ustricmp (source->keyword, L"chapter")) } else if (!ustricmp(source->keyword, L"section")) {
{ state->sectiontext = uadv(source->keyword);
state->chaptertext = uadv (source->keyword); } else if (!ustricmp(source->keyword, L"appendix")) {
} state->apptext = uadv(source->keyword);
else if (!ustricmp (source->keyword, L"section"))
{
state->sectiontext = uadv (source->keyword);
}
else if (!ustricmp (source->keyword, L"appendix"))
{
state->apptext = uadv (source->keyword);
} }
} }
} }
} }
word * word *number_mktext(numberstate * state, paragraph * p, wchar_t * category,
number_mktext (numberstate * state, paragraph * p, wchar_t * category,
int prev, int *errflag) int prev, int *errflag)
{ {
word *ret = NULL; word *ret = NULL;
@ -157,16 +138,15 @@ number_mktext (numberstate * state, paragraph * p, wchar_t * category,
int i, level; int i, level;
level = -2; /* default for non-section-heading */ level = -2; /* default for non-section-heading */
switch (p->type) switch (p->type) {
{
case para_Chapter: case para_Chapter:
state->chapternum++; state->chapternum++;
for (i = 0; i < state->maxsectlevel; i++) for (i = 0; i < state->maxsectlevel; i++)
state->sectionlevels[i] = 0; state->sectionlevels[i] = 0;
dotext (&pret, category ? category : state->chaptertext); dotext(&pret, category ? category : state->chaptertext);
dospace (&pret); dospace(&pret);
ret2 = pret; ret2 = pret;
donumber (&pret, state->chapternum); donumber(&pret, state->chapternum);
state->ischapter = 1; state->ischapter = 1;
state->oklevel = 0; state->oklevel = 0;
level = -1; level = -1;
@ -174,46 +154,43 @@ number_mktext (numberstate * state, paragraph * p, wchar_t * category,
case para_Heading: case para_Heading:
case para_Subsect: case para_Subsect:
level = (p->type == para_Heading ? 0 : p->aux); level = (p->type == para_Heading ? 0 : p->aux);
if (level > state->oklevel) if (level > state->oklevel) {
{ error(err_sectjump, &p->fpos);
error (err_sectjump, &p->fpos);
*errflag = TRUE; *errflag = TRUE;
ret = NULL; ret = NULL;
break; break;
} }
state->oklevel = level + 1; state->oklevel = level + 1;
if (state->maxsectlevel <= level) if (state->maxsectlevel <= level) {
{
state->maxsectlevel = level + 32; state->maxsectlevel = level + 32;
state->sectionlevels = resize (state->sectionlevels, state->sectionlevels = resize(state->sectionlevels,
state->maxsectlevel); state->maxsectlevel);
} }
state->sectionlevels[level]++; state->sectionlevels[level]++;
for (i = level + 1; i < state->maxsectlevel; i++) for (i = level + 1; i < state->maxsectlevel; i++)
state->sectionlevels[i] = 0; state->sectionlevels[i] = 0;
dotext (&pret, category ? category : state->sectiontext); dotext(&pret, category ? category : state->sectiontext);
dospace (&pret); dospace(&pret);
ret2 = pret; ret2 = pret;
if (state->ischapter) if (state->ischapter)
donumber (&pret, state->chapternum); donumber(&pret, state->chapternum);
else else
doanumber (&pret, state->appendixnum); doanumber(&pret, state->appendixnum);
for (i = 0; i <= level; i++) for (i = 0; i <= level; i++) {
{ dotext(&pret, L".");
dotext (&pret, L".");
if (state->sectionlevels[i] == 0) if (state->sectionlevels[i] == 0)
state->sectionlevels[i] = 1; state->sectionlevels[i] = 1;
donumber (&pret, state->sectionlevels[i]); donumber(&pret, state->sectionlevels[i]);
} }
break; break;
case para_Appendix: case para_Appendix:
state->appendixnum++; state->appendixnum++;
for (i = 0; i < state->maxsectlevel; i++) for (i = 0; i < state->maxsectlevel; i++)
state->sectionlevels[i] = 0; state->sectionlevels[i] = 0;
dotext (&pret, category ? category : state->apptext); dotext(&pret, category ? category : state->apptext);
dospace (&pret); dospace(&pret);
ret2 = pret; ret2 = pret;
doanumber (&pret, state->appendixnum); doanumber(&pret, state->appendixnum);
state->ischapter = 0; state->ischapter = 0;
state->oklevel = 0; state->oklevel = 0;
level = -1; level = -1;
@ -226,7 +203,7 @@ number_mktext (numberstate * state, paragraph * p, wchar_t * category,
if (prev != para_NumberedList) if (prev != para_NumberedList)
state->listitem = 0; state->listitem = 0;
state->listitem++; state->listitem++;
donumber (&pret, state->listitem); donumber(&pret, state->listitem);
break; break;
} }
@ -234,12 +211,10 @@ number_mktext (numberstate * state, paragraph * p, wchar_t * category,
* Now set up parent, child and sibling links. * Now set up parent, child and sibling links.
*/ */
p->parent = p->child = p->sibling = NULL; p->parent = p->child = p->sibling = NULL;
if (level != -2) if (level != -2) {
{
if (state->currentsects[level + 1]) if (state->currentsects[level + 1])
state->currentsects[level + 1]->sibling = p; state->currentsects[level + 1]->sibling = p;
if (level >= 0 && state->currentsects[level]) if (level >= 0 && state->currentsects[level]) {
{
p->parent = state->currentsects[level]; p->parent = state->currentsects[level];
if (!state->currentsects[level]->child) if (!state->currentsects[level]->child)
state->currentsects[level]->child = p; state->currentsects[level]->child = p;
@ -247,9 +222,7 @@ number_mktext (numberstate * state, paragraph * p, wchar_t * category,
state->currentsects[level + 1] = state->lastsect = p; state->currentsects[level + 1] = state->lastsect = p;
for (i = level + 2; i < state->maxsectlevel + 1; i++) for (i = level + 2; i < state->maxsectlevel + 1; i++)
state->currentsects[i] = NULL; state->currentsects[i] = NULL;
} } else {
else
{
p->parent = state->lastsect; p->parent = state->lastsect;
} }

View file

@ -13,8 +13,7 @@
#define PREFIX 0x0001 /* give `halibut:' prefix */ #define PREFIX 0x0001 /* give `halibut:' prefix */
#define FILEPOS 0x0002 /* give file position prefix */ #define FILEPOS 0x0002 /* give file position prefix */
static void static void do_error(int code, va_list ap)
do_error (int code, va_list ap)
{ {
char error[1024]; char error[1024];
char auxbuf[256]; char auxbuf[256];
@ -23,205 +22,205 @@ do_error (int code, va_list ap)
filepos fpos, fpos2; filepos fpos, fpos2;
int flags; int flags;
switch (code) switch (code) {
{
case err_nomemory: /* no arguments */ case err_nomemory: /* no arguments */
sprintf (error, "out of memory"); sprintf(error, "out of memory");
flags = PREFIX; flags = PREFIX;
break; break;
case err_optnoarg: case err_optnoarg:
sp = va_arg (ap, char *); sp = va_arg(ap, char *);
sprintf (error, "option `-%.200s' requires an argument", sp); sprintf(error, "option `-%.200s' requires an argument", sp);
flags = PREFIX; flags = PREFIX;
break; break;
case err_nosuchopt: case err_nosuchopt:
sp = va_arg (ap, char *); sp = va_arg(ap, char *);
sprintf (error, "unrecognised option `-%.200s'", sp); sprintf(error, "unrecognised option `-%.200s'", sp);
flags = PREFIX; flags = PREFIX;
break; break;
case err_noinput: /* no arguments */ case err_noinput: /* no arguments */
sprintf (error, "no input files"); sprintf(error, "no input files");
flags = PREFIX; flags = PREFIX;
break; break;
case err_cantopen: case err_cantopen:
sp = va_arg (ap, char *); sp = va_arg(ap, char *);
sprintf (error, "unable to open input file `%.200s'", sp); sprintf(error, "unable to open input file `%.200s'", sp);
flags = PREFIX; flags = PREFIX;
break; break;
case err_nodata: /* no arguments */ case err_nodata: /* no arguments */
sprintf (error, "no data in input files"); sprintf(error, "no data in input files");
flags = PREFIX; flags = PREFIX;
break; break;
case err_brokencodepara: case err_brokencodepara:
fpos = *va_arg (ap, filepos *); fpos = *va_arg(ap, filepos *);
sprintf (error, "every line of a code paragraph should begin `\\c'"); sprintf(error,
"every line of a code paragraph should begin `\\c'");
flags = FILEPOS; flags = FILEPOS;
break; break;
case err_kwunclosed: case err_kwunclosed:
fpos = *va_arg (ap, filepos *); fpos = *va_arg(ap, filepos *);
sprintf (error, "expected `}' after paragraph keyword"); sprintf(error, "expected `}' after paragraph keyword");
flags = FILEPOS; flags = FILEPOS;
break; break;
case err_kwexpected: case err_kwexpected:
fpos = *va_arg (ap, filepos *); fpos = *va_arg(ap, filepos *);
sprintf (error, "expected a paragraph keyword"); sprintf(error, "expected a paragraph keyword");
flags = FILEPOS; flags = FILEPOS;
break; break;
case err_kwillegal: case err_kwillegal:
fpos = *va_arg (ap, filepos *); fpos = *va_arg(ap, filepos *);
sprintf (error, "expected no paragraph keyword"); sprintf(error, "expected no paragraph keyword");
flags = FILEPOS; flags = FILEPOS;
break; break;
case err_kwtoomany: case err_kwtoomany:
fpos = *va_arg (ap, filepos *); fpos = *va_arg(ap, filepos *);
sprintf (error, "expected only one paragraph keyword"); sprintf(error, "expected only one paragraph keyword");
flags = FILEPOS; flags = FILEPOS;
break; break;
case err_bodyillegal: case err_bodyillegal:
fpos = *va_arg (ap, filepos *); fpos = *va_arg(ap, filepos *);
sprintf (error, "expected no text after paragraph keyword"); sprintf(error, "expected no text after paragraph keyword");
flags = FILEPOS; flags = FILEPOS;
break; break;
case err_badparatype: case err_badparatype:
wsp = va_arg (ap, wchar_t *); wsp = va_arg(ap, wchar_t *);
sp = ustrtoa (wsp, auxbuf, sizeof (auxbuf)); sp = ustrtoa(wsp, auxbuf, sizeof(auxbuf));
fpos = *va_arg (ap, filepos *); fpos = *va_arg(ap, filepos *);
sprintf (error, "command `%.200s' unrecognised at start of" sprintf(error, "command `%.200s' unrecognised at start of"
" paragraph", sp); " paragraph", sp);
flags = FILEPOS; flags = FILEPOS;
break; break;
case err_badmidcmd: case err_badmidcmd:
wsp = va_arg (ap, wchar_t *); wsp = va_arg(ap, wchar_t *);
sp = ustrtoa (wsp, auxbuf, sizeof (auxbuf)); sp = ustrtoa(wsp, auxbuf, sizeof(auxbuf));
fpos = *va_arg (ap, filepos *); fpos = *va_arg(ap, filepos *);
sprintf (error, "command `%.200s' unexpected in mid-paragraph", sp); sprintf(error, "command `%.200s' unexpected in mid-paragraph", sp);
flags = FILEPOS; flags = FILEPOS;
break; break;
case err_unexbrace: case err_unexbrace:
fpos = *va_arg (ap, filepos *); fpos = *va_arg(ap, filepos *);
sprintf (error, "brace character unexpected in mid-paragraph"); sprintf(error, "brace character unexpected in mid-paragraph");
flags = FILEPOS; flags = FILEPOS;
break; break;
case err_explbr: case err_explbr:
fpos = *va_arg (ap, filepos *); fpos = *va_arg(ap, filepos *);
sprintf (error, "expected `{' after command"); sprintf(error, "expected `{' after command");
flags = FILEPOS; flags = FILEPOS;
break; break;
case err_commenteof: case err_commenteof:
fpos = *va_arg (ap, filepos *); fpos = *va_arg(ap, filepos *);
sprintf (error, "end of file unexpected inside `\\#{...}' comment"); sprintf(error, "end of file unexpected inside `\\#{...}' comment");
flags = FILEPOS; flags = FILEPOS;
break; break;
case err_kwexprbr: case err_kwexprbr:
fpos = *va_arg (ap, filepos *); fpos = *va_arg(ap, filepos *);
sprintf (error, "expected `}' after cross-reference"); sprintf(error, "expected `}' after cross-reference");
flags = FILEPOS; flags = FILEPOS;
break; break;
case err_missingrbrace: case err_missingrbrace:
fpos = *va_arg (ap, filepos *); fpos = *va_arg(ap, filepos *);
sprintf (error, "unclosed braces at end of paragraph"); sprintf(error, "unclosed braces at end of paragraph");
flags = FILEPOS; flags = FILEPOS;
break; break;
case err_nestedstyles: case err_nestedstyles:
fpos = *va_arg (ap, filepos *); fpos = *va_arg(ap, filepos *);
sprintf (error, "unable to nest text styles"); sprintf(error, "unable to nest text styles");
flags = FILEPOS; flags = FILEPOS;
break; break;
case err_nestedindex: case err_nestedindex:
fpos = *va_arg (ap, filepos *); fpos = *va_arg(ap, filepos *);
sprintf (error, "unable to nest index markings"); sprintf(error, "unable to nest index markings");
flags = FILEPOS; flags = FILEPOS;
break; break;
case err_nosuchkw: case err_nosuchkw:
fpos = *va_arg (ap, filepos *); fpos = *va_arg(ap, filepos *);
wsp = va_arg (ap, wchar_t *); wsp = va_arg(ap, wchar_t *);
sp = ustrtoa (wsp, auxbuf, sizeof (auxbuf)); sp = ustrtoa(wsp, auxbuf, sizeof(auxbuf));
sprintf (error, "unable to resolve cross-reference to `%.200s'", sp); sprintf(error, "unable to resolve cross-reference to `%.200s'",
sp);
flags = FILEPOS; flags = FILEPOS;
break; break;
case err_multiBR: case err_multiBR:
fpos = *va_arg (ap, filepos *); fpos = *va_arg(ap, filepos *);
wsp = va_arg (ap, wchar_t *); wsp = va_arg(ap, wchar_t *);
sp = ustrtoa (wsp, auxbuf, sizeof (auxbuf)); sp = ustrtoa(wsp, auxbuf, sizeof(auxbuf));
sprintf (error, "multiple `\\BR' entries given for `%.200s'", sp); sprintf(error, "multiple `\\BR' entries given for `%.200s'", sp);
flags = FILEPOS; flags = FILEPOS;
break; break;
case err_nosuchidxtag: case err_nosuchidxtag:
wsp = va_arg (ap, wchar_t *); wsp = va_arg(ap, wchar_t *);
sp = ustrtoa (wsp, auxbuf, sizeof (auxbuf)); sp = ustrtoa(wsp, auxbuf, sizeof(auxbuf));
sprintf (error, "`\\IM' on unknown index tag `%.200s'", sp); sprintf(error, "`\\IM' on unknown index tag `%.200s'", sp);
flags = 0; flags = 0;
/* FIXME: need to get a filepos to here somehow */ /* FIXME: need to get a filepos to here somehow */
break; break;
case err_cantopenw: case err_cantopenw:
sp = va_arg (ap, char *); sp = va_arg(ap, char *);
sprintf (error, "unable to open output file `%.200s'", sp); sprintf(error, "unable to open output file `%.200s'", sp);
flags = PREFIX; flags = PREFIX;
break; break;
case err_macroexists: case err_macroexists:
fpos = *va_arg (ap, filepos *); fpos = *va_arg(ap, filepos *);
wsp = va_arg (ap, wchar_t *); wsp = va_arg(ap, wchar_t *);
sp = ustrtoa (wsp, auxbuf, sizeof (auxbuf)); sp = ustrtoa(wsp, auxbuf, sizeof(auxbuf));
sprintf (error, "macro `%.200s' already defined", sp); sprintf(error, "macro `%.200s' already defined", sp);
flags = FILEPOS; flags = FILEPOS;
break; break;
case err_sectjump: case err_sectjump:
fpos = *va_arg (ap, filepos *); fpos = *va_arg(ap, filepos *);
sprintf (error, "expected higher heading levels before this one"); sprintf(error, "expected higher heading levels before this one");
flags = FILEPOS; flags = FILEPOS;
break; break;
case err_winhelp_ctxclash: case err_winhelp_ctxclash:
fpos = *va_arg (ap, filepos *); fpos = *va_arg(ap, filepos *);
sp = va_arg (ap, char *); sp = va_arg(ap, char *);
sp2 = va_arg (ap, char *); sp2 = va_arg(ap, char *);
sprintf (error, "Windows Help context id `%.200s' clashes with " sprintf(error, "Windows Help context id `%.200s' clashes with "
"previously defined `%.200s'", sp, sp2); "previously defined `%.200s'", sp, sp2);
flags = FILEPOS; flags = FILEPOS;
break; break;
case err_multikw: case err_multikw:
fpos = *va_arg (ap, filepos *); fpos = *va_arg(ap, filepos *);
fpos2 = *va_arg (ap, filepos *); fpos2 = *va_arg(ap, filepos *);
wsp = va_arg (ap, wchar_t *); wsp = va_arg(ap, wchar_t *);
sp = ustrtoa (wsp, auxbuf, sizeof (auxbuf)); sp = ustrtoa(wsp, auxbuf, sizeof(auxbuf));
sprintf (error, "paragraph keyword `%.200s' already defined at ", sp); sprintf(error, "paragraph keyword `%.200s' already defined at ",
sprintf (error + strlen (error), "%s:%d", fpos2.filename, fpos2.line); sp);
sprintf(error + strlen(error), "%s:%d", fpos2.filename,
fpos2.line);
flags = FILEPOS; flags = FILEPOS;
break; break;
case err_whatever: case err_whatever:
sp = va_arg (ap, char *); sp = va_arg(ap, char *);
vsprintf (error, sp, ap); vsprintf(error, sp, ap);
flags = PREFIX; flags = PREFIX;
break; break;
} }
if (flags & PREFIX) if (flags & PREFIX)
fputs ("halibut: ", stderr); fputs("halibut: ", stderr);
if (flags & FILEPOS) if (flags & FILEPOS) {
{ fprintf(stderr, "%s:%d:", fpos.filename, fpos.line);
fprintf (stderr, "%s:%d:", fpos.filename, fpos.line);
if (fpos.col > 0) if (fpos.col > 0)
fprintf (stderr, "%d:", fpos.col); fprintf(stderr, "%d:", fpos.col);
fputc (' ', stderr); fputc(' ', stderr);
} }
fputs (error, stderr); fputs(error, stderr);
fputc ('\n', stderr); fputc('\n', stderr);
} }
void void fatal(int code, ...)
fatal (int code, ...)
{ {
va_list ap; va_list ap;
va_start (ap, code); va_start(ap, code);
do_error (code, ap); do_error(code, ap);
va_end (ap); va_end(ap);
exit (EXIT_FAILURE); exit(EXIT_FAILURE);
} }
void void error(int code, ...)
error (int code, ...)
{ {
va_list ap; va_list ap;
va_start (ap, code); va_start(ap, code);
do_error (code, ap); do_error(code, ap);
va_end (ap); va_end(ap);
} }

View file

@ -43,8 +43,7 @@ typedef struct macrostack_Tag macrostack;
* Data structure to hold a file name and index, a line and a * Data structure to hold a file name and index, a line and a
* column number, for reporting errors * column number, for reporting errors
*/ */
struct filepos_Tag struct filepos_Tag {
{
char *filename; char *filename;
int line, col; int line, col;
}; };
@ -52,14 +51,11 @@ struct filepos_Tag
/* /*
* Data structure to hold all the file names etc for input * Data structure to hold all the file names etc for input
*/ */
typedef struct pushback_Tag typedef struct pushback_Tag {
{
int chr; int chr;
filepos pos; filepos pos;
} } pushback;
pushback; struct input_Tag {
struct input_Tag
{
char **filenames; /* complete list of input files */ char **filenames; /* complete list of input files */
int nfiles; /* how many in the list */ int nfiles; /* how many in the list */
FILE *currfp; /* the currently open one */ FILE *currfp; /* the currently open one */
@ -75,8 +71,7 @@ struct input_Tag
* Data structure to hold the input form of the source, ie a linked * Data structure to hold the input form of the source, ie a linked
* list of paragraphs * list of paragraphs
*/ */
struct paragraph_Tag struct paragraph_Tag {
{
paragraph *next; paragraph *next;
int type; int type;
wchar_t *keyword; /* for most special paragraphs */ wchar_t *keyword; /* for most special paragraphs */
@ -92,8 +87,7 @@ struct paragraph_Tag
void *private_data; /* for temp use in backends */ void *private_data; /* for temp use in backends */
}; };
enum enum {
{
para_IM, /* index merge */ para_IM, /* index merge */
para_BR, /* bibliography rewrite */ para_BR, /* bibliography rewrite */
para_Rule, /* random horizontal rule */ para_Rule, /* random horizontal rule */
@ -120,8 +114,7 @@ enum
/* /*
* Data structure to hold an individual word * Data structure to hold an individual word
*/ */
struct word_Tag struct word_Tag {
{
word *next, *alt; word *next, *alt;
int type; int type;
int aux; int aux;
@ -129,8 +122,7 @@ struct word_Tag
wchar_t *text; wchar_t *text;
filepos fpos; filepos fpos;
}; };
enum enum {
{
/* ORDERING CONSTRAINT: these normal-word types ... */ /* ORDERING CONSTRAINT: these normal-word types ... */
word_Normal, word_Normal,
word_Emph, word_Emph,
@ -156,8 +148,7 @@ enum
word_HyperEnd /* (also invisible; no text) */ word_HyperEnd /* (also invisible; no text) */
}; };
/* aux values for attributed words */ /* aux values for attributed words */
enum enum {
{
attr_Only = 0x0000, /* a lone word with the attribute */ attr_Only = 0x0000, /* a lone word with the attribute */
attr_First = 0x0001, /* the first of a series */ attr_First = 0x0001, /* the first of a series */
attr_Last = 0x0002, /* the last of a series */ attr_Last = 0x0002, /* the last of a series */
@ -165,8 +156,7 @@ enum
attr_mask = 0x0003, attr_mask = 0x0003,
}; };
/* aux values for quote-type words */ /* aux values for quote-type words */
enum enum {
{
quote_Open = 0x0010, quote_Open = 0x0010,
quote_Close = 0x0020, quote_Close = 0x0020,
quote_mask = 0x0030, quote_mask = 0x0030,
@ -185,12 +175,9 @@ enum
/* /*
* error.c * error.c
*/ */
void void fatal(int code, ...) NORETURN;
fatal (int code, ...) void error(int code, ...);
NORETURN; enum {
void error (int code, ...);
enum
{
err_nomemory, /* out of memory */ err_nomemory, /* out of memory */
err_optnoarg, /* option `-%s' requires an argument */ err_optnoarg, /* option `-%s' requires an argument */
err_nosuchopt, /* unrecognised option `-%s' */ err_nosuchopt, /* unrecognised option `-%s' */
@ -221,27 +208,27 @@ fatal (int code, ...)
err_winhelp_ctxclash, /* WinHelp context ID hash clash */ err_winhelp_ctxclash, /* WinHelp context ID hash clash */
err_multikw, /* keyword clash in sections */ err_multikw, /* keyword clash in sections */
err_whatever /* random error of another type */ err_whatever /* random error of another type */
}; };
/* /*
* malloc.c * malloc.c
*/ */
#ifdef LOGALLOC #ifdef LOGALLOC
void *smalloc (char *file, int line, int size); void *smalloc(char *file, int line, int size);
void *srealloc (char *file, int line, void *p, int size); void *srealloc(char *file, int line, void *p, int size);
void sfree (char *file, int line, void *p); void sfree(char *file, int line, void *p);
#define smalloc(x) smalloc(__FILE__, __LINE__, x) #define smalloc(x) smalloc(__FILE__, __LINE__, x)
#define srealloc(x, y) srealloc(__FILE__, __LINE__, x, y) #define srealloc(x, y) srealloc(__FILE__, __LINE__, x, y)
#define sfree(x) sfree(__FILE__, __LINE__, x) #define sfree(x) sfree(__FILE__, __LINE__, x)
#else #else
void *smalloc (int size); void *smalloc(int size);
void *srealloc (void *p, int size); void *srealloc(void *p, int size);
void sfree (void *p); void sfree(void *p);
#endif #endif
void free_word_list (word * w); void free_word_list(word * w);
void free_para_list (paragraph * p); void free_para_list(paragraph * p);
word *dup_word_list (word * w); word *dup_word_list(word * w);
char *dupstr (char *s); char *dupstr(char *s);
#define mknew(type) ( (type *) smalloc (sizeof (type)) ) #define mknew(type) ( (type *) smalloc (sizeof (type)) )
#define mknewa(type, number) ( (type *) smalloc ((number) * sizeof (type)) ) #define mknewa(type, number) ( (type *) smalloc ((number) * sizeof (type)) )
@ -251,110 +238,104 @@ fatal (int code, ...)
/* /*
* ustring.c * ustring.c
*/ */
wchar_t *ustrdup (wchar_t * s); wchar_t *ustrdup(wchar_t * s);
char *ustrtoa (wchar_t * s, char *outbuf, int size); char *ustrtoa(wchar_t * s, char *outbuf, int size);
int ustrlen (wchar_t * s); int ustrlen(wchar_t * s);
wchar_t *uadv (wchar_t * s); wchar_t *uadv(wchar_t * s);
wchar_t *ustrcpy (wchar_t * dest, wchar_t * source); wchar_t *ustrcpy(wchar_t * dest, wchar_t * source);
wchar_t utolower (wchar_t); wchar_t utolower(wchar_t);
int ustrcmp (wchar_t * lhs, wchar_t * rhs); int ustrcmp(wchar_t * lhs, wchar_t * rhs);
int ustricmp (wchar_t * lhs, wchar_t * rhs); int ustricmp(wchar_t * lhs, wchar_t * rhs);
int utoi (wchar_t *); int utoi(wchar_t *);
int utob (wchar_t *); int utob(wchar_t *);
int uisdigit (wchar_t); int uisdigit(wchar_t);
wchar_t *ustrlow (wchar_t * s); wchar_t *ustrlow(wchar_t * s);
wchar_t *ustrftime (wchar_t * fmt, struct tm *timespec); wchar_t *ustrftime(wchar_t * fmt, struct tm *timespec);
/* /*
* help.c * help.c
*/ */
void help (void); void usage(void);
void usage (void); void showversion(void);
void showversion (void);
/* /*
* licence.c * licence.c
*/ */
void licence (void); void licence(void);
/* /*
* version.c * version.c
*/ */
const char *const version; const char *const version;
/* /*
* misc.c * misc.c
*/ */
typedef struct stackTag *stack; typedef struct stackTag *stack;
stack stk_new (void); stack stk_new(void);
void stk_free (stack); void stk_free(stack);
void stk_push (stack, void *); void stk_push(stack, void *);
void *stk_pop (stack); void *stk_pop(stack);
typedef struct tagRdstring rdstring; typedef struct tagRdstring rdstring;
struct tagRdstring struct tagRdstring {
{
int pos, size; int pos, size;
wchar_t *text; wchar_t *text;
}; };
typedef struct tagRdstringc rdstringc; typedef struct tagRdstringc rdstringc;
struct tagRdstringc struct tagRdstringc {
{
int pos, size; int pos, size;
char *text; char *text;
}; };
extern const rdstring empty_rdstring; extern const rdstring empty_rdstring;
extern const rdstringc empty_rdstringc; extern const rdstringc empty_rdstringc;
void rdadd (rdstring * rs, wchar_t c); void rdadd(rdstring * rs, wchar_t c);
void rdadds (rdstring * rs, wchar_t * p); void rdadds(rdstring * rs, wchar_t * p);
wchar_t *rdtrim (rdstring * rs); wchar_t *rdtrim(rdstring * rs);
void rdaddc (rdstringc * rs, char c); void rdaddc(rdstringc * rs, char c);
void rdaddsc (rdstringc * rs, char *p); void rdaddsc(rdstringc * rs, char *p);
char *rdtrimc (rdstringc * rs); char *rdtrimc(rdstringc * rs);
int compare_wordlists (word * a, word * b); int compare_wordlists(word * a, word * b);
void mark_attr_ends (paragraph * sourceform); void mark_attr_ends(paragraph * sourceform);
typedef struct tagWrappedLine wrappedline; typedef struct tagWrappedLine wrappedline;
struct tagWrappedLine struct tagWrappedLine {
{
wrappedline *next; wrappedline *next;
word *begin, *end; /* first & last words of line */ word *begin, *end; /* first & last words of line */
int nspaces; /* number of whitespaces in line */ int nspaces; /* number of whitespaces in line */
int shortfall; /* how much shorter than max width */ int shortfall; /* how much shorter than max width */
}; };
wrappedline *wrap_para (word *, int, int, int (*)(word *)); wrappedline *wrap_para(word *, int, int, int (*)(word *));
void wrap_free (wrappedline *); void wrap_free(wrappedline *);
/* /*
* input.c * input.c
*/ */
paragraph *read_input (input * in, indexdata * idx); paragraph *read_input(input * in, indexdata * idx);
/* /*
* keywords.c * keywords.c
*/ */
struct keywordlist_Tag struct keywordlist_Tag {
{
int nkeywords; int nkeywords;
int size; int size;
tree234 *keys; /* sorted by `key' field */ tree234 *keys; /* sorted by `key' field */
word **looseends; /* non-keyword list element numbers */ word **looseends; /* non-keyword list element numbers */
int nlooseends; int nlooseends;
int looseendssize; int looseendssize;
}; };
struct keyword_Tag struct keyword_Tag {
{
wchar_t *key; /* the keyword itself */ wchar_t *key; /* the keyword itself */
word *text; /* "Chapter 2", "Appendix Q"... */ word *text; /* "Chapter 2", "Appendix Q"... */
/* (NB: filepos are not set) */ /* (NB: filepos are not set) */
paragraph *para; /* the paragraph referenced */ paragraph *para; /* the paragraph referenced */
}; };
keyword *kw_lookup (keywordlist *, wchar_t *); keyword *kw_lookup(keywordlist *, wchar_t *);
keywordlist *get_keywords (paragraph *); keywordlist *get_keywords(paragraph *);
void free_keywords (keywordlist *); void free_keywords(keywordlist *);
void subst_keywords (paragraph *, keywordlist *); void subst_keywords(paragraph *, keywordlist *);
/* /*
* index.c * index.c
@ -363,76 +344,62 @@ fatal (int code, ...)
/* /*
* Data structure to hold both sides of the index. * Data structure to hold both sides of the index.
*/ */
struct indexdata_Tag struct indexdata_Tag {
{
tree234 *tags; /* holds type `indextag' */ tree234 *tags; /* holds type `indextag' */
tree234 *entries; /* holds type `indexentry' */ tree234 *entries; /* holds type `indexentry' */
}; };
/* /*
* Data structure to hold an index tag (LHS of index). * Data structure to hold an index tag (LHS of index).
*/ */
struct indextag_Tag struct indextag_Tag {
{
wchar_t *name; wchar_t *name;
word *implicit_text; word *implicit_text;
word **explicit_texts; word **explicit_texts;
int nexplicit, explicit_size; int nexplicit, explicit_size;
int nrefs; int nrefs;
indexentry **refs; /* array of entries referenced by tag */ indexentry **refs; /* array of entries referenced by tag */
}; };
/* /*
* Data structure to hold an index entry (RHS of index). * Data structure to hold an index entry (RHS of index).
*/ */
struct indexentry_Tag struct indexentry_Tag {
{
word *text; word *text;
void *backend_data; /* private to back end */ void *backend_data; /* private to back end */
}; };
indexdata *make_index (void); indexdata *make_index(void);
void cleanup_index (indexdata *); void cleanup_index(indexdata *);
/* index_merge takes responsibility for freeing arg 3 iff implicit; never /* index_merge takes responsibility for freeing arg 3 iff implicit; never
* takes responsibility for arg 2 */ * takes responsibility for arg 2 */
void index_merge (indexdata *, int is_explicit, wchar_t *, word *); void index_merge(indexdata *, int is_explicit, wchar_t *, word *);
void build_index (indexdata *); void build_index(indexdata *);
void index_debug (indexdata *); void index_debug(indexdata *);
indextag *index_findtag (indexdata * idx, wchar_t * name); indextag *index_findtag(indexdata * idx, wchar_t * name);
/* /*
* contents.c * contents.c
*/ */
numberstate *number_init (void); numberstate *number_init(void);
void number_cfg (numberstate *, paragraph *); void number_cfg(numberstate *, paragraph *);
word *number_mktext (numberstate *, paragraph *, wchar_t *, int, int *); word *number_mktext(numberstate *, paragraph *, wchar_t *, int, int *);
void number_free (numberstate *); void number_free(numberstate *);
/* /*
* biblio.c * biblio.c
*/ */
void gen_citations (paragraph *, keywordlist *); void gen_citations(paragraph *, keywordlist *);
/* /*
* style.c * style.c
*/ */
struct userstyle_Tag struct userstyle_Tag {
{ };
};
/*
* bk_text.c
*/
void text_backend (paragraph *, keywordlist *, indexdata *);
/* /*
* bk_xhtml.c * bk_xhtml.c
*/ */
void xhtml_backend (paragraph *, keywordlist *, indexdata *); void xhtml_backend(paragraph *, keywordlist *, indexdata *);
/*
* bk_whlp.c
*/
void whlp_backend (paragraph *, keywordlist *, indexdata *);
#endif #endif

View file

@ -5,34 +5,19 @@
#include <stdio.h> #include <stdio.h>
#include "halibut.h" #include "halibut.h"
static char *helptext[] = {
"FIXME: help text goes here",
NULL
};
static char *usagetext[] = { static char *usagetext[] = {
"FIXME: usage text goes here", "halibut.exe file1 [file2 ...]",
NULL NULL
}; };
void void usage(void)
help (void)
{
char **p;
for (p = helptext; *p; p++)
puts (*p);
}
void
usage (void)
{ {
char **p; char **p;
for (p = usagetext; *p; p++) for (p = usagetext; *p; p++)
puts (*p); puts(*p);
} }
void void showversion(void)
showversion (void)
{ {
printf ("Halibut, %s\n", version); printf("Halibut, %s\n", version);
} }

View file

@ -6,22 +6,20 @@
#include <stdlib.h> #include <stdlib.h>
#include "halibut.h" #include "halibut.h"
static int compare_tags (void *av, void *bv); static int compare_tags(void *av, void *bv);
static int compare_entries (void *av, void *bv); static int compare_entries(void *av, void *bv);
indexdata * indexdata *make_index(void)
make_index (void)
{ {
indexdata *ret = mknew (indexdata); indexdata *ret = mknew(indexdata);
ret->tags = newtree234 (compare_tags); ret->tags = newtree234(compare_tags);
ret->entries = newtree234 (compare_entries); ret->entries = newtree234(compare_entries);
return ret; return ret;
} }
static indextag * static indextag *make_indextag(void)
make_indextag (void)
{ {
indextag *ret = mknew (indextag); indextag *ret = mknew(indextag);
ret->name = NULL; ret->name = NULL;
ret->implicit_text = NULL; ret->implicit_text = NULL;
ret->explicit_texts = NULL; ret->explicit_texts = NULL;
@ -30,35 +28,31 @@ make_indextag (void)
return ret; return ret;
} }
static int static int compare_tags(void *av, void *bv)
compare_tags (void *av, void *bv)
{ {
indextag *a = (indextag *) av, *b = (indextag *) bv; indextag *a = (indextag *) av, *b = (indextag *) bv;
return ustricmp (a->name, b->name); return ustricmp(a->name, b->name);
} }
static int static int compare_to_find_tag(void *av, void *bv)
compare_to_find_tag (void *av, void *bv)
{ {
wchar_t *a = (wchar_t *) av; wchar_t *a = (wchar_t *) av;
indextag *b = (indextag *) bv; indextag *b = (indextag *) bv;
return ustricmp (a, b->name); return ustricmp(a, b->name);
} }
static int static int compare_entries(void *av, void *bv)
compare_entries (void *av, void *bv)
{ {
indexentry *a = (indexentry *) av, *b = (indexentry *) bv; indexentry *a = (indexentry *) av, *b = (indexentry *) bv;
return compare_wordlists (a->text, b->text); return compare_wordlists(a->text, b->text);
} }
/* /*
* Back-end utility: find the indextag with a given name. * Back-end utility: find the indextag with a given name.
*/ */
indextag * indextag *index_findtag(indexdata * idx, wchar_t * name)
index_findtag (indexdata * idx, wchar_t * name)
{ {
return find234 (idx->tags, name, compare_to_find_tag); return find234(idx->tags, name, compare_to_find_tag);
} }
/* /*
@ -70,33 +64,30 @@ index_findtag (indexdata * idx, wchar_t * name)
* before the explicit ones. * before the explicit ones.
*/ */
void void
index_merge (indexdata * idx, int is_explicit, wchar_t * tags, word * text) index_merge(indexdata * idx, int is_explicit, wchar_t * tags, word * text)
{ {
indextag *t, *existing; indextag *t, *existing;
/* /*
* FIXME: want to warn on overlapping source sets. * FIXME: want to warn on overlapping source sets.
*/ */
for (; *tags; tags = uadv (tags)) for (; *tags; tags = uadv(tags)) {
{ t = make_indextag();
t = make_indextag ();
t->name = tags; t->name = tags;
existing = add234 (idx->tags, t); existing = add234(idx->tags, t);
if (existing == t) if (existing == t) {
{
/* /*
* Duplicate this so we can free it independently. * Duplicate this so we can free it independently.
*/ */
t->name = ustrdup (tags); t->name = ustrdup(tags);
/* /*
* Every tag has an implicit \IM. So if this tag * Every tag has an implicit \IM. So if this tag
* doesn't exist and we're explicit, then we should * doesn't exist and we're explicit, then we should
* warn (and drop it, since it won't be referenced). * warn (and drop it, since it won't be referenced).
*/ */
if (is_explicit) if (is_explicit) {
{ error(err_nosuchidxtag, tags);
error (err_nosuchidxtag, tags);
continue; continue;
} }
@ -104,13 +95,10 @@ index_merge (indexdata * idx, int is_explicit, wchar_t * tags, word * text)
* Otherwise, this is a new tag with an implicit \IM. * Otherwise, this is a new tag with an implicit \IM.
*/ */
t->implicit_text = text; t->implicit_text = text;
} } else {
else sfree(t);
{
sfree (t);
t = existing; t = existing;
if (!is_explicit) if (!is_explicit) {
{
/* /*
* An implicit \IM for a tag that's had an implicit * An implicit \IM for a tag that's had an implicit
* \IM before. FIXME: we should check the text * \IM before. FIXME: we should check the text
@ -118,23 +106,19 @@ index_merge (indexdata * idx, int is_explicit, wchar_t * tags, word * text)
* differences. And check the tag for case match * differences. And check the tag for case match
* against the existing tag, likewise. * against the existing tag, likewise.
*/ */
} } else {
else
{
/* /*
* An explicit \IM added to a valid tag. In * An explicit \IM added to a valid tag. In
* particular, this removes the implicit \IM if * particular, this removes the implicit \IM if
* present. * present.
*/ */
if (t->implicit_text) if (t->implicit_text) {
{ free_word_list(t->implicit_text);
free_word_list (t->implicit_text);
t->implicit_text = NULL; t->implicit_text = NULL;
} }
if (t->nexplicit >= t->explicit_size) if (t->nexplicit >= t->explicit_size) {
{
t->explicit_size = t->nexplicit + 8; t->explicit_size = t->nexplicit + 8;
t->explicit_texts = resize (t->explicit_texts, t->explicit_texts = resize(t->explicit_texts,
t->explicit_size); t->explicit_size);
} }
t->explicit_texts[t->nexplicit++] = text; t->explicit_texts[t->nexplicit++] = text;
@ -150,129 +134,112 @@ index_merge (indexdata * idx, int is_explicit, wchar_t * tags, word * text)
* entries in the original 2-3 tree with pointers to the RHS * entries in the original 2-3 tree with pointers to the RHS
* entries. * entries.
*/ */
void void build_index(indexdata * i)
build_index (indexdata * i)
{ {
indextag *t; indextag *t;
word **ta; word **ta;
int ti; int ti;
int j; int j;
for (ti = 0; (t = (indextag *) index234 (i->tags, ti)) != NULL; ti++) for (ti = 0; (t = (indextag *) index234(i->tags, ti)) != NULL; ti++) {
{ if (t->implicit_text) {
if (t->implicit_text)
{
t->nrefs = 1; t->nrefs = 1;
ta = &t->implicit_text; ta = &t->implicit_text;
} } else {
else
{
t->nrefs = t->nexplicit; t->nrefs = t->nexplicit;
ta = t->explicit_texts; ta = t->explicit_texts;
} }
if (t->nrefs) if (t->nrefs) {
{ t->refs = mknewa(indexentry *, t->nrefs);
t->refs = mknewa (indexentry *, t->nrefs); for (j = 0; j < t->nrefs; j++) {
for (j = 0; j < t->nrefs; j++) indexentry *ent = mknew(indexentry);
{
indexentry *ent = mknew (indexentry);
ent->text = *ta++; ent->text = *ta++;
t->refs[j] = add234 (i->entries, ent); t->refs[j] = add234(i->entries, ent);
if (t->refs[j] != ent) /* duplicate */ if (t->refs[j] != ent) /* duplicate */
sfree (ent); sfree(ent);
} }
} }
} }
} }
void void cleanup_index(indexdata * i)
cleanup_index (indexdata * i)
{ {
indextag *t; indextag *t;
indexentry *ent; indexentry *ent;
int ti; int ti;
for (ti = 0; (t = (indextag *) index234 (i->tags, ti)) != NULL; ti++) for (ti = 0; (t = (indextag *) index234(i->tags, ti)) != NULL; ti++) {
{ sfree(t->name);
sfree (t->name); free_word_list(t->implicit_text);
free_word_list (t->implicit_text); sfree(t->explicit_texts);
sfree (t->explicit_texts); sfree(t->refs);
sfree (t->refs); sfree(t);
sfree (t);
} }
freetree234 (i->tags); freetree234(i->tags);
for (ti = 0; (ent = (indexentry *) index234 (i->entries, ti)) != NULL; ti++) for (ti = 0; (ent = (indexentry *) index234(i->entries, ti)) != NULL;
{ ti++) {
sfree (ent); sfree(ent);
} }
freetree234 (i->entries); freetree234(i->entries);
sfree (i); sfree(i);
} }
static void dbg_prtwordlist (int level, word * w); static void dbg_prtwordlist(int level, word * w);
static void dbg_prtmerge (int is_explicit, wchar_t * tag, word * text); static void dbg_prtmerge(int is_explicit, wchar_t * tag, word * text);
void void index_debug(indexdata * i)
index_debug (indexdata * i)
{ {
indextag *t; indextag *t;
indexentry *y; indexentry *y;
int ti; int ti;
int j; int j;
printf ("\nINDEX TAGS\n==========\n\n"); printf("\nINDEX TAGS\n==========\n\n");
for (ti = 0; (t = (indextag *) index234 (i->tags, ti)) != NULL; ti++) for (ti = 0; (t = (indextag *) index234(i->tags, ti)) != NULL; ti++) {
{ printf("\n");
printf ("\n");
if (t->implicit_text) if (t->implicit_text)
dbg_prtmerge (0, t->name, t->implicit_text); dbg_prtmerge(0, t->name, t->implicit_text);
for (j = 0; j < t->nexplicit; j++) for (j = 0; j < t->nexplicit; j++)
dbg_prtmerge (1, t->name, t->explicit_texts[j]); dbg_prtmerge(1, t->name, t->explicit_texts[j]);
} }
printf ("\nINDEX ENTRIES\n=============\n\n"); printf("\nINDEX ENTRIES\n=============\n\n");
for (ti = 0; (y = (indexentry *) index234 (i->entries, ti)) != NULL; ti++) for (ti = 0; (y = (indexentry *) index234(i->entries, ti)) != NULL;
{ ti++) {
printf ("\n"); printf("\n");
printf ("{\n"); printf("{\n");
dbg_prtwordlist (1, y->text); dbg_prtwordlist(1, y->text);
printf ("}\n"); printf("}\n");
} }
} }
static void static void dbg_prtmerge(int is_explicit, wchar_t * tag, word * text)
dbg_prtmerge (int is_explicit, wchar_t * tag, word * text)
{ {
printf ("\\IM: %splicit: \"", is_explicit ? "ex" : "im"); printf("\\IM: %splicit: \"", is_explicit ? "ex" : "im");
for (; *tag; tag++) for (; *tag; tag++)
putchar (*tag); putchar(*tag);
printf ("\" {\n"); printf("\" {\n");
dbg_prtwordlist (1, text); dbg_prtwordlist(1, text);
printf ("}\n"); printf("}\n");
} }
static void static void dbg_prtwordlist(int level, word * w)
dbg_prtwordlist (int level, word * w)
{ {
for (; w; w = w->next) for (; w; w = w->next) {
{
wchar_t *wp; wchar_t *wp;
printf ("%*sword %d ", level * 4, "", w->type); printf("%*sword %d ", level * 4, "", w->type);
if (w->text) if (w->text) {
{ printf("\"");
printf ("\"");
for (wp = w->text; *wp; wp++) for (wp = w->text; *wp; wp++)
putchar (*wp); putchar(*wp);
printf ("\""); printf("\"");
} else
printf("(no text)");
if (w->alt) {
printf(" alt = {\n");
dbg_prtwordlist(level + 1, w->alt);
printf("%*s}", level * 4, "");
} }
else printf("\n");
printf ("(no text)");
if (w->alt)
{
printf (" alt = {\n");
dbg_prtwordlist (level + 1, w->alt);
printf ("%*s}", level * 4, "");
}
printf ("\n");
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -7,26 +7,23 @@
#include <assert.h> #include <assert.h>
#include "halibut.h" #include "halibut.h"
static int static int kwcmp(void *av, void *bv)
kwcmp (void *av, void *bv)
{ {
const keyword *a = (const keyword *) av; const keyword *a = (const keyword *) av;
const keyword *b = (const keyword *) bv; const keyword *b = (const keyword *) bv;
return ustrcmp (a->key, b->key); return ustrcmp(a->key, b->key);
} }
static int static int kwfind(void *av, void *bv)
kwfind (void *av, void *bv)
{ {
wchar_t *a = (wchar_t *) av; wchar_t *a = (wchar_t *) av;
const keyword *b = (const keyword *) bv; const keyword *b = (const keyword *) bv;
return ustrcmp (a, b->key); return ustrcmp(a, b->key);
} }
keyword * keyword *kw_lookup(keywordlist * kl, wchar_t * str)
kw_lookup (keywordlist * kl, wchar_t * str)
{ {
return find234 (kl->keys, str, kwfind); return find234(kl->keys, str, kwfind);
} }
/* /*
@ -35,22 +32,20 @@ kw_lookup (keywordlist * kl, wchar_t * str)
* collation, last at the top (so that we can Heapsort them when we * collation, last at the top (so that we can Heapsort them when we
* finish). * finish).
*/ */
keywordlist * keywordlist *get_keywords(paragraph * source)
get_keywords (paragraph * source)
{ {
int errors = FALSE; int errors = FALSE;
keywordlist *kl = mknew (keywordlist); keywordlist *kl = mknew(keywordlist);
numberstate *n = number_init (); numberstate *n = number_init();
int prevpara = para_NotParaType; int prevpara = para_NotParaType;
number_cfg (n, source); number_cfg(n, source);
kl->size = 0; kl->size = 0;
kl->keys = newtree234 (kwcmp); kl->keys = newtree234(kwcmp);
kl->nlooseends = kl->looseendssize = 0; kl->nlooseends = kl->looseendssize = 0;
kl->looseends = NULL; kl->looseends = NULL;
for (; source; source = source->next) for (; source; source = source->next) {
{
wchar_t *p, *q; wchar_t *p, *q;
p = q = source->keyword; p = q = source->keyword;
@ -59,9 +54,8 @@ get_keywords (paragraph * source)
* `question' or whatever - to replace `chapter' or * `question' or whatever - to replace `chapter' or
* `section' on a per-section basis). * `section' on a per-section basis).
*/ */
if (q) if (q) {
{ q = uadv(q); /* point q at the word beyond */
q = uadv (q); /* point q at the word beyond */
if (!*q) if (!*q)
q = NULL; q = NULL;
} }
@ -71,95 +65,80 @@ get_keywords (paragraph * source)
* This also sets up the `parent', `child' and `sibling' * This also sets up the `parent', `child' and `sibling'
* links. * links.
*/ */
source->kwtext = number_mktext (n, source, q, prevpara, &errors); source->kwtext = number_mktext(n, source, q, prevpara, &errors);
prevpara = source->type; prevpara = source->type;
if (p && *p) if (p && *p) {
{ if (source->kwtext || source->type == para_Biblio) {
if (source->kwtext || source->type == para_Biblio)
{
keyword *kw, *ret; keyword *kw, *ret;
kw = mknew (keyword); kw = mknew(keyword);
kw->key = p; kw->key = p;
kw->text = source->kwtext; kw->text = source->kwtext;
kw->para = source; kw->para = source;
ret = add234 (kl->keys, kw); ret = add234(kl->keys, kw);
if (ret != kw) if (ret != kw) {
{ error(err_multikw, &source->fpos, &ret->para->fpos, p);
error (err_multikw, &source->fpos, &ret->para->fpos, p); sfree(kw);
sfree (kw);
/* FIXME: what happens to kw->text? Does it leak? */ /* FIXME: what happens to kw->text? Does it leak? */
} }
} }
} } else {
else if (kl->nlooseends >= kl->looseendssize) {
{
if (kl->nlooseends >= kl->looseendssize)
{
kl->looseendssize = kl->nlooseends + 32; kl->looseendssize = kl->nlooseends + 32;
kl->looseends = resize (kl->looseends, kl->looseendssize); kl->looseends = resize(kl->looseends, kl->looseendssize);
} }
kl->looseends[kl->nlooseends++] = source->kwtext; kl->looseends[kl->nlooseends++] = source->kwtext;
} }
} }
number_free (n); number_free(n);
if (errors) if (errors) {
{ free_keywords(kl);
free_keywords (kl);
return NULL; return NULL;
} }
return kl; return kl;
} }
void void free_keywords(keywordlist * kl)
free_keywords (keywordlist * kl)
{ {
keyword *kw; keyword *kw;
while (kl->nlooseends) while (kl->nlooseends)
free_word_list (kl->looseends[--kl->nlooseends]); free_word_list(kl->looseends[--kl->nlooseends]);
sfree (kl->looseends); sfree(kl->looseends);
while ((kw = index234 (kl->keys, 0)) != NULL) while ((kw = index234(kl->keys, 0)) != NULL) {
{ delpos234(kl->keys, 0);
delpos234 (kl->keys, 0); free_word_list(kw->text);
free_word_list (kw->text); sfree(kw);
sfree (kw);
} }
freetree234 (kl->keys); freetree234(kl->keys);
sfree (kl); sfree(kl);
} }
void void subst_keywords(paragraph * source, keywordlist * kl)
subst_keywords (paragraph * source, keywordlist * kl)
{ {
for (; source; source = source->next) for (; source; source = source->next) {
{
word *ptr; word *ptr;
for (ptr = source->words; ptr; ptr = ptr->next) for (ptr = source->words; ptr; ptr = ptr->next) {
{ if (ptr->type == word_UpperXref || ptr->type == word_LowerXref) {
if (ptr->type == word_UpperXref || ptr->type == word_LowerXref)
{
keyword *kw; keyword *kw;
word **endptr, *close, *subst; word **endptr, *close, *subst;
kw = kw_lookup (kl, ptr->text); kw = kw_lookup(kl, ptr->text);
if (!kw) if (!kw) {
{ error(err_nosuchkw, &ptr->fpos, ptr->text);
error (err_nosuchkw, &ptr->fpos, ptr->text);
subst = NULL; subst = NULL;
} } else
else subst = dup_word_list(kw->text);
subst = dup_word_list (kw->text);
if (subst && ptr->type == word_LowerXref && if (subst && ptr->type == word_LowerXref &&
kw->para->type != para_Biblio && kw->para->type != para_Biblio &&
kw->para->type != para_BiblioCited) kw->para->type != para_BiblioCited)
ustrlow (subst->text); ustrlow(subst->text);
close = mknew (word); close = mknew(word);
close->text = NULL; close->text = NULL;
close->alt = NULL; close->alt = NULL;
close->type = word_XrefEnd; close->type = word_XrefEnd;
@ -168,7 +147,8 @@ subst_keywords (paragraph * source, keywordlist * kl)
close->next = ptr->next; close->next = ptr->next;
ptr->next = subst; ptr->next = subst;
for (endptr = &ptr->next; *endptr; endptr = &(*endptr)->next) for (endptr = &ptr->next; *endptr;
endptr = &(*endptr)->next)
(*endptr)->fpos = ptr->fpos; (*endptr)->fpos = ptr->fpos;
*endptr = close; *endptr = close;

View file

@ -9,10 +9,9 @@ static char *licencetext[] = {
NULL NULL
}; };
void void licence(void)
licence (void)
{ {
char **p; char **p;
for (p = licencetext; *p; p++) for (p = licencetext; *p; p++)
puts (*p); puts(*p);
} }

View file

@ -6,12 +6,11 @@
#include <stdlib.h> #include <stdlib.h>
#include "halibut.h" #include "halibut.h"
static void dbg_prtsource (paragraph * sourceform); static void dbg_prtsource(paragraph * sourceform);
static void dbg_prtwordlist (int level, word * w); static void dbg_prtwordlist(int level, word * w);
static void dbg_prtkws (keywordlist * kws); static void dbg_prtkws(keywordlist * kws);
int int main(int argc, char **argv)
main (int argc, char **argv)
{ {
char **infiles; char **infiles;
char *outfile; char *outfile;
@ -24,35 +23,30 @@ main (int argc, char **argv)
/* /*
* Set up initial (default) parameters. * Set up initial (default) parameters.
*/ */
infiles = mknewa (char *, argc); infiles = mknewa(char *, argc);
outfile = NULL; outfile = NULL;
nfiles = 0; nfiles = 0;
nogo = errs = FALSE; nogo = errs = FALSE;
reportcols = 0; reportcols = 0;
debug = 0; debug = 0;
if (argc == 1) if (argc == 1) {
{ usage();
usage (); exit(EXIT_SUCCESS);
exit (EXIT_SUCCESS);
} }
/* /*
* Parse command line arguments. * Parse command line arguments.
*/ */
while (--argc) while (--argc) {
{
char *p = *++argv; char *p = *++argv;
if (*p == '-') if (*p == '-') {
{
/* /*
* An option. * An option.
*/ */
while (p && *++p) while (p && *++p) {
{
char c = *p; char c = *p;
switch (c) switch (c) {
{
case '-': case '-':
/* /*
* Long option. * Long option.
@ -62,48 +56,31 @@ main (int argc, char **argv)
opt = p++; /* opt will have _one_ leading - */ opt = p++; /* opt will have _one_ leading - */
while (*p && *p != '=') while (*p && *p != '=')
p++; /* find end of option */ p++; /* find end of option */
if (*p == '=') if (*p == '=') {
{
*p++ = '\0'; *p++ = '\0';
val = p; val = p;
} } else
else
val = NULL; val = NULL;
if (!strcmp (opt, "-help")) if (!strcmp(opt, "-version")) {
{ showversion();
help ();
nogo = TRUE; nogo = TRUE;
} } else if (!strcmp(opt, "-licence") ||
else if (!strcmp (opt, "-version")) !strcmp(opt, "-license")) {
{ licence();
showversion ();
nogo = TRUE; nogo = TRUE;
} } else if (!strcmp(opt, "-output")) {
else if (!strcmp (opt, "-licence") ||
!strcmp (opt, "-license"))
{
licence ();
nogo = TRUE;
}
else if (!strcmp (opt, "-output"))
{
if (!val) if (!val)
errs = TRUE, error (err_optnoarg, opt); errs = TRUE, error(err_optnoarg, opt);
else else
outfile = val; outfile = val;
} } else if (!strcmp(opt, "-precise")) {
else if (!strcmp (opt, "-precise"))
{
reportcols = 1; reportcols = 1;
} } else {
else errs = TRUE, error(err_nosuchopt, opt);
{
errs = TRUE, error (err_nosuchopt, opt);
} }
} }
p = NULL; p = NULL;
break; break;
case 'h':
case 'V': case 'V':
case 'L': case 'L':
case 'P': case 'P':
@ -111,18 +88,13 @@ main (int argc, char **argv)
/* /*
* Option requiring no parameter. * Option requiring no parameter.
*/ */
switch (c) switch (c) {
{
case 'h':
help ();
nogo = TRUE;
break;
case 'V': case 'V':
showversion (); showversion();
nogo = TRUE; nogo = TRUE;
break; break;
case 'L': case 'L':
licence (); licence();
nogo = TRUE; nogo = TRUE;
break; break;
case 'P': case 'P':
@ -140,18 +112,16 @@ main (int argc, char **argv)
p++; p++;
if (!*p && argc > 1) if (!*p && argc > 1)
--argc, p = *++argv; --argc, p = *++argv;
else if (!*p) else if (!*p) {
{
char opt[2]; char opt[2];
opt[0] = c; opt[0] = c;
opt[1] = '\0'; opt[1] = '\0';
errs = TRUE, error (err_optnoarg, opt); errs = TRUE, error(err_optnoarg, opt);
} }
/* /*
* Now c is the option and p is the parameter. * Now c is the option and p is the parameter.
*/ */
switch (c) switch (c) {
{
case 'o': case 'o':
outfile = p; outfile = p;
break; break;
@ -166,13 +136,11 @@ main (int argc, char **argv)
char opt[2]; char opt[2];
opt[0] = c; opt[0] = c;
opt[1] = '\0'; opt[1] = '\0';
errs = TRUE, error (err_nosuchopt, opt); errs = TRUE, error(err_nosuchopt, opt);
} }
} }
} }
} } else {
else
{
/* /*
* A non-option argument. * A non-option argument.
*/ */
@ -181,18 +149,17 @@ main (int argc, char **argv)
} }
if (errs) if (errs)
exit (EXIT_FAILURE); exit(EXIT_FAILURE);
if (nogo) if (nogo)
exit (EXIT_SUCCESS); exit(EXIT_SUCCESS);
/* /*
* Do the work. * Do the work.
*/ */
if (nfiles == 0) if (nfiles == 0) {
{ error(err_noinput);
error (err_noinput); usage();
usage (); exit(EXIT_FAILURE);
exit (EXIT_FAILURE);
} }
{ {
@ -210,84 +177,75 @@ main (int argc, char **argv)
in.reportcols = reportcols; in.reportcols = reportcols;
in.stack = NULL; in.stack = NULL;
idx = make_index (); idx = make_index();
sourceform = read_input (&in, idx); sourceform = read_input(&in, idx);
if (!sourceform) if (!sourceform)
exit (EXIT_FAILURE); exit(EXIT_FAILURE);
sfree (in.pushback); sfree(in.pushback);
mark_attr_ends (sourceform); mark_attr_ends(sourceform);
sfree (infiles); sfree(infiles);
keywords = get_keywords (sourceform); keywords = get_keywords(sourceform);
if (!keywords) if (!keywords)
exit (EXIT_FAILURE); exit(EXIT_FAILURE);
gen_citations (sourceform, keywords); gen_citations(sourceform, keywords);
subst_keywords (sourceform, keywords); subst_keywords(sourceform, keywords);
for (p = sourceform; p; p = p->next) for (p = sourceform; p; p = p->next)
if (p->type == para_IM) if (p->type == para_IM)
index_merge (idx, TRUE, p->keyword, p->words); index_merge(idx, TRUE, p->keyword, p->words);
build_index (idx); build_index(idx);
if (debug) if (debug) {
{ index_debug(idx);
index_debug (idx); dbg_prtkws(keywords);
dbg_prtkws (keywords); dbg_prtsource(sourceform);
dbg_prtsource (sourceform);
} }
text_backend (sourceform, keywords, idx); xhtml_backend(sourceform, keywords, idx);
xhtml_backend (sourceform, keywords, idx);
whlp_backend (sourceform, keywords, idx);
free_para_list (sourceform); free_para_list(sourceform);
free_keywords (keywords); free_keywords(keywords);
cleanup_index (idx); cleanup_index(idx);
} }
return 0; return 0;
} }
static void static void dbg_prtsource(paragraph * sourceform)
dbg_prtsource (paragraph * sourceform)
{ {
/* /*
* Output source form in debugging format. * Output source form in debugging format.
*/ */
paragraph *p; paragraph *p;
for (p = sourceform; p; p = p->next) for (p = sourceform; p; p = p->next) {
{
wchar_t *wp; wchar_t *wp;
printf ("para %d ", p->type); printf("para %d ", p->type);
if (p->keyword) if (p->keyword) {
{
wp = p->keyword; wp = p->keyword;
while (*wp) while (*wp) {
{ putchar('\"');
putchar ('\"');
for (; *wp; wp++) for (; *wp; wp++)
putchar (*wp); putchar(*wp);
putchar ('\"'); putchar('\"');
if (*++wp) if (*++wp)
printf (", "); printf(", ");
} }
} } else
else printf("(no keyword)");
printf ("(no keyword)"); printf(" {\n");
printf (" {\n"); dbg_prtwordlist(1, p->words);
dbg_prtwordlist (1, p->words); printf("}\n");
printf ("}\n");
} }
} }
static void static void dbg_prtkws(keywordlist * kws)
dbg_prtkws (keywordlist * kws)
{ {
/* /*
* Output keywords in debugging format. * Output keywords in debugging format.
@ -296,48 +254,41 @@ dbg_prtkws (keywordlist * kws)
int i; int i;
keyword *kw; keyword *kw;
for (i = 0; (kw = index234 (kws->keys, i)) != NULL; i++) for (i = 0; (kw = index234(kws->keys, i)) != NULL; i++) {
{
wchar_t *wp; wchar_t *wp;
printf ("keyword "); printf("keyword ");
wp = kw->key; wp = kw->key;
while (*wp) while (*wp) {
{ putchar('\"');
putchar ('\"');
for (; *wp; wp++) for (; *wp; wp++)
putchar (*wp); putchar(*wp);
putchar ('\"'); putchar('\"');
if (*++wp) if (*++wp)
printf (", "); printf(", ");
} }
printf (" {\n"); printf(" {\n");
dbg_prtwordlist (1, kw->text); dbg_prtwordlist(1, kw->text);
printf ("}\n"); printf("}\n");
} }
} }
static void static void dbg_prtwordlist(int level, word * w)
dbg_prtwordlist (int level, word * w)
{ {
for (; w; w = w->next) for (; w; w = w->next) {
{
wchar_t *wp; wchar_t *wp;
printf ("%*sword %d ", level * 4, "", w->type); printf("%*sword %d ", level * 4, "", w->type);
if (w->text) if (w->text) {
{ printf("\"");
printf ("\"");
for (wp = w->text; *wp; wp++) for (wp = w->text; *wp; wp++)
putchar (*wp); putchar(*wp);
printf ("\""); printf("\"");
} else
printf("(no text)");
if (w->alt) {
printf(" alt = {\n");
dbg_prtwordlist(level + 1, w->alt);
printf("%*s}", level * 4, "");
} }
else printf("\n");
printf ("(no text)");
if (w->alt)
{
printf (" alt = {\n");
dbg_prtwordlist (level + 1, w->alt);
printf ("%*s}", level * 4, "");
}
printf ("\n");
} }
} }

View file

@ -1,17 +1,12 @@
OBJS = biblio.o bk_text.o bk_whlp.o bk_xhtml.o contents.o error.o help.o index.o input.o keywords.o licence.o main.o malloc.o misc.o style.o tree234.o ustring.o version.o winhelp.o OBJS = biblio.o bk_xhtml.o contents.o error.o help.o index.o input.o keywords.o licence.o main.o malloc.o misc.o style.o tree234.o ustring.o version.o winhelp.o
LIBS = LIBS =
# -- Programs --
MAKE = make
CC = gcc CC = gcc
RM = del RM = del
DEFINES = -DVERSION="\"1.0 (NSIS Custom Build)\""
# -- Compilers and linker flags --
DEFINES =
CFLAGS = -Wall -W $(DEFINES) CFLAGS = -Wall -W $(DEFINES)
LFLAGS = -s LFLAGS = -s
all : halibut all : halibut
halibut : $(OBJS) halibut : $(OBJS)

View file

@ -10,32 +10,27 @@
#define LOGPARAMS char *file, int line, #define LOGPARAMS char *file, int line,
static FILE *logallocfp = NULL; static FILE *logallocfp = NULL;
static int logline = 2; /* off by 1: `null pointer is' */ static int logline = 2; /* off by 1: `null pointer is' */
static void static void loginc(void)
loginc (void)
{ {
} }
static void static void logallocinit(void)
logallocinit (void)
{ {
if (!logallocfp) if (!logallocfp) {
{ logallocfp = fopen("malloc.log", "w");
logallocfp = fopen ("malloc.log", "w"); if (!logallocfp) {
if (!logallocfp) fprintf(stderr, "panic: unable to open malloc.log\n");
{ exit(10);
fprintf (stderr, "panic: unable to open malloc.log\n");
exit (10);
} }
setvbuf (logallocfp, NULL, _IOLBF, BUFSIZ); setvbuf(logallocfp, NULL, _IOLBF, BUFSIZ);
fprintf (logallocfp, "null pointer is %p\n", NULL); fprintf(logallocfp, "null pointer is %p\n", NULL);
} }
} }
static void static void logprintf(char *fmt, ...)
logprintf (char *fmt, ...)
{ {
va_list ap; va_list ap;
va_start (ap, fmt); va_start(ap, fmt);
vfprintf (logallocfp, fmt, ap); vfprintf(logallocfp, fmt, ap);
va_end (ap); va_end(ap);
} }
#define LOGPRINT(x) ( logallocinit(), logprintf x ) #define LOGPRINT(x) ( logallocinit(), logprintf x )
@ -50,53 +45,46 @@ logprintf (char *fmt, ...)
* smalloc should guarantee to return a useful pointer - Halibut * smalloc should guarantee to return a useful pointer - Halibut
* can do nothing except die when it's out of memory anyway. * can do nothing except die when it's out of memory anyway.
*/ */
void *(smalloc) (LOGPARAMS int size) void *(smalloc) (LOGPARAMS int size) {
{
void *p; void *p;
LOGINC; LOGINC;
LOGPRINT (("%s %d malloc(%ld)", file, line, (long) size)); LOGPRINT(("%s %d malloc(%ld)", file, line, (long) size));
p = malloc (size); p = malloc(size);
if (!p) if (!p)
fatal (err_nomemory); fatal(err_nomemory);
LOGPRINT ((" returns %p\n", p)); LOGPRINT((" returns %p\n", p));
return p; return p;
} }
/* /*
* sfree should guaranteeably deal gracefully with freeing NULL * sfree should guaranteeably deal gracefully with freeing NULL
*/ */
void (sfree) (LOGPARAMS void *p) void (sfree) (LOGPARAMS void *p) {
{ if (p) {
if (p)
{
LOGINC; LOGINC;
LOGPRINT (("%s %d free(%p)\n", file, line, p)); LOGPRINT(("%s %d free(%p)\n", file, line, p));
free (p); free(p);
} }
} }
/* /*
* srealloc should guaranteeably be able to realloc NULL * srealloc should guaranteeably be able to realloc NULL
*/ */
void *(srealloc) (LOGPARAMS void *p, int size) void *(srealloc) (LOGPARAMS void *p, int size) {
{
void *q; void *q;
if (p) if (p) {
{
LOGINC; LOGINC;
LOGPRINT (("%s %d realloc(%p,%ld)", file, line, p, (long) size)); LOGPRINT(("%s %d realloc(%p,%ld)", file, line, p, (long) size));
q = realloc (p, size); q = realloc(p, size);
LOGPRINT ((" returns %p\n", q)); LOGPRINT((" returns %p\n", q));
} } else {
else
{
LOGINC; LOGINC;
LOGPRINT (("%s %d malloc(%ld)", file, line, (long) size)); LOGPRINT(("%s %d malloc(%ld)", file, line, (long) size));
q = malloc (size); q = malloc(size);
LOGPRINT ((" returns %p\n", q)); LOGPRINT((" returns %p\n", q));
} }
if (!q) if (!q)
fatal (err_nomemory); fatal(err_nomemory);
return q; return q;
} }
@ -104,29 +92,26 @@ void *(srealloc) (LOGPARAMS void *p, int size)
* dupstr is like strdup, but with the never-return-NULL property * dupstr is like strdup, but with the never-return-NULL property
* of smalloc (and also reliably defined in all environments :-) * of smalloc (and also reliably defined in all environments :-)
*/ */
char * char *dupstr(char *s)
dupstr (char *s)
{ {
char *r = smalloc (1 + strlen (s)); char *r = smalloc(1 + strlen(s));
strcpy (r, s); strcpy(r, s);
return r; return r;
} }
/* /*
* Duplicate a linked list of words * Duplicate a linked list of words
*/ */
word * word *dup_word_list(word * w)
dup_word_list (word * w)
{ {
word *head, **eptr = &head; word *head, **eptr = &head;
while (w) while (w) {
{ word *newwd = mknew(word);
word *newwd = mknew (word);
*newwd = *w; /* structure copy */ *newwd = *w; /* structure copy */
newwd->text = ustrdup (w->text); newwd->text = ustrdup(w->text);
if (w->alt) if (w->alt)
newwd->alt = dup_word_list (w->alt); newwd->alt = dup_word_list(w->alt);
*eptr = newwd; *eptr = newwd;
newwd->next = NULL; newwd->next = NULL;
eptr = &newwd->next; eptr = &newwd->next;
@ -140,34 +125,30 @@ dup_word_list (word * w)
/* /*
* Free a linked list of words * Free a linked list of words
*/ */
void void free_word_list(word * w)
free_word_list (word * w)
{ {
word *t; word *t;
while (w) while (w) {
{
t = w; t = w;
w = w->next; w = w->next;
sfree (t->text); sfree(t->text);
if (t->alt) if (t->alt)
free_word_list (t->alt); free_word_list(t->alt);
sfree (t); sfree(t);
} }
} }
/* /*
* Free a linked list of paragraphs * Free a linked list of paragraphs
*/ */
void void free_para_list(paragraph * p)
free_para_list (paragraph * p)
{ {
paragraph *t; paragraph *t;
while (p) while (p) {
{
t = p; t = p;
p = p->next; p = p->next;
sfree (t->keyword); sfree(t->keyword);
free_word_list (t->words); free_word_list(t->words);
sfree (t); sfree(t);
} }
} }

View file

@ -4,19 +4,17 @@
#include "halibut.h" #include "halibut.h"
struct stackTag struct stackTag {
{
void **data; void **data;
int sp; int sp;
int size; int size;
}; };
stack stack stk_new(void)
stk_new (void)
{ {
stack s; stack s;
s = mknew (struct stackTag); s = mknew(struct stackTag);
s->sp = 0; s->sp = 0;
s->size = 0; s->size = 0;
s->data = NULL; s->data = NULL;
@ -24,26 +22,22 @@ stk_new (void)
return s; return s;
} }
void void stk_free(stack s)
stk_free (stack s)
{ {
sfree (s->data); sfree(s->data);
sfree (s); sfree(s);
} }
void void stk_push(stack s, void *item)
stk_push (stack s, void *item)
{ {
if (s->size <= s->sp) if (s->size <= s->sp) {
{
s->size = s->sp + 32; s->size = s->sp + 32;
s->data = resize (s->data, s->size); s->data = resize(s->data, s->size);
} }
s->data[s->sp++] = item; s->data[s->sp++] = item;
} }
void * void *stk_pop(stack s)
stk_pop (stack s)
{ {
if (s->sp > 0) if (s->sp > 0)
return s->data[--s->sp]; return s->data[--s->sp];
@ -57,106 +51,91 @@ stk_pop (stack s)
const rdstring empty_rdstring = { 0, 0, NULL }; const rdstring empty_rdstring = { 0, 0, NULL };
const rdstringc empty_rdstringc = { 0, 0, NULL }; const rdstringc empty_rdstringc = { 0, 0, NULL };
void void rdadd(rdstring * rs, wchar_t c)
rdadd (rdstring * rs, wchar_t c)
{ {
if (rs->pos >= rs->size - 1) if (rs->pos >= rs->size - 1) {
{
rs->size = rs->pos + 128; rs->size = rs->pos + 128;
rs->text = resize (rs->text, rs->size); rs->text = resize(rs->text, rs->size);
} }
rs->text[rs->pos++] = c; rs->text[rs->pos++] = c;
rs->text[rs->pos] = 0; rs->text[rs->pos] = 0;
} }
void void rdadds(rdstring * rs, wchar_t * p)
rdadds (rdstring * rs, wchar_t * p)
{ {
int len = ustrlen (p); int len = ustrlen(p);
if (rs->pos >= rs->size - len) if (rs->pos >= rs->size - len) {
{
rs->size = rs->pos + len + 128; rs->size = rs->pos + len + 128;
rs->text = resize (rs->text, rs->size); rs->text = resize(rs->text, rs->size);
} }
ustrcpy (rs->text + rs->pos, p); ustrcpy(rs->text + rs->pos, p);
rs->pos += len; rs->pos += len;
} }
wchar_t * wchar_t *rdtrim(rdstring * rs)
rdtrim (rdstring * rs)
{ {
rs->text = resize (rs->text, rs->pos + 1); rs->text = resize(rs->text, rs->pos + 1);
return rs->text; return rs->text;
} }
void void rdaddc(rdstringc * rs, char c)
rdaddc (rdstringc * rs, char c)
{ {
if (rs->pos >= rs->size - 1) if (rs->pos >= rs->size - 1) {
{
rs->size = rs->pos + 128; rs->size = rs->pos + 128;
rs->text = resize (rs->text, rs->size); rs->text = resize(rs->text, rs->size);
} }
rs->text[rs->pos++] = c; rs->text[rs->pos++] = c;
rs->text[rs->pos] = 0; rs->text[rs->pos] = 0;
} }
void void rdaddsc(rdstringc * rs, char *p)
rdaddsc (rdstringc * rs, char *p)
{ {
int len = strlen (p); int len = strlen(p);
if (rs->pos >= rs->size - len) if (rs->pos >= rs->size - len) {
{
rs->size = rs->pos + len + 128; rs->size = rs->pos + len + 128;
rs->text = resize (rs->text, rs->size); rs->text = resize(rs->text, rs->size);
} }
strcpy (rs->text + rs->pos, p); strcpy(rs->text + rs->pos, p);
rs->pos += len; rs->pos += len;
} }
char * char *rdtrimc(rdstringc * rs)
rdtrimc (rdstringc * rs)
{ {
rs->text = resize (rs->text, rs->pos + 1); rs->text = resize(rs->text, rs->pos + 1);
return rs->text; return rs->text;
} }
int int compare_wordlists(word * a, word * b)
compare_wordlists (word * a, word * b)
{ {
int t; int t;
while (a && b) while (a && b) {
{
if (a->type != b->type) if (a->type != b->type)
return (a->type < b->type ? -1 : +1); /* FIXME? */ return (a->type < b->type ? -1 : +1); /* FIXME? */
t = a->type; t = a->type;
if ((t != word_Normal && t != word_Code && if ((t != word_Normal && t != word_Code &&
t != word_WeakCode && t != word_Emph) || a->alt || b->alt) t != word_WeakCode && t != word_Emph) || a->alt || b->alt) {
{
int c; int c;
if (a->text && b->text) if (a->text && b->text) {
{ c = ustricmp(a->text, b->text);
c = ustricmp (a->text, b->text);
if (c) if (c)
return c; return c;
} }
c = compare_wordlists (a->alt, b->alt); c = compare_wordlists(a->alt, b->alt);
if (c) if (c)
return c; return c;
a = a->next; a = a->next;
b = b->next; b = b->next;
} } else {
else
{
wchar_t *ap = a->text, *bp = b->text; wchar_t *ap = a->text, *bp = b->text;
while (*ap && *bp) while (*ap && *bp) {
{ wchar_t ac = utolower(*ap), bc = utolower(*bp);
wchar_t ac = utolower (*ap), bc = utolower (*bp);
if (ac != bc) if (ac != bc)
return (ac < bc ? -1 : +1); return (ac < bc ? -1 : +1);
if (!*++ap && a->next && a->next->type == t && !a->next->alt) if (!*++ap && a->next && a->next->type == t
&& !a->next->alt)
a = a->next, ap = a->text; a = a->next, ap = a->text;
if (!*++bp && b->next && b->next->type == t && !b->next->alt) if (!*++bp && b->next && b->next->type == t
&& !b->next->alt)
b = b->next, bp = b->text; b = b->next, bp = b->text;
} }
if (*ap || *bp) if (*ap || *bp)
@ -172,22 +151,18 @@ compare_wordlists (word * a, word * b)
return 0; return 0;
} }
void void mark_attr_ends(paragraph * sourceform)
mark_attr_ends (paragraph * sourceform)
{ {
paragraph *p; paragraph *p;
word *w, *wp; word *w, *wp;
for (p = sourceform; p; p = p->next) for (p = sourceform; p; p = p->next) {
{
wp = NULL; wp = NULL;
for (w = p->words; w; w = w->next) for (w = p->words; w; w = w->next) {
{ if (isattr(w->type)) {
if (isattr (w->type)) int before = (wp && isattr(wp->type) &&
{ sameattr(wp->type, w->type));
int before = (wp && isattr (wp->type) && int after = (w->next && isattr(w->next->type) &&
sameattr (wp->type, w->type)); sameattr(w->next->type, w->type));
int after = (w->next && isattr (w->next->type) &&
sameattr (w->next->type, w->type));
w->aux |= (before ? w->aux |= (before ?
(after ? attr_Always : attr_Last) : (after ? attr_Always : attr_Last) :
(after ? attr_First : attr_Only)); (after ? attr_First : attr_Only));
@ -197,21 +172,18 @@ mark_attr_ends (paragraph * sourceform)
} }
} }
wrappedline * wrappedline *wrap_para(word * text, int width, int subsequentwidth,
wrap_para (word * text, int width, int subsequentwidth,
int (*widthfn) (word *)) int (*widthfn) (word *))
{ {
wrappedline *head = NULL, **ptr = &head; wrappedline *head = NULL, **ptr = &head;
int nwords, wordsize; int nwords, wordsize;
struct wrapword struct wrapword {
{
word *begin, *end; word *begin, *end;
int width; int width;
int spacewidth; int spacewidth;
int cost; int cost;
int nwords; int nwords;
} } *wrapwords;
*wrapwords;
int i, j, n; int i, j, n;
/* /*
@ -219,18 +191,15 @@ wrap_para (word * text, int width, int subsequentwidth,
*/ */
nwords = wordsize = 0; nwords = wordsize = 0;
wrapwords = NULL; wrapwords = NULL;
while (text) while (text) {
{ if (nwords >= wordsize) {
if (nwords >= wordsize)
{
wordsize = nwords + 64; wordsize = nwords + 64;
wrapwords = srealloc (wrapwords, wordsize * sizeof (*wrapwords)); wrapwords = srealloc(wrapwords, wordsize * sizeof(*wrapwords));
} }
wrapwords[nwords].width = 0; wrapwords[nwords].width = 0;
wrapwords[nwords].begin = text; wrapwords[nwords].begin = text;
while (text) while (text) {
{ wrapwords[nwords].width += widthfn(text);
wrapwords[nwords].width += widthfn (text);
wrapwords[nwords].end = text->next; wrapwords[nwords].end = text->next;
if (text->next && (text->next->type == word_WhiteSpace || if (text->next && (text->next->type == word_WhiteSpace ||
text->next->type == word_EmphSpace || text->next->type == word_EmphSpace ||
@ -239,13 +208,10 @@ wrap_para (word * text, int width, int subsequentwidth,
text = text->next; text = text->next;
} }
if (text && text->next && (text->next->type == word_WhiteSpace || if (text && text->next && (text->next->type == word_WhiteSpace ||
text->next->type == word_EmphSpace)) text->next->type == word_EmphSpace)) {
{ wrapwords[nwords].spacewidth = widthfn(text->next);
wrapwords[nwords].spacewidth = widthfn (text->next);
text = text->next; text = text->next;
} } else {
else
{
wrapwords[nwords].spacewidth = 0; wrapwords[nwords].spacewidth = 0;
} }
nwords++; nwords++;
@ -258,8 +224,7 @@ wrap_para (word * text, int width, int subsequentwidth,
* nwords-1, determining the optimal wrapping for each terminal * nwords-1, determining the optimal wrapping for each terminal
* subsequence of the paragraph. * subsequence of the paragraph.
*/ */
for (i = nwords; i--;) for (i = nwords; i--;) {
{
int best = -1; int best = -1;
int bestcost = 0; int bestcost = 0;
int cost; int cost;
@ -269,8 +234,7 @@ wrap_para (word * text, int width, int subsequentwidth,
j = 0; j = 0;
seenspace = 0; seenspace = 0;
while (i + j < nwords) while (i + j < nwords) {
{
/* /*
* See what happens if we put j+1 words on this line. * See what happens if we put j+1 words on this line.
*/ */
@ -279,8 +243,7 @@ wrap_para (word * text, int width, int subsequentwidth,
linelen += spacewidth + wrapwords[i + j].width; linelen += spacewidth + wrapwords[i + j].width;
spacewidth = wrapwords[i + j].spacewidth; spacewidth = wrapwords[i + j].spacewidth;
j++; j++;
if (linelen > thiswidth) if (linelen > thiswidth) {
{
/* /*
* If we're over the width limit, abandon ship, * If we're over the width limit, abandon ship,
* _unless_ there is no best-effort yet (which will * _unless_ there is no best-effort yet (which will
@ -290,17 +253,14 @@ wrap_para (word * text, int width, int subsequentwidth,
if (best > 0) if (best > 0)
break; break;
} }
if (i + j == nwords) if (i + j == nwords) {
{
/* /*
* Special case: if we're at the very end of the * Special case: if we're at the very end of the
* paragraph, we don't score penalty points for the * paragraph, we don't score penalty points for the
* white space left on the line. * white space left on the line.
*/ */
cost = 0; cost = 0;
} } else {
else
{
cost = (thiswidth - linelen) * (thiswidth - linelen); cost = (thiswidth - linelen) * (thiswidth - linelen);
cost += wrapwords[i + j].cost; cost += wrapwords[i + j].cost;
} }
@ -313,8 +273,7 @@ wrap_para (word * text, int width, int subsequentwidth,
* there's no point violating the Principle of Least * there's no point violating the Principle of Least
* Surprise if it doesn't actually gain anything. * Surprise if it doesn't actually gain anything.
*/ */
if (best < 0 || bestcost >= cost) if (best < 0 || bestcost >= cost) {
{
bestcost = cost; bestcost = cost;
best = j; best = j;
} }
@ -332,9 +291,8 @@ wrap_para (word * text, int width, int subsequentwidth,
* `wrappedline' list. * `wrappedline' list.
*/ */
i = 0; i = 0;
while (i < nwords) while (i < nwords) {
{ wrappedline *w = mknew(wrappedline);
wrappedline *w = mknew (wrappedline);
*ptr = w; *ptr = w;
ptr = &w->next; ptr = &w->next;
w->next = NULL; w->next = NULL;
@ -348,11 +306,9 @@ wrap_para (word * text, int width, int subsequentwidth,
*/ */
w->nspaces = 0; w->nspaces = 0;
w->shortfall = width; w->shortfall = width;
for (j = 0; j < n; j++) for (j = 0; j < n; j++) {
{
w->shortfall -= wrapwords[i + j].width; w->shortfall -= wrapwords[i + j].width;
if (j < n - 1 && wrapwords[i + j].spacewidth) if (j < n - 1 && wrapwords[i + j].spacewidth) {
{
w->nspaces++; w->nspaces++;
w->shortfall -= wrapwords[i + j].spacewidth; w->shortfall -= wrapwords[i + j].spacewidth;
} }
@ -360,18 +316,16 @@ wrap_para (word * text, int width, int subsequentwidth,
i += n; i += n;
} }
sfree (wrapwords); sfree(wrapwords);
return head; return head;
} }
void void wrap_free(wrappedline * w)
wrap_free (wrappedline * w)
{ {
while (w) while (w) {
{
wrappedline *t = w->next; wrappedline *t = w->next;
sfree (w); sfree(w);
w = t; w = t;
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -42,18 +42,18 @@ typedef void *(*copyfn234) (void *state, void *element);
* lookups by key will fail: you can only look things up by numeric * lookups by key will fail: you can only look things up by numeric
* index, and you have to use addpos234() and delpos234(). * index, and you have to use addpos234() and delpos234().
*/ */
tree234 *newtree234 (cmpfn234 cmp); tree234 *newtree234(cmpfn234 cmp);
/* /*
* Free a 2-3-4 tree (not including freeing the elements). * Free a 2-3-4 tree (not including freeing the elements).
*/ */
void freetree234 (tree234 * t); void freetree234(tree234 * t);
/* /*
* Add an element e to a sorted 2-3-4 tree t. Returns e on success, * Add an element e to a sorted 2-3-4 tree t. Returns e on success,
* or if an existing element compares equal, returns that. * or if an existing element compares equal, returns that.
*/ */
void *add234 (tree234 * t, void *e); void *add234(tree234 * t, void *e);
/* /*
* Add an element e to an unsorted 2-3-4 tree t. Returns e on * Add an element e to an unsorted 2-3-4 tree t. Returns e on
@ -63,7 +63,7 @@ void *add234 (tree234 * t, void *e);
* Index range can be from 0 to the tree's current element count, * Index range can be from 0 to the tree's current element count,
* inclusive. * inclusive.
*/ */
void *addpos234 (tree234 * t, void *e, int index); void *addpos234(tree234 * t, void *e, int index);
/* /*
* Look up the element at a given numeric index in a 2-3-4 tree. * Look up the element at a given numeric index in a 2-3-4 tree.
@ -83,7 +83,7 @@ void *addpos234 (tree234 * t, void *e, int index);
* consume(p); * consume(p);
* } * }
*/ */
void *index234 (tree234 * t, int index); void *index234(tree234 * t, int index);
/* /*
* Find an element e in a sorted 2-3-4 tree t. Returns NULL if not * Find an element e in a sorted 2-3-4 tree t. Returns NULL if not
@ -125,14 +125,13 @@ void *index234 (tree234 * t, int index);
* for (p = NULL; (p = findrel234(tree, p, NULL, REL234_LT)) != NULL ;) * for (p = NULL; (p = findrel234(tree, p, NULL, REL234_LT)) != NULL ;)
* consume(p); * consume(p);
*/ */
enum enum {
{
REL234_EQ, REL234_LT, REL234_LE, REL234_GT, REL234_GE REL234_EQ, REL234_LT, REL234_LE, REL234_GT, REL234_GE
}; };
void *find234 (tree234 * t, void *e, cmpfn234 cmp); void *find234(tree234 * t, void *e, cmpfn234 cmp);
void *findrel234 (tree234 * t, void *e, cmpfn234 cmp, int relation); void *findrel234(tree234 * t, void *e, cmpfn234 cmp, int relation);
void *findpos234 (tree234 * t, void *e, cmpfn234 cmp, int *index); void *findpos234(tree234 * t, void *e, cmpfn234 cmp, int *index);
void *findrelpos234 (tree234 * t, void *e, cmpfn234 cmp, int relation, void *findrelpos234(tree234 * t, void *e, cmpfn234 cmp, int relation,
int *index); int *index);
/* /*
@ -152,13 +151,13 @@ void *findrelpos234 (tree234 * t, void *e, cmpfn234 cmp, int relation,
* is out of range (delpos234) or the element is already not in the * is out of range (delpos234) or the element is already not in the
* tree (del234) then they return NULL. * tree (del234) then they return NULL.
*/ */
void *del234 (tree234 * t, void *e); void *del234(tree234 * t, void *e);
void *delpos234 (tree234 * t, int index); void *delpos234(tree234 * t, int index);
/* /*
* Return the total element count of a tree234. * Return the total element count of a tree234.
*/ */
int count234 (tree234 * t); int count234(tree234 * t);
/* /*
* Split a tree234 into two valid tree234s. * Split a tree234 into two valid tree234s.
@ -173,8 +172,8 @@ int count234 (tree234 * t);
* in the tree that satisfy the relation are returned; the * in the tree that satisfy the relation are returned; the
* remainder are left. * remainder are left.
*/ */
tree234 *splitpos234 (tree234 * t, int index, int before); tree234 *splitpos234(tree234 * t, int index, int before);
tree234 *split234 (tree234 * t, void *e, cmpfn234 cmp, int rel); tree234 *split234(tree234 * t, void *e, cmpfn234 cmp, int rel);
/* /*
* Join two tree234s together into a single one. * Join two tree234s together into a single one.
@ -188,8 +187,8 @@ tree234 *split234 (tree234 * t, void *e, cmpfn234 cmp, int rel);
* The tree returned is t1 (join234) or t2 (join234r), if the * The tree returned is t1 (join234) or t2 (join234r), if the
* operation is successful. * operation is successful.
*/ */
tree234 *join234 (tree234 * t1, tree234 * t2); tree234 *join234(tree234 * t1, tree234 * t2);
tree234 *join234r (tree234 * t1, tree234 * t2); tree234 *join234r(tree234 * t1, tree234 * t2);
/* /*
* Make a complete copy of a tree234. Element pointers will be * Make a complete copy of a tree234. Element pointers will be
@ -198,6 +197,6 @@ tree234 *join234r (tree234 * t1, tree234 * t2);
* first is private state and the second is the element. A simple * first is private state and the second is the element. A simple
* copy routine probably won't need private state.) * copy routine probably won't need private state.)
*/ */
tree234 *copytree234 (tree234 * t, copyfn234 copyfn, void *copyfnstate); tree234 *copytree234(tree234 * t, copyfn234 copyfn, void *copyfnstate);
#endif /* TREE234_H */ #endif /* TREE234_H */

View file

@ -6,29 +6,23 @@
#include <time.h> #include <time.h>
#include "halibut.h" #include "halibut.h"
wchar_t * wchar_t *ustrdup(wchar_t * s)
ustrdup (wchar_t * s)
{ {
wchar_t *r; wchar_t *r;
if (s) if (s) {
{ r = mknewa(wchar_t, 1 + ustrlen(s));
r = mknewa (wchar_t, 1 + ustrlen (s)); ustrcpy(r, s);
ustrcpy (r, s); } else {
} r = mknew(wchar_t);
else
{
r = mknew (wchar_t);
*r = 0; *r = 0;
} }
return r; return r;
} }
char * char *ustrtoa(wchar_t * s, char *outbuf, int size)
ustrtoa (wchar_t * s, char *outbuf, int size)
{ {
char *p; char *p;
if (!s) if (!s) {
{
*outbuf = '\0'; *outbuf = '\0';
return outbuf; return outbuf;
} }
@ -41,8 +35,7 @@ ustrtoa (wchar_t * s, char *outbuf, int size)
return outbuf; return outbuf;
} }
int int ustrlen(wchar_t * s)
ustrlen (wchar_t * s)
{ {
int len = 0; int len = 0;
while (*s++) while (*s++)
@ -50,26 +43,22 @@ ustrlen (wchar_t * s)
return len; return len;
} }
wchar_t * wchar_t *uadv(wchar_t * s)
uadv (wchar_t * s)
{ {
return s + 1 + ustrlen (s); return s + 1 + ustrlen(s);
} }
wchar_t * wchar_t *ustrcpy(wchar_t * dest, wchar_t * source)
ustrcpy (wchar_t * dest, wchar_t * source)
{ {
wchar_t *ret = dest; wchar_t *ret = dest;
do do {
{
*dest++ = *source; *dest++ = *source;
} }
while (*source++); while (*source++);
return ret; return ret;
} }
int int ustrcmp(wchar_t * lhs, wchar_t * rhs)
ustrcmp (wchar_t * lhs, wchar_t * rhs)
{ {
if (!lhs && !rhs) if (!lhs && !rhs)
return 0; return 0;
@ -86,8 +75,7 @@ ustrcmp (wchar_t * lhs, wchar_t * rhs)
return 0; return 0;
} }
wchar_t wchar_t utolower(wchar_t c)
utolower (wchar_t c)
{ {
if (c == L'\0') if (c == L'\0')
return c; /* this property needed by ustricmp */ return c; /* this property needed by ustricmp */
@ -97,11 +85,10 @@ utolower (wchar_t c)
return c; return c;
} }
int int ustricmp(wchar_t * lhs, wchar_t * rhs)
ustricmp (wchar_t * lhs, wchar_t * rhs)
{ {
wchar_t lc, rc; wchar_t lc, rc;
while ((lc = utolower (*lhs)) == (rc = utolower (*rhs)) && lc && rc) while ((lc = utolower(*lhs)) == (rc = utolower(*rhs)) && lc && rc)
lhs++, rhs++; lhs++, rhs++;
if (!lc && !rc) if (!lc && !rc)
return 0; return 0;
@ -111,33 +98,28 @@ ustricmp (wchar_t * lhs, wchar_t * rhs)
return 1; return 1;
} }
wchar_t * wchar_t *ustrlow(wchar_t * s)
ustrlow (wchar_t * s)
{ {
wchar_t *p = s; wchar_t *p = s;
while (*p) while (*p) {
{ *p = utolower(*p);
*p = utolower (*p);
p++; p++;
} }
return s; return s;
} }
int int utoi(wchar_t * s)
utoi (wchar_t * s)
{ {
int sign = +1; int sign = +1;
int n; int n;
if (*s == L'-') if (*s == L'-') {
{
s++; s++;
sign = -1; sign = -1;
} }
n = 0; n = 0;
while (*s && *s >= L'0' && *s <= L'9') while (*s && *s >= L'0' && *s <= L'9') {
{
n *= 10; n *= 10;
n += (*s - '0'); n += (*s - '0');
s++; s++;
@ -146,24 +128,21 @@ utoi (wchar_t * s)
return n; return n;
} }
int int utob(wchar_t * s)
utob (wchar_t * s)
{ {
if (!ustricmp (s, L"yes") || !ustricmp (s, L"y") || if (!ustricmp(s, L"yes") || !ustricmp(s, L"y") ||
!ustricmp (s, L"true") || !ustricmp (s, L"t")) !ustricmp(s, L"true") || !ustricmp(s, L"t"))
return TRUE; return TRUE;
return FALSE; return FALSE;
} }
int int uisdigit(wchar_t c)
uisdigit (wchar_t c)
{ {
return c >= L'0' && c <= L'9'; return c >= L'0' && c <= L'9';
} }
#define USTRFTIME_DELTA 128 #define USTRFTIME_DELTA 128
wchar_t * wchar_t *ustrftime(wchar_t * wfmt, struct tm * timespec)
ustrftime (wchar_t * wfmt, struct tm * timespec)
{ {
void *blk = NULL; void *blk = NULL;
wchar_t *wblk, *wp; wchar_t *wblk, *wp;
@ -178,29 +157,26 @@ ustrftime (wchar_t * wfmt, struct tm * timespec)
* generate the empty string. Somebody throw a custard pie at * generate the empty string. Somebody throw a custard pie at
* whoever was responsible for that. Please? * whoever was responsible for that. Please?
*/ */
if (wfmt) if (wfmt) {
{ len = ustrlen(wfmt);
len = ustrlen (wfmt); fmt = mknewa(char, 2 + len);
fmt = mknewa (char, 2 + len); ustrtoa(wfmt, fmt + 1, len + 1);
ustrtoa (wfmt, fmt + 1, len + 1);
fmt[0] = ' '; fmt[0] = ' ';
} } else
else
fmt = " %c"; fmt = " %c";
while (1) while (1) {
{
size += USTRFTIME_DELTA; size += USTRFTIME_DELTA;
blk = resize ((char *) blk, size); blk = resize((char *) blk, size);
len = strftime ((char *) blk, size - 1, fmt, timespec); len = strftime((char *) blk, size - 1, fmt, timespec);
if (len > 0) if (len > 0)
break; break;
} }
/* Note: +1 for the terminating 0, -1 for the initial space in fmt */ /* Note: +1 for the terminating 0, -1 for the initial space in fmt */
wblk = resize ((wchar_t *) blk, len); wblk = resize((wchar_t *) blk, len);
text = mknewa (char, len); text = mknewa(char, len);
strftime (text, len, fmt + 1, timespec); strftime(text, len, fmt + 1, timespec);
/* /*
* We operate in the C locale, so this all ought to be kosher * We operate in the C locale, so this all ought to be kosher
* ASCII. If we ever move outside ASCII machines, we may need * ASCII. If we ever move outside ASCII machines, we may need
@ -210,7 +186,7 @@ ustrftime (wchar_t * wfmt, struct tm * timespec)
*wp = *p; *wp = *p;
*wp = 0; *wp = 0;
if (wfmt) if (wfmt)
sfree (fmt); sfree(fmt);
sfree (text); sfree(text);
return wblk; return wblk;
} }

File diff suppressed because it is too large Load diff

View file

@ -9,25 +9,25 @@ typedef struct WHLP_TOPIC_tag *WHLP_TOPIC;
/* /*
* Initialise a new WHlp context and begin accumulating data in it. * Initialise a new WHlp context and begin accumulating data in it.
*/ */
WHLP whlp_new (void); WHLP whlp_new(void);
/* /*
* Close a WHlp context and write out the help file it has created. * Close a WHlp context and write out the help file it has created.
*/ */
void whlp_close (WHLP h, char *filename); void whlp_close(WHLP h, char *filename);
/* /*
* Abandon and free a WHlp context without writing out anything. * Abandon and free a WHlp context without writing out anything.
*/ */
void whlp_abandon (WHLP h); void whlp_abandon(WHLP h);
/* /*
* Specify the title and copyright notice of a help file. Also * Specify the title and copyright notice of a help file. Also
* specify Help macros to be run on loading. * specify Help macros to be run on loading.
*/ */
void whlp_title (WHLP h, char *title); void whlp_title(WHLP h, char *title);
void whlp_copyright (WHLP h, char *copyright); void whlp_copyright(WHLP h, char *copyright);
void whlp_start_macro (WHLP h, char *macro); void whlp_start_macro(WHLP h, char *macro);
/* /*
* Register a help topic. Irritatingly, due to weird phase-order * Register a help topic. Irritatingly, due to weird phase-order
@ -53,13 +53,13 @@ void whlp_start_macro (WHLP h, char *macro);
* On success (i.e. in any circumstance other than a hash clash), a * On success (i.e. in any circumstance other than a hash clash), a
* valid WHLP_TOPIC is returned for later use. * valid WHLP_TOPIC is returned for later use.
*/ */
WHLP_TOPIC whlp_register_topic (WHLP h, char *context_name, char **clash); WHLP_TOPIC whlp_register_topic(WHLP h, char *context_name, char **clash);
/* /*
* Link two topics together in a browse sequence. Automatically * Link two topics together in a browse sequence. Automatically
* takes care of the forward and reverse links. * takes care of the forward and reverse links.
*/ */
void whlp_browse_link (WHLP h, WHLP_TOPIC before, WHLP_TOPIC after); void whlp_browse_link(WHLP h, WHLP_TOPIC before, WHLP_TOPIC after);
/* /*
* After calling whlp_register_topic for all topics, you should * After calling whlp_register_topic for all topics, you should
@ -67,12 +67,12 @@ void whlp_browse_link (WHLP h, WHLP_TOPIC before, WHLP_TOPIC after);
* context names for all anonymous topics. Then you can start * context names for all anonymous topics. Then you can start
* writing actual text. * writing actual text.
*/ */
void whlp_prepare (WHLP h); void whlp_prepare(WHLP h);
/* /*
* Create a link from an index term to a topic. * Create a link from an index term to a topic.
*/ */
void whlp_index_term (WHLP h, char *index, WHLP_TOPIC topic); void whlp_index_term(WHLP h, char *index, WHLP_TOPIC topic);
/* /*
* Call this if you need the id of a topic and you don't already * Call this if you need the id of a topic and you don't already
@ -85,13 +85,13 @@ void whlp_index_term (WHLP h, char *index, WHLP_TOPIC topic);
* *
* Do not call this before calling whlp_prepare(). * Do not call this before calling whlp_prepare().
*/ */
char *whlp_topic_id (WHLP_TOPIC topic); char *whlp_topic_id(WHLP_TOPIC topic);
/* /*
* Call this to specify which help topic will be the first one * Call this to specify which help topic will be the first one
* displayed when the help file is loaded. * displayed when the help file is loaded.
*/ */
void whlp_primary_topic (WHLP h, WHLP_TOPIC topic); void whlp_primary_topic(WHLP h, WHLP_TOPIC topic);
/* /*
* Call this when about to begin writing out the text for a topic. * Call this when about to begin writing out the text for a topic.
@ -101,7 +101,7 @@ void whlp_primary_topic (WHLP h, WHLP_TOPIC topic);
* *
* whlp_begin_topic(helpfile, mytopic, "Title", NULL); * whlp_begin_topic(helpfile, mytopic, "Title", NULL);
*/ */
void whlp_begin_topic (WHLP h, WHLP_TOPIC topic, char *title, ...); void whlp_begin_topic(WHLP h, WHLP_TOPIC topic, char *title, ...);
/* /*
* Call this to set up a font descriptor. You supply the font name, * Call this to set up a font descriptor. You supply the font name,
@ -118,8 +118,7 @@ void whlp_begin_topic (WHLP h, WHLP_TOPIC topic, char *title, ...);
* descriptor you create, but you could work this out just as * descriptor you create, but you could work this out just as
* easily yourself by counting. * easily yourself by counting.
*/ */
enum enum {
{
WHLP_FONT_BOLD = 1, WHLP_FONT_BOLD = 1,
WHLP_FONT_ITALIC = 2, WHLP_FONT_ITALIC = 2,
WHLP_FONT_UNDERLINE = 4, WHLP_FONT_UNDERLINE = 4,
@ -127,15 +126,14 @@ enum
WHLP_FONT_DOUBLEUND = 16, WHLP_FONT_DOUBLEUND = 16,
WHLP_FONT_SMALLCAPS = 32 WHLP_FONT_SMALLCAPS = 32
}; };
enum enum {
{
WHLP_FONTFAM_FIXED = 1, WHLP_FONTFAM_FIXED = 1,
WHLP_FONTFAM_SERIF = 2, WHLP_FONTFAM_SERIF = 2,
WHLP_FONTFAM_SANS = 3, WHLP_FONTFAM_SANS = 3,
WHLP_FONTFAM_SCRIPT = 4, WHLP_FONTFAM_SCRIPT = 4,
WHLP_FONTFAM_DECOR = 5 WHLP_FONTFAM_DECOR = 5
}; };
int whlp_create_font (WHLP h, char *font, int family, int halfpoints, int whlp_create_font(WHLP h, char *font, int family, int halfpoints,
int rendition, int r, int g, int b); int rendition, int r, int g, int b);
/* /*
@ -148,26 +146,23 @@ int whlp_create_font (WHLP h, char *font, int family, int halfpoints,
* whole paragraph, and finally call whlp_end_para() to finish it * whole paragraph, and finally call whlp_end_para() to finish it
* off. * off.
*/ */
enum enum {
{
WHLP_PARA_SPACEABOVE = 1, WHLP_PARA_SPACEBELOW, WHLP_PARA_SPACELINES, WHLP_PARA_SPACEABOVE = 1, WHLP_PARA_SPACEBELOW, WHLP_PARA_SPACELINES,
WHLP_PARA_LEFTINDENT, WHLP_PARA_RIGHTINDENT, WHLP_PARA_FIRSTLINEINDENT, WHLP_PARA_LEFTINDENT, WHLP_PARA_RIGHTINDENT, WHLP_PARA_FIRSTLINEINDENT,
WHLP_PARA_ALIGNMENT WHLP_PARA_ALIGNMENT
}; };
enum enum {
{
WHLP_ALIGN_LEFT, WHLP_ALIGN_RIGHT, WHLP_ALIGN_CENTRE WHLP_ALIGN_LEFT, WHLP_ALIGN_RIGHT, WHLP_ALIGN_CENTRE
}; };
enum enum {
{
WHLP_PARA_SCROLL, WHLP_PARA_NONSCROLL WHLP_PARA_SCROLL, WHLP_PARA_NONSCROLL
}; };
void whlp_para_attr (WHLP h, int attr_id, int attr_param); void whlp_para_attr(WHLP h, int attr_id, int attr_param);
void whlp_set_tabstop (WHLP h, int tabstop, int alignment); void whlp_set_tabstop(WHLP h, int tabstop, int alignment);
void whlp_begin_para (WHLP h, int para_type); void whlp_begin_para(WHLP h, int para_type);
void whlp_end_para (WHLP h); void whlp_end_para(WHLP h);
void whlp_set_font (WHLP h, int font_id); void whlp_set_font(WHLP h, int font_id);
void whlp_text (WHLP h, char *text); void whlp_text(WHLP h, char *text);
void whlp_start_hyperlink (WHLP h, WHLP_TOPIC target); void whlp_start_hyperlink(WHLP h, WHLP_TOPIC target);
void whlp_end_hyperlink (WHLP h); void whlp_end_hyperlink(WHLP h);
void whlp_tab (WHLP h); void whlp_tab(WHLP h);