Diffs between last version checked in and current workfile(s): Index: box.cpp =================================================================== RCS file: /sources/groff/groff/src/preproc/eqn/box.cpp,v retrieving revision 1.3 diff -u -r1.3 box.cpp --- box.cpp 26 May 2005 21:02:00 -0000 1.3 +++ box.cpp 31 Jan 2007 18:18:26 -0000 @@ -226,9 +226,12 @@ void start_string() { - printf(".nr " COMPATIBLE_REG " \\n(.C\n"); - printf(".cp 0\n"); - printf(".ds " LINE_STRING "\n"); + if (output_format == troff) { + printf(".nr " COMPATIBLE_REG " \\n(.C\n"); + printf(".cp 0\n"); + printf(".ds " LINE_STRING "\n"); + } else if (output_format == mathml) + printf("\n"); } void output_string() @@ -238,7 +241,10 @@ void restore_compatibility() { - printf(".cp \\n(" COMPATIBLE_REG "\n"); + if (output_format == troff) + printf(".cp \\n(" COMPATIBLE_REG "\n"); + else if (output_format == mathml) + printf("\n\n"); } void do_text(const char *s) @@ -275,69 +281,73 @@ void box::top_level() { - // debug_print(); - // putc('\n', stderr); box *b = this; - printf(".nr " SAVED_FONT_REG " \\n[.f]\n"); - printf(".ft\n"); - printf(".nr " SAVED_PREV_FONT_REG " \\n[.f]\n"); - printf(".ft %s\n", get_gfont()); - printf(".nr " SAVED_SIZE_REG " \\n[.ps]\n"); - if (gsize > 0) { - char buf[INT_DIGITS + 1]; - sprintf(buf, "%d", gsize); - b = new size_box(strsave(buf), b); + if (output_format == troff) { + // debug_print(); + // putc('\n', stderr); + printf(".nr " SAVED_FONT_REG " \\n[.f]\n"); + printf(".ft\n"); + printf(".nr " SAVED_PREV_FONT_REG " \\n[.f]\n"); + printf(".ft %s\n", get_gfont()); + printf(".nr " SAVED_SIZE_REG " \\n[.ps]\n"); + if (gsize > 0) { + char buf[INT_DIGITS + 1]; + sprintf(buf, "%d", gsize); + b = new size_box(strsave(buf), b); + } + current_roman_font = get_grfont(); + // This catches tabs used within \Z (which aren't allowed). + b->check_tabs(0); + int r = b->compute_metrics(DISPLAY_STYLE); + printf(".ft \\n[" SAVED_PREV_FONT_REG "]\n"); + printf(".ft \\n[" SAVED_FONT_REG "]\n"); + printf(".nr " MARK_OR_LINEUP_FLAG_REG " %d\n", r); + if (r == FOUND_MARK) { + printf(".nr " SAVED_MARK_REG " \\n[" MARK_REG "]\n"); + printf(".nr " MARK_WIDTH_REG " 0\\n[" WIDTH_FORMAT "]\n", b->uid); + } + else if (r == FOUND_LINEUP) + printf(".if r" SAVED_MARK_REG " .as1 " LINE_STRING " \\h'\\n[" + SAVED_MARK_REG "]u-\\n[" MARK_REG "]u'\n"); + else + assert(r == FOUND_NOTHING); + // The problem here is that the argument to \f is read in copy mode, + // so we cannot use \E there; so we hide it in a string instead. + // Another problem is that if we use \R directly, then the space will + // prevent it working in a macro argument. + printf(".ds " SAVE_FONT_STRING " " + "\\R'" SAVED_INLINE_FONT_REG " \\\\n[.f]'" + "\\fP" + "\\R'" SAVED_INLINE_PREV_FONT_REG " \\\\n[.f]'" + "\\R'" SAVED_INLINE_SIZE_REG " \\\\n[.ps]'" + "\\s0" + "\\R'" SAVED_INLINE_PREV_SIZE_REG " \\\\n[.ps]'" + "\n" + ".ds " RESTORE_FONT_STRING " " + "\\f[\\\\n[" SAVED_INLINE_PREV_FONT_REG "]]" + "\\f[\\\\n[" SAVED_INLINE_FONT_REG "]]" + "\\s'\\\\n[" SAVED_INLINE_PREV_SIZE_REG "]u'" + "\\s'\\\\n[" SAVED_INLINE_SIZE_REG "]u'" + "\n"); + printf(".as1 " LINE_STRING " \\&\\E*[" SAVE_FONT_STRING "]"); + printf("\\f[%s]", get_gfont()); + printf("\\s'\\En[" SAVED_SIZE_REG "]u'"); + current_roman_font = get_grfont(); + b->output(); + printf("\\E*[" RESTORE_FONT_STRING "]\n"); + if (r == FOUND_LINEUP) + printf(".if r" SAVED_MARK_REG " .as1 " LINE_STRING " \\h'\\n[" + MARK_WIDTH_REG "]u-\\n[" SAVED_MARK_REG "]u-(\\n[" + WIDTH_FORMAT "]u-\\n[" MARK_REG "]u)'\n", + b->uid); + b->extra_space(); + if (!inline_flag) + printf(".ne \\n[" HEIGHT_FORMAT "]u-%dM>?0+(\\n[" + DEPTH_FORMAT "]u-%dM>?0)\n", + b->uid, body_height, b->uid, body_depth); + } else if (output_format == mathml) { + b->output(); } - current_roman_font = get_grfont(); - // This catches tabs used within \Z (which aren't allowed). - b->check_tabs(0); - int r = b->compute_metrics(DISPLAY_STYLE); - printf(".ft \\n[" SAVED_PREV_FONT_REG "]\n"); - printf(".ft \\n[" SAVED_FONT_REG "]\n"); - printf(".nr " MARK_OR_LINEUP_FLAG_REG " %d\n", r); - if (r == FOUND_MARK) { - printf(".nr " SAVED_MARK_REG " \\n[" MARK_REG "]\n"); - printf(".nr " MARK_WIDTH_REG " 0\\n[" WIDTH_FORMAT "]\n", b->uid); - } - else if (r == FOUND_LINEUP) - printf(".if r" SAVED_MARK_REG " .as1 " LINE_STRING " \\h'\\n[" - SAVED_MARK_REG "]u-\\n[" MARK_REG "]u'\n"); - else - assert(r == FOUND_NOTHING); - // The problem here is that the argument to \f is read in copy mode, - // so we cannot use \E there; so we hide it in a string instead. - // Another problem is that if we use \R directly, then the space will - // prevent it working in a macro argument. - printf(".ds " SAVE_FONT_STRING " " - "\\R'" SAVED_INLINE_FONT_REG " \\\\n[.f]'" - "\\fP" - "\\R'" SAVED_INLINE_PREV_FONT_REG " \\\\n[.f]'" - "\\R'" SAVED_INLINE_SIZE_REG " \\\\n[.ps]'" - "\\s0" - "\\R'" SAVED_INLINE_PREV_SIZE_REG " \\\\n[.ps]'" - "\n" - ".ds " RESTORE_FONT_STRING " " - "\\f[\\\\n[" SAVED_INLINE_PREV_FONT_REG "]]" - "\\f[\\\\n[" SAVED_INLINE_FONT_REG "]]" - "\\s'\\\\n[" SAVED_INLINE_PREV_SIZE_REG "]u'" - "\\s'\\\\n[" SAVED_INLINE_SIZE_REG "]u'" - "\n"); - printf(".as1 " LINE_STRING " \\&\\E*[" SAVE_FONT_STRING "]"); - printf("\\f[%s]", get_gfont()); - printf("\\s'\\En[" SAVED_SIZE_REG "]u'"); - current_roman_font = get_grfont(); - b->output(); - printf("\\E*[" RESTORE_FONT_STRING "]\n"); - if (r == FOUND_LINEUP) - printf(".if r" SAVED_MARK_REG " .as1 " LINE_STRING " \\h'\\n[" - MARK_WIDTH_REG "]u-\\n[" SAVED_MARK_REG "]u-(\\n[" - WIDTH_FORMAT "]u-\\n[" MARK_REG "]u)'\n", - b->uid); - b->extra_space(); - if (!inline_flag) - printf(".ne \\n[" HEIGHT_FORMAT "]u-%dM>?0+(\\n[" - DEPTH_FORMAT "]u-%dM>?0)\n", - b->uid, body_height, b->uid, body_depth); delete b; next_uid = 0; } @@ -538,8 +548,15 @@ void quoted_text_box::output() { - if (text) - fputs(text, stdout); + if (text) { + if (output_format == troff) + fputs(text, stdout); + else if (output_format == mathml) { + fputs("", stdout); + fputs(text, stdout); + fputs("", stdout); + } + } } tab_box::tab_box() : disabled(0) @@ -569,7 +586,11 @@ void space_box::output() { - printf("\\h'%dM'", thick_space); + if (output_format == troff) + printf("\\h'%dM'", thick_space); + else if (output_format == mathml) + //    doesn't display right under Firefox 1.5. + printf(""); } half_space_box::half_space_box() @@ -579,7 +600,10 @@ void half_space_box::output() { - printf("\\h'%dM'", thin_space); + if (output_format == troff) + printf("\\h'%dM'", thin_space); + else if (output_format == mathml) + printf(""); } void box_list::list_debug_print(const char *sep) --- box.h.~1.6.~ 2005-06-16 05:47:49.000000000 -0400 +++ box.h 2007-01-30 17:48:29.000000000 -0500 @@ -216,6 +216,14 @@ void debug_print(); }; +class big_box : public pointer_box { +public: + big_box(box *); + int compute_metrics(int); + void output(); + void debug_print(); +}; + class fat_box : public pointer_box { public: fat_box(box *); Index: delim.cpp =================================================================== RCS file: /sources/groff/groff/src/preproc/eqn/delim.cpp,v retrieving revision 1.2 diff -u -r1.2 delim.cpp --- delim.cpp 26 May 2005 21:02:00 -0000 1.2 +++ delim.cpp 31 Jan 2007 18:18:27 -0000 @@ -378,11 +378,17 @@ void delim_box::output() { - if (left) - printf("\\*[" LEFT_DELIM_STRING_FORMAT "]", uid); - p->output(); - if (right) - printf("\\*[" RIGHT_DELIM_STRING_FORMAT "]", uid); + if (output_format == troff) { + if (left) + printf("\\*[" LEFT_DELIM_STRING_FORMAT "]", uid); + p->output(); + if (right) + printf("\\*[" RIGHT_DELIM_STRING_FORMAT "]", uid); + } else if (output_format == mathml) { + printf("%s", left); + p->output(); + printf("%s", right); + } } void delim_box::check_tabs(int level) Index: eqn.h =================================================================== RCS file: /sources/groff/groff/src/preproc/eqn/eqn.h,v retrieving revision 1.3 diff -u -r1.3 eqn.h --- eqn.h 26 May 2005 21:02:00 -0000 1.3 +++ eqn.h 31 Jan 2007 18:18:27 -0000 @@ -29,6 +29,8 @@ #include "box.h" +typedef enum {troff, mathml} eqnmode_t; + extern char start_delim; extern char end_delim; extern int non_empty_flag; @@ -37,6 +39,7 @@ extern int one_size_reduction_flag; extern int compatible_flag; extern int nroff; +extern eqnmode_t output_format; void init_lex(const char *str, const char *filename, int lineno); void lex_error(const char *message, Index: eqn.man =================================================================== RCS file: /sources/groff/groff/src/preproc/eqn/eqn.man,v retrieving revision 1.10 diff -u -r1.10 eqn.man --- eqn.man 20 Feb 2005 10:38:37 -0000 1.10 +++ eqn.man 31 Jan 2007 18:18:27 -0000 @@ -176,13 +176,16 @@ .BI \-T name The output is for device .IR name . -The only effect of this is to define a macro +Normally, the only effect of this is to define a macro .I name with a value of\~\c -.BR 1 . -Typically +.BR 1 ; .B eqnrc will use this to provide definitions appropriate for the output device. +However, if the specified device is "MathML", the output will be +MathML markup rather than troff commands, and +.B eqnrc +will not be loaded at all. The default output device is .BR @DEVICE@ . . @@ -232,10 +235,16 @@ .B eqn and Unix eqn are described here. . +GNU +.B eqn +emits Presentation MathML output when invoked with the +,B -T MathML +option. +. .LP -Most of the new features of GNU +Most of the new features of the GNU .B eqn -are based on \*(tx. +input language are based on \*(tx. There are some references to the differences between \*(tx and GNU .B eqn below; @@ -349,6 +358,11 @@ . .SS New primitives .TP +.IB big\ e1 +Enlarges the expression it modifies; intended to have semantics like +CSS 'large'. In troff output, the point size is increased by 5; in +MathML output, the expression is wrapped in an +pair. .IB e1\ smallover\ e2 This is similar to .BR over ; @@ -390,6 +404,8 @@ { type "operator" vcenter size +5 \e(*S } .RE . +(Note that vcenter is silently ignored when generating MathML.) +. .TP .IB e1\ accent\ e2 This sets @@ -726,6 +742,8 @@ primitive emboldens an equation by overprinting two copies of the equation horizontally offset by this amount. +(This parameter is not used in MathML mode; instead, fat text is +wrapped in an tag pair.) . .TP .B over_hang @@ -1142,11 +1160,51 @@ .B @MACRODIR@/eqnrc Initialization file. . +.SH MATHL MODE LIMITATIONS +MathML is designed on the assumption that it cannot know the exact +physical characteristics of the media and devices on which it will +be rendered. It does not support fine control of motions and sizes +to the same degree troff does. Thus: +.IP * +.B eqn +parameters have no effect on the generated MathML. +.LP +.IP * +The +.BR special, +.BR up , +.BR down , +.BR fwd , +and +.BR back , +operations cannot be implemented, and will yield a +MathML message instead. +.IP * +The +.B vcenter +keyword is silently ignored, as centering on the math axis is the +MathML default. +.IP * +Characters that eqn over troff sets extra large - notably the integral +sign - may appear too small and need to have their wrappers +adjusted by hand. +.LP +See the +.B BUGS +section for translation limits specific to +.BR eqn . . .SH BUGS Inline equations will be set at the point size that is current at the beginning of the input line. . +In MathML mode, the +.BR mark, +and +.B lineup +features don't work. These could, in theory, be implemented with + elements. +. . .SH "SEE ALSO" .BR groff (@MAN1EXT@), Index: lex.cpp =================================================================== RCS file: /sources/groff/groff/src/preproc/eqn/lex.cpp,v retrieving revision 1.3 diff -u -r1.3 lex.cpp --- lex.cpp 16 Jun 2005 09:47:49 -0000 1.3 +++ lex.cpp 31 Jan 2007 18:18:28 -0000 @@ -120,10 +120,12 @@ { "special", SPECIAL }, }; -static struct { +struct builtin_def { const char *name; const char *def; -} def_table[] = { +}; + +static struct builtin_def common_defs[] = { { "ALPHA", "\\(*A" }, { "BETA", "\\(*B" }, { "CHI", "\\(*X" }, @@ -215,11 +217,6 @@ { "and", "{roman \"and\"}" }, { "if", "{roman \"if\"}" }, { "for", "{roman \"for\"}" }, - { "sum", "{type \"operator\" vcenter size +5 \\(*S}" }, - { "prod", "{type \"operator\" vcenter size +5 \\(*P}" }, - { "int", "{type \"operator\" vcenter size +8 \\(is}" }, - { "union", "{type \"operator\" vcenter size +5 \\(cu}" }, - { "inter", "{type \"operator\" vcenter size +5 \\(ca}" }, { "times", "type \"binary\" \\(mu" }, { "ldots", "type \"inner\" { . . . }" }, { "inf", "\\(if" }, @@ -228,34 +225,58 @@ { "half", "{1 smallover 2}" }, { "hat_def", "roman \"^\"" }, { "hat", "accent { hat_def }" }, - { "dot_def", "back 15 \"\\v'-52M'.\\v'52M'\"" }, - { "dot", "accent { dot_def }" }, - { "dotdot_def", "back 25 \"\\v'-52M'..\\v'52M'\"" }, - { "dotdot", "accent { dotdot_def }" }, { "tilde_def", "\"~\"" }, { "tilde", "accent { tilde_def }" }, - { "utilde_def", "\"\\v'75M'~\\v'-75M'\"" }, - { "utilde", "uaccent { utilde_def }" }, - { "vec_def", "up 52 size -5 \\(->" }, - { "vec", "accent { vec_def }" }, - { "dyad_def", "up 52 size -5 {\\(<- back 60 \\(->}" }, - { "dyad", "accent { dyad_def }" }, { "==", "type \"relation\" \\(==" }, { "!=", "type \"relation\" \\(!=" }, { "+-", "type \"binary\" \\(+-" }, { "->", "type \"relation\" \\(->" }, { "<-", "type \"relation\" \\(<-" }, - { "<<", "{ < back 20 < }" }, - { ">>", "{ > back 20 > }" }, - { "...", "type \"inner\" vcenter { . . . }" }, + { "<<", "type \"relation\" \\(<<" }, + { ">>", "type \"relation\" \\(>>" }, { "prime", "'" }, { "approx", "type \"relation\" \"\\(~=\"" }, { "grad", "\\(gr" }, { "del", "\\(gr" }, - { "cdot", "type \"binary\" vcenter ." }, + { "cdot", "type \"binary\" \\(md" }, { "dollar", "$" }, }; +/* composite definitions that require troff size and motion operators */ +static struct builtin_def troff_defs[] = { + { "sum", "{type \"operator\" vcenter size +5 \\(*S}" }, + { "prod", "{type \"operator\" vcenter size +5 \\(*P}" }, + { "int", "{type \"operator\" vcenter size +8 \\(is}" }, + { "union", "{type \"operator\" vcenter size +5 \\(cu}" }, + { "inter", "{type \"operator\" vcenter size +5 \\(ca}" }, + { "dot_def", "up 52 back 15 \".\"" }, + { "dot", "accent { dot_def }" }, + { "dotdot_def", "up 52 back 25 \"..\"" }, + { "dotdot", "accent { dotdot_def }" }, + { "utilde_def", "down 75 \"~\"" }, + { "utilde", "uaccent { utilde_def }" }, + { "vec_def", "up 52 size -5 \\(->" }, + { "vec", "accent { vec_def }" }, + { "dyad_def", "up 52 size -5 { \\(<> }" }, + { "dyad", "accent { dyad_def }" }, + { "...", "type \"inner\" vcenter { . . . }" }, +}; + +/* equivalent definitions for MathML mode */ +static struct builtin_def mathml_defs[] = { + { "sum", "{type \"operator\" size big \\(*S}" }, + { "prod", "{type \"operator\" size big \\(*P}" }, + { "int", "{type \"operator\" size big \\(is}" }, + { "union", "{type \"operator\" size big \\(cu}" }, + { "inter", "{type \"operator\" size big \\(ca}" }, + { "dot", "accent { \".\" }" }, + { "dotdot", "accent { \"..\" }" }, + { "utilde", "uaccent { \"~\" }" }, + { "vec", "accent { \\(-> }" }, + { "dyad", "accent { \\(<> }" }, + { "...", "type \"inner\" { . . . }" }, +}; + void init_table(const char *device) { unsigned int i; @@ -265,12 +286,29 @@ def->tok = token_table[i].token; macro_table.define(token_table[i].name, def); } - for (i = 0; i < sizeof(def_table)/sizeof(def_table[0]); i++) { + for (i = 0; i < sizeof(common_defs)/sizeof(common_defs[0]); i++) { definition *def = new definition[1]; def->is_macro = 1; - def->contents = strsave(def_table[i].def); + def->contents = strsave(common_defs[i].def); def->is_simple = 1; - macro_table.define(def_table[i].name, def); + macro_table.define(common_defs[i].name, def); + } + if (output_format == troff) { + for (i = 0; i < sizeof(troff_defs)/sizeof(troff_defs[0]); i++) { + definition *def = new definition[1]; + def->is_macro = 1; + def->contents = strsave(troff_defs[i].def); + def->is_simple = 1; + macro_table.define(troff_defs[i].name, def); + } + } else if (output_format == mathml) { + for (i = 0; i < sizeof(mathml_defs)/sizeof(mathml_defs[0]); i++) { + definition *def = new definition[1]; + def->is_macro = 1; + def->contents = strsave(mathml_defs[i].def); + def->is_simple = 1; + macro_table.define(mathml_defs[i].name, def); + } } definition *def = new definition[1]; def->is_macro = 1; Index: limit.cpp =================================================================== RCS file: /sources/groff/groff/src/preproc/eqn/limit.cpp,v retrieving revision 1.2 diff -u -r1.2 limit.cpp --- limit.cpp 26 May 2005 21:02:00 -0000 1.2 +++ limit.cpp 31 Jan 2007 18:18:28 -0000 @@ -139,33 +139,53 @@ void limit_box::output() { - printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid); - if (to != 0) { + if (output_format == troff) { + printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid); + if (to != 0) { + printf("\\Z" DELIMITER_CHAR); + printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); + printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u" + "+(-\\n[" WIDTH_FORMAT "]u+\\n[" SUB_KERN_FORMAT "]u/2u)'", + uid, to->uid, p->uid); + to->output(); + printf(DELIMITER_CHAR); + } + if (from != 0) { + printf("\\Z" DELIMITER_CHAR); + printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid); + printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u" + "+(-\\n[" SUB_KERN_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'", + uid, p->uid, from->uid); + from->output(); + printf(DELIMITER_CHAR); + } + printf("\\s[\\n[" SIZE_FORMAT "]u]", uid); printf("\\Z" DELIMITER_CHAR); - printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u" - "+(-\\n[" WIDTH_FORMAT "]u+\\n[" SUB_KERN_FORMAT "]u/2u)'", - uid, to->uid, p->uid); - to->output(); + "-(\\n[" WIDTH_FORMAT "]u/2u)'", + uid, p->uid); + p->output(); printf(DELIMITER_CHAR); + printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid); + } else if (output_format == mathml) { + if (from != 0 && to != 0) { + printf(""); + p->output(); + from->output(); + to->output(); + printf(""); + } else if (from != 0) { + printf(""); + p->output(); + from->output(); + printf(""); + } else if (to != 0) { + printf(""); + p->output(); + to->output(); + printf(""); + } } - if (from != 0) { - printf("\\Z" DELIMITER_CHAR); - printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid); - printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u" - "+(-\\n[" SUB_KERN_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'", - uid, p->uid, from->uid); - from->output(); - printf(DELIMITER_CHAR); - } - printf("\\s[\\n[" SIZE_FORMAT "]u]", uid); - printf("\\Z" DELIMITER_CHAR); - printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u" - "-(\\n[" WIDTH_FORMAT "]u/2u)'", - uid, p->uid); - p->output(); - printf(DELIMITER_CHAR); - printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid); } void limit_box::debug_print() Index: list.cpp =================================================================== RCS file: /sources/groff/groff/src/preproc/eqn/list.cpp,v retrieving revision 1.2 diff -u -r1.2 list.cpp --- list.cpp 26 May 2005 21:02:00 -0000 1.2 +++ list.cpp 31 Jan 2007 18:18:28 -0000 @@ -208,8 +208,10 @@ void list_box::output() { + if (output_format == mathml) + printf(""); for (int i = 0; i < list.len; i++) { - if (i > 0) { + if (output_format == troff && i > 0) { int n = compute_spacing(is_script, list.p[i-1]->spacing_type, list.p[i]->spacing_type); @@ -218,6 +220,8 @@ } list.p[i]->output(); } + if (output_format == mathml) + printf(""); } void list_box::handle_char_type(int st, int ft) Index: main.cpp =================================================================== RCS file: /sources/groff/groff/src/preproc/eqn/main.cpp,v retrieving revision 1.3 diff -u -r1.3 main.cpp --- main.cpp 29 Dec 2005 21:26:49 -0000 1.3 +++ main.cpp 31 Jan 2007 18:18:28 -0000 @@ -45,7 +45,7 @@ int compatible_flag = 0; int no_newline_in_delim_flag = 0; int html = 0; - +eqnmode_t output_format; int read_line(FILE *fp, string *p) { @@ -67,7 +67,8 @@ { string linebuf; string str; - printf(".lf 1 %s\n", filename); + if (output_format == troff) + printf(".lf 1 %s\n", filename); current_filename = filename; current_lineno = 0; while (read_line(fp, &linebuf)) { @@ -110,11 +111,12 @@ inline_flag = 0; yyparse(); restore_compatibility(); - if (non_empty_flag) { + if (output_format == troff && non_empty_flag) { printf(".lf %d\n", current_lineno - 1); output_string(); } - printf(".lf %d\n", current_lineno); + if (output_format == troff) + printf(".lf %d\n", current_lineno); put_string(linebuf, stdout); } else if (start_delim != '\0' && linebuf.search(start_delim) >= 0 @@ -171,14 +173,14 @@ ptr = &linebuf[0]; } str += '\0'; - if (html) { + if (output_format == troff && html) { printf(".as1 %s ", LINE_STRING); html_begin_suppress(); printf("\n"); } init_lex(str.contents(), current_filename, start_lineno); yyparse(); - if (html) { + if (output_format == troff && html) { printf(".as1 %s ", LINE_STRING); html_end_suppress(); printf("\n"); @@ -193,9 +195,11 @@ } } restore_compatibility(); - printf(".lf %d\n", current_lineno); + if (output_format == troff) + printf(".lf %d\n", current_lineno); output_string(); - printf(".lf %d\n", current_lineno + 1); + if (output_format == troff) + printf(".lf %d\n", current_lineno + 1); return 1; } @@ -302,6 +306,9 @@ if (strcmp(device, "ps:html") == 0) { device = "ps"; html = 1; + } else if (strcmp(device, "MathML") == 0) { + output_format = mathml; + load_startup_file = 0; } break; case 's': @@ -349,19 +356,21 @@ } init_table(device); init_char_table(); - printf(".if !'\\*(.T'%s' " - ".if !'\\*(.T'html' " // the html device uses `-Tps' to render - // equations as images - ".tm warning: %s should have been given a `-T\\*(.T' option\n", - device, program_name); - printf(".if '\\*(.T'html' " - ".if !'%s'ps' " - ".tm warning: %s should have been given a `-Tps' option\n", - device, program_name); - printf(".if '\\*(.T'html' " - ".if !'%s'ps' " - ".tm warning: (it is advisable to invoke groff via: groff -Thtml -e)\n", - device); + if (output_format == troff) { + printf(".if !'\\*(.T'%s' " + ".if !'\\*(.T'html' " // the html device uses `-Tps' to render + // equations as images + ".tm warning: %s should have been given a `-T\\*(.T' option\n", + device, program_name); + printf(".if '\\*(.T'html' " + ".if !'%s'ps' " + ".tm warning: %s should have been given a `-Tps' option\n", + device, program_name); + printf(".if '\\*(.T'html' " + ".if !'%s'ps' " + ".tm warning: (it is advisable to invoke groff via: groff -Thtml -e)\n", + device); + } if (load_startup_file) { char *path; FILE *fp = config_macro_path.open_file(STARTUP_FILE, &path); Index: other.cpp =================================================================== RCS file: /sources/groff/groff/src/preproc/eqn/other.cpp,v retrieving revision 1.2 diff -u -r1.2 other.cpp --- other.cpp 26 May 2005 21:02:00 -0000 1.2 +++ other.cpp 31 Jan 2007 18:18:29 -0000 @@ -65,17 +65,24 @@ void accent_box::output() { - printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u+\\n[" - SKEW_FORMAT "]u'", - p->uid, ab->uid, p->uid); - printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); - ab->output(); - printf("\\h'-\\n[" WIDTH_FORMAT "]u'", ab->uid); - printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid); - printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u+\\n[" - SKEW_FORMAT "]u)'", - p->uid, ab->uid, p->uid); - p->output(); + if (output_format == troff) { + printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u+\\n[" + SKEW_FORMAT "]u'", + p->uid, ab->uid, p->uid); + printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); + ab->output(); + printf("\\h'-\\n[" WIDTH_FORMAT "]u'", ab->uid); + printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid); + printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u+\\n[" + SKEW_FORMAT "]u)'", + p->uid, ab->uid, p->uid); + p->output(); + } else if (output_format == mathml) { + printf(""); + p->output(); + ab->output(); + printf("") + } } #endif @@ -110,19 +117,26 @@ void accent_box::output() { - printf("\\Z" DELIMITER_CHAR); - printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u+\\n[" SKEW_FORMAT "]u" - "-(\\n[" WIDTH_FORMAT "]u/2u)'", - uid, p->uid, ab->uid); - printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); - ab->output(); - printf(DELIMITER_CHAR); - printf("\\Z" DELIMITER_CHAR); - printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u-(\\n[" WIDTH_FORMAT "]u/2u)'", - uid, p->uid); - p->output(); - printf(DELIMITER_CHAR); - printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid); + if (output_format == troff) { + printf("\\Z" DELIMITER_CHAR); + printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u+\\n[" SKEW_FORMAT "]u" + "-(\\n[" WIDTH_FORMAT "]u/2u)'", + uid, p->uid, ab->uid); + printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); + ab->output(); + printf(DELIMITER_CHAR); + printf("\\Z" DELIMITER_CHAR); + printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u-(\\n[" WIDTH_FORMAT "]u/2u)'", + uid, p->uid); + p->output(); + printf(DELIMITER_CHAR); + printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid); + } else if (output_format == mathml) { + printf(""); + p->output(); + ab->output(); + printf(""); + } } void accent_box::check_tabs(int level) @@ -153,10 +167,14 @@ void overline_char_box::output() { - printf("\\v'-%dM/2u-%dM'", 7*default_rule_thickness, x_height); - printf((draw_flag ? "\\D'l%dM 0'" : "\\l'%dM\\&\\(ru'"), - accent_width); - printf("\\v'%dM/2u+%dM'", 7*default_rule_thickness, x_height); + if (output_format == troff) { + printf("\\v'-%dM/2u-%dM'", 7*default_rule_thickness, x_height); + printf((draw_flag ? "\\D'l%dM 0'" : "\\l'%dM\\&\\(ru'"), + accent_width); + printf("\\v'%dM/2u+%dM'", 7*default_rule_thickness, x_height); + } else if (output_format == mathml) { + printf("¯"); + } } void overline_char_box::debug_print() @@ -197,16 +215,22 @@ void overline_box::output() { - // 9 - printf("\\Z" DELIMITER_CHAR); - printf("\\v'-\\n[" HEIGHT_FORMAT "]u-(%dM/2u)'", - p->uid, 7*default_rule_thickness); - if (draw_flag) - printf("\\D'l\\n[" WIDTH_FORMAT "]u 0'", p->uid); - else - printf("\\l'\\n[" WIDTH_FORMAT "]u\\&\\(ru'", p->uid); - printf(DELIMITER_CHAR); - p->output(); + if (output_format == troff) { + // 9 + printf("\\Z" DELIMITER_CHAR); + printf("\\v'-\\n[" HEIGHT_FORMAT "]u-(%dM/2u)'", + p->uid, 7*default_rule_thickness); + if (draw_flag) + printf("\\D'l\\n[" WIDTH_FORMAT "]u 0'", p->uid); + else + printf("\\l'\\n[" WIDTH_FORMAT "]u\\&\\(ru'", p->uid); + printf(DELIMITER_CHAR); + p->output(); + } else if (output_format == mathml) { + printf(""); + p->output(); + printf("¯"); + } } void overline_box::debug_print() @@ -267,18 +291,25 @@ void uaccent_box::output() { - printf("\\Z" DELIMITER_CHAR); - printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u-(\\n[" WIDTH_FORMAT "]u/2u)'", - uid, ab->uid); - printf("\\v'\\n[" DEPTH_FORMAT "]u'", p->uid); - ab->output(); - printf(DELIMITER_CHAR); - printf("\\Z" DELIMITER_CHAR); - printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u-(\\n[" WIDTH_FORMAT "]u/2u)'", - uid, p->uid); - p->output(); - printf(DELIMITER_CHAR); - printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid); + if (output_format == troff) { + printf("\\Z" DELIMITER_CHAR); + printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u-(\\n[" WIDTH_FORMAT "]u/2u)'", + uid, ab->uid); + printf("\\v'\\n[" DEPTH_FORMAT "]u'", p->uid); + ab->output(); + printf(DELIMITER_CHAR); + printf("\\Z" DELIMITER_CHAR); + printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u-(\\n[" WIDTH_FORMAT "]u/2u)'", + uid, p->uid); + p->output(); + printf(DELIMITER_CHAR); + printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid); + } else if (output_format == mathml) { + printf(""); + p->output(); + ab->output(); + printf(""); + } } void uaccent_box::check_tabs(int level) @@ -314,10 +345,14 @@ void underline_char_box::output() { - printf("\\v'%dM/2u'", 7*default_rule_thickness); - printf((draw_flag ? "\\D'l%dM 0'" : "\\l'%dM\\&\\(ru'"), - accent_width); - printf("\\v'-%dM/2u'", 7*default_rule_thickness); + if (output_format == troff) { + printf("\\v'%dM/2u'", 7*default_rule_thickness); + printf((draw_flag ? "\\D'l%dM 0'" : "\\l'%dM\\&\\(ru'"), + accent_width); + printf("\\v'-%dM/2u'", 7*default_rule_thickness); + } else if (output_format == mathml) { + printf("_"); + } } void underline_char_box::debug_print() @@ -360,16 +395,22 @@ void underline_box::output() { - // 10 - printf("\\Z" DELIMITER_CHAR); - printf("\\v'\\n[" DEPTH_FORMAT "]u+(%dM/2u)'", - p->uid, 7*default_rule_thickness); - if (draw_flag) - printf("\\D'l\\n[" WIDTH_FORMAT "]u 0'", p->uid); - else - printf("\\l'\\n[" WIDTH_FORMAT "]u\\&\\(ru'", p->uid); - printf(DELIMITER_CHAR); - p->output(); + if (output_format == troff) { + // 10 + printf("\\Z" DELIMITER_CHAR); + printf("\\v'\\n[" DEPTH_FORMAT "]u+(%dM/2u)'", + p->uid, 7*default_rule_thickness); + if (draw_flag) + printf("\\D'l\\n[" WIDTH_FORMAT "]u 0'", p->uid); + else + printf("\\l'\\n[" WIDTH_FORMAT "]u\\&\\(ru'", p->uid); + printf(DELIMITER_CHAR); + p->output(); + } else if (output_format == mathml) { + printf(""); + p->output(); + printf("¯"); + } } // we want an underline box to have 0 subscript kern @@ -405,9 +446,15 @@ void size_box::output() { - printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid); - p->output(); - printf("\\s[\\n[" SIZE_FORMAT "]u]", uid); + if (output_format == troff) { + printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid); + p->output(); + printf("\\s[\\n[" SIZE_FORMAT "]u]", uid); + } else if (output_format == mathml) { + printf("", size); + p->output(); + printf(""); + } } size_box::~size_box() @@ -449,12 +496,32 @@ void font_box::output() { - printf("\\f[%s]", f); - const char *old_roman_font = current_roman_font; - current_roman_font = f; - p->output(); - current_roman_font = old_roman_font; - printf("\\f[\\n[" FONT_FORMAT "]]", uid); + if (output_format == troff) { + printf("\\f[%s]", f); + const char *old_roman_font = current_roman_font; + current_roman_font = f; + p->output(); + current_roman_font = old_roman_font; + printf("\\f[\\n[" FONT_FORMAT "]]", uid); + } else if (output_format == mathml) { + char *mlfont = f; + // bold and italic are already in MathML; translate eqn roman here + switch (f[0]) { + case 'I': case 'i': + mlfont = "italic"; + break; + case 'B': case 'b': + mlfont = "bold"; + break; + case 'R': case 'r': + default: + mlfont = "normal"; + break; + } + printf("", mlfont); + p->output(); + printf(""); + } } void font_box::debug_print() @@ -480,10 +547,16 @@ void fat_box::output() { - p->output(); - printf("\\h'-\\n[" WIDTH_FORMAT "]u'", p->uid); - printf("\\h'%dM'", fat_offset); - p->output(); + if (output_format == troff) { + p->output(); + printf("\\h'-\\n[" WIDTH_FORMAT "]u'", p->uid); + printf("\\h'%dM'", fat_offset); + p->output(); + } else if (output_format == mathml) { + printf(""); + p->output(); + printf(""); + } } @@ -519,9 +592,14 @@ void vmotion_box::output() { - printf("\\v'%dM'", -n); - p->output(); - printf("\\v'%dM'", n); + if (output_format == troff) { + printf("\\v'%dM'", -n); + p->output(); + printf("\\v'%dM'", n); + } else if (output_format == mathml) { + printf("eqn vertical motion cannot be expressed in MathML"); + p->output(); + } } void vmotion_box::debug_print() @@ -552,8 +630,13 @@ void hmotion_box::output() { - printf("\\h'%dM'", n); - p->output(); + if (output_format == troff) { + printf("\\h'%dM'", n); + p->output(); + } else if (output_format == mathml) { + printf("eqn horizontal motion cannot be expessed in MathML"); + p->output(); + } } void hmotion_box::debug_print() @@ -587,9 +670,11 @@ void vcenter_box::output() { - printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); + if (output_format == troff) + printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); p->output(); - printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid); + if (output_format == troff) + printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid); } void vcenter_box::debug_print() Index: over.cpp =================================================================== RCS file: /sources/groff/groff/src/preproc/eqn/over.cpp,v retrieving revision 1.2 diff -u -r1.2 over.cpp --- over.cpp 26 May 2005 21:02:00 -0000 1.2 +++ over.cpp 31 Jan 2007 18:18:29 -0000 @@ -118,64 +118,71 @@ void over_box::output() { - if (reduce_size) - printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid); -#ifdef USE_Z - printf("\\Z" DELIMITER_CHAR); -#endif - // move up to the numerator baseline - printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); - // move across so that it's centered - printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'", - uid, num->uid); - - // print the numerator - num->output(); - -#ifdef USE_Z - printf(DELIMITER_CHAR); -#else - // back again - printf("\\h'-\\n[" WIDTH_FORMAT "]u'", num->uid); - printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'", - uid, num->uid); - // down again - printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid); -#endif -#ifdef USE_Z - printf("\\Z" DELIMITER_CHAR); -#endif - // move down to the denominator baseline - printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid); - - // move across so that it's centered - printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'", - uid, den->uid); - - // print the the denominator - den->output(); - -#ifdef USE_Z - printf(DELIMITER_CHAR); -#else - // back again - printf("\\h'-\\n[" WIDTH_FORMAT "]u'", den->uid); - printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'", - uid, den->uid); - // up again - printf("\\v'-\\n[" SUB_LOWER_FORMAT "]u'", uid); -#endif - if (reduce_size) - printf("\\s[\\n[" SIZE_FORMAT "]u]", uid); - // draw the line - printf("\\h'%dM'", null_delimiter_space); - printf("\\v'-%dM'", axis_height); - fputs(draw_flag ? "\\D'l" : "\\l'", stdout); - printf("\\n[" WIDTH_FORMAT "]u-%dM", - uid, 2*null_delimiter_space); - fputs(draw_flag ? " 0'" : "\\&\\(ru'", stdout); - printf("\\v'%dM'", axis_height); - printf("\\h'%dM'", null_delimiter_space); + if (output_format == troff) { + if (reduce_size) + printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid); + #ifdef USE_Z + printf("\\Z" DELIMITER_CHAR); + #endif + // move up to the numerator baseline + printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); + // move across so that it's centered + printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'", + uid, num->uid); + + // print the numerator + num->output(); + + #ifdef USE_Z + printf(DELIMITER_CHAR); + #else + // back again + printf("\\h'-\\n[" WIDTH_FORMAT "]u'", num->uid); + printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'", + uid, num->uid); + // down again + printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid); + #endif + #ifdef USE_Z + printf("\\Z" DELIMITER_CHAR); + #endif + // move down to the denominator baseline + printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid); + + // move across so that it's centered + printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'", + uid, den->uid); + + // print the the denominator + den->output(); + + #ifdef USE_Z + printf(DELIMITER_CHAR); + #else + // back again + printf("\\h'-\\n[" WIDTH_FORMAT "]u'", den->uid); + printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'", + uid, den->uid); + // up again + printf("\\v'-\\n[" SUB_LOWER_FORMAT "]u'", uid); + #endif + if (reduce_size) + printf("\\s[\\n[" SIZE_FORMAT "]u]", uid); + // draw the line + printf("\\h'%dM'", null_delimiter_space); + printf("\\v'-%dM'", axis_height); + fputs(draw_flag ? "\\D'l" : "\\l'", stdout); + printf("\\n[" WIDTH_FORMAT "]u-%dM", + uid, 2*null_delimiter_space); + fputs(draw_flag ? " 0'" : "\\&\\(ru'", stdout); + printf("\\v'%dM'", axis_height); + printf("\\h'%dM'", null_delimiter_space); + } else if (output_format == mathml) { + printf("", reduce_size ? "false" : "true"); + num->output(); + den->output(); + printf(""); + } } void over_box::debug_print() Index: pile.cpp =================================================================== RCS file: /sources/groff/groff/src/preproc/eqn/pile.cpp,v retrieving revision 1.3 diff -u -r1.3 pile.cpp --- pile.cpp 26 May 2005 21:02:00 -0000 1.3 +++ pile.cpp 31 Jan 2007 18:18:29 -0000 @@ -56,45 +56,62 @@ void pile_box::output() { - int i; - printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); - for (i = 0; i < col.len; i++) { - switch (col.align) { - case LEFT_ALIGN: - break; - case CENTER_ALIGN: - printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'", - uid, col.p[i]->uid); - break; - case RIGHT_ALIGN: - printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'", - uid, col.p[i]->uid); - break; - default: - assert(0); + if (output_format == troff) { + int i; + printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); + for (i = 0; i < col.len; i++) { + switch (col.align) { + case LEFT_ALIGN: + break; + case CENTER_ALIGN: + printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'", + uid, col.p[i]->uid); + break; + case RIGHT_ALIGN: + printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'", + uid, col.p[i]->uid); + break; + default: + assert(0); + } + col.p[i]->output(); + printf("\\h'-\\n[" WIDTH_FORMAT "]u'", col.p[i]->uid); + switch (col.align) { + case LEFT_ALIGN: + break; + case CENTER_ALIGN: + printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'", + col.p[i]->uid, uid); + break; + case RIGHT_ALIGN: + printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'", + col.p[i]->uid, uid); + break; + default: + assert(0); + } + if (i != col.len - 1) + printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid); } - col.p[i]->output(); - printf("\\h'-\\n[" WIDTH_FORMAT "]u'", col.p[i]->uid); + printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid); + printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", col.len - 1, uid); + printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid); + } else if (output_format == mathml) { + char *av; switch (col.align) { - case LEFT_ALIGN: - break; - case CENTER_ALIGN: - printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'", - col.p[i]->uid, uid); - break; - case RIGHT_ALIGN: - printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'", - col.p[i]->uid, uid); - break; - default: - assert(0); + case LEFT_ALIGN: av = "left"; break; + case RIGHT_ALIGN: av = "right"; break; + case CENTER_ALIGN: av = "center"; break; + default: assert(0); } - if (i != col.len - 1) - printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid); + printf("", av); + for (int i = 0; i < col.len; i++) { + printf(""); + col.p[i]->output(); + printf(""); + } + printf(""); } - printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid); - printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", col.len - 1, uid); - printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid); } pile_box::pile_box(box *pp) : col(pp) @@ -163,51 +180,73 @@ void matrix_box::output() { - printf("\\h'%dM'", matrix_side_sep); - for (int i = 0; i < len; i++) { - int j; - printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); - for (j = 0; j < p[i]->len; j++) { - switch (p[i]->align) { - case LEFT_ALIGN: - break; - case CENTER_ALIGN: - printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'", - uid, i, p[i]->p[j]->uid); - break; - case RIGHT_ALIGN: - printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'", - uid, i, p[i]->p[j]->uid); - break; - default: - assert(0); + if (output_format == troff) { + printf("\\h'%dM'", matrix_side_sep); + for (int i = 0; i < len; i++) { + int j; + printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); + for (j = 0; j < p[i]->len; j++) { + switch (p[i]->align) { + case LEFT_ALIGN: + break; + case CENTER_ALIGN: + printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'", + uid, i, p[i]->p[j]->uid); + break; + case RIGHT_ALIGN: + printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'", + uid, i, p[i]->p[j]->uid); + break; + default: + assert(0); + } + p[i]->p[j]->output(); + printf("\\h'-\\n[" WIDTH_FORMAT "]u'", p[i]->p[j]->uid); + switch (p[i]->align) { + case LEFT_ALIGN: + break; + case CENTER_ALIGN: + printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u/2u'", + p[i]->p[j]->uid, uid, i); + break; + case RIGHT_ALIGN: + printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u'", + p[i]->p[j]->uid, uid, i); + break; + default: + assert(0); + } + if (j != p[i]->len - 1) + printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid); } - p[i]->p[j]->output(); - printf("\\h'-\\n[" WIDTH_FORMAT "]u'", p[i]->p[j]->uid); - switch (p[i]->align) { - case LEFT_ALIGN: - break; - case CENTER_ALIGN: - printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u/2u'", - p[i]->p[j]->uid, uid, i); - break; - case RIGHT_ALIGN: - printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u'", - p[i]->p[j]->uid, uid, i); - break; - default: - assert(0); + printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid); + printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", p[i]->len - 1, uid); + printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u'", uid, i); + if (i != len - 1) + printf("\\h'%dM'", column_sep); + } + printf("\\h'%dM'", matrix_side_sep); + } else if (output_format == mathml) { + int n = p[0]->len; // Each column must have the same number of rows in it + printf(""); + for (int i = 0; i < n; i++) { + printf(""); + for (int j = 0; j < len; j++) { + char *av; + switch (p[j]->align) { + case LEFT_ALIGN: av = "left"; break; + case RIGHT_ALIGN: av = "right"; break; + case CENTER_ALIGN: av = "center"; break; + default: assert(0); + } + printf("", av); + p[j]->p[i]->output(); + printf(""); } - if (j != p[i]->len - 1) - printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid); + printf(""); } - printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid); - printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", p[i]->len - 1, uid); - printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u'", uid, i); - if (i != len - 1) - printf("\\h'%dM'", column_sep); + printf(""); } - printf("\\h'%dM'", matrix_side_sep); } matrix_box::matrix_box(column *pp) Index: script.cpp =================================================================== RCS file: /sources/groff/groff/src/preproc/eqn/script.cpp,v retrieving revision 1.3 diff -u -r1.3 script.cpp --- script.cpp 26 May 2005 21:02:00 -0000 1.3 +++ script.cpp 31 Jan 2007 18:18:29 -0000 @@ -168,26 +168,47 @@ void script_box::output() { - p->output(); - if (sup != 0) { - printf("\\Z" DELIMITER_CHAR); - printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); - printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid); - sup->output(); - printf("\\s[\\n[" SIZE_FORMAT "]u]", uid); - printf(DELIMITER_CHAR); - } - if (sub != 0) { - printf("\\Z" DELIMITER_CHAR); - printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid); - printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid); - printf("\\h'-\\n[" SUB_KERN_FORMAT "]u'", p->uid); - sub->output(); - printf("\\s[\\n[" SIZE_FORMAT "]u]", uid); - printf(DELIMITER_CHAR); + if (output_format == troff) { + p->output(); + if (sup != 0) { + printf("\\Z" DELIMITER_CHAR); + printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); + printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid); + sup->output(); + printf("\\s[\\n[" SIZE_FORMAT "]u]", uid); + printf(DELIMITER_CHAR); + } + if (sub != 0) { + printf("\\Z" DELIMITER_CHAR); + printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid); + printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid); + printf("\\h'-\\n[" SUB_KERN_FORMAT "]u'", p->uid); + sub->output(); + printf("\\s[\\n[" SIZE_FORMAT "]u]", uid); + printf(DELIMITER_CHAR); + } + printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'", + uid, p->uid); + } else if (output_format == mathml) { + if (sup != 0 and sub != 0) { + printf(""); + p->output(); + sub->output(); + sup->output(); + printf(""); + } else if (sup != 0) { + printf(""); + p->output(); + sup->output(); + printf(""); + } else if (sub != 0) { + printf(""); + p->output(); + sub->output(); + printf(""); + } + } - printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'", - uid, p->uid); } void script_box::hint(unsigned flags) --- special.cpp.~1.2.~ 2005-05-26 17:02:00.000000000 -0400 +++ special.cpp 2007-01-31 13:14:09.000000000 -0500 @@ -104,7 +104,10 @@ void special_box::output() { - printf("\\*[" STRING_FORMAT "]", uid); + if (output_format == troff) + printf("\\*[" STRING_FORMAT "]", uid); + else if (output_format == mathml) + printf("eqn specials cannot be expressed in MathML"); } void special_box::debug_print() Index: sqrt.cpp =================================================================== RCS file: /sources/groff/groff/src/preproc/eqn/sqrt.cpp,v retrieving revision 1.2 diff -u -r1.2 sqrt.cpp --- sqrt.cpp 26 May 2005 21:02:00 -0000 1.2 +++ sqrt.cpp 31 Jan 2007 18:18:29 -0000 @@ -150,21 +150,27 @@ void sqrt_box::output() { - printf("\\Z" DELIMITER_CHAR); - printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid); - printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); - printf("\\*[" SQRT_STRING_FORMAT "]", uid); - printf("\\s[\\n[" SIZE_FORMAT "]u]", uid); - printf(DELIMITER_CHAR); + if (output_format == troff) { + printf("\\Z" DELIMITER_CHAR); + printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid); + printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); + printf("\\*[" SQRT_STRING_FORMAT "]", uid); + printf("\\s[\\n[" SIZE_FORMAT "]u]", uid); + printf(DELIMITER_CHAR); - printf("\\Z" DELIMITER_CHAR); - printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u" - "+\\n[" SQRT_WIDTH_FORMAT "]u/2u'", - uid, p->uid, uid); - p->output(); - printf(DELIMITER_CHAR); + printf("\\Z" DELIMITER_CHAR); + printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u" + "+\\n[" SQRT_WIDTH_FORMAT "]u/2u'", + uid, p->uid, uid); + p->output(); + printf(DELIMITER_CHAR); - printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid); + printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid); + } else if (output_format == mathml) { + printf(""); + p->output(); + printf(""); + } } void sqrt_box::debug_print() Index: text.cpp =================================================================== RCS file: /sources/groff/groff/src/preproc/eqn/text.cpp,v retrieving revision 1.2 diff -u -r1.2 text.cpp --- text.cpp 26 May 2005 21:02:00 -0000 1.2 +++ text.cpp 31 Jan 2007 18:18:30 -0000 @@ -18,10 +18,391 @@ with groff; see the file COPYING. If not, write to the Free Software Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ +#include #include "eqn.h" #include "pbox.h" #include "ptable.h" +struct map { + char *from; + 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", "&lamda;"}, // ISOgrk3 + {"*L", "Λ"}, // ISOgrk3 + {"*m", "μ"}, // ISOgrk3 + {"*M", "M"}, + {"*n", "&nu"}, // 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: horizintal 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 +}; + +char *special_to_entity(const char *sp) +{ + struct map *mp; + char *entity; + for (mp = entity_table; + mp < entity_table + sizeof(entity_table)/sizeof(entity_table[0]); + mp++){ + if (strcmp(mp->from, sp) == 0) + return mp->to; + } + return NULL; +} + class char_box : public simple_box { unsigned char c; char next_is_italic; @@ -48,6 +429,18 @@ void handle_char_type(int, int); }; +enum spacing_type { + s_ordinary, + s_operator, + s_binary, + s_relation, + s_opening, + s_closing, + s_punctuation, + s_inner, + s_suppress, +}; + const char *spacing_type_table[] = { "ordinary", "operator", @@ -115,24 +508,24 @@ void init_char_table() { - set_special_char_type("pl", 2, -1); // binary - set_special_char_type("mi", 2, -1); - set_special_char_type("eq", 3, -1); // relation - set_special_char_type("<=", 3, -1); - set_special_char_type(">=", 3, -1); - char_table['}'].spacing_type = 5; // closing - char_table[')'].spacing_type = 5; - char_table[']'].spacing_type = 5; - char_table['{'].spacing_type = 4; // opening - char_table['('].spacing_type = 4; - char_table['['].spacing_type = 4; - char_table[','].spacing_type = 6; // punctuation - char_table[';'].spacing_type = 6; - char_table[':'].spacing_type = 6; - char_table['.'].spacing_type = 6; - char_table['>'].spacing_type = 3; - char_table['<'].spacing_type = 3; - char_table['*'].spacing_type = 2; // binary + set_special_char_type("pl", s_binary, -1); + set_special_char_type("mi", s_binary, -1); + set_special_char_type("eq", s_relation, -1); + set_special_char_type("<=", s_relation, -1); + set_special_char_type(">=", s_relation, -1); + char_table['}'].spacing_type = s_closing; + char_table[')'].spacing_type = s_closing; + char_table[']'].spacing_type = s_closing; + char_table['{'].spacing_type = s_opening; + char_table['('].spacing_type = s_opening; + char_table['['].spacing_type = s_opening; + char_table[','].spacing_type = s_punctuation; + char_table[';'].spacing_type = s_punctuation; + char_table[':'].spacing_type = s_punctuation; + char_table['.'].spacing_type = s_punctuation; + char_table['>'].spacing_type = s_relation; + char_table['<'].spacing_type = s_relation; + char_table['*'].spacing_type = s_binary; for (int i = 0; i < 256; i++) if (csalpha(i)) char_table[i].font_type = LETTER_TYPE; @@ -180,21 +573,44 @@ void char_box::output() { - int font_type = char_table[c].font_type; - if (font_type != LETTER_TYPE) - printf("\\f[%s]", current_roman_font); - if (!prev_is_italic) - fputs("\\,", stdout); - if (c == '\\') - fputs("\\e", stdout); - else - putchar(c); - if (!next_is_italic) - fputs("\\/", stdout); - else - fputs("\\&", stdout); // suppress ligaturing and kerning - if (font_type != LETTER_TYPE) - fputs("\\fP", stdout); + if (output_format == troff) { + int font_type = char_table[c].font_type; + if (font_type != LETTER_TYPE) + printf("\\f[%s]", current_roman_font); + if (!prev_is_italic) + fputs("\\,", stdout); + if (c == '\\') + fputs("\\e", stdout); + else + putchar(c); + if (!next_is_italic) + fputs("\\/", stdout); + else + fputs("\\&", stdout); // suppress ligaturing and kerning + if (font_type != LETTER_TYPE) + fputs("\\fP", stdout); + } else if (output_format == mathml) { + if (isdigit(c)) + printf(""); + else if (char_table[c].spacing_type) + printf(""); + else + printf(""); + if (c == '<') + printf("<"); + else if (c == '>') + printf(">"); + else if (c == '&') + printf("&"); + else + putchar(c); + if (isdigit(c)) + printf(""); + else if (char_table[c].spacing_type) + printf(""); + else + printf(""); + } } int char_box::left_is_italic() @@ -237,12 +653,20 @@ void special_char_box::output() { - int font_type = get_special_char_font_type(s); - if (font_type != LETTER_TYPE) - printf("\\f[%s]", current_roman_font); - printf("\\,\\[%s]\\/", s); - if (font_type != LETTER_TYPE) - printf("\\fP"); + if (output_format == troff) { + int font_type = get_special_char_font_type(s); + if (font_type != LETTER_TYPE) + printf("\\f[%s]", current_roman_font); + printf("\\,\\[%s]\\/", s); + if (font_type != LETTER_TYPE) + printf("\\fP"); + } else if (output_format == mathml) { + char *entity = special_to_entity(s); + if (entity != NULL) + printf("%s", entity); + else + printf("unknown eqn/troff special char %s", s); + } } int special_char_box::is_char() End of diffs.