Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / starmath / source / ooxmlimport.cxx
blobf0913f157078c7e37b899c330bf5dfcad63963ab
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
11 #include "ooxmlimport.hxx"
12 #include <types.hxx>
14 #include <oox/mathml/importutils.hxx>
15 #include <oox/token/namespaces.hxx>
16 #include <rtl/ustring.hxx>
17 #include <rtl/ustrbuf.hxx>
18 #include <sal/log.hxx>
20 using namespace oox::formulaimport;
23 The primary internal data structure for the formula is the text representation
24 (the SmNode tree is built from it), so read data must be converted into this format.
27 #define OPENING( token ) XML_STREAM_OPENING( token )
28 #define CLOSING( token ) XML_STREAM_CLOSING( token )
30 // TODO create IS_OPENING(), IS_CLOSING() instead of doing 'next == OPENING( next )' ?
32 SmOoxmlImport::SmOoxmlImport( oox::formulaimport::XmlStream& s )
33 : m_rStream( s )
37 OUString SmOoxmlImport::ConvertToStarMath()
39 return handleStream();
42 // "toplevel" of reading, there will be oMath (if there was oMathPara, that was
43 // up to the parent component to handle)
45 // NOT complete
46 OUString SmOoxmlImport::handleStream()
48 m_rStream.ensureOpeningTag( M_TOKEN( oMath ));
49 OUStringBuffer ret;
50 while( !m_rStream.atEnd() && m_rStream.currentToken() != CLOSING( M_TOKEN( oMath )))
52 // strictly speaking, it is not OMathArg here, but currently supported
53 // functionality is the same like OMathArg, in the future this may need improving
54 OUString item = readOMathArg( M_TOKEN( oMath ));
55 if( item.isEmpty())
56 continue;
57 if( !ret.isEmpty())
58 ret.append(" ");
59 ret.append(item);
61 m_rStream.ensureClosingTag( M_TOKEN( oMath ));
62 // Placeholders are written out as nothing (i.e. nothing inside e.g. the <e> element),
63 // which will result in "{}" in the formula text. Fix this up.
64 OUString ret2 = ret.makeStringAndClear().replaceAll( "{}", "<?>" );
65 // And as a result, empty parts of the formula that are not placeholders are written out
66 // as a single space, so fix that up too.
67 ret2 = ret2.replaceAll( "{ }", "{}" );
68 SAL_INFO( "starmath.ooxml", "Formula: " << ret2 );
69 return ret2;
72 OUString SmOoxmlImport::readOMathArg( int stoptoken )
74 OUStringBuffer ret;
75 while( !m_rStream.atEnd() && m_rStream.currentToken() != CLOSING( stoptoken ))
77 if( !ret.isEmpty())
78 ret.append(" ");
79 switch( m_rStream.currentToken())
81 case OPENING( M_TOKEN( acc )):
82 ret.append(handleAcc());
83 break;
84 case OPENING( M_TOKEN( bar )):
85 ret.append(handleBar());
86 break;
87 case OPENING( M_TOKEN( box )):
88 ret.append(handleBox());
89 break;
90 case OPENING( M_TOKEN( borderBox )):
91 ret.append(handleBorderBox());
92 break;
93 case OPENING( M_TOKEN( d )):
94 ret.append(handleD());
95 break;
96 case OPENING( M_TOKEN( eqArr )):
97 ret.append(handleEqArr());
98 break;
99 case OPENING( M_TOKEN( f )):
100 ret.append(handleF());
101 break;
102 case OPENING( M_TOKEN( func )):
103 ret.append(handleFunc());
104 break;
105 case OPENING( M_TOKEN( limLow )):
106 ret.append(handleLimLowUpp( LimLow ));
107 break;
108 case OPENING( M_TOKEN( limUpp )):
109 ret.append(handleLimLowUpp( LimUpp ));
110 break;
111 case OPENING( M_TOKEN( groupChr )):
112 ret.append(handleGroupChr());
113 break;
114 case OPENING( M_TOKEN( m )):
115 ret.append(handleM());
116 break;
117 case OPENING( M_TOKEN( nary )):
118 ret.append(handleNary());
119 break;
120 case OPENING( M_TOKEN( r )):
121 ret.append(handleR());
122 break;
123 case OPENING( M_TOKEN( rad )):
124 ret.append(handleRad());
125 break;
126 case OPENING( M_TOKEN( sPre )):
127 ret.append(handleSpre());
128 break;
129 case OPENING( M_TOKEN( sSub )):
130 ret.append(handleSsub());
131 break;
132 case OPENING( M_TOKEN( sSubSup )):
133 ret.append(handleSsubsup());
134 break;
135 case OPENING( M_TOKEN( sSup )):
136 ret.append(handleSsup());
137 break;
138 default:
139 m_rStream.handleUnexpectedTag();
140 break;
143 return ret.makeStringAndClear();
146 OUString SmOoxmlImport::readOMathArgInElement( int token )
148 m_rStream.ensureOpeningTag( token );
149 OUString ret = readOMathArg( token );
150 m_rStream.ensureClosingTag( token );
151 return ret;
154 OUString SmOoxmlImport::handleAcc()
156 m_rStream.ensureOpeningTag( M_TOKEN( acc ));
157 sal_Unicode accChr = 0x302;
158 if( XmlStream::Tag accPr = m_rStream.checkOpeningTag( M_TOKEN( accPr )))
160 if( XmlStream::Tag chr = m_rStream.checkOpeningTag( M_TOKEN( chr )))
162 accChr = chr.attribute( M_TOKEN( val ), accChr );
163 m_rStream.ensureClosingTag( M_TOKEN( chr ));
165 m_rStream.ensureClosingTag( M_TOKEN( accPr ));
167 // see aTokenTable in parse.cxx
168 OUString acc;
169 switch( accChr )
171 case MS_BAR:
172 case MS_COMBBAR:
173 acc = "bar";
174 break;
175 case MS_CHECK:
176 case MS_COMBCHECK:
177 acc = "check";
178 break;
179 case MS_ACUTE:
180 case MS_COMBACUTE:
181 acc = "acute";
182 break;
183 case MS_GRAVE:
184 case MS_COMBGRAVE:
185 acc = "grave";
186 break;
187 case MS_BREVE:
188 case MS_COMBBREVE:
189 acc = "breve";
190 break;
191 case MS_CIRCLE:
192 case MS_COMBCIRCLE:
193 acc = "circle";
194 break;
195 case MS_RIGHTARROW:
196 case MS_VEC:
197 // prefer wide variants for these 3, .docx can't seem to differentiate
198 // between e.g. 'vec' and 'widevec', if whatever the accent is above is short, this
199 // shouldn't matter, but short above a longer expression doesn't look right
200 acc = "widevec";
201 break;
202 case MS_HARPOON:
203 acc = "wideharpoon";
204 break;
205 case MS_TILDE:
206 case MS_COMBTILDE:
207 acc = "widetilde";
208 break;
209 case MS_HAT:
210 case MS_COMBHAT:
211 acc = "widehat";
212 break;
213 case MS_DOT:
214 case MS_COMBDOT:
215 acc = "dot";
216 break;
217 case MS_DDOT:
218 case MS_COMBDDOT:
219 acc = "ddot";
220 break;
221 case MS_DDDOT:
222 acc = "dddot";
223 break;
224 default:
225 acc = "acute";
226 SAL_WARN( "starmath.ooxml", "Unknown m:chr in m:acc \'" << accChr << "\'" );
227 break;
229 OUString e = readOMathArgInElement( M_TOKEN( e ));
230 m_rStream.ensureClosingTag( M_TOKEN( acc ));
231 return acc + " {" + e + "}";
234 OUString SmOoxmlImport::handleBar()
236 m_rStream.ensureOpeningTag( M_TOKEN( bar ));
237 enum pos_t { top, bot } topbot = bot;
238 if( m_rStream.checkOpeningTag( M_TOKEN( barPr )))
240 if( XmlStream::Tag pos = m_rStream.checkOpeningTag( M_TOKEN( pos )))
242 if( pos.attribute( M_TOKEN( val )) == "top" )
243 topbot = top;
244 else if( pos.attribute( M_TOKEN( val )) == "bot" )
245 topbot = bot;
246 m_rStream.ensureClosingTag( M_TOKEN( pos ));
248 m_rStream.ensureClosingTag( M_TOKEN( barPr ));
250 OUString e = readOMathArgInElement( M_TOKEN( e ));
251 m_rStream.ensureClosingTag( M_TOKEN( bar ));
252 if( topbot == top )
253 return "overline {" + e + "}";
254 else
255 return "underline {" + e + "}";
258 OUString SmOoxmlImport::handleBox()
260 // there does not seem to be functionality in LO to actually implement this
261 // (or is there), but at least read in the contents instead of ignoring them
262 m_rStream.ensureOpeningTag( M_TOKEN( box ));
263 OUString e = readOMathArgInElement( M_TOKEN( e ));
264 m_rStream.ensureClosingTag( M_TOKEN( box ));
265 return e;
269 OUString SmOoxmlImport::handleBorderBox()
271 m_rStream.ensureOpeningTag( M_TOKEN( borderBox ));
272 bool isStrikeH = false;
273 if( m_rStream.checkOpeningTag( M_TOKEN( borderBoxPr )))
275 if( XmlStream::Tag strikeH = m_rStream.checkOpeningTag( M_TOKEN( strikeH )))
277 if( strikeH.attribute( M_TOKEN( val ), false ))
278 isStrikeH = true;
279 m_rStream.ensureClosingTag( M_TOKEN( strikeH ));
281 m_rStream.ensureClosingTag( M_TOKEN( borderBoxPr ));
283 OUString e = readOMathArgInElement( M_TOKEN( e ));
284 m_rStream.ensureClosingTag( M_TOKEN( borderBox ));
285 if( isStrikeH )
286 return "overstrike {" + e + "}";
287 // LO does not seem to implement anything for handling the other cases
288 return e;
291 OUString SmOoxmlImport::handleD()
293 m_rStream.ensureOpeningTag( M_TOKEN( d ));
294 OUString opening = "(";
295 OUString closing = ")";
296 OUString separator = "|";
297 if( XmlStream::Tag dPr = m_rStream.checkOpeningTag( M_TOKEN( dPr )))
299 if( XmlStream::Tag begChr = m_rStream.checkOpeningTag( M_TOKEN( begChr )))
301 opening = begChr.attribute( M_TOKEN( val ), opening );
302 m_rStream.ensureClosingTag( M_TOKEN( begChr ));
304 if( XmlStream::Tag sepChr = m_rStream.checkOpeningTag( M_TOKEN( sepChr )))
306 separator = sepChr.attribute( M_TOKEN( val ), separator );
307 m_rStream.ensureClosingTag( M_TOKEN( sepChr ));
309 if( XmlStream::Tag endChr = m_rStream.checkOpeningTag( M_TOKEN( endChr )))
311 closing = endChr.attribute( M_TOKEN( val ), closing );
312 m_rStream.ensureClosingTag( M_TOKEN( endChr ));
314 m_rStream.ensureClosingTag( M_TOKEN( dPr ));
316 if( opening == "{" )
317 opening = "left lbrace ";
318 if( closing == "}" )
319 closing = " right rbrace";
320 if( opening == u"\u27e6" )
321 opening = "left ldbracket ";
322 if( closing == u"\u27e7" )
323 closing = " right rdbracket";
324 if( opening == "|" )
325 opening = "left lline ";
326 if( closing == "|" )
327 closing = " right rline";
328 if (opening == OUStringChar(MS_DLINE)
329 || opening == OUStringChar(MS_DVERTLINE))
330 opening = "left ldline ";
331 if (closing == OUStringChar(MS_DLINE)
332 || closing == OUStringChar(MS_DVERTLINE))
333 closing = " right rdline";
334 if (opening == OUStringChar(MS_LANGLE)
335 || opening == OUStringChar(MS_LMATHANGLE))
336 opening = "left langle ";
337 if (closing == OUStringChar(MS_RANGLE)
338 || closing == OUStringChar(MS_RMATHANGLE))
339 closing = " right rangle";
340 // use scalable brackets (the explicit "left" or "right")
341 if( opening == "(" || opening == "[" )
342 opening = "left " + opening;
343 if( closing == ")" || closing == "]" )
344 closing = " right " + closing;
345 if( separator == "|" ) // plain "|" would be actually "V" (logical or)
346 separator = " mline ";
347 if( opening.isEmpty())
348 opening = "left none ";
349 if( closing.isEmpty())
350 closing = " right none";
351 OUStringBuffer ret;
352 ret.append( opening );
353 bool first = true;
354 while( m_rStream.findTag( OPENING( M_TOKEN( e ))))
356 if( !first )
357 ret.append( separator );
358 first = false;
359 ret.append( readOMathArgInElement( M_TOKEN( e )));
361 ret.append( closing );
362 m_rStream.ensureClosingTag( M_TOKEN( d ));
363 return ret.makeStringAndClear();
366 OUString SmOoxmlImport::handleEqArr()
368 m_rStream.ensureOpeningTag( M_TOKEN( eqArr ));
369 OUStringBuffer ret;
371 { // there must be at least one m:e
372 if( !ret.isEmpty())
373 ret.append("#");
374 ret.append(" ");
375 ret.append(readOMathArgInElement( M_TOKEN( e )));
376 ret.append(" ");
377 } while( !m_rStream.atEnd() && m_rStream.findTag( OPENING( M_TOKEN( e ))));
378 m_rStream.ensureClosingTag( M_TOKEN( eqArr ));
379 return "stack {" + ret.makeStringAndClear() + "}";
382 OUString SmOoxmlImport::handleF()
384 m_rStream.ensureOpeningTag( M_TOKEN( f ));
385 enum operation_t { bar, lin, noBar } operation = bar;
386 if( m_rStream.checkOpeningTag( M_TOKEN( fPr )))
388 if( XmlStream::Tag type = m_rStream.checkOpeningTag( M_TOKEN( type )))
390 if( type.attribute( M_TOKEN( val )) == "bar" )
391 operation = bar;
392 else if( type.attribute( M_TOKEN( val )) == "lin" )
393 operation = lin;
394 else if( type.attribute( M_TOKEN( val )) == "noBar" )
395 operation = noBar;
396 m_rStream.ensureClosingTag( M_TOKEN( type ));
398 m_rStream.ensureClosingTag( M_TOKEN( fPr ));
400 OUString num = readOMathArgInElement( M_TOKEN( num ));
401 OUString den = readOMathArgInElement( M_TOKEN( den ));
402 m_rStream.ensureClosingTag( M_TOKEN( f ));
403 if( operation == bar )
404 return "{" + num + "} over {" + den + "}";
405 else if( operation == lin )
406 return "{" + num + "} / {" + den + "}";
407 else // noBar
409 return "binom {" + num + "} {" + den + "}";
413 OUString SmOoxmlImport::handleFunc()
415 //lim from{x rightarrow 1} x
416 m_rStream.ensureOpeningTag( M_TOKEN( func ));
417 OUString fname = readOMathArgInElement( M_TOKEN( fName ));
418 // fix the various functions
419 if( fname.startsWith( "lim csub {" ))
420 fname = "lim from {" + fname.copy( 10 );
421 OUString ret = fname + " {" + readOMathArgInElement( M_TOKEN( e )) + "}";
422 m_rStream.ensureClosingTag( M_TOKEN( func ));
423 return ret;
426 OUString SmOoxmlImport::handleLimLowUpp( LimLowUpp_t limlowupp )
428 int token = limlowupp == LimLow ? M_TOKEN( limLow ) : M_TOKEN( limUpp );
429 m_rStream.ensureOpeningTag( token );
430 OUString e = readOMathArgInElement( M_TOKEN( e ));
431 OUString lim = readOMathArgInElement( M_TOKEN( lim ));
432 m_rStream.ensureClosingTag( token );
433 // fix up overbrace/underbrace (use { }, as {} will be converted to a placeholder)
434 if( limlowupp == LimUpp && e.endsWith( " overbrace { }" ))
435 return e.copy( 0, e.getLength() - 2 ) + lim + "}";
436 if( limlowupp == LimLow && e.endsWith( " underbrace { }" ))
437 return e.copy( 0, e.getLength() - 2 ) + lim + "}";
438 return e
439 + ( limlowupp == LimLow ? OUStringLiteral( " csub {" ) : OUStringLiteral( " csup {" ))
440 + lim + "}";
443 OUString SmOoxmlImport::handleGroupChr()
445 m_rStream.ensureOpeningTag( M_TOKEN( groupChr ));
446 sal_Unicode chr = 0x23df;
447 enum pos_t { top, bot } pos = bot;
448 if( m_rStream.checkOpeningTag( M_TOKEN( groupChrPr )))
450 if( XmlStream::Tag chrTag = m_rStream.checkOpeningTag( M_TOKEN( chr )))
452 chr = chrTag.attribute( M_TOKEN( val ), chr );
453 m_rStream.ensureClosingTag( M_TOKEN( chr ));
455 if( XmlStream::Tag posTag = m_rStream.checkOpeningTag( M_TOKEN( pos )))
457 if( posTag.attribute( M_TOKEN( val ), OUString( "bot" )) == "top" )
458 pos = top;
459 m_rStream.ensureClosingTag( M_TOKEN( pos ));
461 m_rStream.ensureClosingTag( M_TOKEN( groupChrPr ));
463 OUString e = readOMathArgInElement( M_TOKEN( e ));
464 m_rStream.ensureClosingTag( M_TOKEN( groupChr ));
465 if( pos == top && chr == u'\x23de')
466 return "{" + e + "} overbrace { }";
467 if( pos == bot && chr == u'\x23df')
468 return "{" + e + "} underbrace { }";
469 if( pos == top )
470 return "{" + e + "} csup {" + OUStringChar( chr ) + "}";
471 else
472 return "{" + e + "} csub {" + OUStringChar( chr ) + "}";
475 OUString SmOoxmlImport::handleM()
477 m_rStream.ensureOpeningTag( M_TOKEN( m ));
478 OUStringBuffer allrows;
479 do // there must be at least one m:mr
481 m_rStream.ensureOpeningTag( M_TOKEN( mr ));
482 OUStringBuffer row;
483 do // there must be at least one m:e
485 if( !row.isEmpty())
486 row.append(" # ");
487 row.append(readOMathArgInElement( M_TOKEN( e )));
488 } while( !m_rStream.atEnd() && m_rStream.findTag( OPENING( M_TOKEN( e ))));
489 if( !allrows.isEmpty())
490 allrows.append(" ## ");
491 allrows.append(row);
492 m_rStream.ensureClosingTag( M_TOKEN( mr ));
493 } while( !m_rStream.atEnd() && m_rStream.findTag( OPENING( M_TOKEN( mr ))));
494 m_rStream.ensureClosingTag( M_TOKEN( m ));
495 return "matrix {" + allrows.makeStringAndClear() + "}";
498 OUString SmOoxmlImport::handleNary()
500 m_rStream.ensureOpeningTag( M_TOKEN( nary ));
501 sal_Unicode chr = 0x222b;
502 bool subHide = false;
503 bool supHide = false;
504 if( m_rStream.checkOpeningTag( M_TOKEN( naryPr )))
506 if( XmlStream::Tag chrTag = m_rStream.checkOpeningTag( M_TOKEN( chr )))
508 chr = chrTag.attribute( M_TOKEN( val ), chr );
509 m_rStream.ensureClosingTag( M_TOKEN( chr ));
511 if( XmlStream::Tag subHideTag = m_rStream.checkOpeningTag( M_TOKEN( subHide )))
513 subHide = subHideTag.attribute( M_TOKEN( val ), subHide );
514 m_rStream.ensureClosingTag( M_TOKEN( subHide ));
516 if( XmlStream::Tag supHideTag = m_rStream.checkOpeningTag( M_TOKEN( supHide )))
518 supHide = supHideTag.attribute( M_TOKEN( val ), supHide );
519 m_rStream.ensureClosingTag( M_TOKEN( supHide ));
521 m_rStream.ensureClosingTag( M_TOKEN( naryPr ));
523 OUString sub = readOMathArgInElement( M_TOKEN( sub ));
524 OUString sup = readOMathArgInElement( M_TOKEN( sup ));
525 OUString e = readOMathArgInElement( M_TOKEN( e ));
526 OUString ret;
527 switch( chr )
529 case MS_INT:
530 ret = "int";
531 break;
532 case MS_IINT:
533 ret = "iint";
534 break;
535 case MS_IIINT:
536 ret = "iiint";
537 break;
538 case MS_LINT:
539 ret = "lint";
540 break;
541 case MS_LLINT:
542 ret = "llint";
543 break;
544 case MS_LLLINT:
545 ret = "lllint";
546 break;
547 case MS_PROD:
548 ret = "prod";
549 break;
550 case MS_COPROD:
551 ret = "coprod";
552 break;
553 case MS_SUM:
554 ret = "sum";
555 break;
556 default:
557 SAL_WARN( "starmath.ooxml", "Unknown m:nary chr \'" << chr << "\'" );
558 break;
560 if( !subHide )
561 ret += " from {" + sub + "}";
562 if( !supHide )
563 ret += " to {" + sup + "}";
564 ret += " {" + e + "}";
565 m_rStream.ensureClosingTag( M_TOKEN( nary ));
566 return ret;
569 // NOT complete
570 OUString SmOoxmlImport::handleR()
572 m_rStream.ensureOpeningTag( M_TOKEN( r ));
573 bool normal = false;
574 bool literal = false;
575 if( XmlStream::Tag rPr = m_rStream.checkOpeningTag( M_TOKEN( rPr )))
577 if( XmlStream::Tag litTag = m_rStream.checkOpeningTag( M_TOKEN( lit )))
579 literal = litTag.attribute( M_TOKEN( val ), true );
580 m_rStream.ensureClosingTag( M_TOKEN( lit ));
582 if( XmlStream::Tag norTag = m_rStream.checkOpeningTag( M_TOKEN( nor )))
584 normal = norTag.attribute( M_TOKEN( val ), true );
585 m_rStream.ensureClosingTag( M_TOKEN( nor ));
587 m_rStream.ensureClosingTag( M_TOKEN( rPr ));
589 OUStringBuffer text;
590 while( !m_rStream.atEnd() && m_rStream.currentToken() != CLOSING( m_rStream.currentToken()))
592 switch( m_rStream.currentToken())
594 case OPENING( M_TOKEN( t )):
596 XmlStream::Tag rtag = m_rStream.ensureOpeningTag( M_TOKEN( t ));
597 if( rtag.attribute( OOX_TOKEN( xml, space )) != "preserve" )
598 text.append(rtag.text.trim());
599 else
600 text.append(rtag.text);
601 m_rStream.ensureClosingTag( M_TOKEN( t ));
602 break;
604 default:
605 m_rStream.handleUnexpectedTag();
606 break;
609 m_rStream.ensureClosingTag( M_TOKEN( r ));
610 if( normal || literal )
612 text.insert(0, "\"");
613 text.append("\"");
615 return text.makeStringAndClear().replaceAll("{", "\\{").replaceAll("}", "\\}");
618 OUString SmOoxmlImport::handleRad()
620 m_rStream.ensureOpeningTag( M_TOKEN( rad ));
621 bool degHide = false;
622 if( m_rStream.checkOpeningTag( M_TOKEN( radPr )))
624 if( XmlStream::Tag degHideTag = m_rStream.checkOpeningTag( M_TOKEN( degHide )))
626 degHide = degHideTag.attribute( M_TOKEN( val ), degHide );
627 m_rStream.ensureClosingTag( M_TOKEN( degHide ));
629 m_rStream.ensureClosingTag( M_TOKEN( radPr ));
631 OUString deg = readOMathArgInElement( M_TOKEN( deg ));
632 OUString e = readOMathArgInElement( M_TOKEN( e ));
633 m_rStream.ensureClosingTag( M_TOKEN( rad ));
634 if( degHide )
635 return "sqrt {" + e + "}";
636 else
637 return "nroot {" + deg + "} {" + e + "}";
640 OUString SmOoxmlImport::handleSpre()
642 m_rStream.ensureOpeningTag( M_TOKEN( sPre ));
643 OUString sub = readOMathArgInElement( M_TOKEN( sub ));
644 OUString sup = readOMathArgInElement( M_TOKEN( sup ));
645 OUString e = readOMathArgInElement( M_TOKEN( e ));
646 m_rStream.ensureClosingTag( M_TOKEN( sPre ));
647 return "{" + e + "} lsub {" + sub + "} lsup {" + sup + "}";
650 OUString SmOoxmlImport::handleSsub()
652 m_rStream.ensureOpeningTag( M_TOKEN( sSub ));
653 OUString e = readOMathArgInElement( M_TOKEN( e ));
654 OUString sub = readOMathArgInElement( M_TOKEN( sub ));
655 m_rStream.ensureClosingTag( M_TOKEN( sSub ));
656 return "{" + e + "} rsub {" + sub + "}";
659 OUString SmOoxmlImport::handleSsubsup()
661 m_rStream.ensureOpeningTag( M_TOKEN( sSubSup ));
662 OUString e = readOMathArgInElement( M_TOKEN( e ));
663 OUString sub = readOMathArgInElement( M_TOKEN( sub ));
664 OUString sup = readOMathArgInElement( M_TOKEN( sup ));
665 m_rStream.ensureClosingTag( M_TOKEN( sSubSup ));
666 return "{" + e + "} rsub {" + sub + "} rsup {" + sup + "}";
669 OUString SmOoxmlImport::handleSsup()
671 m_rStream.ensureOpeningTag( M_TOKEN( sSup ));
672 OUString e = readOMathArgInElement( M_TOKEN( e ));
673 OUString sup = readOMathArgInElement( M_TOKEN( sup ));
674 m_rStream.ensureClosingTag( M_TOKEN( sSup ));
675 return "{" + e + "} ^ {" + sup + "}";
678 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */