sections->level) {
currentfile=currentfile->parent;
if (currentfile) {
/* printf(" * up one file level to '%s'\n", currentfile->filename);*/
} else {
/* printf(" * up one file level (off top of tree)\n");*/
}
}
if (currentfile) { /* new file (we had to skip up a file to
get here, so we must be dealing with a
level no lower than the configured
leaf_level */
xhtmlfile *file = xhtml_new_file(sect);
currentfile->next=file;
sect->file=file;
file->parent=currentfile->parent;
file->is_leaf=(level==conf.leaf_level);
file->sections=sect;
/* printf("connected '%s' to new file '%s' [III]\n", sect->fragment, file->filename);*/
currentfile=file;
currentsect=sect;
} else {
fatal(err_whatever, "Ran off the top trying to connect sibling: strange document.");
}
}
}
}
}
topsection = lastsection; /* get correct end of the chain */
xhtml_fixup_layout(topfile); /* leaf files not at leaf level marked as such */
}
static void xhtml_do_index();
static void xhtml_do_file(xhtmlfile *file);
static void xhtml_do_top_file(xhtmlfile *file, paragraph *sourceform);
static void xhtml_do_paras(FILE *fp, paragraph *p);
static int xhtml_do_contents_limit(FILE *fp, xhtmlfile *file, int limit);
static int xhtml_do_contents_section_limit(FILE *fp, xhtmlsection *section, int limit);
static int xhtml_add_contents_entry(FILE *fp, xhtmlsection *section, int limit);
static int xhtml_do_contents(FILE *fp, xhtmlfile *file);
static int xhtml_do_naked_contents(FILE *fp, xhtmlfile *file);
static void xhtml_do_sections(FILE *fp, xhtmlsection *sections);
/*
* Do all the files in this structure.
*/
static void xhtml_do_files(xhtmlfile *file)
{
xhtml_do_file(file);
if (file->child)
xhtml_do_files(file->child);
if (file->next)
xhtml_do_files(file->next);
}
/*
* Free up all memory used by the file tree from 'xfile' downwards
*/
static void xhtml_free_file(xhtmlfile* xfile)
{
if (xfile==NULL) {
return;
}
if (xfile->filename) {
sfree(xfile->filename);
}
xhtml_free_file(xfile->child);
xhtml_free_file(xfile->next);
sfree(xfile);
}
/*
* Main function.
*/
void xhtml_backend(paragraph *sourceform, keywordlist *in_keywords,
indexdata *in_idx)
{
/* int i;*/
indexentry *ientry;
int ti;
xhtmlsection *xsect;
sourceparas = sourceform;
conf = xhtml_configure(sourceform);
keywords = in_keywords;
idx = in_idx;
/* Clear up the index entries backend data pointers */
for (ti=0; (ientry = (indexentry *)index234(idx->entries, ti))!=NULL; ti++) {
ientry->backend_data=NULL;
}
xhtml_ponder_layout(sourceform);
/* old system ... (writes to *.alt, but gets some stuff wrong and is ugly) */
/* xhtml_level_0(sourceform);
for (i=1; i<=conf.leaf_level; i++)
{
xhtml_level(sourceform, i);
}*/
/* new system ... (writes to *.html, but isn't fully trusted) */
xhtml_do_top_file(topfile, sourceform);
assert(!topfile->next); /* shouldn't have a sibling at all */
xhtml_do_files(topfile->child);
xhtml_do_index();
/* release file, section, index data structures */
xsect = topsection;
while (xsect) {
xhtmlsection *tmp = xsect->chain;
if (xsect->fragment) {
sfree(xsect->fragment);
}
sfree(xsect);
xsect = tmp;
}
xhtml_free_file(topfile);
for (ti = 0; (ientry=(indexentry *)index234(idx->entries, ti))!=NULL; ti++) {
if (ientry->backend_data!=NULL) {
xhtmlindex *xi = (xhtmlindex*) ientry->backend_data;
if (xi->sections!=NULL) {
sfree(xi->sections);
}
sfree(xi);
}
ientry->backend_data = NULL;
}
}
static int xhtml_para_level(paragraph *p)
{
switch (p->type)
{
case para_UnnumberedChapter:
case para_Chapter:
case para_Appendix:
return 1;
break;
/* case para_BiblioCited:
return 2;
break;*/
case para_Heading:
case para_Subsect:
return p->aux+2;
break;
default:
return -1;
break;
}
}
static char* xhtml_index_filename = "Index.html";
/* Output the nav links for the current file.
* file == NULL means we're doing the index
*/
static void xhtml_donavlinks(FILE *fp, xhtmlfile *file)
{
xhtmlfile *xhtml_next_file = NULL;
if (xhtml_last_file==NULL) {
fprintf(fp, "Previous | ");
} else {
fprintf(fp, "
Previous | ", xhtml_last_file->filename);
}
fprintf(fp, "Contents | ");
if (file != NULL) { /* otherwise we're doing nav links for the index */
if (xhtml_next_file==NULL)
xhtml_next_file = file->child;
if (xhtml_next_file==NULL)
xhtml_next_file = file->next;
if (xhtml_next_file==NULL)
xhtml_next_file = file->parent->next;
}
if (xhtml_next_file==NULL) {
if (file==NULL) { /* index, so no next file */
fprintf(fp, "Next ");
} else {
fprintf(fp, "Next", xhtml_index_filename);
}
} else {
fprintf(fp, "Next", xhtml_next_file->filename);
}
fprintf(fp, "
\n");
}
/* Write out the index file */
static void xhtml_do_index()
{
word temp_word = { NULL, NULL, word_Normal, 0, 0, L"Index", { NULL, 0, 0} };
indexentry *y;
int ti;
FILE *fp = fopen(xhtml_index_filename, "w");
if (fp==NULL)
fatal(err_cantopenw, xhtml_index_filename);
xhtml_doheader(fp, &temp_word);
xhtml_donavlinks(fp, NULL);
fprintf(fp, "\n");
/* iterate over idx->entries using the tree functions and display everything */
for (ti = 0; (y = (indexentry *)index234(idx->entries, ti)) != NULL; ti++) {
if (y->backend_data) {
int i;
xhtmlindex *xi;
fprintf(fp, "- ");
xhtml_para(fp, y->text);
fprintf(fp, "
\n- ");
xi = (xhtmlindex*) y->backend_data;
for (i=0; insection; i++) {
xhtmlsection *sect = xi->sections[i];
if (sect) {
fprintf(fp, "", sect->file->filename, sect->fragment);
if (sect->para->kwtext) {
xhtml_para(fp, sect->para->kwtext);
} else if (sect->para->words) {
xhtml_para(fp, sect->para->words);
}
fprintf(fp, "");
if (i+1nsection) {
fprintf(fp, ", ");
}
}
}
fprintf(fp, "
\n");
}
}
fprintf(fp, "
\n");
xhtml_donavlinks(fp, NULL);
xhtml_dofooter(fp);
fclose(fp);
}
/* Output the given file. This includes whatever contents at beginning and end, etc. etc. */
static void xhtml_do_file(xhtmlfile *file)
{
FILE *fp = fopen(file->filename, "w");
if (fp==NULL)
fatal(err_cantopenw, file->filename);
if (file->sections->para->words) {
xhtml_doheader(fp, file->sections->para->words);
} else if (file->sections->para->kwtext) {
xhtml_doheader(fp, file->sections->para->kwtext);
} else {
xhtml_doheader(fp, NULL);
}
xhtml_donavlinks(fp, file);
if (file->is_leaf && conf.leaf_contains_contents && xhtml_do_contents(NULL, file)>=conf.leaf_smallest_contents)
xhtml_do_contents(fp, file);
xhtml_do_sections(fp, file->sections);
if (!file->is_leaf)
xhtml_do_naked_contents(fp, file);
xhtml_donavlinks(fp, file);
xhtml_dofooter(fp);
fclose(fp);
xhtml_last_file = file;
}
/* Output the top-level file. */
static void xhtml_do_top_file(xhtmlfile *file, paragraph *sourceform)
{
paragraph *p;
int done=FALSE;
FILE *fp = fopen(file->filename, "w");
if (fp==NULL)
fatal(err_cantopenw, file->filename);
/* Do the title -- only one allowed */
for (p = sourceform; p && !done; p = p->next)
{
if (p->type == para_Title)
{
xhtml_doheader(fp, p->words);
done=TRUE;
}
}
if (!done)
xhtml_doheader(fp, NULL /* Eek! */);
/* Do the preamble and copyright */
for (p = sourceform; p; p = p->next)
{
if (p->type == para_Preamble)
{
fprintf(fp, "");
xhtml_para(fp, p->words);
fprintf(fp, "
\n");
}
}
for (p = sourceform; p; p = p->next)
{
if (p->type == para_Copyright)
{
fprintf(fp, "");
xhtml_para(fp, p->words);
fprintf(fp, "
\n");
}
}
xhtml_do_contents(fp, file);
xhtml_do_sections(fp, file->sections);
xhtml_dofooter(fp);
fclose(fp);
}
/* Convert a Unicode string to an ASCII one. '?' is
* used for unmappable characters.
*/
static void xhtml_utostr(wchar_t *in, char **out)
{
int l = ustrlen(in);
int i;
*out = smalloc(l+1);
for (i=0; i=32 && in[i]<=126)
(*out)[i]=(char)in[i];
else
(*out)[i]='?';
}
(*out)[i]=0;
}
/*
* Write contents for the given file, and subfiles, down to
* the appropriate contents depth. Returns the number of
* entries written.
*/
static int xhtml_do_contents(FILE *fp, xhtmlfile *file)
{
int level, limit, start_level, count = 0;
if (!file)
return 0;
level = (file->sections)?(file->sections->level):(0);
limit = conf.contents_depth[(level>5)?(5):(level)];
start_level = (file->is_leaf) ? (level-1) : (level);
last_level = start_level;
count += xhtml_do_contents_section_limit(fp, file->sections, limit);
count += xhtml_do_contents_limit(fp, file->child, limit);
if (fp!=NULL) {
while (last_level > start_level) {
last_level--;
fprintf(fp, "\n");
}
}
return count;
}
/* As above, but doesn't do anything in the current file */
static int xhtml_do_naked_contents(FILE *fp, xhtmlfile *file)
{
int level, limit, start_level, count = 0;
if (!file)
return 0;
level = (file->sections)?(file->sections->level):(0);
limit = conf.contents_depth[(level>5)?(5):(level)];
start_level = (file->is_leaf) ? (level-1) : (level);
last_level = start_level;
count = xhtml_do_contents_limit(fp, file->child, limit);
if (fp!=NULL) {
while (last_level > start_level) {
last_level--;
fprintf(fp, "\n");
}
}
return count;
}
/*
* Write contents for the given file, children, and siblings, down to
* given limit contents depth.
*/
static int xhtml_do_contents_limit(FILE *fp, xhtmlfile *file, int limit)
{
int count = 0;
while (file) {
count += xhtml_do_contents_section_limit(fp, file->sections, limit);
count += xhtml_do_contents_limit(fp, file->child, limit);
file = file->next;
}
return count;
}
/*
* Write contents entries for the given section tree, down to the
* limit contents depth.
*/
static int xhtml_do_contents_section_deep_limit(FILE *fp, xhtmlsection *section, int limit)
{
int count = 0;
while (section) {
if (!xhtml_add_contents_entry(fp, section, limit))
return 0;
else
count++;
count += xhtml_do_contents_section_deep_limit(fp, section->child, limit);
section = section->next;
}
return count;
}
/*
* Write contents entries for the given section tree, down to the
* limit contents depth.
*/
static int xhtml_do_contents_section_limit(FILE *fp, xhtmlsection *section, int limit)
{
int count = 0;
if (!section)
return 0;
xhtml_add_contents_entry(fp, section, limit);
count=1;
count += xhtml_do_contents_section_deep_limit(fp, section->child, limit);
/* section=section->child;
while (section && xhtml_add_contents_entry(fp, section, limit)) {
section = section->next;
}*/
return count;
}
/*
* Add a section entry, unless we're exceeding the limit, in which
* case return FALSE (otherwise return TRUE).
*/
static int xhtml_add_contents_entry(FILE *fp, xhtmlsection *section, int limit)
{
if (!section || section->level > limit)
return FALSE;
if (fp==NULL)
return TRUE;
while (last_level > section->level) {
last_level--;
fprintf(fp, "\n");
}
while (last_level < section->level) {
last_level++;
fprintf(fp, "\n");
}
fprintf(fp, "- ", section->file->filename, section->fragment);
/* if (section->para->kwtext) {
xhtml_para(fp, section->para->kwtext);
} else */if (section->para->words) {
xhtml_para(fp, section->para->words);
}
fprintf(fp, "
\n");
return TRUE;
}
/*
* Write all the sections in this file. Do all paragraphs in this section, then all
* children (recursively), then go on to the next one (tail recursively).
*/
static void xhtml_do_sections(FILE *fp, xhtmlsection *sections)
{
while (sections) {
currentsection = sections;
xhtml_do_paras(fp, sections->para);
xhtml_do_sections(fp, sections->child);
sections = sections->next;
}
}
/* Write this list of paragraphs. Close off all lists at the end. */
static void xhtml_do_paras(FILE *fp, paragraph *p)
{
int last_type = -1, first=TRUE;
if (!p)
return;
/* for (; p && (xhtml_para_level(p)>limit || xhtml_para_level(p)==-1 || first); p=p->next) {*/
for (; p && (xhtml_para_level(p)==-1 || first); p=p->next) {
first=FALSE;
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:
xhtml_heading(fp, p);
break;
case para_Heading:
case para_Subsect:
xhtml_heading(fp, p);
break;
case para_Rule:
fprintf(fp, "\n
\n");
break;
case para_Normal:
fprintf(fp, "\n");
xhtml_para(fp, p->words);
fprintf(fp, "
\n");
break;
case para_Bullet:
case para_NumberedList:
case para_BiblioCited:
if (last_type!=p->type) {
/* start up list if necessary */
if (p->type == para_Bullet) {
fprintf(fp, "\n");
} else if (p->type == para_NumberedList) {
fprintf(fp, "\n");
} else if (p->type == para_BiblioCited) {
fprintf(fp, "\n");
}
}
if (p->type == para_Bullet || p->type == para_NumberedList)
fprintf(fp, "
- ");
else if (p->type == para_BiblioCited) {
fprintf(fp, "
- ");
xhtml_para(fp, p->kwtext);
fprintf(fp, "
\n- ");
}
xhtml_para(fp, p->words);
if (p->type == para_BiblioCited) {
fprintf(fp, "
\n");
} else if (p->type == para_Bullet || p->type == para_NumberedList) {
fprintf(fp, " ");
}
if (p->type == para_Bullet || p->type == para_NumberedList || p->type == para_BiblioCited)
/* close off list if necessary */
{
paragraph *p2 = p->next;
int close_off=FALSE;
/* if (p2 && (xhtml_para_level(p2)>limit || xhtml_para_level(p2)==-1)) {*/
if (p2 && xhtml_para_level(p2)==-1) {
if (p2->type != p->type)
close_off=TRUE;
} else {
close_off=TRUE;
}
if (close_off) {
if (p->type == para_Bullet) {
fprintf(fp, "
\n");
} else if (p->type == para_NumberedList) {
fprintf(fp, "\n");
} else if (p->type == para_BiblioCited) {
fprintf(fp, "\n");
}
}
}
break;
case para_Code:
xhtml_codepara(fp, p->words);
break;
}
last_type = p->type;
}
}
/*
* Output a header for this XHTML file.
*/
static void xhtml_doheader(FILE *fp, word *title)
{
fprintf(fp, "\n");
fprintf(fp, "\n\n\n");
if (title==NULL)
fprintf(fp, "The thing with no name!");
else
xhtml_para(fp, title);
fprintf(fp, "\n");
fprintf(fp, "\n", version);
if (conf.author)
fprintf(fp, "\n", conf.author);
if (conf.description)
fprintf(fp, "\n", conf.description);
if (conf.head_end)
fprintf(fp, "%ls\n", conf.head_end);
fprintf(fp, "\n\n");
if (conf.body)
fprintf(fp, "%ls\n", conf.body);
else
fprintf(fp, "\n");
if (conf.body_start)
fprintf(fp, "%ls\n", conf.body_start);
}
/*
* Output a footer for this XHTML file.
*/
static void xhtml_dofooter(FILE *fp)
{
fprintf(fp, "\n
\n\n");
if (conf.body_end)
fprintf(fp, "%ls\n", conf.body_end);
if (!conf.suppress_address) {
fprintf(fp,"
\n");
if (conf.address_start)
fprintf(fp, "%ls\n", conf.address_start);
/* Do the version ID */
if (conf.include_version_id) {
paragraph *p;
int started = 0;
for (p = sourceparas; p; p = p->next)
if (p->type == para_VersionID) {
xhtml_versionid(fp, p->words, started);
started = 1;
}
}
if (conf.address_end)
fprintf(fp, "%ls\n", conf.address_end);
fprintf(fp, "\n");
}
fprintf(fp, "\n\n\n");
}
/*
* Output the versionid paragraph. Typically this is a version control
* ID string (such as $Id...$ in RCS).
*/
static void xhtml_versionid(FILE *fp, word *text, int started)
{
rdstringc t = { 0, 0, NULL };
rdaddc(&t, '['); /* FIXME: configurability */
xhtml_rdaddwc(&t, text, NULL);
rdaddc(&t, ']'); /* FIXME: configurability */
if (started)
fprintf(fp, "
\n");
fprintf(fp, "%s\n", t.text);
sfree(t.text);
}
/* Is this an XHTML reserved character? */
static int xhtml_reservedchar(int c)
{
if (c=='&' || c=='<' || c=='>' || c=='"')
return TRUE;
else
return FALSE;
}
/*
* Convert a wide string into valid XHTML: Anything outside ASCII will
* be fixed up as an entity. Currently we don't worry about constraining the
* encoded character set, which we should probably do at some point (we can
* still fix up and return FALSE - see the last comment here). We also don't
* currently
*
* Because this is only used for words, spaces are HARD spaces (any other
* spaces will be word_Whitespace not word_Normal). So they become
* Unless hard_spaces is FALSE, of course (code paragraphs break the above
* rule).
*
* 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.
*
* 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 xhtml_convert(wchar_t *s, char **result, int hard_spaces) {
int doing = (result != 0);
int ok = TRUE;
char *p = NULL;
int plen = 0, psize = 0;
for (; *s; s++) {
wchar_t c = *s;
#define ensure_size(i) if (i>=psize) { psize = i+256; p = resize(p, psize); }
if (((c == 32 && !hard_spaces) || (c > 32 && c <= 126 && !xhtml_reservedchar(c)))) {
/* Char is OK. */
if (doing)
{
ensure_size(plen);
p[plen++] = (char)c;
}
} else {
/* Char needs fixing up. */
/* ok = FALSE; -- currently we never return FALSE; we
* might want to when considering a character set for the
* encoded document.
*/
if (doing)
{
if (c==32) { /* a space in a word is a hard space */
ensure_size(plen+6); /* includes space for the NUL, which is subsequently stomped on */
sprintf(p+plen, " ");
plen+=6;
} else {
/* FIXME: entity names! */
ensure_size(plen+8); /* includes space for the NUL, which is subsequently stomped on */
plen+=sprintf(p+plen, "%04i;", (int)c);
}
}
}
}
if (doing) {
p = resize(p, plen+1);
p[plen] = '\0';
*result = p;
}
return ok;
}
/*
* This formats the given words as XHTML.
*/
static void xhtml_rdaddwc(rdstringc *rs, word *text, word *end) {
char *c;
keyword *kwl;
xhtmlsection *sect;
indextag *itag;
int ti;
for (; text && text != end; text = text->next) {
switch (text->type) {
case word_HyperLink:
xhtml_utostr(text->text, &c);
rdaddsc(rs, "");
sfree(c);
break;
case word_UpperXref:
case word_LowerXref:
kwl = kw_lookup(keywords, text->text);
if (kwl) {
sect=xhtml_find_section(kwl->para);
if (sect) {
rdaddsc(rs, "file->filename);
rdaddc(rs, '#');
rdaddsc(rs, sect->fragment);
rdaddsc(rs, "\">");
} else {
rdaddsc(rs, "");
error(err_whatever, "Couldn't locate cross-reference! (Probably a bibliography entry.)");
}
} else {
rdaddsc(rs, "");
error(err_whatever, "Couldn't locate cross-reference! (Wasn't in source file.)");
}
break;
case word_IndexRef: /* in theory we could make an index target here */
/* rdaddsc(rs, "text, &c);
rdaddsc(rs, c);
sfree(c);
rdaddsc(rs, "\">");*/
/* what we _do_ need to do is to fix up the backend data
* for any indexentry this points to.
*/
for (ti=0; (itag = (indextag *)index234(idx->tags, ti))!=NULL; ti++) {
/* FIXME: really ustricmp() and not ustrcmp()? */
if (ustricmp(itag->name, text->text)==0) {
break;
}
}
if (itag!=NULL) {
if (itag->refs!=NULL) {
int i;
for (i=0; inrefs; i++) {
xhtmlindex *idx_ref;
indexentry *ientry;
ientry = itag->refs[i];
if (ientry->backend_data==NULL) {
idx_ref = (xhtmlindex*) smalloc(sizeof(xhtmlindex));
if (idx_ref==NULL)
fatal(err_nomemory);
idx_ref->nsection = 0;
idx_ref->size = 4;
idx_ref->sections = (xhtmlsection**) smalloc(idx_ref->size * sizeof(xhtmlsection*));
if (idx_ref->sections==NULL)
fatal(err_nomemory);
ientry->backend_data = idx_ref;
} else {
idx_ref = ientry->backend_data;
if (idx_ref->nsection+1 > idx_ref->size) {
int new_size = idx_ref->size * 2;
idx_ref->sections = srealloc(idx_ref->sections, new_size * sizeof(xhtmlsection));
if (idx_ref->sections==NULL) {
fatal(err_nomemory);
}
idx_ref->size = new_size;
}
}
idx_ref->sections[idx_ref->nsection++] = currentsection;
#if 0
#endif
}
} else {
fatal(err_whatever, "Index tag had no entries!");
}
} else {
fprintf(stderr, "Looking for index entry '%ls'\n", text->text);
fatal(err_whatever, "Couldn't locate index entry! (Wasn't in index.)");
}
break;
case word_HyperEnd:
case word_XrefEnd:
rdaddsc(rs, "");
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))
rdaddsc(rs, "");
else if ((towordstyle(text->type) == word_Code || towordstyle(text->type) == word_WeakCode) &&
(attraux(text->aux) == attr_First ||
attraux(text->aux) == attr_Only))
rdaddsc(rs, "");
if (removeattr(text->type) == word_Normal) {
if (xhtml_convert(text->text, &c, TRUE)) /* spaces in the word are hard */
rdaddsc(rs, c);
else
xhtml_rdaddwc(rs, text->alt, NULL);
sfree(c);
} else if (removeattr(text->type) == word_WhiteSpace) {
rdaddc(rs, ' ');
} else if (removeattr(text->type) == word_Quote) {
rdaddsc(rs, """);
}
if (towordstyle(text->type) == word_Emph &&
(attraux(text->aux) == attr_Last ||
attraux(text->aux) == attr_Only))
rdaddsc(rs, "");
else if ((towordstyle(text->type) == word_Code || towordstyle(text->type) == word_WeakCode) &&
(attraux(text->aux) == attr_Last ||
attraux(text->aux) == attr_Only))
rdaddsc(rs, "");
break;
}
}
}
/* Output a heading, formatted as XHTML.
*/
static void xhtml_heading(FILE *fp, paragraph *p)
{
rdstringc t = { 0, 0, NULL };
word *tprefix = p->kwtext;
word *nprefix = p->kwtext2;
word *text = p->words;
int level = xhtml_para_level(p);
xhtmlsection *sect = xhtml_find_section(p);
char *fragment;
if (sect) {
fragment = sect->fragment;
} else {
fragment = ""; /* FIXME: what else can we do? */
error(err_whatever, "Couldn't locate heading cross-reference!");
}
if (level>2 && nprefix) { /* FIXME: configurability on the level thing */
xhtml_rdaddwc(&t, nprefix, NULL);
rdaddc(&t, ' '); /* FIXME: as below */
} else if (tprefix) {
xhtml_rdaddwc(&t, tprefix, NULL);
rdaddsc(&t, ": "); /* FIXME: configurability */
}
xhtml_rdaddwc(&t, text, NULL);
fprintf(fp, "%s\n", fragment, level, t.text, level);
sfree(t.text);
}
/* Output a paragraph. Styles are handled by xhtml_rdaddwc().
* This looks pretty simple; I may have missed something ...
*/
static void xhtml_para(FILE *fp, word *text)
{
rdstringc out = { 0, 0, NULL };
xhtml_rdaddwc(&out, text, NULL);
fprintf(fp, "%s", out.text);
sfree(out.text);
}
/* Output a code paragraph. I'm treating this as preformatted, which
* may not be entirely correct. See xhtml_para() for my worries about
* this being overly-simple; however I think that most of the complexity
* of the text backend came entirely out of word wrapping anyway.
*/
static void xhtml_codepara(FILE *fp, word *text)
{
fprintf(fp, "");
for (; text; text = text->next) if (text->type == word_WeakCode) {
char *c;
xhtml_convert(text->text, &c, FALSE);
fprintf(fp, "%s\n", c);
sfree(c);
}
fprintf(fp, "\n");
}