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,15 +5,13 @@
#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;
@ -23,20 +21,17 @@ gentext (int num)
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,40 +46,29 @@ 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); error(err_nosuchkw, &para->fpos, para->keyword);
} } else if (kw->text) {
else if (kw->text)
{
error(err_multiBR, &para->fpos, para->keyword); error(err_multiBR, &para->fpos, para->keyword);
} } else {
else
{
kw->text = dup_word_list(para->words); kw->text = dup_word_list(para->words);
} }
} } else if (para->type == para_NoCite) {
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);
} }
@ -93,8 +77,7 @@ gen_citations (paragraph * source, keywordlist * kl)
/* /*
* 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,14 +89,11 @@ 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); keyword *kw = kw_lookup(kl, para->keyword);
assert(kw != NULL); assert(kw != NULL);
if (!kw->text) if (!kw->text) {
{
word *wd = smalloc(sizeof(word)); word *wd = smalloc(sizeof(word));
wd->text = gentext(++bibnum); wd->text = gentext(++bibnum);
wd->type = word_Normal; wd->type = word_Normal;

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,8 +23,7 @@ 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;
@ -42,16 +40,14 @@ number_init (void)
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);
@ -62,8 +58,7 @@ 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;
@ -74,14 +69,12 @@ 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;
@ -89,16 +82,14 @@ donumber (word *** wret, int num)
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)
@ -108,8 +99,7 @@ doanumber (word *** wret, int num)
} }
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;
@ -117,8 +107,7 @@ doanumber (word *** wret, int num)
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")) {
{
if (!ustricmp (source->keyword, L"chapter"))
{
state->chaptertext = uadv(source->keyword); state->chaptertext = uadv(source->keyword);
} } else if (!ustricmp(source->keyword, L"section")) {
else if (!ustricmp (source->keyword, L"section"))
{
state->sectiontext = uadv(source->keyword); state->sectiontext = uadv(source->keyword);
} } else if (!ustricmp(source->keyword, L"appendix")) {
else if (!ustricmp (source->keyword, L"appendix"))
{
state->apptext = uadv(source->keyword); 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,8 +138,7 @@ 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++)
@ -174,16 +154,14 @@ 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);
@ -198,8 +176,7 @@ number_mktext (numberstate * state, paragraph * p, wchar_t * category,
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;
@ -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,8 +22,7 @@ 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;
@ -54,7 +52,8 @@ do_error (int code, va_list ap)
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:
@ -136,7 +135,8 @@ do_error (int code, va_list ap)
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:
@ -183,8 +183,10 @@ do_error (int code, va_list ap)
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:
@ -196,8 +198,7 @@ do_error (int code, va_list ap)
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);
@ -207,8 +208,7 @@ do_error (int code, va_list ap)
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);
@ -217,8 +217,7 @@ fatal (int code, ...)
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);

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, ...)
NORETURN;
void error(int code, ...); void error(int code, ...);
enum 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' */
@ -268,7 +255,6 @@ fatal (int code, ...)
/* /*
* help.c * help.c
*/ */
void help (void);
void usage(void); void usage(void);
void showversion(void); void showversion(void);
@ -292,14 +278,12 @@ fatal (int code, ...)
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;
}; };
@ -317,8 +301,7 @@ fatal (int code, ...)
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 */
@ -335,8 +318,7 @@ fatal (int code, ...)
/* /*
* 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 */
@ -344,8 +326,7 @@ fatal (int code, ...)
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) */
@ -363,8 +344,7 @@ 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' */
}; };
@ -372,8 +352,7 @@ fatal (int code, ...)
/* /*
* 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;
@ -385,8 +364,7 @@ fatal (int code, ...)
/* /*
* 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 */
}; };
@ -416,23 +394,12 @@ fatal (int code, ...)
/* /*
* 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

@ -9,8 +9,7 @@
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);
@ -18,8 +17,7 @@ make_index (void)
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;
@ -30,23 +28,20 @@ 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);
@ -55,8 +50,7 @@ compare_entries (void *av, void *bv)
/* /*
* 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);
} }
@ -77,13 +71,11 @@ index_merge (indexdata * idx, int is_explicit, wchar_t * tags, word * text)
/* /*
* 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.
*/ */
@ -94,8 +86,7 @@ index_merge (indexdata * idx, int is_explicit, wchar_t * tags, word * text)
* 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,21 +106,17 @@ 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);
@ -150,31 +134,24 @@ 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);
@ -185,15 +162,13 @@ build_index (indexdata * i)
} }
} }
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);
@ -201,8 +176,8 @@ cleanup_index (indexdata * i)
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);
@ -212,8 +187,7 @@ cleanup_index (indexdata * 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;
@ -221,8 +195,7 @@ index_debug (indexdata * i)
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);
@ -231,8 +204,8 @@ index_debug (indexdata * i)
} }
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);
@ -240,8 +213,7 @@ index_debug (indexdata * i)
} }
} }
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++)
@ -251,24 +223,19 @@ dbg_prtmerge (int is_explicit, wchar_t * tag, word * 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
else
printf("(no text)"); printf("(no text)");
if (w->alt) if (w->alt) {
{
printf(" alt = {\n"); printf(" alt = {\n");
dbg_prtwordlist(level + 1, w->alt); dbg_prtwordlist(level + 1, w->alt);
printf("%*s}", level * 4, ""); printf("%*s}", level * 4, "");

File diff suppressed because it is too large Load diff

View file

@ -7,24 +7,21 @@
#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,8 +32,7 @@ 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);
@ -49,8 +45,7 @@ get_keywords (paragraph * source)
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,8 +54,7 @@ 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;
@ -74,10 +68,8 @@ get_keywords (paragraph * source)
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);
@ -85,18 +77,14 @@ get_keywords (paragraph * source)
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);
} }
@ -106,8 +94,7 @@ get_keywords (paragraph * source)
number_free(n); number_free(n);
if (errors) if (errors) {
{
free_keywords(kl); free_keywords(kl);
return NULL; return NULL;
} }
@ -115,15 +102,13 @@ get_keywords (paragraph * source)
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);
@ -132,26 +117,20 @@ free_keywords (keywordlist * kl)
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 &&
@ -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,8 +9,7 @@ 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++)

