Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * Version: MPL 1.1 / GPLv3+ / LGPLv3+
4 : : *
5 : : * The contents of this file are subject to the Mozilla Public License Version
6 : : * 1.1 (the "License"); you may not use this file except in compliance with
7 : : * the License or as specified alternatively below. You may obtain a copy of
8 : : * the License at http://www.mozilla.org/MPL/
9 : : *
10 : : * Software distributed under the License is distributed on an "AS IS" basis,
11 : : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : : * for the specific language governing rights and limitations under the
13 : : * License.
14 : : *
15 : : * Major Contributor(s):
16 : : * Copyright (C) 2011 Lubos Lunak <l.lunak@suse.cz> (initial developer)
17 : : *
18 : : * All Rights Reserved.
19 : : *
20 : : * For minor contributions see the git repository.
21 : : *
22 : : * Alternatively, the contents of this file may be used under the terms of
23 : : * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
24 : : * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
25 : : * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
26 : : * instead of those above.
27 : : */
28 : :
29 : :
30 : : #include "ooxmlimport.hxx"
31 : :
32 : : #include <oox/token/tokens.hxx>
33 : : #include <oox/token/namespaces.hxx>
34 : : #include <rtl/oustringostreaminserter.hxx>
35 : :
36 : : using namespace oox;
37 : : using namespace oox::formulaimport;
38 : :
39 : : /*
40 : : The primary internal data structure for the formula is the text representation
41 : : (the SmNode tree is built from it), so read data must be converted into this format.
42 : : */
43 : :
44 : : #define M_TOKEN( token ) OOX_TOKEN( officeMath, token )
45 : : #define OPENING( token ) XML_STREAM_OPENING( token )
46 : : #define CLOSING( token ) XML_STREAM_CLOSING( token )
47 : :
48 : : // TODO create IS_OPENING(), IS_CLOSING() instead of doing 'next == OPENING( next )' ?
49 : :
50 : 426 : SmOoxmlImport::SmOoxmlImport( oox::formulaimport::XmlStream& s )
51 : 426 : : stream( s )
52 : : {
53 : 426 : }
54 : :
55 : 426 : OUString SmOoxmlImport::ConvertToStarMath()
56 : : {
57 : 426 : return handleStream();
58 : : }
59 : :
60 : : // "toplevel" of reading, there will be oMath (if there was oMathPara, that was
61 : : // up to the parent component to handle)
62 : :
63 : : // NOT complete
64 : 426 : OUString SmOoxmlImport::handleStream()
65 : : {
66 : 426 : stream.ensureOpeningTag( M_TOKEN( oMath ));
67 : 426 : OUString ret;
68 [ + - ][ + - ]: 852 : while( !stream.atEnd() && stream.currentToken() != CLOSING( M_TOKEN( oMath )))
[ + - ][ + + ]
[ + + ]
69 : : {
70 : : // strictly speaking, it is not OMathArg here, but currently supported
71 : : // functionality is the same like OMathArg, in the future this may need improving
72 [ + - ]: 426 : OUString item = readOMathArg();
73 [ - + ]: 426 : if( item.isEmpty())
74 : 0 : continue;
75 [ - + ]: 426 : if( !ret.isEmpty())
76 : 0 : ret += " ";
77 [ + - ]: 852 : ret += item;
78 : 426 : }
79 [ + - ]: 426 : stream.ensureClosingTag( M_TOKEN( oMath ));
80 : : // Placeholders are written out as nothing (i.e. nothing inside e.g. the <e> element),
81 : : // which will result in "{}" in the formula text. Fix this up.
82 : 426 : ret = ret.replaceAll( "{}", "<?>" );
83 : : // And as a result, empty parts of the formula that are not placeholders are written out
84 : : // as a single space, so fix that up too.
85 : 426 : ret = ret.replaceAll( "{ }", "{}" );
86 : : SAL_INFO( "starmath.ooxml", "Formula: " << ret );
87 : 426 : return ret;
88 : : }
89 : :
90 : 2622 : OUString SmOoxmlImport::readOMathArg()
91 : : {
92 : 2622 : OUString ret;
93 [ + - ][ + - ]: 6660 : while( !stream.atEnd() && stream.currentToken() != CLOSING( stream.currentToken()))
[ + - ][ + - ]
[ + + ][ + + ]
94 : : {
95 [ + + ]: 4038 : if( !ret.isEmpty())
96 : 1500 : ret += " ";
97 [ + - ][ + + : 4038 : switch( stream.currentToken())
+ + + + +
+ + + + +
+ + + + +
+ + - ]
98 : : {
99 : : case OPENING( M_TOKEN( acc )):
100 [ + - ]: 144 : ret += handleAcc();
101 : 144 : break;
102 : : case OPENING( M_TOKEN( bar )):
103 [ + - ]: 12 : ret += handleBar();
104 : 12 : break;
105 : : case OPENING( M_TOKEN( box )):
106 [ + - ]: 3 : ret += handleBox();
107 : 3 : break;
108 : : case OPENING( M_TOKEN( borderBox )):
109 [ + - ]: 12 : ret += handleBorderBox();
110 : 12 : break;
111 : : case OPENING( M_TOKEN( d )):
112 [ + - ]: 261 : ret += handleD();
113 : 261 : break;
114 : : case OPENING( M_TOKEN( eqArr )):
115 [ + - ]: 30 : ret += handleEqArr();
116 : 30 : break;
117 : : case OPENING( M_TOKEN( f )):
118 [ + - ]: 204 : ret += handleF();
119 : 204 : break;
120 : : case OPENING( M_TOKEN( func )):
121 [ + - ]: 72 : ret += handleFunc();
122 : 72 : break;
123 : : case OPENING( M_TOKEN( limLow )):
124 [ + - ]: 36 : ret += handleLimLowUpp( LimLow );
125 : 36 : break;
126 : : case OPENING( M_TOKEN( limUpp )):
127 [ + - ]: 24 : ret += handleLimLowUpp( LimUpp );
128 : 24 : break;
129 : : case OPENING( M_TOKEN( groupChr )):
130 [ + - ]: 24 : ret += handleGroupChr();
131 : 24 : break;
132 : : case OPENING( M_TOKEN( m )):
133 [ + - ]: 12 : ret += handleM();
134 : 12 : break;
135 : : case OPENING( M_TOKEN( nary )):
136 [ + - ]: 72 : ret += handleNary();
137 : 72 : break;
138 : : case OPENING( M_TOKEN( r )):
139 [ + - ]: 2802 : ret += handleR();
140 : 2802 : break;
141 : : case OPENING( M_TOKEN( rad )):
142 [ + - ]: 36 : ret += handleRad();
143 : 36 : break;
144 : : case OPENING( M_TOKEN( sPre )):
145 [ + - ]: 24 : ret += handleSpre();
146 : 24 : break;
147 : : case OPENING( M_TOKEN( sSub )):
148 [ + - ]: 48 : ret += handleSsub();
149 : 48 : break;
150 : : case OPENING( M_TOKEN( sSubSup )):
151 [ + - ]: 24 : ret += handleSsubsup();
152 : 24 : break;
153 : : case OPENING( M_TOKEN( sSup )):
154 [ + - ]: 198 : ret += handleSsup();
155 : 198 : break;
156 : : default:
157 [ # # ]: 0 : stream.handleUnexpectedTag();
158 : 0 : break;
159 : : }
160 : : }
161 : 2622 : return ret;
162 : : }
163 : :
164 : 2196 : OUString SmOoxmlImport::readOMathArgInElement( int token )
165 : : {
166 : 2196 : stream.ensureOpeningTag( token );
167 : 2196 : OUString ret = readOMathArg();
168 [ + - ]: 2196 : stream.ensureClosingTag( token );
169 : 2196 : return ret;
170 : : }
171 : :
172 : 144 : OUString SmOoxmlImport::handleAcc()
173 : : {
174 [ + - ][ + - ]: 144 : stream.ensureOpeningTag( M_TOKEN( acc ));
175 : 144 : sal_Unicode accChr = 0x302;
176 [ + - ][ + - ]: 144 : if( XmlStream::Tag accPr = stream.checkOpeningTag( M_TOKEN( accPr )))
[ + - ]
177 : : {
178 [ + - ][ + - ]: 144 : if( XmlStream::Tag chr = stream.checkOpeningTag( M_TOKEN( chr )))
[ + + ]
179 : : {
180 [ + - ]: 141 : accChr = chr.attribute( M_TOKEN( val ), accChr );
181 [ + - ]: 141 : stream.ensureClosingTag( M_TOKEN( chr ));
182 [ + - ]: 144 : }
183 [ + - ]: 144 : stream.ensureClosingTag( M_TOKEN( accPr ));
184 [ + - ]: 144 : }
185 : : // see aTokenTable in parse.cxx
186 : 144 : OUString acc;
187 [ - + + + : 144 : switch( accChr )
+ + + + +
+ - - - ]
188 : : {
189 : : case MS_BAR:
190 : 0 : acc = "bar";
191 : 0 : break;
192 : : case MS_CHECK:
193 : 12 : acc = "check";
194 : 12 : break;
195 : : case MS_ACUTE:
196 : 12 : acc = "acute";
197 : 12 : break;
198 : : case MS_GRAVE:
199 : 12 : acc = "grave";
200 : 12 : break;
201 : : case MS_BREVE:
202 : 12 : acc = "breve";
203 : 12 : break;
204 : : case MS_CIRCLE:
205 : 12 : acc = "circle";
206 : 12 : break;
207 : : case MS_VEC:
208 : : // prefer wide variants for these 3, .docx can't seem to differentiate
209 : : // between e.g. 'vec' and 'widevec', if whatever the accent is above is short, this
210 : : // shouldn't matter, but short above a longer expression doesn't look right
211 : 36 : acc = "widevec";
212 : 36 : break;
213 : : case MS_TILDE:
214 : 24 : acc = "widetilde";
215 : 24 : break;
216 : : case MS_HAT:
217 : 12 : acc = "widehat";
218 : 12 : break;
219 : : case MS_DOT:
220 : 12 : acc = "dot";
221 : 12 : break;
222 : : case MS_DDOT:
223 : 0 : acc = "ddot";
224 : 0 : break;
225 : : case MS_DDDOT:
226 : 0 : acc = "dddot";
227 : 0 : break;
228 : : default:
229 : 0 : acc = "acute";
230 : : SAL_WARN( "starmath.ooxml", "Unknown m:chr in m:acc \'" << accChr << "\'" );
231 : 0 : break;
232 : : }
233 [ + - ]: 144 : OUString e = readOMathArgInElement( M_TOKEN( e ));
234 [ + - ]: 144 : stream.ensureClosingTag( M_TOKEN( acc ));
235 : 144 : return acc + " {" + e + "}";
236 : : }
237 : :
238 : 12 : OUString SmOoxmlImport::handleBar()
239 : : {
240 [ + - ][ + - ]: 12 : stream.ensureOpeningTag( M_TOKEN( bar ));
241 : 12 : enum pos_t { top, bot } topbot = bot;
242 [ + - ][ + - ]: 12 : if( stream.checkOpeningTag( M_TOKEN( barPr )))
[ + - ][ + - ]
243 : : {
244 [ + - ][ + - ]: 12 : if( XmlStream::Tag pos = stream.checkOpeningTag( M_TOKEN( pos )))
[ + + ]
245 : : {
246 [ + - ][ - + ]: 9 : if( pos.attribute( M_TOKEN( val )) == "top" )
247 : 0 : topbot = top;
248 [ + - ][ + - ]: 9 : else if( pos.attribute( M_TOKEN( val )) == "bot" )
249 : 9 : topbot = bot;
250 [ + - ]: 9 : stream.ensureClosingTag( M_TOKEN( pos ));
251 [ + - ]: 12 : }
252 [ + - ]: 12 : stream.ensureClosingTag( M_TOKEN( barPr ));
253 : : }
254 [ + - ]: 12 : OUString e = readOMathArgInElement( M_TOKEN( e ));
255 [ + - ]: 12 : stream.ensureClosingTag( M_TOKEN( bar ));
256 [ - + ]: 12 : if( topbot == top )
257 : 0 : return "overline {" + e + "}";
258 : : else
259 : 12 : return "underline {" + e + "}";
260 : : }
261 : :
262 : 3 : OUString SmOoxmlImport::handleBox()
263 : : {
264 : : // there does not seem to be functionality in LO to actually implement this
265 : : // (or is there), but at least read in the contents instead of ignoring them
266 : 3 : stream.ensureOpeningTag( M_TOKEN( box ));
267 : 3 : OUString e = readOMathArgInElement( M_TOKEN( e ));
268 [ + - ]: 3 : stream.ensureClosingTag( M_TOKEN( box ));
269 : 3 : return e;
270 : : }
271 : :
272 : :
273 : 12 : OUString SmOoxmlImport::handleBorderBox()
274 : : {
275 [ + - ][ + - ]: 12 : stream.ensureOpeningTag( M_TOKEN( borderBox ));
276 : 12 : bool isStrikeH = false;
277 [ + - ][ + - ]: 12 : if( stream.checkOpeningTag( M_TOKEN( borderBoxPr )))
[ + - ][ + - ]
278 : : {
279 [ + - ][ + - ]: 12 : if( XmlStream::Tag strikeH = stream.checkOpeningTag( M_TOKEN( strikeH )))
[ + - ]
280 : : {
281 [ + - ][ + - ]: 12 : if( strikeH.attribute( M_TOKEN( val ), false ))
282 : 12 : isStrikeH = true;
283 [ + - ]: 12 : stream.ensureClosingTag( M_TOKEN( strikeH ));
284 [ + - ]: 12 : }
285 [ + - ]: 12 : stream.ensureClosingTag( M_TOKEN( borderBoxPr ));
286 : : }
287 [ + - ]: 12 : OUString e = readOMathArgInElement( M_TOKEN( e ));
288 [ + - ]: 12 : stream.ensureClosingTag( M_TOKEN( borderBox ));
289 [ + - ]: 12 : if( isStrikeH )
290 : 12 : return "overstrike {" + e + "}";
291 : : // LO does not seem to implement anything for handling the other cases
292 : 12 : return e;
293 : : }
294 : :
295 : 261 : OUString SmOoxmlImport::handleD()
296 : : {
297 [ + - ][ + - ]: 261 : stream.ensureOpeningTag( M_TOKEN( d ));
298 : 261 : OUString opening = "(";
299 : 261 : OUString closing = ")";
300 : 261 : OUString separator = "|";
301 [ + - ][ + - ]: 261 : if( XmlStream::Tag dPr = stream.checkOpeningTag( M_TOKEN( dPr )))
[ + - ]
302 : : {
303 [ + - ][ + - ]: 261 : if( XmlStream::Tag begChr = stream.checkOpeningTag( M_TOKEN( begChr )))
[ + + ]
304 : : {
305 [ + - ]: 192 : opening = begChr.attribute( M_TOKEN( val ), opening );
306 [ + - ]: 192 : stream.ensureClosingTag( M_TOKEN( begChr ));
307 [ + - ]: 261 : }
308 [ + - ][ + - ]: 261 : if( XmlStream::Tag sepChr = stream.checkOpeningTag( M_TOKEN( sepChr )))
[ + + ]
309 : : {
310 [ + - ]: 21 : separator = sepChr.attribute( M_TOKEN( val ), separator );
311 [ + - ]: 21 : stream.ensureClosingTag( M_TOKEN( sepChr ));
312 [ + - ]: 261 : }
313 [ + - ][ + - ]: 261 : if( XmlStream::Tag endChr = stream.checkOpeningTag( M_TOKEN( endChr )))
[ + + ]
314 : : {
315 [ + - ]: 192 : closing = endChr.attribute( M_TOKEN( val ), closing );
316 [ + - ]: 192 : stream.ensureClosingTag( M_TOKEN( endChr ));
317 [ + - ]: 261 : }
318 [ + - ]: 261 : stream.ensureClosingTag( M_TOKEN( dPr ));
319 [ + - ]: 261 : }
320 [ + + ]: 261 : if( opening == "{" )
321 : 6 : opening = "left lbrace ";
322 [ - + ]: 261 : if( closing == "}" )
323 : 0 : closing = " right rbrace";
324 [ + + ]: 261 : if( opening == OUString( sal_Unicode( 0x27e6 )))
325 : 12 : opening = "left ldbracket ";
326 [ + + ]: 261 : if( closing == OUString( sal_Unicode( 0x27e7 )))
327 : 12 : closing = " right rdbracket";
328 [ + + ]: 261 : if( opening == "|" )
329 : 12 : opening = "left lline ";
330 [ + + ]: 261 : if( closing == "|" )
331 : 12 : closing = " right rline";
332 [ + + ]: 261 : if( opening == OUString( sal_Unicode( 0x2225 )))
333 : 12 : opening = "left ldline ";
334 [ + + ]: 261 : if( closing == OUString( sal_Unicode( 0x2225 )))
335 : 12 : closing = " right rdline";
336 [ + + ]: 261 : if( opening == OUString( sal_Unicode( 0x2329 )))
337 : 24 : opening = "left langle ";
338 [ + + ]: 261 : if( closing == OUString( sal_Unicode( 0x232a )))
339 : 24 : closing = " right rangle";
340 : : // use scalable brackets (the explicit "left" or "right")
341 [ + + ][ + + ]: 261 : if( opening == "(" || opening == "[" )
[ + + ]
342 : 192 : opening = "left " + opening;
343 [ + + ][ + + ]: 261 : if( closing == ")" || closing == "]" )
[ + + ]
344 : 192 : closing = " right " + closing;
345 [ + + ]: 261 : if( separator == "|" ) // plain "|" would be actually "V" (logical or)
346 : 258 : separator = " mline ";
347 [ - + ]: 261 : if( opening.isEmpty())
348 : 0 : opening = "left none ";
349 [ + + ]: 261 : if( closing.isEmpty())
350 : 6 : closing = " right none";
351 : 261 : OUStringBuffer ret;
352 [ + - ]: 261 : ret.append( opening );
353 : 261 : bool first = true;
354 [ + - ][ + + ]: 552 : while( stream.findTag( OPENING( M_TOKEN( e ))))
355 : : {
356 [ + + ]: 291 : if( !first )
357 [ + - ]: 42 : ret.append( separator );
358 : 291 : first = false;
359 [ + - ][ + - ]: 291 : ret.append( readOMathArgInElement( M_TOKEN( e )));
360 : : }
361 [ + - ]: 261 : ret.append( closing );
362 [ + - ]: 261 : stream.ensureClosingTag( M_TOKEN( d ));
363 [ + - ]: 261 : return ret.makeStringAndClear();
364 : : }
365 : :
366 : 30 : OUString SmOoxmlImport::handleEqArr()
367 : : {
368 [ + - ][ + - ]: 30 : stream.ensureOpeningTag( M_TOKEN( eqArr ));
369 : 30 : OUString ret;
370 [ + - ][ + + ]: 132 : do
[ + + ]
371 : : { // there must be at least one m:e
372 [ + + ]: 66 : if( !ret.isEmpty())
373 : 36 : ret += "#";
374 : 66 : ret += " ";
375 [ + - ]: 66 : ret += readOMathArgInElement( M_TOKEN( e ));
376 : 66 : ret += " ";
377 [ + - ][ + - ]: 132 : } while( !stream.atEnd() && stream.findTag( OPENING( M_TOKEN( e ))));
378 [ + - ]: 30 : stream.ensureClosingTag( M_TOKEN( eqArr ));
379 : 30 : return "stack {" + ret + "}";
380 : : }
381 : :
382 : 204 : OUString SmOoxmlImport::handleF()
383 : : {
384 [ + - ][ + - ]: 204 : stream.ensureOpeningTag( M_TOKEN( f ));
385 : 204 : enum operation_t { bar, lin, noBar } operation = bar;
386 [ + - ][ + - ]: 204 : if( stream.checkOpeningTag( M_TOKEN( fPr )))
[ + - ][ + + ]
387 : : {
388 [ + - ][ + - ]: 114 : if( XmlStream::Tag type = stream.checkOpeningTag( M_TOKEN( type )))
[ + + ]
389 : : {
390 [ + - ][ - + ]: 36 : if( type.attribute( M_TOKEN( val )) == "bar" )
391 : 0 : operation = bar;
392 [ + - ][ + + ]: 36 : else if( type.attribute( M_TOKEN( val )) == "lin" )
393 : 12 : operation = lin;
394 [ + - ][ + - ]: 24 : else if( type.attribute( M_TOKEN( val )) == "noBar" )
395 : 24 : operation = noBar;
396 [ + - ]: 36 : stream.ensureClosingTag( M_TOKEN( type ));
397 [ + - ]: 114 : }
398 [ + - ]: 114 : stream.ensureClosingTag( M_TOKEN( fPr ));
399 : : }
400 [ + - ]: 204 : OUString num = readOMathArgInElement( M_TOKEN( num ));
401 [ + - ]: 204 : OUString den = readOMathArgInElement( M_TOKEN( den ));
402 [ + - ]: 204 : stream.ensureClosingTag( M_TOKEN( f ));
403 [ + + ]: 204 : if( operation == bar )
404 : 168 : return "{" + num + "} over {" + den + "}";
405 [ + + ]: 36 : else if( operation == lin )
406 : 12 : return "{" + num + "} / {" + den + "}";
407 : : else // noBar
408 : : {
409 : 24 : return "binom {" + num + "} {" + den + "}";
410 : 204 : }
411 : : }
412 : :
413 : 72 : OUString SmOoxmlImport::handleFunc()
414 : : {
415 : : //lim from{x rightarrow 1} x
416 [ + - ][ + - ]: 72 : stream.ensureOpeningTag( M_TOKEN( func ));
417 [ + - ]: 72 : OUString fname = readOMathArgInElement( M_TOKEN( fName ));
418 : : // fix the various functions
419 [ + + ]: 72 : if( fname.match( "lim csub {", 0 )) // startsWith()
420 : 12 : fname = "lim from {" + fname.copy( 10 );
421 [ + - ]: 72 : OUString ret = fname + " {" + readOMathArgInElement( M_TOKEN( e )) + "}";
422 [ + - ]: 72 : stream.ensureClosingTag( M_TOKEN( func ));
423 : 72 : return ret;
424 : : }
425 : :
426 : 60 : OUString SmOoxmlImport::handleLimLowUpp( LimLowUpp_t limlowupp )
427 : : {
428 [ + + ]: 60 : int token = limlowupp == LimLow ? M_TOKEN( limLow ) : M_TOKEN( limUpp );
429 [ + - ][ + - ]: 60 : stream.ensureOpeningTag( token );
430 [ + - ]: 60 : OUString e = readOMathArgInElement( M_TOKEN( e ));
431 [ + - ]: 60 : OUString lim = readOMathArgInElement( M_TOKEN( lim ));
432 [ + - ]: 60 : stream.ensureClosingTag( token );
433 : : // fix up overbrace/underbrace (use { }, as {} will be converted to a placeholder)
434 [ + + ][ + + ]: 60 : if( limlowupp == LimUpp && e.endsWith( " overbrace { }" ))
[ + + ]
435 : 12 : return e.copy( 0, e.getLength() - 2 ) + lim + "}";
436 [ + + ][ + + ]: 48 : if( limlowupp == LimLow && e.endsWith( " underbrace { }" ))
[ + + ]
437 : 12 : return e.copy( 0, e.getLength() - 2 ) + lim + "}";
438 : : return e
439 : : + ( limlowupp == LimLow ? OUString( " csub {" ) : OUString( " csup {" ))
440 [ + + ][ + + ]: 60 : + lim + "}";
[ + + ]
441 : : }
442 : :
443 : 24 : OUString SmOoxmlImport::handleGroupChr()
444 : : {
445 [ + - ][ + - ]: 24 : stream.ensureOpeningTag( M_TOKEN( groupChr ));
446 : 24 : sal_Unicode chr = 0x23df;
447 : 24 : enum pos_t { top, bot } pos = bot;
448 [ + - ][ + - ]: 24 : if( stream.checkOpeningTag( M_TOKEN( groupChrPr )))
[ + - ][ + - ]
449 : : {
450 [ + - ][ + - ]: 24 : if( XmlStream::Tag chrTag = stream.checkOpeningTag( M_TOKEN( chr )))
[ + + ]
451 : : {
452 [ + - ]: 21 : chr = chrTag.attribute( M_TOKEN( val ), chr );
453 [ + - ]: 21 : stream.ensureClosingTag( M_TOKEN( chr ));
454 [ + - ]: 24 : }
455 [ + - ][ + - ]: 24 : if( XmlStream::Tag posTag = stream.checkOpeningTag( M_TOKEN( pos )))
[ + + ]
456 : : {
457 [ + - ][ + + ]: 21 : if( posTag.attribute( M_TOKEN( val ), OUString( "bot" )) == "top" )
458 : 12 : pos = top;
459 [ + - ]: 21 : stream.ensureClosingTag( M_TOKEN( pos ));
460 [ + - ]: 24 : }
461 [ + - ]: 24 : stream.ensureClosingTag( M_TOKEN( groupChrPr ));
462 : : }
463 [ + - ]: 24 : OUString e = readOMathArgInElement( M_TOKEN( e ));
464 [ + - ]: 24 : stream.ensureClosingTag( M_TOKEN( groupChr ));
465 [ + + ][ + - ]: 24 : if( pos == top && chr == sal_Unicode( 0x23de ))
466 : 12 : return "{" + e + "} overbrace { }";
467 [ + - ][ + - ]: 12 : if( pos == bot && chr == sal_Unicode( 0x23df ))
468 : 12 : return "{" + e + "} underbrace { }";
469 [ # # ]: 0 : if( pos == top )
470 : 0 : return "{" + e + "} csup {" + OUString( chr ) + "}";
471 : : else
472 : 24 : return "{" + e + "} csub {" + OUString( chr ) + "}";
473 : : }
474 : :
475 : 12 : OUString SmOoxmlImport::handleM()
476 : : {
477 [ + - ][ + - ]: 12 : stream.ensureOpeningTag( M_TOKEN( m ));
478 : 12 : OUString allrows;
479 [ + - ][ + + ]: 48 : do // there must be at least one m:mr
[ + + ]
480 : : {
481 [ + - ][ + - ]: 24 : stream.ensureOpeningTag( M_TOKEN( mr ));
482 : 24 : OUString row;
483 [ + - ][ + + ]: 96 : do // there must be at least one m:e
[ + + ]
484 : : {
485 [ + + ]: 48 : if( !row.isEmpty())
486 : 24 : row += " # ";
487 [ + - ]: 48 : row += readOMathArgInElement( M_TOKEN( e ));
488 [ + - ][ + - ]: 96 : } while( !stream.atEnd() && stream.findTag( OPENING( M_TOKEN( e ))));
489 [ + + ]: 24 : if( !allrows.isEmpty())
490 : 12 : allrows += " ## ";
491 : 24 : allrows += row;
492 [ + - ]: 24 : stream.ensureClosingTag( M_TOKEN( mr ));
493 [ + - ][ + - ]: 48 : } while( !stream.atEnd() && stream.findTag( OPENING( M_TOKEN( mr ))));
494 [ + - ]: 12 : stream.ensureClosingTag( M_TOKEN( m ));
495 : 12 : return "matrix {" + allrows + "}";
496 : : }
497 : :
498 : 72 : OUString SmOoxmlImport::handleNary()
499 : : {
500 [ + - ][ + - ]: 72 : stream.ensureOpeningTag( M_TOKEN( nary ));
501 : 72 : sal_Unicode chr = 0x222b;
502 : 72 : bool subHide = false;
503 : 72 : bool supHide = false;
504 [ + - ][ + - ]: 72 : if( stream.checkOpeningTag( M_TOKEN( naryPr )))
[ + - ][ + - ]
505 : : {
506 [ + - ][ + - ]: 72 : if( XmlStream::Tag chrTag = stream.checkOpeningTag( M_TOKEN( chr )))
[ + - ]
507 : : {
508 [ + - ]: 72 : chr = chrTag.attribute( M_TOKEN( val ), chr );
509 [ + - ]: 72 : stream.ensureClosingTag( M_TOKEN( chr ));
510 [ + - ]: 72 : }
511 [ + - ][ + - ]: 72 : if( XmlStream::Tag subHideTag = stream.checkOpeningTag( M_TOKEN( subHide )))
[ + + ]
512 : : {
513 [ + - ]: 12 : subHide = subHideTag.attribute( M_TOKEN( val ), subHide );
514 [ + - ]: 12 : stream.ensureClosingTag( M_TOKEN( subHide ));
515 [ + - ]: 72 : }
516 [ + - ][ + - ]: 72 : if( XmlStream::Tag supHideTag = stream.checkOpeningTag( M_TOKEN( supHide )))
[ + + ]
517 : : {
518 [ + - ]: 12 : supHide = supHideTag.attribute( M_TOKEN( val ), supHide );
519 [ + - ]: 12 : stream.ensureClosingTag( M_TOKEN( supHide ));
520 [ + - ]: 72 : }
521 [ + - ]: 72 : stream.ensureClosingTag( M_TOKEN( naryPr ));
522 : : }
523 [ + - ]: 72 : OUString sub = readOMathArgInElement( M_TOKEN( sub ));
524 [ + - ]: 72 : OUString sup = readOMathArgInElement( M_TOKEN( sup ));
525 [ + - ]: 72 : OUString e = readOMathArgInElement( M_TOKEN( e ));
526 : 72 : OUString ret;
527 [ - - - - : 72 : switch( chr )
- + + - +
- ]
528 : : {
529 : : case MS_INT:
530 : 0 : ret = "int";
531 : 0 : break;
532 : : case MS_IINT:
533 : 0 : ret = "liint";
534 : 0 : break;
535 : : case MS_IIINT:
536 : 0 : ret = "liiint";
537 : 0 : break;
538 : : case MS_LINT:
539 : 0 : ret = "lint";
540 : 0 : break;
541 : : case MS_LLINT:
542 : 0 : ret = "llint";
543 : 0 : break;
544 : : case MS_LLLINT:
545 : 12 : ret = "lllint";
546 : 12 : break;
547 : : case MS_PROD:
548 : 12 : ret = "prod";
549 : 12 : break;
550 : : case MS_COPROD:
551 : 0 : ret = "coprod";
552 : 0 : break;
553 : : case MS_SUM:
554 : 48 : ret = "sum";
555 : 48 : break;
556 : : default:
557 : : SAL_WARN( "starmath.ooxml", "Unknown m:nary chr \'" << chr << "\'" );
558 : 0 : break;
559 : : }
560 [ + + ]: 72 : if( !subHide )
561 : 60 : ret += " from {" + sub + "}";
562 [ + + ]: 72 : if( !supHide )
563 : 60 : ret += " to {" + sup + "}";
564 : 72 : ret += " {" + e + "}";
565 [ + - ]: 72 : stream.ensureClosingTag( M_TOKEN( nary ));
566 : 72 : return ret;
567 : : }
568 : :
569 : : // NOT complete
570 : 2802 : OUString SmOoxmlImport::handleR()
571 : : {
572 [ + - ][ + - ]: 2802 : stream.ensureOpeningTag( M_TOKEN( r ));
573 [ + - ][ + - ]: 2802 : if( XmlStream::Tag rPr = stream.checkOpeningTag( OOX_TOKEN( doc, rPr )))
[ + + ]
574 : : { // TODO
575 : : // stream.checkOpeningTag( OOX_TOKEN( doc, rFonts ));
576 : : // stream.ensureClosingTag( OOX_TOKEN( doc, rFonts ));
577 [ + - ]: 507 : stream.ensureClosingTag( OOX_TOKEN( doc, rPr ));
578 [ + - ]: 2802 : }
579 : 2802 : OUString text;
580 [ + - ][ + - ]: 5604 : while( !stream.atEnd() && stream.currentToken() != CLOSING( stream.currentToken()))
[ + - ][ + - ]
[ + + ][ + + ]
581 : : {
582 [ + - ][ + - ]: 2802 : switch( stream.currentToken())
583 : : {
584 : : case OPENING( M_TOKEN( t )):
585 : : {
586 [ + - ]: 2802 : XmlStream::Tag rtag = stream.ensureOpeningTag( M_TOKEN( t ));
587 [ + - ][ + + ]: 2802 : if( rtag.attribute( OOX_TOKEN( xml, space )) != "preserve" )
588 : 1800 : text += rtag.text.trim();
589 : : else
590 : 1002 : text += rtag.text;
591 [ + - ]: 2802 : stream.ensureClosingTag( M_TOKEN( t ));
592 [ + - ]: 2802 : break;
593 : : }
594 : : default:
595 [ # # ]: 0 : stream.handleUnexpectedTag();
596 : 0 : break;
597 : : }
598 : : }
599 [ + - ]: 2802 : stream.ensureClosingTag( M_TOKEN( r ));
600 : 2802 : return text.replaceAll("{", "\\{").replaceAll("}", "\\}");
601 : : }
602 : :
603 : 36 : OUString SmOoxmlImport::handleRad()
604 : : {
605 [ + - ][ + - ]: 36 : stream.ensureOpeningTag( M_TOKEN( rad ));
606 : 36 : bool degHide = false;
607 [ + - ][ + - ]: 36 : if( stream.checkOpeningTag( M_TOKEN( radPr )))
[ + - ][ + + ]
608 : : {
609 [ + - ][ + - ]: 27 : if( XmlStream::Tag degHideTag = stream.checkOpeningTag( M_TOKEN( degHide )))
[ + + ]
610 : : {
611 [ + - ]: 24 : degHide = degHideTag.attribute( M_TOKEN( val ), degHide );
612 [ + - ]: 24 : stream.ensureClosingTag( M_TOKEN( degHide ));
613 [ + - ]: 27 : }
614 [ + - ]: 27 : stream.ensureClosingTag( M_TOKEN( radPr ));
615 : : }
616 [ + - ]: 36 : OUString deg = readOMathArgInElement( M_TOKEN( deg ));
617 [ + - ]: 36 : OUString e = readOMathArgInElement( M_TOKEN( e ));
618 [ + - ]: 36 : stream.ensureClosingTag( M_TOKEN( rad ));
619 [ + + ]: 36 : if( degHide )
620 : 24 : return "sqrt {" + e + "}";
621 : : else
622 : 36 : return "nroot {" + deg + "} {" + e + "}";
623 : : }
624 : :
625 : 24 : OUString SmOoxmlImport::handleSpre()
626 : : {
627 [ + - ][ + - ]: 24 : stream.ensureOpeningTag( M_TOKEN( sPre ));
628 [ + - ]: 24 : OUString sub = readOMathArgInElement( M_TOKEN( sub ));
629 [ + - ]: 24 : OUString sup = readOMathArgInElement( M_TOKEN( sup ));
630 [ + - ]: 24 : OUString e = readOMathArgInElement( M_TOKEN( e ));
631 [ + - ]: 24 : stream.ensureClosingTag( M_TOKEN( sPre ));
632 : 24 : return "{" + e + "} lsub {" + sub + "} lsup {" + sup + "}";
633 : : }
634 : :
635 : 48 : OUString SmOoxmlImport::handleSsub()
636 : : {
637 [ + - ][ + - ]: 48 : stream.ensureOpeningTag( M_TOKEN( sSub ));
638 [ + - ]: 48 : OUString e = readOMathArgInElement( M_TOKEN( e ));
639 [ + - ]: 48 : OUString sub = readOMathArgInElement( M_TOKEN( sub ));
640 [ + - ]: 48 : stream.ensureClosingTag( M_TOKEN( sSub ));
641 : 48 : return "{" + e + "} rsub {" + sub + "}";
642 : : }
643 : :
644 : 24 : OUString SmOoxmlImport::handleSsubsup()
645 : : {
646 [ + - ][ + - ]: 24 : stream.ensureOpeningTag( M_TOKEN( sSubSup ));
647 [ + - ]: 24 : OUString e = readOMathArgInElement( M_TOKEN( e ));
648 [ + - ]: 24 : OUString sub = readOMathArgInElement( M_TOKEN( sub ));
649 [ + - ]: 24 : OUString sup = readOMathArgInElement( M_TOKEN( sup ));
650 [ + - ]: 24 : stream.ensureClosingTag( M_TOKEN( sSubSup ));
651 : 24 : return "{" + e + "} rsub {" + sub + "} rsup {" + sup + "}";
652 : : }
653 : :
654 : 198 : OUString SmOoxmlImport::handleSsup()
655 : : {
656 [ + - ][ + - ]: 198 : stream.ensureOpeningTag( M_TOKEN( sSup ));
657 [ + - ]: 198 : OUString e = readOMathArgInElement( M_TOKEN( e ));
658 [ + - ]: 198 : OUString sup = readOMathArgInElement( M_TOKEN( sup ));
659 [ + - ]: 198 : stream.ensureClosingTag( M_TOKEN( sSup ));
660 : 198 : return "{" + e + "} ^ {" + sup + "}";
661 : : }
662 : :
663 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|