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, paragraph *end, int indexable);
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 */
if (topfile->child) {
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;
}
sfree(conf.fsect);
}
static int xhtml_para_level(paragraph *p)
{
switch (p->type)
{
case para_Title:
return 0;
break;
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;
}
}
/* 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;
fprintf(fp, "", conf.nav_attrs);
} else {
fprintf(fp, ">");
}
if (xhtml_last_file==NULL) {
fprintf(fp, "Previous | ");
} else {
fprintf(fp, "Previous | ", xhtml_last_file->filename);
}
fprintf(fp, "Contents | ", conf.contents_filename);
if (file == NULL) {
fprintf(fp, "Index | ");
} else {
fprintf(fp, "Index | ", conf.index_filename);
}
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", conf.index_filename);
}
} else {
fprintf(fp, "Next", xhtml_next_file->filename);
}
fprintf(fp, "
\n");
}
/* Write out the index file */
static void xhtml_do_index_body(FILE *fp)
{
indexentry *y;
int ti;
if (count234(idx->entries) == 0)
return; /* don't write anything at all */
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, FALSE);
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, FALSE);
} else if (sect->para->words) {
xhtml_para(fp, sect->para->words, FALSE);
}
fprintf(fp, "");
if (i+1nsection) {
fprintf(fp, ", ");
}
}
}
fprintf(fp, "
\n");
}
}
fprintf(fp, "
\n");
}
static void xhtml_do_index()
{
word temp_word = { NULL, NULL, word_Normal, 0, 0, L"Index", { NULL, 0, 0} };
FILE *fp = fopen(conf.index_filename, "w");
if (fp==NULL)
fatal(err_cantopenw, conf.index_filename);
xhtml_doheader(fp, &temp_word);
xhtml_donavlinks(fp, NULL);
xhtml_do_index_body(fp);
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! */);
/*
* Display the title.
*/
for (p = sourceform; p; p = p->next)
{
if (p->type == para_Title) {
xhtml_heading(fp, p, FALSE);
break;
}
}
/* Do the preamble */
for (p = sourceform; p; p = p->next)
{
if (p->type == para_Chapter || p->type == para_Heading ||
p->type == para_Subsect || p->type == para_Appendix ||
p->type == para_UnnumberedChapter) {
/*
* We've found the end of the preamble. Do every normal
* paragraph up to there.
*/
xhtml_do_paras(fp, sourceform, p, FALSE);
break;
}
}
xhtml_do_contents(fp, file);
xhtml_do_sections(fp, file->sections);
/*
* Put the index in the top file if we're in single-file mode
* (leaf-level 0).
*/
if (conf.leaf_level == 0 && count234(idx->entries) > 0) {
fprintf(fp, "Index
\n");
xhtml_do_index_body(fp);
}
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, 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 || section->level < 0)
return TRUE;
if (last_level > section->level) {
while (last_level > section->level) {
last_level--;
fprintf(fp, "\n");
}
fprintf(fp, "\n");
} else if (last_level < section->level) {
assert(last_level == section->level - 1);
last_level++;
fprintf(fp, "