View file

@ -10,8 +10,7 @@ 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;
@ -31,8 +30,7 @@ main (int argc, char **argv)
reportcols = 0; reportcols = 0;
debug = 0; debug = 0;
if (argc == 1) if (argc == 1) {
{
usage(); usage();
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
@ -40,19 +38,15 @@ main (int argc, char **argv)
/* /*
* 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")) {
{
help ();
nogo = TRUE;
}
else if (!strcmp (opt, "-version"))
{
showversion(); showversion();
nogo = TRUE; nogo = TRUE;
} } else if (!strcmp(opt, "-licence") ||
else if (!strcmp (opt, "-licence") || !strcmp(opt, "-license")) {
!strcmp (opt, "-license"))
{
licence(); licence();
nogo = TRUE; nogo = TRUE;
} } else if (!strcmp(opt, "-output")) {
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,12 +88,7 @@ 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;
@ -140,8 +112,7 @@ 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';
@ -150,8 +121,7 @@ main (int argc, char **argv)
/* /*
* 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;
@ -170,9 +140,7 @@ main (int argc, char **argv)
} }
} }
} }
} } else {
else
{
/* /*
* A non-option argument. * A non-option argument.
*/ */
@ -188,8 +156,7 @@ main (int argc, char **argv)
/* /*
* 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);
@ -234,16 +201,13 @@ main (int argc, char **argv)
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);
@ -253,23 +217,19 @@ main (int argc, char **argv)
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);
@ -277,8 +237,7 @@ dbg_prtsource (paragraph * sourceform)
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);
@ -286,8 +245,7 @@ dbg_prtsource (paragraph * sourceform)
} }
} }
static void static void dbg_prtkws(keywordlist * kws)
dbg_prtkws (keywordlist * kws)
{ {
/* /*
* Output keywords in debugging format. * Output keywords in debugging format.
@ -296,13 +254,11 @@ 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);
@ -316,24 +272,19 @@ dbg_prtkws (keywordlist * kws)
} }
} }
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
else
printf("(no text)"); printf("(no text)");
if (w->alt) if (w->alt) {
{
printf(" alt = {\n"); printf(" alt = {\n");
dbg_prtwordlist(level + 1, w->alt); dbg_prtwordlist(level + 1, w->alt);
printf("%*s}", level * 4, ""); printf("%*s}", level * 4, "");

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,18 +10,14 @@
#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"); fprintf(stderr, "panic: unable to open malloc.log\n");
exit(10); exit(10);
} }
@ -29,8 +25,7 @@ logallocinit (void)
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);
@ -50,8 +45,7 @@ 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));
@ -65,10 +59,8 @@ void *(smalloc) (LOGPARAMS int size)
/* /*
* 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);
@ -78,18 +70,14 @@ void (sfree) (LOGPARAMS void *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);
@ -104,8 +92,7 @@ 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);
@ -115,13 +102,11 @@ dupstr (char *s)
/* /*
* 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);
@ -140,12 +125,10 @@ 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);
@ -158,12 +141,10 @@ free_word_list (word * w)
/* /*
* 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);

View file

@ -4,15 +4,13 @@
#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;
@ -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,11 +51,9 @@ 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);
} }
@ -69,12 +61,10 @@ rdadd (rdstring * rs, wchar_t 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);
} }
@ -82,18 +72,15 @@ rdadds (rdstring * rs, wchar_t * 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);
} }
@ -101,12 +88,10 @@ rdaddc (rdstringc * rs, char 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);
} }
@ -114,28 +99,23 @@ rdaddsc (rdstringc * rs, char *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;
@ -145,18 +125,17 @@ compare_wordlists (word * a, word * b)
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,18 +151,14 @@ 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) && int before = (wp && isattr(wp->type) &&
sameattr(wp->type, w->type)); sameattr(wp->type, w->type));
int after = (w->next && isattr(w->next->type) && int after = (w->next && isattr(w->next->type) &&
@ -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,17 +191,14 @@ 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 ||
@ -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,8 +291,7 @@ 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;
@ -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;
} }
@ -365,11 +321,9 @@ wrap_para (word * text, int width, int subsequentwidth,
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

@ -125,8 +125,7 @@ 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);

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 {
else
{
r = mknew(wchar_t); 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,8 +85,7 @@ 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)
@ -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,8 +128,7 @@ 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"))
@ -155,15 +136,13 @@ utob (wchar_t * s)
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,18 +157,15 @@ 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);

File diff suppressed because it is too large Load diff

View file

@ -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,8 +126,7 @@ 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,
@ -148,18 +146,15 @@ 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);