In the previous chapter, we have seen that TeX is able to read and evaluate an XML file. The Raweb is not typeset directly: there is a stylesheet that converts it into XSL/Format, see Chapter 7. The purpose of the next chapter is to explain how XSL/Format has to be interpreted by TeX; in this chapter we explain everything else, the big part being MathML, described in [3].
We describe here the file raweb-cfg.sty. It starts with the following lines
\makeatletter \immediate\write20{Loading mathml support and raweb extensions $ Revision: 2.14 $}
It is not a real style file, so that the category code of the `@´ character is not known, and we do not want to use the \ProvidesPackage command for the identification. The revision number given above is computed by RCS, it is likely that the Tralics distribution comes with another version of this file.
This file was obtained by some additions to a file named mathml2.xmt, and it starts with the following copyright notice.
1 % patch to xmltex.tex plus mathml2.xmt plus other stuff 2 %% Copyright 2000 David Carlisle, for the original mathml part 3 %% Copyright 2004, 2006 Jos\'e Grimm 4 5 %% This file is distributed under the LaTeX Project Public License 6 %% (LPPL) as found at http://www.latex-project.org/lppl.txt 7 %% Either version 1.0, or at your option, any later version.
We have seen in the previous chapter that, if xmltex.tex is loaded and LaTeX reads an XML file, then the first occurence of an element in a name space `xx´ provokes loading of file yy.xmt, assuming that `xx´ and `yy´ are associated in the catalogue. In our case, the root element is in the `fo´ namespace, some file is loaded, and the interpretation of the root element provokes loading of all required packages, as well as \begin{document}. After that, it is not possible to load other packages, so that the yy.xmt file cannot be a real LaTeX package.
For some unknown reason, in some cases, this autoloading mechanism did not work with the file mathml2.xmt, so that we decided to load it systematically, using a hook. At the end of the previous chapter we have explained that, if your file is called foo.tex, then foo.cfg is loaded. Thus this file is loaded if it has foo.cfg as alternate name (in Chapter 8, we give an example where a Perl script makes a symbolic link from foo.cfg to raweb-cfg.sty). As a consequence, the file is loaded before anything else (in particular before the class file), but we can use the begin-document hook.
Redefinition of \utfeight@protect@chars. Compare this with the definition on page 2.2, line 123. The idea is that using \let rather than \def should be more efficient. Some tests show that the speedup factor is nearly 10 percent.
8 \def\utfeight@protect@chars{% 9 \let\utfeightax\string 10 \let\utfeightay\string 11 \let\utfeightaz\string 12 \let\utfeightb\utfeightb@jg@ 13 \let\utfeightc\utfeightc@jg@ 14 \let\utfeightd\utfeightd@jg@}
Three auxiliary definitions used above.
15 \def\utfeightb@jg@#1#2{#1\string#2} 16 \def\utfeightc@jg@#1#2#3{#1\string#2\string#3} 17 \def\utfeightd@jg@#1#2#3#4{#1\string#2\string#3\string#4}
We redefine this also (original definition on page 2.2, line 96).
18 \begingroup 19 \catcode`<\active 20 \catcode`&\active 21 \gdef\utfeight@protect@internal{% 22 \let\utfeightax\noexpand 23 \let\utfeightay\noexpand 24 \let\utfeightaz\utfeightaz@jg@int 25 \let<\relax\let&\relax 26 \let\utfeightb\utfeightb@jg@int 27 \let\utfeightc\utfeightc@jg@int 28 \let\utfeightd\utfeightd@jg@int}
These are the auxiliary commands.
29 \def\utfeightaz@jg@int{\noexpand\utfeightaz\noexpand} 30 \def\utfeightb@jg@int#1#2{\noexpand\utfeightb#1\string#2} 31 \def\utfeightc@jg@int#1#2#3{\noexpand\utfeightc#1\string#2\string#3} 32 \def\utfeightd@jg@int#1#2#3#4{\noexpand\utfeightd#1\string#2\string#3\string#4}
This is redefined (original on page 2.16, line 885); we locally change the meaning of the ampersand character, using the command \XML@amp@markup shown below.
33 \gdef\utfeight@chardef#1{% 34 \begingroup 35 \utfeight@protect@chars 36 \let&\XML@amp@markup@jg % <- modified 37 \xdef\x@temp{#1}% 38 \endgroup 39 \let#1\x@temp} 40 \endgroup
The fotex.xmt file contains a declaration of the form `\XMLnamespaceattributeX {fo} {external-destination} {FOexternaldestination} {}´ The `X´ after the command name means that the argument is evaluated in an \xdef. In the case where we want a & in an URL, this does not work. Thus we redefine the meaning of &: in the case of & the expansion is &, otherwise the standard behavior is used.
41 \def\XML@amp@markup@jg#1;{% 42 \XML@amp@markup@jgw#1;amp;\@nil} 43 \def\XML@amp@markup@jgw#1amp;#2\@nil{% 44 \ifx b#2b\XML@amp@markup#1;\else\string&\fi}
We pretend here that mathml2.xmt has been loaded (we do not want the original file to be loaded later).
45 \global\expandafter\let\csname xmt:mathml2.xmt\endcsname\@ne
We declare the namespaces.
46 \DeclareNamespace{m}{http://www.w3.org/1998/Math/MathML} 47 \DeclareNamespace{fotex}{http://www.tug.org/fotex} 48 \DeclareNamespace{fo}{http://www.w3.org/1999/XSL/Format}
Let´s start with simple things: <m:mrow>text</m:mrow> translates to \bgroup text \egroup. This differs from the original coding, allowing constructions like ${x^2}^3$.
49 \XMLelement{m:mrow} 50 {} 51 {\bgroup} 52 {\egroup}
Processing of <m:msub> base subscript </m:msub>. The translation is base_{subscript}. The MathML standard says that there is a subscriptshift attribute that specifies the minimum amount to shift the baseline of subscript down. This is not implemented.
53 \XMLelement{m:msub} 54 {} 55 {\xmlgrab} 56 {\xmltextwochildren\@firstofone\sb#1}
Processing of <m:msup> base supscript </m:msup>. The translation is base^{supscript}. The attribute superscriptshift defined by the standard is ignored.
57 \XMLelement{m:msup} 58 {} 59 {\xmlgrab} 60 {\xmltextwochildren\@firstofone\sp#1}
Processing of <m:msubsup> base subscript superscript </m:msubsup>: the translation is base_{subscript}^{supercript}. The attributes subscriptshift and superscriptshift defined by the standard are ignored.
61 \XMLelement{m:msubsup} 62 {} 63 {\xmlgrab} 64 {\xmltexthreechildren\@firstofone\sb\sp#1}
Processing of <m:mstyle atts> text </m:mstyle>. The translation is text. However, the attributes of the element influence typesetting of it. The attributes veryverythinmathspace, verythinmathspace, thinmathspace, mediummathspace, thickmathspace, verythickmathspace, and veryverythickmathspace can be modified (default value k/18em, for k=1 to 7). TeX provides only three values: thin, medium and thick. The attribute scriptsizemultiplier gives the quotient of the font size at level N and N+1 and scriptminsize indicates the minimum size (TeX has three levels of math fonts: text, script, and scriptscript; there is no such limit in MathML, however there is a limit on the size). The default value of the multiplier is 0.71. If the main font is a 10pt, then the script size will be 7pt, and scriptscript size will be 5pt (these are the default values or TeX; however the default scriptminsize is 8pt). We ignore the background attribute.
In this piece of code, we consider the value of the displaystyle attribute. If it is true, we evaluate \displaystyle. If it is neither true nor false, nothing happens. If it is false, we look at the scriptlevel attribute. We execute \textstyle, or \scriptstyle, or \scriptscriptstyle, if it is 0, 1 or 2. If the attribute is not provided, we use 0 as default value; if the value is out of range, we use 2.
65 \XMLelement{m:mstyle} 66 {\XMLattribute{displaystyle}{\XML@att@displaystyle}{foo} % 67 \XMLattribute{scriptlevel}{\XML@scriptlevel}{0}% 68 } 69 {\xmlgrab} 70 {{\ifx\XML@att@displaystyle\att@true\displaystyle 71 \else\ifx\XML@att@displaystyle\att@false 72 \ifx\XML@scriptlevel\att@dzero\textstyle 73 \else\ifx\XML@scriptlevel\att@done\scriptstyle 74 \else \scriptscriptstyle\fi\fi 75 \fi %do nothing if neither true nor false 76 \fi#1}}
Processing of <m:mroot> base index </m:mroot>. We call \mathmlroot with base and index as arguments (note that the empty group {} disappears when this calls the intermediate command). The MathML norm says that the scriptlevel of index should be increased by two (thus, it will be as small as the TeX version).
77 \XMLelement{m:mroot} 78 {} 79 {\xmlgrab} 80 {\xmltextwochildren\mathmlroot{}#1} 81 82 \def\mathmlroot#1#2{\root#2\of{#1}}
Processing of <m:msqrt> base </m:msqrt>. We just call \sqrt.
83 \XMLelement{m:msqrt} 84 {} 85 {\xmlgrab} 86 {\sqrt{#1}}
Processing of <m:mtext>...</m:mtext>. That´s easy, we use \text.
87 \XMLelement{m:mtext} 88 {} 89 {\xmlgrab} 90 {\text{#1}}
Processing of <m:ms>...</m:ms>. Not yet implemented. The MathML doc says: The <m:ms> element is used to represent “string literals” in expressions meant to be interpreted by computer algebra systems.
91 % \XMLelement{m:ms} {} {"} {"}
Processing of <m:mn>...</m:mn>. The MathML doc says: Unlike <mi>, <mn> elements are (typically) rendered in an unslanted font by default, regardless of their content.
92 \XMLelement{m:mn} 93 {} 94 {\xmlgrab} 95 {\mathrm{#1}}
Processing of <m:mi mathvariant=xx>...</m:mi>. The MathML doc says that the fontstyle attribute is deprecated, and the mathvariant attribute can take one of the following values: normal, bold, italic, bold-italic, double-struck, bold-fraktur, script, bold-script, fraktur, sans-serif, bold-sans-serif, sans-serif-italic, sans-serif-bold-italic, monospace.
96 \XMLelement{m:mi} 97 {\XMLattribute{mathvariant}{\XML@mathmlvariant}{normal}} 98 {\xmlgrab} 99 {\mi@test#1\relax}
As you can see, not all variants are implemented here. On the other hand, the test done on line 107 is false in the case where the content of the element is a letter plus some space. (The MathML norm does not say how to get a single letter using an upright variant).
100 \gdef\mi@test#1#2\relax{ 101 \ifx\XML@mathmlvariant\att@mathml@bold 102 \mathbf{#1#2}\else 103 \ifx\XML@mathmlvariant\att@mathml@sansserif 104 \mathsf{#1#2}\else 105 \ifx\XML@mathmlvariant\att@mathml@tt 106 \texttt{#1#2}\else 107 \ifx\mi@test#2\mi@test 108 \expandafter#1 109 \else 110 \mathrm{#1#2} 111 \fi\fi\fi\fi}
These are used in the code above.
112 \XMLstring\att@mathml@bold<>bold</> 113 \XMLstring\att@mathml@sansserif<>sans-serif</> 114 \XMLstring\att@mathml@tt<>monospace</>
Processing of <m:mspace atts></m:mspace>. The MathML doc says that attributes width, height, depth, linebreak are allowed. Here we consider only the width. The \@defaultunits command is called for the case where a dimension is given without a unit.
115 \XMLelement{m:mspace} 116 {\XMLattribute{width}{\XML@mspacewidth}{0}} 117 {} 118 {\@defaultunits\dimen@\XML@mspacewidth pt\relax\@nnil 119 \ifnum\dimen@=\z@\else\kern\dimen@\fi}
Processing of <m:mfenced open=A close=B separators=...>content</m:mfenced>. We ignore the separators. The translation is \left A content \right B. However, what \left and \right want are numbers (to be precise, slots into math fonts that indicate how large delimiters can be made from smaller pieces); what TeX wants is a character with a \delcode, what the XML file contains is a character. We hack a bit, because we cannot expand all these Unicode characters.
120 \XMLelement{m:mfenced} 121 { \XMLattribute{open}{\XML@fenceopen}{(} 122 \XMLattribute{close}{\XML@fenceclose}{)} 123 } 124 {\jg@hacko\left\XML@fenceopen} 125 {\jg@hackc\right\XML@fenceclose}
This code is easy: for instance, if the character is U+2329, we replace it by \langle.
126 \def\jg@hacko{% 127 \ifx\XML@fenceopen\jg@lt\let\XML@fenceopen\langle\fi 128 \ifx\XML@fenceopen\jg@lbra\let\XML@fenceopen\langle\fi 129 \ifx\XML@fenceopen\jg@xlbra\let\XML@fenceopen\langle\fi 130 \ifx\XML@fenceopen\jg@gt\let\XML@fenceopen\rangle\fi 131 \ifx\XML@fenceopen\jg@rbra\let\XML@fenceopen\rangle\fi 132 \ifx\XML@fenceopen\jg@xrbra\let\XML@fenceopen\rangle\fi 133 \ifx\XML@fenceopen\jg@verbar\let\XML@fenceopen\|\fi 134 \ifx\XML@fenceopen\jg@Verbar\let\XML@fenceopen\|\fi 135 \ifx\XML@fenceopen\jg@lfloor\let\XML@fenceopen\lfloor\fi 136 \ifx\XML@fenceopen\jg@rfloor\let\XML@fenceopen\rfloor\fi 137 \ifx\XML@fenceopen\jg@lceil\let\XML@fenceopen\lceil\fi 138 \ifx\XML@fenceopen\jg@rceil\let\XML@fenceopen\rceil\fi 139 \ifx\XML@fenceopen\jg@lmoustache\let\XML@fenceopen\lmoustache\fi 140 \ifx\XML@fenceopen\jg@rmoustache\let\XML@fenceopen\rmoustache\fi 141 \ifx\XML@fenceopen\jg@lgroup\let\XML@fenceopen\lgroup\fi 142 \ifx\XML@fenceopen\jg@rgroup\let\XML@fenceopen\rgroup\fi 143 \ifx\XML@fenceopen\jg@uparrow\let\XML@fenceopen\uparrow\fi 144 \ifx\XML@fenceopen\jg@downarrow\let\XML@fenceopen\downarrow\fi 145 \ifx\XML@fenceopen\jg@Uparrow\let\XML@fenceopen\Uparrow\fi 146 \ifx\XML@fenceopen\jg@Downarrow\let\XML@fenceopen\Downarrow\fi 147 \ifx\XML@fenceopen\jg@updownarrow\let\XML@fenceopen\updownarrow\fi 148 \ifx\XML@fenceopen\jg@Updownarrow\let\XML@fenceopen\Updownarrow\fi 149 }
Same code for closing delimiters.
150 \def\jg@hackc{% 151 \ifx\XML@fenceclose\jg@gt\let\XML@fenceclose\rangle\fi 152 \ifx\XML@fenceclose\jg@rbra\let\XML@fenceclose\rangle\fi 153 \ifx\XML@fenceclose\jg@xrbra\let\XML@fenceclose\rangle\fi 154 \ifx\XML@fenceclose\jg@lt\let\XML@fenceclose\langle\fi 155 \ifx\XML@fenceclose\jg@lbra\let\XML@fenceclose\langle\fi 156 \ifx\XML@fenceclose\jg@xlbra\let\XML@fenceclose\langle\fi 157 \ifx\XML@fenceclose\jg@verbar\let\XML@fenceclose\|\fi 158 \ifx\XML@fenceclose\jg@Verbar\let\XML@fenceclose\|\fi 159 \ifx\XML@fenceclose\jg@lfloor\let\XML@fenceclose\lfloor\fi 160 \ifx\XML@fenceclose\jg@rfloor\let\XML@fenceclose\rfloor\fi 161 \ifx\XML@fenceclose\jg@lceil\let\XML@fenceclose\lceil\fi 162 \ifx\XML@fenceclose\jg@rceil\let\XML@fenceclose\rceil\fi 163 \ifx\XML@fenceclose\jg@lmoustache\let\XML@fenceclose\lmoustache\fi 164 \ifx\XML@fenceclose\jg@rmoustache\let\XML@fenceclose\rmoustache\fi 165 \ifx\XML@fenceclose\jg@lgroup\let\XML@fenceclose\lgroup\fi 166 \ifx\XML@fenceclose\jg@rgroup\let\XML@fenceclose\rgroup\fi 167 \ifx\XML@fenceclose\jg@uparrow\let\XML@fenceclose\uparrow\fi 168 \ifx\XML@fenceclose\jg@downarrow\let\XML@fenceclose\downarrow\fi 169 \ifx\XML@fenceclose\jg@Uparrow\let\XML@fenceclose\Uparrow\fi 170 \ifx\XML@fenceclose\jg@Downarrow\let\XML@fenceclose\Downarrow\fi 171 \ifx\XML@fenceclose\jg@updownarrow\let\XML@fenceclose\updownarrow\fi 172 \ifx\XML@fenceclose\jg@Updownarrow\let\XML@fenceclose\Updownarrow\fi 173 }
Here we put each delimiter in a string command.
174 \XMLstring\jg@verbar<>‖</> 175 \XMLstring\jg@Verbar<>‖</> 176 \XMLstring\jg@lfloor<>⌊</> 177 \XMLstring\jg@rfloor<>⌋</> 178 \XMLstring\jg@lceil<>⌈</> 179 \XMLstring\jg@rceil<>⌉</> 180 \XMLstring\jg@lmoustache<>⎰</> 181 \XMLstring\jg@rmoustache<>⎱</> 182 \XMLstring\jg@lgroup<>〔</> 183 \XMLstring\jg@rgroup<>〕</> 184 \XMLstring\jg@uparrow<>↑</> 185 \XMLstring\jg@Uparrow<>⇑</> 186 \XMLstring\jg@downarrow<>↓</> 187 \XMLstring\jg@Downarrow<>⇓</> 188 \XMLstring\jg@updownarrow<>↕</> 189 \XMLstring\jg@Updownarrow<>⇕</>
The Unicode standard says that U+2329 and U+232A should not be used for math. For this reason, we add U+27E8 and U+27E9 in this list.
190 \XMLstring\jg@lbra<>〈</> 191 \XMLstring\jg@rbra<>〉</> 192 \XMLstring\jg@xlbra<>⟨</> 193 \XMLstring\jg@xrbra<>⟩</>
The translation by Tralics of $\vec x$ is <mover accent='true'> <mi>x</mi> <mo>→</mo> </mover>. A non obvious point is how to translate this back. This idea is that we evaluate the accent in a context (defined by \notinover), this will set the two commands \cur@mo@content and \jg@cur@acc. Let´s declare them here.
194 \let\notinover\relax 195 \def\cur@mo@content{TOTO} 196 \let\jg@cur@acc\relax
Processing of <m:munderover accent=bool accentunder=bool> base underscript overscript</m:munderover>. This is wrong. Moreover, attributes are ignored.
197 \XMLelement{m:munderover} 198 { } 199 {\xmlgrab} 200 {\xmltexthreechildren\@firstofone\sb\sp#1}
Processing of <m:mover accent=bool> base overscript</m:mover>. We use an intermediate command. If no accent, we use \stackrel. Otherwise, we call a command, say \jg@bindings, evaluate the accent in an environment where \notinover is \over, then execute two commands \cur@mo@content and \jg@cur@acc (\X and \Y for simplicity). Evaluating the overscript should define \X, and evaluating \X should define \Y, in such a way that \Y applied to the base should put an accent on it.
201 \XMLelement{m:mover} 202 {\XMLattribute{accent}{\XML@overaccent}{none}} 203 {\xmlgrab} 204 {\xmltextwochildren\xml@implement@over{}#1}
205 \def\xml@implement@over#1#2{% 206 \ifx\XML@overaccent\att@true {% 207 \jg@bindings 208 \let\notinover\over #2\let\notinover\relax \cur@mo@content\jg@cur@acc{#1}% 209 }\else\stackrel{#2}{#1}\fi}
Processing of <m:munder accentunder=bool> base underscript</m:munder>. We use an intermediate command: same idea as above. If no accent, we use \underset.
210 \XMLelement{m:munder} 211 {\XMLattribute{accentunder}{\XML@underaccent}{none}} 212 {\xmlgrab} 213 {\xmltextwochildren\xml@implement@under{}#1}
214 \def\xml@implement@under#1#2{% 215 \ifx\XML@underaccent\att@true {% 216 \jg@ubindings 217 \let\notinover\over #2\let\notinover\relax \cur@mo@content\jg@cur@acc{#1}% 218 }\else \underset{#2}{#1}\fi}
Processing of <m:mo atts>...</m:mo>. The MathML norm says that the following attributes are recognized: form, fence, separator, lspace, rspace, stretchy, symmetric, maxsize, minsize, largeop, movablelimits, and accent. We implement only two attributes. We assume that, if form = `prefix´ is given, that our operator is like log or sin, and never used as an accent. Thus, we generate a \mathop with an operator font. We set \limits or \nolimits, depending on the value of the movablelimits attribute. Otherwise, some command is called.
219 \XMLelement{m:mo} 220 {\XMLattribute{form}{\XML@mathmlform}{inline}% 221 \XMLattribute{movablelimits}{\XML@movablelimits}{false}} 222 {\xmlgrab} 223 {\ifx\XML@mathmlform\att@PREFIX 224 \ifx\XML@movablelimits\att@true 225 \mathop{\operator@font #1}\limits 226 \else 227 \mathop{\operator@font #1}\nolimits 228 \fi 229 \else\special@mo{#1}\fi}
For some strange reason, the default code does not produce a less than sign. Hence we hack a bit. In the case of accent, we have two commands, let´s call them \X and \Y. We define \X, so that it will define \Y. The definition is global (it must be seen by the caller of the <mo> element). In the case of grave accent, what we have here is a 7bit character, and we have to set \Y directly. In the case of 3 or 4 dots, we have to set this command.
230 \def\special@mo#1{% 231 \def\jg@tck{#1}% save the argument 232 \ifx\notinover\over% we cannot typeset here 233 \ifx\jg@tck\jg@accgrave % strange 234 \global\let\jg@cur@acc\jg@grave@acc 235 \global\let\cur@mo@content\relax 236 \else \ifx\jg@tck\jg@accdddot % strange 237 \global\let\jg@cur@acc\dddot 238 \global\let\cur@mo@content\relax 239 \else \ifx\jg@tck\jg@accddddot % strange 240 \global\let\jg@cur@acc\ddddot 241 \global\let\cur@mo@content\relax 242 \else\gdef\cur@mo@content{#1}\fi\fi\fi 243 \else % typeset the argument, handle < and > in the correct way 244 \ifx\jg@tck\jg@gt\string>\else 245 \ifx\jg@tck\jg@lt\string<\else 246 #1\fi\fi\fi}
Some declarations, needed above.
247 \XMLstring\jg@lt<><</> 248 \XMLstring\jg@gt<>></> 249 \XMLstring\jg@accgrave<>`</> 250 \XMLstring\jg@accdddot<>⃛</> 251 \XMLstring\jg@accddddot<>⃜</>
This is the big hack. Remember that, in the case of \vec, the accent is an arrow, in fact, a Unicode character, that typesets as an arrow. What we do is to redefine \rightarrow, in order to put in \Y (in fact in \jg@cur@acc) a command that behaves like \vec. In the case of a breve accent, the character 2D8 is defined to be \ifmmode \u\else \textasciibreve \fi, so that we have to redefine \u. In the case of the character 302, the definition is \ifmmode \hat{}\else \^{}\fi, so that we have to redefine \hat in such a way that it reads an argument, and evaluates to something that looks like \hat.
252 \def\jg@bindings{% 253 \def\texttildelow {\global\let\jg@cur@acc\jg@tilde@acc}% 254 % \def\textasciimacron {\global\let\jg@cur@acc\jg@cur@accB}% 255 \def\textasciicircum{\global\let\jg@cur@acc\jg@hat@acc} 256 \def\textasciicaron {\global\let\jg@cur@acc\jg@check@acc}% 257 \def\u{\global\let\jg@cur@acc\jg@breve@acc}% 258 \def\hat##1{\global\let\jg@cur@acc\jg@hat@acc}% 259 \def\dot##1{\global\let\jg@cur@acc\jg@dot@acc}% 260 \def\mathring##1{\global\let\jg@cur@acc\jg@ring@acc}% 261 \def\textasciidieresis{\global\let\jg@cur@acc\jg@ddot@acc}% 262 \let\JGG@orig@rarrow\rightarrow 263 \let\JGG@orig@larrow\leftarrow 264 \def\rightarrow{\global\let\jg@cur@acc\jg@overRarrow@acc}% 265 \def\leftarrow{\global\let\jg@cur@acc\jg@overLarrow@acc}% 266 \def\textoverbrace{\global\let\jg@cur@acc\overbrace} 267 \def\textunderbrace{\global\let\jg@cur@acc\underbrace} 268 \def\textasciiacute{\global\let\jg@cur@acc\acute} 269 \def\textasciimacron{\global\let\jg@cur@acc\overline} 270 \def\ring{\global\let\jg@cur@acc\mathring} 271 }
The same idea is used in the case of underaccent.
272 \def\jg@ubindings{% 273 \let\JGG@orig@rarrow\rightarrow 274 \let\JGG@orig@larrow\leftarrow 275 \def\texttildelow {\global\let\jg@cur@acc\jg@tilde@acc}% 276 \def\textasciimacron {\global\let\jg@cur@acc\underline}% 277 \def\textasciicaron {\global\let\jg@cur@acc\jg@check@acc}% 278 \def\u{\global\let\jg@cur@acc\jg@breve@acc}% 279 \def\hat##1{\global\let\jg@cur@acc\jg@hat@acc}% 280 \def\dot##1{\global\let\jg@cur@acc\jg@dot@acc}% 281 \def\textasciidieresis{\global\let\jg@cur@acc\jg@ddot@acc}% 282 \let\JGG@orig@rarrow\rightarrow 283 \let\JGG@orig@larrow\leftarrow 284 \def\rightarrow{\global\let\jg@cur@acc\jg@underRarrow@acc}% 285 \def\leftarrow{\global\let\jg@cur@acc\jg@underLarrow@acc}% 286 \def\textoverbrace{\global\let\jg@cur@acc\overbrace} 287 \def\textunderbrace{\global\let\jg@cur@acc\underbrace} 288 \def\jgunderline{\global\let\jg@cur@acc\underline} 289 }
This defines braces as delimiters. The plain.tex file says: N.B. { and } should NOT get delcodes; otherwise parameter grouping fails!
290 \global\delcode`{"66308 291 \global\delcode`}"67309
This is the original definition of the accent commands.
292 \def\jg@tilde@acc{\mathaccent"707E } 293 \def\jg@check@acc{\mathaccent"7014 } 294 \def\jg@breve@acc{\mathaccent"7015 } 295 \def\jg@hat@acc{\mathaccent"705E } 296 \def\jg@dot@acc{\mathaccent"705F } 297 \def\jg@ddot@acc{\mathaccent"707F } 298 \def\jg@grave@acc{\mathaccent"7012 } 299 \def\jg@ring@acc{\protect \mathaccentV {mathring}017 }
Note that when \jg@overRarrow@acc is called, \rightarrow does something strange. We must redefine it here, because \rightarrowfill@ uses it.
300 \def\jg@overRarrow@acc{\let\rightarrow\JGG@orig@rarrow 301 \mathpalette{\overarrow@\rightarrowfill@}} 302 \def\jg@overLarrow@acc{\let\leftarrow\JGG@orig@larrow 303 \mathpalette{\overarrow@\leftarrowfill@}} 304 \def\jg@underRarrow@acc{\let\rightarrow\JGG@orig@rarrow 305 \mathpalette{\underarrow@\rightarrowfill@}} 306 \def\jg@underLarrow@acc{\let\leftarrow\JGG@orig@larrow 307 \mathpalette{\underarrow@\leftarrowfill@}}
This is the main math element. Only the display attribute is taken into account. It can be `inline´ or `block´. If it is block, we use brackets, otherwise parentheses. The original code defined a command \GATHER.
308 \XMLelement{m:math} 309 {\XMLattribute{display}{\XML@mathmlmode}{inline}} 310 { 311 \ifx\XML@mathmlmode\att@BLOCK\[\else\(\fi 312 } 313 { 314 \ifx\XML@mathmlmode\att@BLOCK\]\else\)\fi 315 }
Processing of <m:mfrac linethickness=A numalign=B denomalign=C bevelled=D>num denom</m:mfrac>. We ignore the bevelled attribute. In the current version, we also ignore the horizontal alignment attributes.
316 \XMLelement{m:mfrac} 317 {\XMLattribute{linethickness}{\XML@linethickness}{true}% 318 \XMLattribute{numalign}{\XML@numalign}{center}% 319 \XMLattribute{denomalign}{\XML@denomalign}{center}% 320 } 321 {\xmlgrab} 322 {\xmltextwochildren\xml@implement@frac{}#1}
323 \def\xml@implement@frac#1#2{% 324 \ifx\XML@linethickness\att@true\frac{#1}{#2}% 325 \else \genfrac{}{}\XML@linethickness{}{#1}{#2}\fi
Processing of <m:mtable atts>body</m:mtable>. The MathML specification says that the following attributes are allowed: align, rowalign, columnalign, groupalign, alignmentscope, columnwidth, width, rowspacing, columnspacing, rowlines, columnlines, frame, framespacing, equalrows, equalcolumns, displaystyle, side, and minlabelspacing. They are currently all ignored. New implementation, dated January 2005.
326 \XMLelement{m:mtable} 327 {} 328 {\xmlgrab } 329 {\jg@start@mtable#1\jg@end@mtable }
Processing of <m:mtr atts>body</m:mtr>. The attributes are: rowalign, columnalign, and groupalign.
330 \XMLelement{m:mtr} 331 {} 332 {\xmlgrab } 333 {\jg@start@mtr#1}
Processing of <m:mtd atts>body</m:mtd>. The attributes are: rowspan, columnspan, rowalign, columnalign, and groupalign.
334 \XMLelement{m:mtd} 335 {\XMLattribute{columnalign}{\XML@mtdalign}{center} 336 \XMLattribute{columnspan}{\XML@mtdspan}{1}} 337 {\xmlgrab} 338 {\jg@start@mtd{#1}}
The current implementation of math tables uses two token lists, one holds the table, the other one holds the current row. The same holds for normal tables, but since normal tables can contain math tables, we need four lists.
339 \newtoks\jg@mtable@toks 340 \newtoks\jg@mrow@toks 341 \newtoks\jg@table@toks 342 \newtoks\jg@row@toks
There is a command \addto@hook that inserts some tokens at the end of a token list; it is similar to \gaddto@hook without the \global. The command \merge@toks appends the current row to the table (action has to be global, because it is executed from the group that defines the row). We also need a command that adds the content of a command to the back of the token list, this is used by normal table when constructing the optional argument of \\.
343 \newcommand\merge@toks[2]{% 344 \expandafter\gaddto@hook\expandafter#1\expandafter{\the#2}} 345 \long\def\gaddto@hook#1#2{\global#1\expandafter{\the#1#2}} 346 \newcommand\merge@cmd[2]{% 347 \expandafter\gaddto@hook\expandafter#1\expandafter{#2}}
When we see the start of a table, we initialize the token list. What we will finally evaluate is an array, declared as *{99}{c}. In the current implementation, it is possible to count the number of columns, and replace 99 by a better value, but this would cost more than constructing a preamble of length 99. We shall see later that, for normal tables, we count the number of columns. Note that, in amsmath, matrices are declared in this way, using the counter MaxMatrixCols, with initial value 10, instead of the constant 99. We initialize the row token list to be empty, and \ifStartTable to true (this means that the next row is the first one).
348 \newif\ifStartTable\newif\ifStartRow 349 \newif\ifStartRowx\newif\ifStartTablex 350 \newcommand\jg@start@mtable{% 351 \jg@mtable@toks{\begin{array}{*{99}{c}}}% 352 \jg@mrow@toks{}% 353 \StartTabletrue}
When the end of the array is seen, we insert the last row and the \end{array} in the token list, then evaluate it.
354 \newcommand\jg@end@mtable{% 355 \merge@toks\jg@mtable@toks\jg@mrow@toks 356 \addto@hook\jg@mtable@toks{\end{array}}% 357 \the\jg@mtable@toks}
When we see the start of a row, we insert the previous row into the table; we reset it; we define the command \ifStartRow to true (this means that the next cell is the first in the row). In the case where \ifStartTable is true, we set it to false, otherwise we add a \\, the row separator, in the array.
358 \newcommand\jg@start@mtr{% 359 \merge@toks\jg@mtable@toks\jg@mrow@toks 360 \ifStartTable 361 \glbal\StartTablefalse 362 \else \gaddto@hook\jg@mtable@toks{\\}\fi 363 \jg@mrow@toks{}% 364 \StartRowtrue}
The main action associated to a cell consists in putting the content in the \jg@row@toks token list; in the case where \ifStartRow is true, we set it to false, otherwise we add a &, the cell separator, in the token list. In \temp, we put the content of our cell, plus some \hfill in the case where alignment is left or right; if alignment is `left´, we insert an empty group after the \hfill (the preamble of the array for our cell is \hfil\ignorespaces#\unskip\hfil). In the general case, there is no need to use a temporary command: we could add the tokens directly into the token list; however, in the case where the span is greater than one, the action is a bit more complicated, in this case, we use a temporary token register.
365 \newcommand\jg@start@mtd[1]{% 366 \ifStartRow 367 \global\StartRowfalse 368 \else\gaddto@hook\jg@mrow@toks{\tabcellsep}\fi 369 \ifx\XML@mtdalign\att@mtd@left 370 \def\temp{#1\hfill{}}% 371 \else\ifx\XML@mtdalign\att@mtd@right 372 \def\temp{\hfill#1}% 373 \else \def\temp{#1}\fi\fi% 374 \ifnum\XML@mtdspan=1\else 375 \toks0=\expandafter{\temp}% 376 \edef\temp{\noexpand\multicolumn{\XML@mtdspan}{c}{\the\toks0}}% 377 \fi 378 \expandafter\gaddto@hook\expandafter\jg@mrow@toks\expandafter{\temp}}
In this section, we define some elements that Tralics constructs when evaluating a command from the epic package. These elements are in the default namespace with `pic-´ prefix; in a future version, we will move them in another namespace.
Processing of <picture width=A height=B xpos=C ypos=D>...</picture>. This defines the picture environment. Translation is \begin{picture} (A,B)(C,D) ... \end{picture}.
379 \XMLelement{picture} 380 {\XMLattribute{width}{\XML@width}{1} 381 \XMLattribute{height}{\XML@height}{1} 382 \XMLattribute{xpos}{\XML@xpos}{0} 383 \XMLattribute{ypos}{\XML@ypos}{0} 384 } 385 {\begin{picture}(\XML@width,\XML@height)(\XML@xpos,\XML@ypos)} 386 {\end{picture}}
Processing of <pic-put xpos=A ypos=B>C</pic-put>. We translate this into \put(A,B){C}.
387 \XMLelement{pic-put} 388 {\XMLattribute{xpos}{\XML@xpos}{0} 389 \XMLattribute{ypos}{\XML@ypos}{0}} 390 {\xmlgrab} 391 {\put(\XML@xpos,\XML@ypos){#1}}
Processing of <pic-arc xpos=A ypos=B angle=C></pic-arc>. We translate this in an obvious manner into \arc(A,B){C}.
392 \XMLelement{pic-arc} 393 {\XMLattribute{xpos}{\XML@xpos}{0} 394 \XMLattribute{angle}{\XML@angle}{0} 395 \XMLattribute{ypos}{\XML@ypos}{0}} 396 {\xmlgrab} 397 {\arc(\XML@xpos,\XML@ypos){\XML@angle}}
Processing of <pic-scaleput xpos=A ypos=B xscale=xs yscale=ys xscaley=xsy yscaley=ysy>C</pic-scaleput>. We translate this into \scaleput(A,B){C}. Other attributes are put in variables named \xscale, \yscale, \xscaley, and \yscalex.
398 \XMLelement{pic-scaleput} 399 {\XMLattribute{xscale}{\xscale}{1.0} 400 \XMLattribute{yscale}{\yscale}{1.0} 401 \XMLattribute{xscaley}{\xscaley}{0.0} 402 \XMLattribute{yscalex}{\yscalex}{0.0} 403 \XMLattribute{xpos}{\XML@xpos}{0} 404 \XMLattribute{ypos}{\XML@ypos}{0}} 405 {\xmlgrab} 406 {\scaleput(\XML@xpos,\XML@ypos){#1}}
Processing of <pic-thicklines/> and <pic-thinlines/>. We call a command, that is executed just after the group. In the case of <pic-linethickness size=V/>, the command takes an argument; we have to expand the value of the attribute, put this in a global variable, and ask for that variable to be expanded after the group. In a first version, we redefined the three commands \thinlines, \thicklines and \linethickness. The current code is simpler.
407 \XMLelement{pic-thicklines} 408 {}{}{\aftergroup\thicklines}
409 \XMLelement{pic-thinlines} 410 {}{}{\aftergroup\thinlines}
411 \XMLelement{pic-linethickness} 412 {\XMLattribute{size}{\XML@size}{1pt}} 413 {} 414 {\xdef\temp{\noexpand\linethickness{\XML@size}}\aftergroup\temp}
Processing of <pic-multiput xpos=A ypos=B repeat=C dx=D dy=E>obj</pic-multiput>. We translate this as \multiput(A,B)(D,E){C}{obj}.
415 \XMLelement{pic-multiput} 416 {\XMLattribute{xpos}{\XML@xpos}{0} 417 \XMLattribute{ypos}{\XML@ypos}{0} 418 \XMLattribute{repeat}{\XML@repeat}{1} 419 \XMLattribute{dx}{\XML@dx}{1} 420 \XMLattribute{dy}{\XML@dy}{1}} 421 {\xmlgrab} 422 {\multiput(\XML@xpos,\XML@ypos)(\XML@dx,\XML@dy){\XML@repeat}{#1}}
Processing of <pic-bezier a1=A1 a2=A2 b1=B1 b2=B2 c1=C1 c2=C2 repeat=D/>. Translation is \qbezier[D](A1,A2)(B1,B2),(C1,C2).
423 \XMLelement{pic-bezier} 424 {\XMLattribute{a1}{\XML@ai}{0} 425 \XMLattribute{a2}{\XML@aii}{0} 426 \XMLattribute{b1}{\XML@bi}{0} 427 \XMLattribute{b2}{\XML@bii}{0} 428 \XMLattribute{c1}{\XML@ci}{0} 429 \XMLattribute{c2}{\XML@cii}{0} 430 \XMLattribute{repeat}{\XML@repeat}{0}} 431 {} 432 { 433 \qbezier[\XML@repeat](\XML@ai,\XML@aii)(\XML@bi,\XML@bii)(\XML@ci,\XML@cii) 434 }
Processing of <pic-line xdir=A ydir=B width=C/>. The translation is \line(A,B){C}.
435 \XMLelement{pic-line} 436 {\XMLattribute{xdir}{\XML@xdir}{0} 437 \XMLattribute{ydir}{\XML@ydir}{0} 438 \XMLattribute{width}{\XML@width}{0}} 439 {} 440 {\line(\XML@xdir,\XML@ydir){\XML@width}}
Processing of <pic-vector xdir=A ydir=B width=C/>. The translation is \vector(A,B){C}.
441 \XMLelement{pic-vector} 442 {\XMLattribute{xdir}{\XML@xdir}{0} 443 \XMLattribute{ydir}{\XML@ydir}{0} 444 \XMLattribute{width}{\XML@width}{0}} 445 {} 446 {\vector(\XML@xdir,\XML@ydir){\XML@width}}
Processing of <pic-curve unit-length=A>B</pic-curve>. The translation is \curve(B). There are two hacks here: one is that \curve modifies \unitlength globally, so that we have to reset it. The other hack is that \ignorespaces must be ignored: the argument of \curve is a sequence of numbers, converted to dimensions by using \unitlength. Between a sequence of digits and a unit of measure, spaces are allowed (but here, spaces are active, there expansion is: space plus \ignorespaces).
447 \newdimen\jgunitlength 448 \newcommand\withulength[1]{% 449 {\def\ignorespaces{}% 450 \jgunitlength=\unitlength \setlength\unitlength{\XML@ulength pt}% 451 #1\global\unitlength\jgunitlength}} 452 453 \XMLelement{pic-curve} 454 {\XMLattribute{unit-length}{\XML@ulength}{1}} 455 {\xmlgrab} 456 {\withulength{\curve(#1)}}
Processing of <pic-closecurve unit-length=A>B</pic-closecurve>. With the same hack as above, the translation is \closecurve(B).
457 \XMLelement{pic-closecurve} 458 {\XMLattribute{unit-length}{\XML@ulength}{1}} 459 {\xmlgrab} 460 {\withulength{\closecurve(#1)}}
Processing of <pic-tagcurve unit-length=A>B</pic-tagcurve>. With the same hack as above, the translation is \tagcurve(B).
461 \XMLelement{pic-tagcurve} 462 {\XMLattribute{unit-length}{\XML@ulength}{1}} 463 {\xmlgrab} 464 {\withulength{\tagcurve(#1)}}
Processing of <pic-frame>X</pic-frame>. Translation is \frame{X}.
465 \XMLelement{pic-frame} 466 {} 467 {\xmlgrab} 468 {\frame{#1}}
Processing of <pic-circle size=A full=B/>. Translation is \circle{A} or \circle*{A}. A star is used B is given and not `false´.
469 \XMLelement{pic-circle} 470 {\XMLattribute{size}{\XML@size}{1} 471 \XMLattribute{full}{\XML@full}{false}} 472 {} 473 {\ifx\XML@full\att@false\circle{\XML@size}\else \circle*{\XML@size}\fi}
Processing of <pic-circle size=A unit-length=B/>. Translation is \bigcircle{A}. We locally change \unitlength.
474 \XMLelement{pic-bigcircle} 475 {\XMLattribute{size}{\XML@size}{1} 476 \XMLattribute{unit-length}{\XML@ulength}{1}} 477 {} 478 {\withulength{\bigcircle{\XML@size}}}
The strings defined here are needed in the next command.
479 \XMLstring\att@l<>l</> 480 \XMLstring\att@r<>r</> 481 \XMLstring\att@t<>t</> 482 \XMLstring\att@b<>b</> 483 \XMLstring\att@lt<>lt</> 484 \XMLstring\att@lb<>lb</> 485 \XMLstring\att@rt<>rt</> 486 \XMLstring\att@rb<>rb</> 487 \XMLstring\att@tl<>tl</> 488 \XMLstring\att@bl<>bl</> 489 \XMLstring\att@tr<>tr</> 490 \XMLstring\att@br<>br</>
Given a string A, in \XML@pos, we construct a string B, that has the same characters (order is irrelevant), with category code 11. Moreover, if we have a command \bar and an argument gee, we evaluate \bar[B]{gee} (in fact, we construct a command that does this; this command will be evaluated after all conditionals have been closed.)
491 \def\@att@to@rtb#1#2{% 492 \ifx\XML@pos\att@l \def\jg@tmp{#1[l]{#2}} 493 \else\ifx\XML@pos\att@r \def\jg@tmp{#1[r]{#2}}% 494 \else\ifx\XML@pos\att@t \def\jg@tmp{#1[t]{#2}}% 495 \else\ifx\XML@pos\att@b \def\jg@tmp{#1[b]{#2}}% 496 \else\ifx\XML@pos\att@lt \def\jg@tmp{#1[lt]{#2}}% 497 \else\ifx\XML@pos\att@lb \def\jg@tmp{#1[lb]{#2}}% 498 \else\ifx\XML@pos\att@rt \def\jg@tmp{#1[rt]{#2}}% 499 \else\ifx\XML@pos\att@rb \def\jg@tmp{#1[rb]{#2}}% 500 \else\ifx\XML@pos\att@tl \def\jg@tmp{#1[lt]{#2}}% 501 \else\ifx\XML@pos\att@bl \def\jg@tmp{#1[lb]{#2}}% 502 \else\ifx\XML@pos\att@tr \def\jg@tmp{#1[rt]{#2}}% 503 \else\ifx\XML@pos\att@br \def\jg@tmp{#1[rb]{#2}}% 504 \else \def\jg@tmp{#1{#2}} 505 \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi 506 \jg@tmp 507 }
Processing <pic-framebox width=A height=B position=C framed=D>obj</pic-framebox>. The translation is \framebox(A,B)[CC]{obj} (it could be \makebox if the attribute framed is false). Here CC is the value of C, processed as indicated above.
508 \XMLelement{pic-framebox} 509 {\XMLattribute{width}{\XML@width}{0} 510 \XMLattribute{height}{\XML@height}{0} 511 \XMLattribute{position}{\XML@pos}{} 512 \XMLattribute{framed}{\XML@framed}{false} 513 } 514 {\xmlgrab} 515 {\let\cmd\framebox\ifx\XML@framed\att@false\let\cmd\makebox\fi 516 \@att@to@rtb{\cmd(\XML@width,\XML@height)}{#1}}
Processing <pic-dashbox width=A height=B position=C dashdim=D> obj </pic-dashbox>. The translation is \dashbox{D}(A,B)[CC]{obj}, where CC is as above.
517 \XMLelement{pic-dashbox} 518 {\XMLattribute{width}{\XML@width}{0} 519 \XMLattribute{height}{\XML@height}{0} 520 \XMLattribute{position}{\XML@pos}{w} 521 \XMLattribute{dashdim}{\XML@dashdim}{1pt} 522 } 523 {\xmlgrab} 524 {\@att@to@rtb{\dashbox{\XML@dashdim}(\XML@width,\XML@height)}{#1}}
Processing of <pic-oval xpos=A ypos=B specs=C>obj</pic-oval>.
The translation is \oval(A,B)[CC]{obj}, where CC is as above.
525 \XMLelement{pic-oval} 526 {\XMLattribute{xpos}{\XML@xpos}{0} 527 \XMLattribute{specs}{\XML@pos}{} 528 \XMLattribute{ypos}{\XML@ypos}{0}} 529 {\xmlgrab} 530 {\@att@to@rtb{\oval(\XML@xpos,\XML@ypos)}{#1}}
We found no easy way to describe the title page of the Raweb using XSL/Format; thus additional elements were invented and described here. The \ra@atxy command adds a box (that occupies no space) at a give position in the page (the position is absolute).
531 \newbox\ra@atxybox 532 \def\ra@atxy(#1,#2)#3{\global\setbox\ra@atxybox=\hbox 533 {\unhbox\ra@atxybox 534 \vtop to 0pt{\kern #2\hbox to 0pt{\kern #1\relax #3\hss}\vss}}}
We use \@texttop (a command that does nothing)(note: ➳) for insertion of our box. After that, we kill our command. We have to shift horizontally by 1in plus \hoffset and the current margin, vertically by 1in, plus \voffset plus \headheight plus \headsep plus \topmargin.
535 \def\ra@useatxy{{% 536 \let\@themargin\oddsidemargin 537 \vtop to 0pt{\kern-\headsep \kern-\topmargin \kern-\headheight 538 \kern-1in \kern-\voffset 539 \hbox to 0pt{\kern-\@themargin \kern-1in \kern-\hoffset 540 \unhbox\ra@atxybox \hss}\vss}}% 541 \global\let\@texttop\relax}
The command \firstchar is nowadays useless. In the times when Inria themes were 1A, 1B, 2A, 2B etc, we used it to remove the letter. Nowadays themes are NUM, COG, etc, and we hope people give only the theme.(note: ➳) We insert the logo, and, above it, the theme with some rules.
542 \def\foratheme#1{\vskip8cm \vfil 543 \ra@atxy(74mm,175mm) {\hbox to 70mm{% 544 \hrulefill\hspace{8mm} 545 \def\firstchar##1##2\relax{##1##2} % ducon 546 \href{http://www.inria.fr/recherche/equipes/listes/theme% 547 _\firstchar#1\relax.en.html}{THEME \uppercase{#1}}% 548 \hspace{8mm}\hrulefill}}}
549 \def\foinria{% 550 \ra@atxy(7.8cm,2.5cm){\includegraphics[width=5.7cm]{Logo-INRIA-couleur}}% 551 \ra@atxy(55mm,173mm){\includegraphics{LogoRA\ra@year}}% 552 \setbox0\hbox to 14cm{% 553 \noindent\hskip3cm\hfill 554 {\fontencoding{T1}\fontfamily{ptm}\fontseries{m}% 555 \fontshape{n}\fontsize{10pt}{12pt}\selectfont 556 \href{http://www.inria.fr}{INSTITUT NATIONAL DE RECHERCHE EN % 557 INFORMATIQUE ET EN AUTOMATIQUE}}% 558 \hskip-5cm\hfill}% 559 \null\vskip0.7cm \leavevmode\hskip-3.5cm\box0\null\vskip2cm\vfil}
This is a hack: we just want \cleardoublepage. This is not used anymore.
560 \XMLelement{cleardoublepage} 561 {} {\cleardoublepage} {}
This is a hack: we want a rule below the page headings. We found no other way. This is not used anymore.
562 \XMLelement{pagestylehrule} 563 {} {\hbox to0pt{\rule[-1ex]{\textwidth}{.03cm}\hss}} {}
For the HTML version of the Raweb, we convert all math formulas into images. The idea is to construct an XML file that contains a <formula> for each object to convert. This file is translated by TeX into a dvi file, containing one formula per page; after that the dvi is converted to PostScript then png, or some other image format recognized by HTML.
A non trivial problem is the size of the image. When TeX translates the formula, it creates a box, and prints the dimension of the box on the transcript file. We want the baseline of the image to be aligned with the baseline of the text, but HTML provides only `center´ or `bottom´ as alignment options; for this reason, if the alignment cannot be `bottom´, said otherwise, if the depth of the box is non-zero, we add some blank space so that the height and depth will be the same. If two much space is added, this is not a good thing to do.
Assume that x is (a bit more than) the maximum of the height and depth of \sizebox. We modify the height and depth to be x; we insert a vertical invisible rule of height x and depth x. This code is not used any more.
\def\@centerinlinemath{% \dimen1=\ifdim\ht\sizebox<\dp\sizebox \dp\sizebox\else\ht\sizebox\fi \advance\dimen1by.5pt \vrule width0pt height\dimen1 depth\dimen1 \dp\sizebox=\dimen1\ht\sizebox=\dimen1\relax}
We noticed that if the images contains a single table, it is not vertically centered. In fact, the following code
$\vcenter{\vrule height 0pt depth5pt width2pt}$
produces a box of height 5pt, and depth 0pt (for details, see TeXbook, appendix G, rule 8: the distance between the center of the box and the baseline is parameter of the current math font). In fact, the \vcenter command is designed for math mode only, and the the distance between the center of the box and the math axis is zero.
In a first version, we used the `E´ option of dvips; this produces a set of PostScript files, one for each formula, with the correct bounding box. This bounding box is computed by dvips, according to characters and rules of the dvi file. If the TeX file contains a \special command that asks a PostScript interpreter to draw a circle of radius R, and an empty box that has the size of the circle, followed by some text, then you will see the circle followed by the text when viewing the PostScript file; but dvips is not a PostScript interpreter and has no idea of the size of the circle.
We solve this problem by adding two rules, one at the left of the image and one below. If everything works correctly, conversion from PostScript to png will remove them, but this is not always the case. The code is taken from latex2html, it has a strange feature. In the case of overflow, only the vertical rule is added. This is the code that adds rules to the box in \sizebox.
\hbox{\vrule width1pt\kern-.5pt\vtop{\vbox{% \kern1pt\kern0.6 pt\hbox{\hglue1.7pt\copy\sizebox\hglue0.6 pt}}\kern.3pt% \ifdim\dp\sizebox>0pt\kern1pt\fi \kern0.6 pt% \ifdim\hsize>\wd\sizebox \hrule depth1pt\fi}}% \ifdim\ht\sizebox<\vsize \ifdim\wd\sizebox<\hsize\hfill\fi \vfill \else\vss\fi
Assume that (x,y) is the position of the upper left corner of the image, (X,Y) are the dimensions of the image. If ϵ is the width of the rule plus the distance to the image, then the bounding box of the page will be , , y, . These quantities can be computed by dvips; it is then obvious to remove the two rules.
We now use a different method. The bounding box is not computed anymore by dvips; we call an external program with the parameters x, y, X and Y. This program has a comment that says: should (x,y) be (78,72) or (72,72) ? but it uses (62,41); if pstoimg is unavailable, then convert is used with (64, 44). Remember that TeX puts its origin at 1in (this is 72pt) from the upper left corner, but we have no idea what the current margins could be. If we ask TeX what it puts on the dvi, we see that the main vertical box contains 16pt of glue, and a box shifted by 62pt, this one starts with a header, then 25pt of glue. After that we see a vbox containing some kerns: -25pt, -16pt, -12pt, and two kerns with sum 0, and absolute value 72.27pt. We also noticed that the message Underfull \hbox (badness 10000) has occurred while \output is active [][][][] printed on each page is a consequence of loading the hyperref package, that tries to put something in the header (which is empty, of course); as a consequence, we have patched the file, so that the hyperref package is not loaded in the case were we just want to convert a piece of XML into an image.
The result is cropped. This means: if Y is too big, a smaller value will be used; in particular this will remove the additional blank space added (as explained above for vertical centering). We simplified a bit the algorithm: no rules are printed, the size is no more adjusted.
There are two elements <formula> and <tree> that produce images. A formula contains a <math> element, and a tree contains a table (that defines the nodes and their layout) together with the connections. When we see a formula in a table, we simply ignore it (we typeset the math). Nothing special has to be done for math formulas, because they contain no tables, no trees (only MathML stuff).
Here we translate <formula id=A>math</formula>; the id attribute is the number of the image.
564 \XMLelement{formula} 565 {\XMLattribute{id}{\XML@formid}{none}} 566 {\formula@start} 567 {\formula@end}
The two commands \@inlinemathA and \@inlinemathZ are used to start and finish a math image; originally, they were used directly in the code of <formula>. When we evaluate a <tree>, we must change these two commands.
568 \def\formula@start{\@inlinemathA{\XML@formid}} 569 \let\formula@end\@inlinemathZ
There are two differences between a tree and a formula. To start with, we do not have a tree number, so that we invent one; in reality, the tree number is irrelevant. The second difference is that nodes in a tree can be connected by non-straight lines; as a consequence the size needed by the tree is bigger than the size of the table. We allow a kern at the left of the table and below the table.
570 \XMLelement{tree} 571 {\XMLattribute{hpos}{\XML@hpos}{0pt} 572 \XMLattribute{vpos}{\XML@vpos}{0pt} 573 } 574 { 575 \stepcounter{treecounter} 576 \let\formula@start\relax 577 \let\formula@end\relax 578 \startdimen=\XML@hpos 579 \enddimen=\XML@vpos 580 \@inlinemathA{\thetreecounter}} 581 {\@inlinemathZ}
It may happen that space must be added around the object. Currently, we need space on the left and bottom, thus we declare these two variables. Since assignment is local, there is no need to reset them.
582 \newdimen\startdimen 583 \newdimen\enddimen
For some strange reasons, the fotex.sty file says that eps files should be included by converting them into pdf; this works for pdfTeX, but not for LaTeX. We make sure here that this rule is never applied.
584 \newbox\sizebox 585 \AtBeginDocument{ 586 \@namedef{Gin@rule@.eps}#1{{eps}{.eps}{#1}}
We redefine \normalsize, in the same way as latex2html. This is really, really, strange.
587 \let\realnormalsize=\relax 588 \def\adjustnormalsize{% 589 \def\normalsize{\mathsurround=0pt \realnormalsize 590 \parindent=0pt\abovedisplayskip=0pt\belowdisplayskip=0pt}% 591 \def\phantompar{\csname par\endcsname}% 592 \normalsize}}
The action at the start of a formula is the following: we remember the id somewhere, we start a new page, and we construct a box; this box will start with a strut and some space.
593 \def\@inlinemathA#1{% 594 \xdef\@mathenv{#1}% 595 \adjustnormalsize \newpage\clearpage 596 \setbox\sizebox=\hbox\bgroup 597 \vrule height1.5ex width0pt 598 \kern\startdimen }
This is done at the end. The action is the following: we terminate the box, we modify the depth of the box in the case additional vertical space is needed, and print the dimensions on the log file. We insert the box on the current page and start a new one.
599 \def\@inlinemathZ{% 600 \egroup 601 \ifdim\enddimen>0pt 602 \dimen1=\dp\sizebox\advance\dimen1by \enddimen\dp\sizebox=\dimen1 603 \fi 604 \typeout{l2hSize % 605 :\@mathenv:\the\ht\sizebox::\the\dp\sizebox::\the\wd\sizebox.} 606 \box\sizebox 607 \clearpage 608 }
A tree is defined by a set of nodes, together with connections. The elements here are handled by the tree-dvips package, using commands described in part I of this report. All elements, except <node> have an empty content. Translation of element <foo> is in general \foo, with arguments depending on the attributes.
The content of a <node> is typeset normally, it has an a name attribute, that identifies it uniquely (On each page in the PostScript file, there is a unique node with a given name).
609 \XMLelement{node} 610 {\XMLattribute{name}{\XML@name}{somename}} 611 {\xmlgrab} 612 {\node{\XML@name}{#1}}
A <nodepoint> element has a name, and two optional attributes xpos, ypos.
613 \XMLelement{nodepoint} 614 {\XMLattribute{name}{\XML@name}{somenode} 615 \XMLattribute{xpos}{\XML@xpos}{0pt} 616 \XMLattribute{ypos}{\XML@ypos}{0pt}} 617 {\xmlgrab} 618 {\nodepoint{\XMl@name}[\XML@xpos][\XML@ypos]}
A <nodebox> element has a nameA attribute. The effect is to add a frame around the node defined by the name.
619 \XMLelement{nodebox} 620 {\XMLattribute{nameA}{\XML@nameA}{somenode} 621 } 622 {\xmlgrab} 623 {\nodebox{\XML@nameA}}
A <nodeoval> element has a nameA attribute. The effect is to put an oval around the node defined by the name.
624 \XMLelement{nodeoval} 625 {\XMLattribute{nameA}{\XML@nameA}{somenode} 626 } 627 {\xmlgrab} 628 {\nodeoval{\XML@nameA}}
A <nodecircle> element has a nameA attribute. The effect is to put an circle around the node defined by the name. There is another attribute depth that specifies a parameter of the circle.
629 \XMLelement{nodecircle} 630 {\XMLattribute{nameA}{\XML@nameA}{somenode} 631 \XMLattribute{depth}{\XML@depth}{0pt} 632 } 633 {\xmlgrab} 634 {\nodecircle[\XML@depth]{\XML@nameA}}
A <nodetriangle> element has two names, nameA and nameB. The effect is to insert a triangle between the nodes defined by the names.
635 \XMLelement{nodetriangle} 636 {\XMLattribute{nameA}{\XML@nameA}{nodeA} 637 \XMLattribute{nameB}{\XML@nameB}{nodeB} 638 } 639 {\xmlgrab} 640 {\nodetriangle{\XML@nameA}{\XML@nameB}}
Both elements <nodeconnect> and <anodeconnect> have a nameA and nameB attributes; the effect is to connect the nodes defined by the names; if the first letter of the element is a, there will be an arrow. The attributes posA and posB explain the positions of the connection, it can be one of top, bottom, left, right, or a combination. For instance `br´ stands for bottom right. This is the reverse order of that chosen for pictures in section 3.3.1, but we check nothing here.
641 \XMLelement{nodeconnect} 642 {\XMLattribute{nameA}{\XML@nameA}{nodeA} 643 \XMLattribute{nameB}{\XML@nameB}{nodeB} 644 \XMLattribute{posA}{\XML@posA}{b} 645 \XMLattribute{posB}{\XML@posB}{t} 646 } 647 {\xmlgrab} 648 {\nodeconnect[\XML@posA]{\XML@nameA}[\XML@posB]{\XML@nameB}} 649 650 \XMLelement{anodeconnect} 651 {\XMLattribute{nameA}{\XML@nameA}{nodeA} 652 \XMLattribute{nameB}{\XML@nameB}{nodeB} 653 \XMLattribute{posA}{\XML@posA}{b} 654 \XMLattribute{posB}{\XML@posB}{t} 655 } 656 {\xmlgrab} 657 {\anodeconnect[\XML@posA]{\XML@nameA}[\XML@posB]{\XML@nameB}}
Both elements <barnodeconnect> and <abarnodeconnect> have a nameA and nameB attributes; the effect is to connect the nodes defined by the names; if the first letter of the element is a, there will be an arrow. The attribute depth is optional.
658 \XMLelement{barnodeconnect} 659 {\XMLattribute{nameA}{\XML@nameA}{nodeA} 660 \XMLattribute{nameB}{\XML@nameB}{nodeB} 661 \XMLattribute{depth}{\XML@depth}{5pt} 662 } 663 {\xmlgrab} 664 {\barnodeconnect[\XML@depth]{\XML@nameA}{\XML@nameB}} 665 666 \XMLelement{abarnodeconnect} 667 {\XMLattribute{nameA}{\XML@nameA}{nodeA} 668 \XMLattribute{nameB}{\XML@nameB}{nodeB} 669 \XMLattribute{depth}{\XML@depth}{5pt} 670 } 671 {\xmlgrab} 672 {\abarnodeconnect[\XML@depth]{\XML@nameA}{\XML@nameB}}
Both elements <nodecurve> and <anodecurve> have a nameA and nameB attributes; the effect is to connect the nodes defined by the names; if the first letter of the element is a, there will be an arrow. The attributes depthA and depthB are optional.
673 \XMLelement{nodecurve} 674 {\XMLattribute{nameA}{\XML@nameA}{nodeA} 675 \XMLattribute{nameB}{\XML@nameB}{nodeB} 676 \XMLattribute{posA}{\XML@posA}{b} 677 \XMLattribute{posB}{\XML@posB}{t} 678 \XMLattribute{depthA}{\XML@depthA}{5pt} 679 \XMLattribute{depthB}{\XML@depthB}{5pt} 680 } 681 {\xmlgrab} 682 {\nodecurve[\XML@posA]{\XML@nameA}[\XML@posB]{\XML@nameB}{\XML@depthA}[\XML@depthB]} 683 684 \XMLelement{anodecurve} 685 {\XMLattribute{nameA}{\XML@nameA}{nodeA} 686 \XMLattribute{nameB}{\XML@nameB}{nodeB} 687 \XMLattribute{posA}{\XML@posA}{b} 688 \XMLattribute{posB}{\XML@posB}{t} 689 \XMLattribute{depthA}{\XML@depthA}{5pt} 690 \XMLattribute{depthB}{\XML@depthB}{5pt} 691 } 692 {\xmlgrab} 693 {\anodecurve[\XML@posA]{\XML@nameA}[\XML@posB]{\XML@nameB}{\XML@depthA}[\XML@depthB]}
We use the same method for normal tables as for math table, said otherwise, we read everything, construct the code, and finally evaluate it. This piece of code is only used for trees, so that we assume that cells have no borders. We could handle all attributes.
A <table> has a unique attribute vpos, currently unused.
694 \XMLelement{table} 695 {\XMLattribute{vpos}{\XML@vpos}{b}} 696 {\xmlgrab } 697 {\jg@start@table#1\jg@end@table }
A <row> can have lots of attributes, but we consider only one; it defines the vertical space after the current row.
698 \XMLelement{row} 699 {\XMLattribute{spaceafter}{\XML@spaceafter}{0pt}} 700 {\xmlgrab } 701 {\jg@start@tr#1}
Attributes right-border, left-border, halign and rows are declared for a <cell>, but only cols is used (this is the number of effective columns spanned by the cell).
702 \XMLelement{cell} 703 {\XMLattribute{cols}{\XML@cols}{1} 704 \XMLattribute{rows}{\XML@rows}{1} 705 \XMLattribute{halign}{\XML@halign}{center} 706 \XMLattribute{right-border}{\XML@rightborder}{false} 707 \XMLattribute{left-border}{\XML@leftborder}{false} 708 } 709 {\xmlgrab} 710 {\jg@start@td{#1}}
Action when we start a table. We kill the two token lists, and say that we are at the start of the table. For our application, we need a lot of space between rows, so that \arraystretch is redefined to some value; an intermediate macro is used, it can be redefined, for instance at begin-document, by a config file. The redefinition is local.
711 \def\@myarraystretch{1.7}% 712 \newcounter{localcolcounter} 713 \newcounter{globalcolcounter} 714 715 \newcommand\jg@start@table{% 716 \let\arraystretch\@myarraystretch 717 \jg@table@toks{}% 718 \jg@row@toks{}% 719 \setcounter{globalcolcounter}{1}% 720 \StartTablextrue}
Action when we see the end of a table. Since we are at the end of the table, we know the number of columns of the last row, so that we can compute the number of columns of the table. After that, we insert the last row to the table. We insert the \begin and \end commands, then evaluate everything.
721 \newcommand\jg@end@table{% 722 \ifnum\value{localcolcounter}>\value{globalcolcounter}% 723 \setcounter{globalcolcounter}{\value{localcolcounter}}\fi 724 \merge@toks\jg@table@toks\jg@row@toks 725 \addto@hook\jg@table@toks{\end{tabular}}% 726 \edef\foo{\noexpand\begin{tabular}{*{\theglobalcolcounter}{c}}% 727 \the\jg@table@toks}% 728 \foo}
Action when we see the start of a row. We insert the content of the row token list to the table, and clear it. If this is not the first row of the table, we insert a double backslash, plus its optional argument; the current column counter is the number of columns of this row, and from this we deduce the current number of columns of the table. In any case, we compute the optional argument to be inserted at the end of the row, we say that the number of columns of this row is zero, and we are at the start of the row.
729 \newcommand\jg@start@tr{% 730 \merge@toks\jg@table@toks\jg@row@toks 731 \ifStartTablex 732 \global\StartTablexfalse 733 \else 734 \gaddto@hook\jg@table@toks{\\}% 735 \merge@cmd\jg@table@toks\Rowsep 736 \ifnum\value{localcolcounter}>\value{globalcolcounter}% 737 \setcounter{globalcolcounter}{\value{localcolcounter}}\fi 738 \fi 739 \jg@row@toks{}% 740 \ifdim\XML@spaceafter=0pt \gdef\Rowsep{}\else 741 \xdef\Rowsep{[\XML@spaceafter]}\fi 742 \setcounter{localcolcounter}{0}% 743 \global\StartRowxtrue}
Action when we see a cell (in the argument of the command). If this not the first cell of the row, we insert an ampersand character (in \tabcellsep). We increment the current column number by N, the span; if this is not one, we must use \multicolumn.
744 \newcommand\jg@start@td[1]{% 745 \ifStartRowx\global\StartRowxfalse 746 \else \gaddto@hook\jg@row@toks{\tabcellsep}\fi 747 \addtocounter{localcolcounter}{\XML@cols}% 748 \ifx\XML@mtdalign\att@mtd@left 749 \def\temp{#1\hfill{}}% 750 \else\ifx\XML@mtdalign\att@mtd@right 751 \def\temp{\hfill#1}% 752 \else \def\temp{#1}\fi\fi% 753 \ifnum\XML@cols=1 \else 754 \toks0=\expandafter{\temp}% 755 \edef\temp{\noexpand\multicolumn{\XML@cols}{c}{\the\toks0}}% 756 \fi 757 \expandafter\gaddto@hook\expandafter\jg@row@toks\expandafter{\temp}}
The <hi> element has a rend attribute that indicates how to typeset the content; we use \csname for dispatching.
758 \XMLelement{hi} 759 {\XMLattribute{rend}{\XML@rend}{rm}} 760 {\xmlgrab} 761 {\csname rend@\XML@rend\endcsname{#1}}
In order to be complete, we should implement all font commands.
762 \let\rend@it\textit 763 \let\rend@bf\textbf 764 \let\rend@rm\textrm 765 \def\rend@small#1{{\small #1}} 766 \def\rend@sub#1{\textsubscript{#1}} 767 \let\rend@sup\textsuperscriptscript
We want TeX and LaTeX to typeset properly.
768 \XMLelement{TeX} 769 {}{\TeX{}}{} 770 771 \XMLelement{LaTeX} 772 {}{\LaTeX{}}{}
We use this for producing little images.
773 \XMLelement{preview} 774 {} 775 {\begin{preview}} 776 {\end{preview}}
777 \XMLstring\att@true<>true</> 778 \XMLstring\att@false<>false</> 779 \XMLstring\jg@OverBrace<>︷</> 780 \XMLstring\jg@UnderBrace<>︸</> 781 \XMLstring\jg@OverBar<>¯</> 782 \XMLstring\jg@UnderBAr<>̲</> 783 \XMLstring\att@mtd@left<>left</> 784 \XMLstring\att@mtd@right<>right</> 785 \XMLstring\att@mtd@center<>center</> 786 \XMLstring\att@none<>none</> 787 \XMLstring\att@dzero<>0</> 788 \XMLstring\att@done<>1</> 789 \XMLstring\att@dtwo<>2</> 790 \XMLstring\att@mathml@rm<>rm</> 791 \XMLstring\att@BLOCK<>block</> 792 \XMLstring\att@PREFIX<>prefix</> 793 \XMLstring\att@EQUATION<>equation</> 794 \XMLstring\att@sub<>sub</>
Some commands must be redefined at start of document. Note: the Unicode character 3F5 is `greek unate epsilon symbol´, we translate it as ϵ, the character 3B5 `greek small letter epsilon´ is translated as ε.
795 \AtBeginDocument{ 796 \UnicodeCharacter{x332}{\jgunderline} 797 \UnicodeCharacter{x3F5}{\epsilon} 798 \UnicodeCharacter{x3B5}{\varepsilon} 799 \let\downslopeellipsis\ddots 800 \mathchardef\Rightarrow="3229 801 \let\@texttop\ra@useatxy 802 \let\XURL\relax 803 \selectlanguage{english} 804 \let\@item\jg@item 805 }
The fotex.cfg file contains the definitions of some elements. Two of them are used by the Raweb. The action associated to these elements is shown above.
806 \XMLelement{fo:RATHEME} 807 {} 808 {\xmlgrab} 809 {\foratheme{#1}} 810 811 \XMLelement{fo:INRIA} 812 {\XMLattribute{year}{\ra@@year}{2001}} 813 {} 814 {\xdef\ra@year{\ra@@year}\foinria}