XML only defines four entities (< > & ") out of the box, others need to be declared in the document's DOCTYPE. For web feeds such as RSS and Atom, is is particularly cumbersome to define the math entities as these feeds are supposed to be stand-alone and thus the entity definitions have to be inlined.
Therefore, character references are now used instead of entity references, making the MathML output directly embeddable into these feeds. The entity table is no longer used and thus removed. * src/preproc/eqn/text.cpp: Remove struct map, entity_table, and special_to_entity. Include "unicode.h" header file. (special_char_box::output): Instead of named entity reference, print XML character reference with Unicode codepoint for MathML. Add support for Unicode code sequence as an input character. References: https://www.w3.org/TR/REC-xml/#sec-references --- src/preproc/eqn/text.cpp | 386 +-------------------------------------- 1 file changed, 6 insertions(+), 380 deletions(-) diff --git a/src/preproc/eqn/text.cpp b/src/preproc/eqn/text.cpp index 19b2e8f684ab..284ff1ff1101 100644 --- a/src/preproc/eqn/text.cpp +++ b/src/preproc/eqn/text.cpp @@ -27,383 +27,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "eqn.h" #include "pbox.h" #include "ptable.h" - -struct map { - const char *from; - const char *to; -}; - -struct map entity_table[] = { - // Classic troff special characters - {"%", "­"}, // ISOnum - {"'", "´"}, // ISOdia - {"!=", "≠"}, // ISOtech - {"**", "∗"}, // ISOtech - {"*a", "α"}, // ISOgrk3 - {"*A", "A"}, - {"*b", "β"}, // ISOgrk3 - {"*B", "B"}, - {"*d", "δ"}, // ISOgrk3 - {"*D", "Δ"}, // ISOgrk3 - {"*e", "ε"}, // ISOgrk3 - {"*E", "E"}, - {"*f", "φ"}, // ISOgrk3 - {"*F", "Φ"}, // ISOgrk3 - {"*g", "γ"}, // ISOgrk3 - {"*G", "Γ"}, // ISOgrk3 - {"*h", "θ"}, // ISOgrk3 - {"*H", "Θ"}, // ISOgrk3 - {"*i", "ι"}, // ISOgrk3 - {"*I", "I"}, - {"*k", "κ"}, // ISOgrk3 - {"*K", "K;"}, - {"*l", "λ"}, // ISOgrk3 - {"*L", "Λ"}, // ISOgrk3 - {"*m", "μ"}, // ISOgrk3 - {"*M", "M"}, - {"*n", "ν"}, // ISOgrk3 - {"*N", "N"}, - {"*o", "o"}, - {"*O", "O"}, - {"*p", "π"}, // ISOgrk3 - {"*P", "Π"}, // ISOgrk3 - {"*q", "ψ"}, // ISOgrk3 - {"*Q", "&PSI;"}, // ISOgrk3 - {"*r", "ρ"}, // ISOgrk3 - {"*R", "R"}, - {"*s", "σ"}, // ISOgrk3 - {"*S", "Σ"}, // ISOgrk3 - {"*t", "τ"}, // ISOgrk3 - {"*T", "Τ"}, // ISOgrk3 - {"*u", "υ"}, // ISOgrk3 - {"*U", "Υ"}, // ISOgrk3 - {"*w", "ω"}, // ISOgrk3 - {"*W", "Ω"}, // ISOgrk3 - {"*x", "χ"}, // ISOgrk3 - {"*X", "Χ"}, // ISOgrk3 - {"*y", "η"}, // ISOgrk3 - {"*Y", "Η"}, // ISOgrk3 - {"*z", "ζ"}, // ISOgrk3 - {"*Z", "Ζ"}, // ISOgrk3 - {"+-", "±"}, // ISOnum - {"->", "→"}, // ISOnum - {"12", "½"}, // ISOnum - {"14", "¼"}, // ISOnum - {"34", "¾"}, // ISOnum - {"<-", "←"}, // ISOnum - {"==", "≡"}, // ISOtech - {"Fi", "ffi"}, // ISOpub - {"Fl", "ffl"}, // ISOpub - {"aa", "´"}, // ISOdia - {"ap", "∼"}, // ISOtech - {"bl", "&phonexb;"}, // ISOpub - {"br", "│"}, // ISObox - {"bs", "☎"}, // ISOpub (for the Bell logo) - {"bu", "•"}, // ISOpub - {"bv", "|"}, // ISOnum - {"ca", "∩"}, // ISOtech - {"ci", "○"}, // ISOpub - {"co", "©"}, // ISOnum - {"ct", "¢"}, // ISOnum - {"cu", "∪"}, // ISOtech - {"da", "↓"}, // ISOnum - {"de", "°"}, // ISOnum - {"dg", "†"}, // ISOpub - {"dd", "‡"}, // ISOpub - {"di", "÷"}, // ISOnum - {"em", "—"}, // ISOpub - {"eq", "="}, // ISOnum - {"es", "∅"}, // ISOamso - {"ff", "ff"}, // ISOpub - {"fi", "fi"}, // ISOpub - {"fl", "fl"}, // ISOpub - {"fm", "′"}, // ISOtech - {"ge", "≥"}, // ISOtech - {"gr", "∇"}, // ISOtech - {"hy", "‐"}, // ISOnum - {"ib", "⊆"}, // ISOtech - {"if", "∞"}, // ISOtech - {"ip", "⊇"}, // ISOtech - {"is", "∫"}, // ISOtech - {"le", "≤"}, // ISOtech - // Some pile characters go here - {"mi", "−"}, // ISOtech - {"mo", "∈"}, // ISOtech - {"mu", "×"}, // ISOnum - {"no", "¬"}, // ISOnum - {"or", "|"}, // ISOnum - {"pl", "+"}, // ISOnum - {"pt", "∝"}, // ISOtech - {"rg", "™"}, // ISOnum - // More pile characters go here - {"rn", "¯"}, // ISOdia - {"ru", "_"}, // ISOnum - {"sb", "⊂"}, // ISOtech - {"sc", "§"}, // ISOnum - {"sl", "/"}, - {"sp", "⊃"}, // ISOtech - {"sq", "▪"}, // ISOpub - {"sr", "√"}, // ISOtech - {"ts", "ς"}, // ISOgrk3 - {"ua", "↑"}, // ISOnum - {"ul", "_"}, - {"~=", "≅"}, // ISOtech - // Extended specials supported by groff; see groff_char(7). - // These are listed in the order they occur on that man page. - {"-D", "Ð"}, // ISOlat: Icelandic uppercase eth - {"Sd", "ð"}, // ISOlat1: Icelandic lowercase eth - {"TP", "Þ"}, // ISOlat1: Icelandic uppercase thorn - {"Tp", "þ"}, // ISOlat1: Icelandic lowercase thorn - {"ss", "ß"}, // ISOlat1 - // Ligatures - // ff, fi, fl, ffi, ffl from old troff go here - {"AE", "Æ"}, // ISOlat1 - {"ae", "æ"}, // ISOlat1 - {"OE", "Œ"}, // ISOlat2 - {"oe", "œ"}, // ISOlat2 - {"IJ", "ij"}, // ISOlat2: Dutch IJ ligature - {"ij", "IJ"}, // ISOlat2: Dutch ij ligature - {".i", "ı"}, // ISOlat2,ISOamso - {".j", "&jnodot;"}, // ISOamso (undocumented but in 1.19) - // Accented characters - {"'A", "Á"}, // ISOlat1 - {"'C", "Ć"}, // ISOlat2 - {"'E", "É"}, // ISOlat1 - {"'I", "Í"}, // ISOlat1 - {"'O", "Ó"}, // ISOlat1 - {"'U", "Ú"}, // ISOlat1 - {"'Y", "Ý"}, // ISOlat1 - {"'a", "á"}, // ISOlat1 - {"'c", "ć"}, // ISOlat2 - {"'e", "é"}, // ISOlat1 - {"'i", "í"}, // ISOlat1 - {"'o", "ó"}, // ISOlat1 - {"'u", "ú"}, // ISOlat1 - {"'y", "ý"}, // ISOlat1 - {":A", "Ä"}, // ISOlat1 - {":E", "Ë"}, // ISOlat1 - {":I", "Ï"}, // ISOlat1 - {":O", "Ö"}, // ISOlat1 - {":U", "Ü"}, // ISOlat1 - {":Y", "Ÿ"}, // ISOlat2 - {":a", "ä"}, // ISOlat1 - {":e", "ë"}, // ISOlat1 - {":i", "ï"}, // ISOlat1 - {":o", "ö"}, // ISOlat1 - {":u", "ü"}, // ISOlat1 - {":y", "ÿ"}, // ISOlat1 - {"^A", "Â"}, // ISOlat1 - {"^E", "Ê"}, // ISOlat1 - {"^I", "Î"}, // ISOlat1 - {"^O", "Ô"}, // ISOlat1 - {"^U", "Û"}, // ISOlat1 - {"^a", "â"}, // ISOlat1 - {"^e", "ê"}, // ISOlat1 - {"^i", "î"}, // ISOlat1 - {"^o", "ô"}, // ISOlat1 - {"^u", "û"}, // ISOlat1 - {"`A", "À"}, // ISOlat1 - {"`E", "È"}, // ISOlat1 - {"`I", "Ì"}, // ISOlat1 - {"`O", "Ò"}, // ISOlat1 - {"`U", "Ù"}, // ISOlat1 - {"`a", "à"}, // ISOlat1 - {"`e", "è"}, // ISOlat1 - {"`i", "ì"}, // ISOlat1 - {"`o", "ò"}, // ISOlat1 - {"`u", "ù"}, // ISOlat1 - {"~A", "Ã"}, // ISOlat1 - {"~N", "Ñ"}, // ISOlat1 - {"~O", "Õ"}, // ISOlat1 - {"~a", "ã"}, // ISOlat1 - {"~n", "ñ"}, // ISOlat1 - {"~o", "õ"}, // ISOlat1 - {"vS", "Š"}, // ISOlat2 - {"vs", "š"}, // ISOlat2 - {"vZ", "Ž"}, // ISOlat2 - {"vz", "ž"}, // ISOlat2 - {",C", "Ç"}, // ISOlat1 - {",c", "ç"}, // ISOlat1 - {"/L", "Ł"}, // ISOlat2: Polish L with a slash - {"/l", "ł"}, // ISOlat2: Polish l with a slash - {"/O", "Ø"}, // ISOlat1 - {"/o", "ø"}, // ISOlat1 - {"oA", "Å"}, // ISOlat1 - {"oa", "å"}, // ISOlat1 - // Accents - {"a\"","˝"}, // ISOdia: double acute accent (Hungarian umlaut) - {"a-", "¯"}, // ISOdia: macron or bar accent - {"a.", "˙"}, // ISOdia: dot above - {"a^", "ˆ"}, // ISOdia: circumflex accent - {"aa", "´"}, // ISOdia: acute accent - {"ga", "`"}, // ISOdia: grave accent - {"ab", "˘"}, // ISOdia: breve accent - {"ac", "¸"}, // ISOdia: cedilla accent - {"ad", "¨"}, // ISOdia: umlaut or dieresis - {"ah", "ˇ"}, // ISOdia: caron (aka hacek accent) - {"ao", "˚"}, // ISOdia: ring or circle accent - {"a~", "˜"}, // ISOdia: tilde accent - {"ho", "˛"}, // ISOdia: hook or ogonek accent - {"ha", "^"}, // ASCII circumflex, hat, caret - {"ti", "~"}, // ASCII tilde, large tilde - // Quotes - {"Bq", "‚"}, // ISOpub: low double comma quote - {"bq", "„"}, // ISOpub: low single comma quote - {"lq", "“"}, // ISOnum - {"rq", "”"}, // ISOpub - {"oq", "‘"}, // ISOnum: single open quote - {"cq", "’"}, // ISOnum: single closing quote (ASCII 39) - {"aq", "&zerosp;'"}, // apostrophe quote - {"dq", "\""}, // double quote (ASCII 34) - {"Fo", "«"}, // ISOnum - {"Fc", "»"}, // ISOnum - //{"fo", "&fo;"}, - //{"fc", "&fc;"}, - // Punctuation - {"r!", "¡"}, // ISOnum - {"r?", "¿"}, // ISOnum - // Old troff \(em goes here - {"en", "–"}, // ISOpub: en dash - // Old troff \(hy goes here - // Brackets - {"lB", "["}, // ISOnum: left (square) bracket - {"rB", "]"}, // ISOnum: right (square) bracket - {"lC", "{"}, // ISOnum: left (curly) brace - {"rC", "}"}, // ISOnum: right (curly) brace - {"la", "⟨"}, // ISOtech: left angle bracket - {"ra", "⟩"}, // ISOtech: right angle bracket - // Old troff \(bv goes here - // Bracket-pile characters could go here. - // Arrows - // Old troff \(<- and \(-> go here - {"<>", "↔"}, // ISOamsa - {"da", "↓"}, // ISOnum - {"ua", "↑"}, // ISOnum - {"lA", "⇐"}, // ISOtech - {"rA", "⇒"}, // ISOtech - {"hA", "⇔"}, // ISOtech: horizontal double-headed arrow - {"dA", "⇓"}, // ISOamsa - {"uA", "⇑"}, // ISOamsa - {"vA", "⇕"}, // ISOamsa: vertical double-headed double arrow - //{"an", "&an;"}, - // Lines - {"-h", "ℏ"}, // ISOamso: h-bar (Planck's constant) - // Old troff \(or goes here - {"ba", "|"}, // ISOnum - // Old troff \(br, \{u, \(ul, \(bv go here - {"bb", "¦"}, // ISOnum - {"sl", "/"}, - {"rs", "\"}, // ISOnum - // Text markers - // Old troff \(ci, \(bu, \(dd, \(dg go here - {"lz", "◊"}, // ISOpub - // Old troff sq goes here - {"ps", "¶"}, // ISOnum: paragraph or pilcrow sign - {"sc", "§"}, // ISOnum (in old troff) - // Old troff \(lh, \{h go here - {"at", "@"}, // ISOnum - {"sh", "#"}, // ISOnum - //{"CR", "&CR;"}, - {"OK", "✓"}, // ISOpub - // Legalize - // Old troff \(co, \{g go here - {"tm", "™"}, // ISOnum - // Currency symbols - {"Do", "$"}, // ISOnum - {"ct", "¢"}, // ISOnum - {"eu", "€"}, - {"Eu", "€"}, - {"Ye", "¥"}, // ISOnum - {"Po", "£"}, // ISOnum - {"Cs", "¤"}, // ISOnum: currency sign - {"Fn", "&fnof"}, // ISOtech - // Units - // Old troff de goes here - {"%0", "‰"}, // ISOtech: per thousand, per mille sign - // Old troff \(fm goes here - {"sd", "″"}, // ISOtech - {"mc", "µ"}, // ISOnum - {"Of", "ª"}, // ISOnum - {"Om", "º"}, // ISOnum - // Logical symbols - {"AN", "∧"}, // ISOtech - {"OR", "∨"}, // ISOtech - // Old troff \(no goes here - {"te", "∃"}, // ISOtech: there exists, existential quantifier - {"fa", "∀"}, // ISOtech: for all, universal quantifier - {"st", "&bepsi"}, // ISOamsr: such that - {"3d", "∴"}, // ISOtech - {"tf", "∴"}, // ISOtech - // Mathematical symbols - // Old troff "12", "14", "34" goes here - {"S1", "¹"}, // ISOnum - {"S2", "²"}, // ISOnum - {"S3", "³"}, // ISOnum - // Old troff \(pl", \-, \(+- go here - {"t+-", "±"}, // ISOnum - {"-+", "∓"}, // ISOtech - {"pc", "·"}, // ISOnum - {"md", "·"}, // ISOnum - // Old troff \(mu goes here - {"tmu", "×"}, // ISOnum - {"c*", "⊗"}, // ISOamsb: multiply sign in a circle - {"c+", "⊕"}, // ISOamsb: plus sign in a circle - // Old troff \(di goes here - {"tdi", "÷"}, // ISOnum - {"f/", "―"}, // ISOnum: horizontal bar for fractions - // Old troff \(** goes here - {"<=", "≤"}, // ISOtech - {">=", "≥"}, // ISOtech - {"<<", "≪"}, // ISOamsr - {">>", "≫"}, // ISOamsr - {"!=", "≠"}, // ISOtech - // Old troff \(eq and \(== go here - {"=~", "≅"}, // ISOamsr - // Old troff \(ap goes here - {"~~", "≈"}, // ISOtech - // This appears to be an error in the groff table. - // It clashes with the Bell Labs use of ~= for a congruence sign - // {"~=", "≈"}, // ISOamsr - // Old troff \(pt, \(es, \(mo go here - {"nm", "∉"}, // ISOtech - {"nb", "⊄"}, // ISOamsr - {"nc", "⊅"}, // ISOamsn - {"ne", "≢"}, // ISOamsn - // Old troff \(sb, \(sp, \(ib, \(ip, \(ca, \(cu go here - {"/_", "∠"}, // ISOamso - {"pp", "⊥"}, // ISOtech - // Old troff \(is goes here - {"sum", "∑"}, // ISOamsb - {"product", "∏"}, // ISOamsb - {"gr", "∇"}, // ISOtech - // Old troff \(sr. \{n, \(if go here - {"Ah", "ℵ"}, // ISOtech - {"Im", "ℑ"}, // ISOamso: Fraktur I, imaginary - {"Re", "ℜ"}, // ISOamso: Fraktur R, real - {"wp", "℘"}, // ISOamso - {"pd", "∂"}, // ISOtech: partial differentiation sign - // Their table duplicates the Greek letters here. - // We list only the variant forms here, mapping them into - // the ISO Greek 4 variants (which may or may not be correct :-() - {"+f", "&b.phiv;"}, // ISOgrk4: variant phi - {"+h", "&b.thetas;"}, // ISOgrk4: variant theta - {"+p", "&b.omega;"}, // ISOgrk4: variant pi, looking like omega - // Card symbols - {"CL", "♣"}, // ISOpub: club suit - {"SP", "♠"}, // ISOpub: spade suit - {"HE", "♥"}, // ISOpub: heart suit - {"DI", "♦"}, // ISOpub: diamond suit -}; - -const char *special_to_entity(const char *sp) -{ - struct map *mp; - for (mp = entity_table; mp < entity_table + countof(entity_table); mp++) { - if (strcmp(mp->from, sp) == 0) - return mp->to; - } - return NULL; -} +#include "unicode.h" class char_box : public simple_box { unsigned char c; @@ -665,9 +289,11 @@ void special_char_box::output() printf("\\fP"); } else if (output_format == mathml) { - const char *entity = special_to_entity(s); - if (entity != NULL) - printf("<mo>%s</mo>", entity); + const char *unicode_code_point = valid_unicode_code_sequence(s); + if (unicode_code_point == NULL) + unicode_code_point = glyph_name_to_unicode(s); + if (unicode_code_point != NULL) + printf("<mo>&#x%s;</mo>", unicode_code_point); else printf("<merror>unknown eqn/troff special char %s</merror>", s); } -- 2.52.0
