📄 bk_xhtml.c
字号:
} fprintf(fp, "</body>\n\n</html>\n");}static void chm_dofooter(FILE * fp){ fprintf(fp, "</ul></BODY></HTML>\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, "<br>\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 + 7); /* includes space for the NUL, which is subsequently stomped on */ sprintf(p + plen, " "); plen += 6; } else { switch (c) { case '&': ensure_size(plen + 6); /* includes space for the NUL, which is subsequently stomped on */ plen += sprintf(p + plen, "&"); break; case '"': ensure_size(plen + 7); /* includes space for the NUL, which is subsequently stomped on */ plen += sprintf(p + plen, """); break; case '<': if (plen > 1 && *(s - 1) == '\\' && *(s - 2) == '\\') { ensure_size(--plen); p[plen - 1] = (char) c; p[plen] = 0; } else { ensure_size(plen + 5); /* includes space for the NUL, which is subsequently stomped on */ plen += sprintf(p + plen, "<"); } break; case '>': if (plen > 1 && *(s - 1) == '\\' && *(s - 2) == '\\') { ensure_size(--plen); p[plen - 1] = (char) c; p[plen] = 0; } else { ensure_size(plen + 5); /* includes space for the NUL, which is subsequently stomped on */ plen += sprintf(p + plen, ">"); } break; default: ensure_size(plen + 8); /* includes space for the NUL, which is subsequently stomped on */ plen += sprintf(p + plen, "&#%04i;", (int) c); break; } } } } } 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; wchar_t *s; for (; text && text != end; text = text->next) { switch (text->type) { case word_HyperLink: xhtml_utostr(text->text, &c); rdaddsc(rs, "<a href=\""); if(chm_toc && *c == '.' && *(c+1) == '.') rdaddsc(rs, c + 1); else rdaddsc(rs, c); rdaddsc(rs, "\">"); sfree(c); break; case word_LocalHyperLink: xhtml_utostr(text->text, &c); rdaddsc(rs, "<a href=\""); if (conf.rlink_prefix) { char *c2; xhtml_utostr(conf.rlink_prefix, &c2); rdaddsc(rs, c2); sfree(c2); } rdaddsc(rs, c); if (conf.rlink_suffix) { char *c2; xhtml_utostr(conf.rlink_suffix, &c2); rdaddsc(rs, c2); sfree(c2); } rdaddsc(rs, "\">"); sfree(c); break; case word_UpperXref: case word_LowerXref: case word_FreeTextXref: kwl = kw_lookup(keywords, text->text); if (kwl) { sect = xhtml_find_section(kwl->para); if (sect) { rdaddsc(rs, "<a href=\""); rdaddsc(rs, sect->file->filename); rdaddc(rs, '#'); rdaddsc(rs, sect->fragment); rdaddsc(rs, "\">"); } else { rdaddsc(rs, "<a href=\"Apologies.html\"><!-- probably a bibliography cross reference -->"); error(err_whatever, "Couldn't locate cross-reference! (Probably a bibliography entry.)"); } } else { rdaddsc(rs, "<a href=\"Apologies.html\"><!-- unknown cross-reference -->"); 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, "<a name=\"idx-"); xhtml_utostr(text->text, &c); rdaddsc(rs, c); sfree(c); rdaddsc(rs, "\"></a>");*/ /* 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; i < itag->nrefs; 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, "</a>"); 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, "<em>"); else if ((towordstyle(text->type) == word_Code || towordstyle(text->type) == word_WeakCode) && (attraux(text->aux) == attr_First || attraux(text->aux) == attr_Only)) rdaddsc(rs, "<code>"); if (removeattr(text->type) == word_Normal) { static int dont_convert = 0; if (dont_convert) { char buf[2] = " "; dont_convert = 0; s = text->text; for (; *s; s++) { buf[0] = (char) *s; rdaddsc(rs, buf); } buf[0] = 0; rdaddsc(rs, buf); } else { if (*text->text == '\\' && text->next && text->next->text && (*text->next->text == '&' || *text->next->text == '<' || *text->next->text == '>' || *text->next->text == '"')) dont_convert = 1; else { 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, "</em>"); else if ((towordstyle(text->type) == word_Code || towordstyle(text->type) == word_WeakCode) && (attraux(text->aux) == attr_Last || attraux(text->aux) == attr_Only)) rdaddsc(rs, "</code>"); 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); xhtmlheadfmt *fmt; char *fragment; if (sect) { fragment = sect->fragment; } else { if (p->type == para_Title) fragment = "title"; else { fragment = ""; /* FIXME: what else can we do? */ error(err_whatever, "Couldn't locate heading cross-reference!"); } } if (p->type == para_Title) fmt = NULL; else if (level == 1) fmt = &conf.fchapter; else if (level - 1 < conf.nfsect) fmt = &conf.fsect[level - 1]; else fmt = &conf.fsect[conf.nfsect - 1]; if (fmt && fmt->just_numbers && nprefix) { xhtml_rdaddwc(&t, nprefix, NULL); if (fmt) { char *c; if (xhtml_convert(fmt->number_suffix, &c, FALSE)) { rdaddsc(&t, c); sfree(c); } } } else if (fmt && !fmt->just_numbers && tprefix) { xhtml_rdaddwc(&t, tprefix, NULL); if (fmt) { char *c; if (xhtml_convert(fmt->number_suffix, &c, FALSE)) { rdaddsc(&t, c); sfree(c); } } } xhtml_rdaddwc(&t, text, NULL); /* * If we're outputting in single-file mode, we need to lower * the level of each heading by one, because the overall * document title will be sitting right at the top as an <h1> * and so chapters and sections should start at <h2>. * * Even if not, the document title will come back from * xhtml_para_level() as level zero, so we must increment that * no matter what leaf_level is set to. */ if (conf.leaf_level == 0 || level == 0) level++; fprintf(fp, "<a name=\"%s\"></a><h%i>%s</h%i>\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, "<pre>"); 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, "</pre>\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -