00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <iostream>
00022 #include <qstring.h>
00023 #include <qfontmetrics.h>
00024
00025 #include <klocale.h>
00026 #include <kmessagebox.h>
00027
00028
00029
00030 #include "kformulamathmlread.h"
00031 #include "symboltable.h"
00032
00033 KFORMULA_NAMESPACE_BEGIN
00034 using namespace std;
00035
00036 class MathML2KFormulaPrivate
00037 {
00038 friend class MathML2KFormula;
00039
00040 public:
00041 MathML2KFormulaPrivate( MathML2KFormula* mml_filter,
00042 const ContextStyle& contextStyle,
00043 const QDomDocument& formuladoc );
00044 ~MathML2KFormulaPrivate();
00045
00046 void math( QDomElement element );
00047
00048
00049 void mi( QDomElement element, QDomNode docnode );
00050 void mn( QDomElement element, QDomNode docnode );
00051 void mo( QDomElement element, QDomNode docnode );
00052 void mtext( QDomElement element, QDomNode docnode );
00053 void mspace( QDomElement element, QDomNode docnode );
00054 void ms( QDomElement element, QDomNode docnode );
00055
00056
00057
00058 void mrow( QDomElement element, QDomNode docnode );
00059 void mfrac( QDomElement element, QDomNode docnode );
00060 void msqrt( QDomElement element, QDomNode docnode );
00061 void mroot( QDomElement element, QDomNode docnode );
00062 void mstyle( QDomElement element, QDomNode docnode );
00063
00064
00065
00066 void mfenced( QDomElement element, QDomNode docnode );
00067
00068
00069
00070 void msub_msup( QDomElement element, QDomNode docnode );
00071 void msubsup( QDomElement element, QDomNode docnode );
00072 void munder( QDomElement element, QDomNode docnode, bool oasisFormat );
00073 void mover( QDomElement element, QDomNode docnode, bool oasisFormat );
00074 void munderover( QDomElement element, QDomNode docnode, bool oasisFormat );
00075
00076
00077
00078 void mtable( QDomElement element, QDomNode docnode );
00079
00080
00081
00082
00083
00084 protected:
00085 void createTextElements( QString text, QDomNode docnode );
00086 void createNameSequence( QString text, QDomNode docnode );
00087 double convertToPoint( QString value, bool* ok );
00088 bool isEmbellishedOperator( QDomNode node, QDomElement* mo, bool oasisFormat );
00089 bool isSpaceLike( QDomNode node, bool oasisFormat );
00090
00091 enum MathVariant {
00092 normal,
00093 bold,
00094 italic,
00095 bold_italic,
00096 double_struck,
00097 bold_fraktur,
00098 script,
00099 bold_script,
00100 fraktur,
00101 sans_serif,
00102 bold_sans_serif,
00103 sans_serif_italic,
00104 sans_serif_bold_italic,
00105 monospace
00106 };
00107
00108 struct MathStyle {
00109 MathStyle()
00110 : scriptsizemultiplier( 0.71 ),
00111 scriptminsize( 8 ),
00112 veryverythinmathspace( 1.0/18.0 ),
00113 verythinmathspace( 2.0/18.0 ),
00114 thinmathspace( 3.0/18.0 ),
00115 mediummathspace( 4.0/18.0 ),
00116 thickmathspace( 5.0/18.0 ),
00117 verythickmathspace( 6.0/18.0 ),
00118 veryverythickmathspace( 7.0/18.0 ),
00119
00120 useVariant( false )
00121 {
00122 }
00123
00124 void styleChange()
00125 {
00126 kdDebug( DEBUGID ) << "Style Change:"
00127 << "\n scriptlevel = " << scriptlevel
00128 << "\n displaystyle = " << displaystyle
00129 << "\n scriptsizemultiplier = "
00130 << scriptsizemultiplier
00131 << "\n scriptminsize = " << scriptminsize
00132 << endl;
00133 }
00134
00135 void setStyles( QDomElement element )
00136 {
00137 if ( !useVariant )
00138 return;
00139
00140 switch ( mathvariant )
00141 {
00142 case normal:
00143 element.setAttribute( "STYLE", "normal" );
00144 break;
00145 case bold:
00146 element.setAttribute( "STYLE", "bold" );
00147 break;
00148
00149 case bold_italic:
00150 element.setAttribute( "STYLE", "bolditalic" );
00151 break;
00152 case italic:
00153 element.setAttribute( "STYLE", "italic" );
00154 break;
00155
00156 case double_struck:
00157 element.setAttribute( "FAMILY", "doublestruck" );
00158 break;
00159
00160 case bold_fraktur:
00161 element.setAttribute( "STYLE", "bold" );
00162 case fraktur:
00163 element.setAttribute( "FAMILY", "fraktur" );
00164 break;
00165
00166 case bold_script:
00167 element.setAttribute( "STYLE", "bold" );
00168 case script:
00169 element.setAttribute( "FAMILY", "script" );
00170 break;
00171
00172 case bold_sans_serif:
00173 element.setAttribute( "STYLE", "bold" );
00174 case sans_serif:
00175 element.setAttribute( "FAMILY", "normal" );
00176 break;
00177 case sans_serif_bold_italic:
00178 element.setAttribute( "STYLE", "bolditalic" );
00179 element.setAttribute( "FAMILY", "normal" );
00180 break;
00181 case sans_serif_italic:
00182 element.setAttribute( "STYLE", "italic" );
00183 element.setAttribute( "FAMILY", "normal" );
00184 break;
00185
00186
00187 default:
00188 break;
00189 }
00190 }
00191
00192 void readStyles( QDomElement mmlElement )
00193 {
00194 if ( mmlElement.hasAttribute( "mathvariant" ) )
00195 {
00196 useVariant = true;
00197
00198 if ( mmlElement.attribute( "mathvariant" ) == "normal" )
00199 mathvariant = normal;
00200 else if ( mmlElement.attribute( "mathvariant" ) == "bold" )
00201 mathvariant = bold;
00202 else if ( mmlElement.attribute( "mathvariant" ) == "italic" )
00203 mathvariant = italic;
00204 else if ( mmlElement.attribute( "mathvariant" ) == "bold-italic" )
00205 mathvariant = bold_italic;
00206 else if ( mmlElement.attribute( "mathvariant" ) == "double-struck" )
00207 mathvariant = double_struck;
00208 else if ( mmlElement.attribute( "mathvariant" ) == "bold-fraktur" )
00209 mathvariant = bold_fraktur;
00210 else if ( mmlElement.attribute( "mathvariant" ) == "script" )
00211 mathvariant = script;
00212 else if ( mmlElement.attribute( "mathvariant" ) == "bold-script" )
00213 mathvariant = bold_script;
00214 else if ( mmlElement.attribute( "mathvariant" ) == "fraktur" )
00215 mathvariant = fraktur;
00216 else if ( mmlElement.attribute( "mathvariant" ) == "sans-serif" )
00217 mathvariant = sans_serif;
00218 else if ( mmlElement.attribute( "mathvariant" ) == "bold-sans-serif" )
00219 mathvariant = bold_sans_serif;
00220 else if ( mmlElement.attribute( "mathvariant" ) == "sans-serif-italic" )
00221 mathvariant = sans_serif_italic;
00222 else if ( mmlElement.attribute( "mathvariant" ) == "sans-serif-bold-italic" )
00223 mathvariant = sans_serif_bold_italic;
00224 else if ( mmlElement.attribute( "mathvariant" ) == "monospace" )
00225 mathvariant = monospace;
00226 }
00227 }
00228
00229
00230
00231 int scriptlevel;
00232 bool displaystyle;
00233 double scriptsizemultiplier;
00234 double scriptminsize;
00235
00236
00237 double veryverythinmathspace;
00238 double verythinmathspace;
00239 double thinmathspace;
00240 double mediummathspace;
00241 double thickmathspace;
00242 double verythickmathspace;
00243 double veryverythickmathspace;
00244
00245
00246
00247 MathVariant mathvariant;
00248 bool useVariant;
00249
00250 };
00251
00252 MathStyle style;
00253 QDomDocument doc;
00254
00255 private:
00256 const ContextStyle& context;
00257 MathML2KFormula* filter;
00258 };
00259
00260 MathML2KFormulaPrivate::MathML2KFormulaPrivate( MathML2KFormula* mml_filter, const ContextStyle& cs, const QDomDocument& formuladoc )
00261 : doc( formuladoc ), context( cs ), filter( mml_filter )
00262 {
00263 }
00264
00265 MathML2KFormulaPrivate::~MathML2KFormulaPrivate()
00266 {
00267 }
00268
00269 void MathML2KFormulaPrivate::math( QDomElement element )
00270 {
00271 QDomElement formula = doc.createElement( "FORMULA" );
00272 QDomNode n = element.firstChild();
00273
00274 QString display = element.attribute( "display" );
00275
00276 if ( display == "block" ) {
00277 style.displaystyle = true;
00278 }
00279 else {
00280
00281 style.displaystyle = false;
00282 }
00283
00284 style.scriptlevel = 0;
00285
00286
00287
00288
00289
00290 while ( !n.isNull() ) {
00291 filter->processElement( n, doc, formula );
00292 n = n.nextSibling();
00293 }
00294
00295 doc.appendChild( formula );
00296 }
00297
00298 void MathML2KFormulaPrivate::mi( QDomElement element, QDomNode docnode )
00299 {
00300 MathStyle previousStyle( style );
00301 QString text = element.text().stripWhiteSpace();
00302 if ( text.length() == 1 ) {
00303 style.mathvariant = italic;
00304 style.useVariant = true;
00305 style.readStyles( element );
00306 createTextElements( text, docnode );
00307 } else {
00308 style.readStyles( element );
00309 createNameSequence( text, docnode );
00310 }
00311 style = previousStyle;
00312 }
00313
00314 void MathML2KFormulaPrivate::mo( QDomElement element, QDomNode docnode )
00315 {
00316 MathStyle previousStyle( style );
00317 style.readStyles( element );
00318
00319 QString text = element.text().stripWhiteSpace();
00320 createTextElements( text, docnode );
00321
00322 style = previousStyle;
00323 }
00324
00325 void MathML2KFormulaPrivate::mn( QDomElement element, QDomNode docnode )
00326 {
00327 MathStyle previousStyle( style );
00328 style.readStyles( element );
00329
00330 QString text = element.text().stripWhiteSpace();
00331 createTextElements( text, docnode );
00332
00333 style = previousStyle;
00334 }
00335
00336 void MathML2KFormulaPrivate::mtext( QDomElement element, QDomNode docnode )
00337 {
00338 MathStyle previousStyle( style );
00339 style.readStyles( element );
00340
00341 QDomNode n = element.firstChild();
00342
00343 while ( !n.isNull() ) {
00344 if ( n.isText() ) {
00345 QString text = n.toText().data().stripWhiteSpace();
00346 createTextElements( text, docnode );
00347 }
00348 else if ( n.isElement() ) {
00349 filter->processElement( n, doc, docnode );
00350 }
00351 else {
00352 kdDebug( DEBUGID ) << "<mtext> child: " << n.nodeName() << endl;
00353 }
00354
00355 n = n.nextSibling();
00356 }
00357
00358 style = previousStyle;
00359 }
00360
00361 void MathML2KFormulaPrivate::ms( QDomElement element, QDomNode docnode )
00362 {
00363 QString lquote = element.attribute( "lquote", "\"" );
00364 QString rquote = element.attribute( "rquote", "\"" );
00365 QString text;
00366
00367 text = lquote;
00368 text += element.text().stripWhiteSpace();
00369 text += rquote;
00370
00371 createTextElements( text, docnode );
00372 }
00373
00374 void MathML2KFormulaPrivate::mspace( QDomElement element, QDomNode docnode )
00375 {
00376
00377 QString width = element.attribute( "width" );
00378
00379 QDomElement spaceelement = doc.createElement( "SPACE" );
00380
00381
00382 if ( width == "veryverythinmathspace" ) {
00383 spaceelement.setAttribute( "WIDTH", "thin" );
00384 }
00385 else if ( width == "verythinmathspace" ) {
00386 spaceelement.setAttribute( "WIDTH", "thin" );
00387 }
00388 else if ( width == "thinmathspace" ) {
00389 spaceelement.setAttribute( "WIDTH", "thin" );
00390 }
00391 else if ( width == "mediummathspace" ) {
00392 spaceelement.setAttribute( "WIDTH", "medium" );
00393 }
00394 else if ( width == "thickmathspace" ) {
00395 spaceelement.setAttribute( "WIDTH", "thick" );
00396 }
00397 else if ( width == "verythickmathspace" ) {
00398 spaceelement.setAttribute( "WIDTH", "thick" );
00399 }
00400 else if ( width == "veryverythickmathspace" ) {
00401 spaceelement.setAttribute( "WIDTH", "quad" );
00402 }
00403
00404 else {
00405
00406
00407 double w = 0;
00408 bool ok;
00409
00410 if ( width.endsWith( "em" ) ) {
00411
00412 w = context.getDefaultFont().pointSize();
00413 if ( w == -1 ) {
00414 QFontMetrics fm( context.getDefaultFont() );
00415 w = fm.width( 'm' );
00416 }
00417 w = w * width.remove( width.length() - 2, 2 ).toDouble( &ok );
00418
00419 }
00420 else if ( width.endsWith( "px" ) ) {
00421 w = width.remove( width.length() - 2, 2 ).toDouble( &ok );
00422
00423 }
00424 else if ( width.endsWith( "in" ) ) {
00425 w = width.remove( width.length() - 2, 2 ).toDouble( &ok );
00426 w *= 72;
00427 }
00428 else if ( width.endsWith( "cm" ) ) {
00429 w = width.remove( width.length() - 2, 2 ).toDouble( &ok );
00430 w *= 1/2.54 * 72;
00431 }
00432 else if ( width.endsWith( "mm" ) ) {
00433 w = width.remove( width.length() - 2, 2 ).toDouble( &ok );
00434 w *= 1/25.4 * 72;
00435 }
00436 else if ( width.endsWith( "pt" ) ) {
00437 w = width.remove( width.length() - 2, 2 ).toDouble( &ok );
00438
00439 }
00440 else if ( width.endsWith( "pc" ) ) {
00441 w = width.remove( width.length() - 2, 2 ).toDouble( &ok );
00442 w /= 12;
00443 }
00444 else {
00445 w = width.toDouble( &ok );
00446 }
00447
00448 if ( !ok )
00449 return;
00450
00451 if ( w < 20 )
00452 spaceelement.setAttribute( "WIDTH", "thin" );
00453 else if ( w < 40 )
00454 spaceelement.setAttribute( "WIDTH", "medium" );
00455 else if ( w < 80 )
00456 spaceelement.setAttribute( "WIDTH", "thick" );
00457 else
00458 spaceelement.setAttribute( "WIDTH", "quad" );
00459 }
00460
00461 docnode.appendChild( spaceelement );
00462 }
00463
00464 void MathML2KFormulaPrivate::mrow( QDomElement element, QDomNode docnode )
00465 {
00466 QDomNode n = element.firstChild();
00467 while ( !n.isNull() ) {
00468 if ( n.isElement () ) {
00469 QDomElement e = n.toElement();
00470
00471 filter->processElement( e, doc, docnode );
00472 }
00473 else {
00474 kdDebug( DEBUGID ) << "<mrow> child: " << n.nodeName() << endl;
00475 }
00476 n = n.nextSibling();
00477 }
00478 }
00479
00480 void MathML2KFormulaPrivate::mfrac( QDomElement element, QDomNode docnode )
00481 {
00482 QDomNode n = element.firstChild();
00483 QDomElement fraction = doc.createElement( "FRACTION" );
00484
00485 MathStyle previousStyle( style );
00486 style.displaystyle ? style.displaystyle = false : style.scriptlevel += 1;
00487 style.styleChange();
00488
00489 int i = 0;
00490 while ( !n.isNull() && i < 2 ) {
00491 if ( n.isElement() ) {
00492 ++i;
00493 if ( i == 1 ) {
00494 QDomElement numerator =
00495 doc.createElement( "NUMERATOR" );
00496 QDomElement sequence = doc.createElement( "SEQUENCE" );
00497 numerator.appendChild( sequence );
00498 QDomElement e = n.toElement();
00499 filter->processElement( e, doc, sequence );
00500 fraction.appendChild( numerator );
00501
00502 }
00503 else {
00504 QDomElement denominator =
00505 doc.createElement( "DENOMINATOR" );
00506 QDomElement sequence = doc.createElement( "SEQUENCE" );
00507 denominator.appendChild( sequence );
00508 QDomElement e = n.toElement();
00509 filter->processElement( e, doc, sequence );
00510 fraction.appendChild( denominator );
00511
00512 }
00513 }
00514 else {
00515 kdDebug( DEBUGID ) << "<mfrac> child: " << n.nodeName() << endl;
00516 }
00517 n = n.nextSibling();
00518 }
00519
00520 style = previousStyle;
00521 docnode.appendChild( fraction );
00522 }
00523
00524 void MathML2KFormulaPrivate::mroot( QDomElement element, QDomNode docnode )
00525 {
00526 QDomNode n = element.firstChild();
00527 int i = 0;
00528 QDomElement root = doc.createElement( "ROOT" );
00529
00530 while ( !n.isNull() && i < 2 ) {
00531 if ( n.isElement() ) {
00532 ++i;
00533 if ( i == 1 ) {
00534 QDomElement content = doc.createElement( "CONTENT" );
00535 QDomElement sequence = doc.createElement( "SEQUENCE" );
00536 content.appendChild( sequence );
00537 QDomElement e = n.toElement();
00538 filter->processElement( e, doc, sequence );
00539
00540 root.appendChild(content);
00541 }
00542 else {
00543 MathStyle previousStyle( style );
00544 style.scriptlevel += 2;
00545 style.displaystyle = false;
00546 style.styleChange();
00547
00548 QDomElement index = doc.createElement( "INDEX" );
00549 QDomElement sequence = doc.createElement( "SEQUENCE" );
00550 index.appendChild( sequence );
00551 QDomElement e = n.toElement();
00552 filter->processElement( e, doc, sequence );
00553 root.appendChild( index );
00554
00555 style = previousStyle;
00556 }
00557 }
00558 else {
00559 kdDebug( DEBUGID ) << "<mroot> child: " << n.nodeName() << endl;
00560 }
00561 n = n.nextSibling();
00562 }
00563 docnode.appendChild( root );
00564 }
00565
00566 void MathML2KFormulaPrivate::msqrt( QDomElement element, QDomNode docnode )
00567 {
00568 QDomNode n = element.firstChild();
00569 QDomElement root = doc.createElement( "ROOT" );
00570
00571 QDomElement content = doc.createElement( "CONTENT" );
00572 QDomElement sequence = doc.createElement( "SEQUENCE" );
00573 content.appendChild( sequence );
00574 root.appendChild( content );
00575
00576 while ( !n.isNull() ) {
00577 if ( n.isElement() ) {
00578 filter->processElement( n.toElement(), doc, sequence );
00579 }
00580 else {
00581 kdDebug( DEBUGID ) << "<msqrt> child: " << n.nodeName() << endl;
00582 }
00583 n = n.nextSibling();
00584 }
00585
00586 docnode.appendChild( root );
00587 }
00588
00589 void MathML2KFormulaPrivate::mstyle( QDomElement element, QDomNode docnode )
00590 {
00591 bool ok;
00592
00593 MathStyle previousStyle( style );
00594 style.readStyles( element );
00595
00596 if ( element.hasAttribute( "scriptlevel" ) ) {
00597 QString scriptlevel = element.attribute( "scriptlevel" );
00598 if ( scriptlevel.startsWith( "+" ) || scriptlevel.startsWith( "-" ) )
00599 style.scriptlevel += scriptlevel.toInt( &ok );
00600 else
00601 style.scriptlevel = scriptlevel.toInt( &ok );
00602 if ( !ok )
00603 style.scriptlevel = previousStyle.scriptlevel;
00604 }
00605 if ( element.hasAttribute( "displaystyle" ) ) {
00606 QString displaystyle = element.attribute( "displaystyle" );
00607 if ( displaystyle == "true" )
00608 style.displaystyle = true;
00609 else if ( displaystyle == "false" )
00610 style.displaystyle = false;
00611 }
00612 if ( element.hasAttribute( "scriptsizemultiplier" ) ) {
00613 style.scriptsizemultiplier =
00614 element.attribute( "scriptsizemultiplier" ).toDouble( &ok );
00615 if ( !ok )
00616 style.scriptsizemultiplier = previousStyle.scriptsizemultiplier;
00617 }
00618 if ( element.hasAttribute( "scriptminsize" ) ) {
00619 QString scriptminsize = element.attribute( "scriptminsize" );
00620 style.scriptminsize = convertToPoint( scriptminsize, &ok );
00621 if ( !ok )
00622 style.scriptminsize = previousStyle.scriptminsize;
00623 }
00624
00625 if ( element.hasAttribute( "veryverythinmathspace" ) ) {
00626 QString vvthinmspace = element.attribute( "veryverythinmathspace" );
00627 style.veryverythinmathspace = convertToPoint( vvthinmspace, &ok );
00628 if ( !ok )
00629 style.veryverythinmathspace = previousStyle.veryverythinmathspace;
00630 }
00631 if ( element.hasAttribute( "verythinmathspace" ) ) {
00632 QString vthinmspace = element.attribute( "verythinmathspace" );
00633 style.verythinmathspace = convertToPoint( vthinmspace, &ok );
00634 if ( !ok )
00635 style.verythinmathspace = previousStyle.verythinmathspace;
00636 }
00637 if ( element.hasAttribute( "thinmathspace" ) ) {
00638 QString thinmathspace = element.attribute( "thinmathspace" );
00639 style.thinmathspace = convertToPoint( thinmathspace, &ok );
00640 if ( !ok )
00641 style.thinmathspace = previousStyle.thinmathspace;
00642 }
00643 if ( element.hasAttribute( "mediummathspace" ) ) {
00644 QString mediummathspace = element.attribute( "mediummathspace" );
00645 style.mediummathspace = convertToPoint( mediummathspace, &ok );
00646 if ( !ok )
00647 style.mediummathspace = previousStyle.mediummathspace;
00648 }
00649 if ( element.hasAttribute( "thickmathspace" ) ) {
00650 QString thickmathspace = element.attribute( "thickmathspace" );
00651 style.thickmathspace = convertToPoint( thickmathspace, &ok );
00652 if ( !ok )
00653 style.thickmathspace = previousStyle.thickmathspace;
00654 }
00655 if ( element.hasAttribute( "verythickmathspace" ) ) {
00656 QString vthickmspace = element.attribute( "verythickmathspace" );
00657 style.verythickmathspace = convertToPoint( vthickmspace, &ok );
00658 if ( !ok )
00659 style.verythickmathspace = previousStyle.verythickmathspace;
00660 }
00661 if ( element.hasAttribute( "veryverythickmathspace" ) ) {
00662 QString vvthickmspace = element.attribute( "veryverythickmathspace" );
00663 style.veryverythickmathspace = convertToPoint( vvthickmspace, &ok );
00664 if ( !ok )
00665 style.veryverythickmathspace =
00666 previousStyle.veryverythickmathspace;
00667 }
00668
00669 style.styleChange();
00670
00671 QDomNode n = element.firstChild();
00672 while ( !n.isNull() ) {
00673 filter->processElement( n, doc, docnode );
00674 n = n.nextSibling();
00675 }
00676
00677 style = previousStyle;
00678 }
00679
00680 void MathML2KFormulaPrivate::mfenced( QDomElement element, QDomNode docnode )
00681 {
00682 QDomElement bracket = doc.createElement( "BRACKET" );
00683 QString value = element.attribute( "open", "(" );
00684 bracket.setAttribute( "LEFT", QString::number( value.at( 0 ).latin1() ) );
00685 value = element.attribute( "close", ")" );
00686 bracket.setAttribute( "RIGHT", QString::number( value.at( 0 ).latin1() ) );
00687
00688 QDomElement content = doc.createElement( "CONTENT" );
00689 QDomElement sequence = doc.createElement( "SEQUENCE" );
00690 content.appendChild( sequence );
00691
00692 QString separators = element.attribute( "separators", "," );
00693
00694 QDomNode n = element.firstChild();
00695 uint i = 0;
00696 while ( !n.isNull() ) {
00697 if ( n.isElement() ) {
00698 if ( i != 0 && !separators.isEmpty() ) {
00699 QDomElement textelement = doc.createElement( "TEXT" );
00700 if ( i > separators.length() )
00701 i = separators.length();
00702 textelement.setAttribute( "CHAR", QString( separators.at( i - 1 ) ) );
00703
00704 sequence.appendChild( textelement );
00705 }
00706 ++i;
00707 QDomElement e = n.toElement();
00708 filter->processElement( e, doc, sequence );
00709 }
00710 else {
00711 kdDebug( DEBUGID ) << "<mfenced> child: " << n.nodeName() << endl;
00712 }
00713 n = n.nextSibling();
00714 }
00715 bracket.appendChild( content );
00716 docnode.appendChild( bracket );
00717 }
00718
00719 void MathML2KFormulaPrivate::mtable( QDomElement element, QDomNode docnode )
00720 {
00721 MathStyle previousStyle( style );
00722 QString displaystyle = element.attribute( "displaystyle", "false" );
00723 if ( displaystyle == "true" ) {
00724 style.displaystyle = true;
00725 }
00726 else {
00727
00728 style.displaystyle = false;
00729 }
00730 style.styleChange();
00731
00732 QString subtag;
00733 int rows = 0; int cols = 0;
00734 QDomNode n = element.firstChild();
00735
00736 while ( !n.isNull() ) {
00737 if ( n.isElement() ) {
00738 QDomElement e = n.toElement();
00739 subtag = e.tagName();
00740 if (subtag == "mtr")
00741 {
00742 ++rows;
00743
00744
00745
00746 QDomNode cellnode = e.firstChild();
00747 int cc = 0;
00748
00749 while ( !cellnode.isNull() ) {
00750 if ( cellnode.isElement() )
00751 cc++;
00752 cellnode = cellnode.nextSibling();
00753 }
00754
00755 if ( cc > cols )
00756 cols = cc;
00757
00758 }
00759 }
00760 else {
00761 kdDebug( DEBUGID ) << "<mtable> child: " << n.nodeName() << endl;
00762 }
00763 n = n.nextSibling();
00764 }
00765
00766
00767
00768
00769 n = element.firstChild();
00770 QDomElement matrix = doc.createElement( "MATRIX" );
00771 matrix.setAttribute( "COLUMNS", cols );
00772 matrix.setAttribute( "ROWS", rows );
00773
00774 while ( !n.isNull() ) {
00775 if ( n.isElement() ) {
00776 QDomElement e = n.toElement();
00777 subtag = e.tagName();
00778 if ( subtag == "mtr" ) {
00779 QDomNode cellnode = e.firstChild();
00780 int cc = 0;
00781 while ( !cellnode.isNull() ) {
00782 if ( cellnode.isElement() ) {
00783 ++cc;
00784 QDomElement cell = doc.createElement( "SEQUENCE" );
00785 QDomElement cellelement = cellnode.toElement();
00786 filter->processElement( cellelement, doc, cell );
00787 matrix.appendChild( cell );
00788 }
00789 cellnode = cellnode.nextSibling();
00790 }
00791
00792
00793 for(; cc < cols; cc++ ) {
00794 QDomElement cell = doc.createElement( "SEQUENCE" );
00795 matrix.appendChild( cell );
00796 }
00797 }
00798 }
00799 n = n.nextSibling();
00800 }
00801
00802 style = previousStyle;
00803 docnode.appendChild(matrix);
00804 }
00805
00806 void MathML2KFormulaPrivate::msub_msup( QDomElement element, QDomNode docnode )
00807 {
00808 QDomNode n = element.firstChild();
00809 int i = 0;
00810 QDomElement root = doc.createElement( "INDEX" );
00811
00812 while ( !n.isNull() && i < 2 ) {
00813 if ( n.isElement() ) {
00814 ++i;
00815 if ( i == 1 ) {
00816 QDomElement content = doc.createElement( "CONTENT" );
00817 QDomElement sequence = doc.createElement( "SEQUENCE" );
00818 content.appendChild( sequence );
00819 QDomElement e = n.toElement();
00820 filter->processElement( e, doc, sequence );
00821
00822 root.appendChild( content );
00823 }
00824 else {
00825 QDomElement index;
00826 if ( element.tagName() == "msup" )
00827 index = doc.createElement( "UPPERRIGHT" );
00828 else
00829 index = doc.createElement( "LOWERRIGHT" );
00830
00831 MathStyle previousStyle( style );
00832 style.scriptlevel += 1;
00833 style.displaystyle = false;
00834 style.styleChange();
00835
00836 QDomElement sequence = doc.createElement( "SEQUENCE" );
00837 index.appendChild( sequence );
00838 QDomElement e = n.toElement();
00839 filter->processElement( e, doc, sequence );
00840 root.appendChild( index );
00841
00842 style = previousStyle;
00843 }
00844 }
00845 else {
00846 kdDebug( DEBUGID ) << "<" << element.tagName() << "> child: "
00847 << n.nodeName() << endl;
00848 }
00849 n = n.nextSibling();
00850 }
00851 docnode.appendChild( root );
00852 }
00853
00854 void MathML2KFormulaPrivate::munder( QDomElement element, QDomNode docnode, bool oasisFormat )
00855 {
00856 bool accentunder;
00857
00858 QString au = element.attribute( "accentunder" );
00859 if ( au == "true" )
00860 accentunder = true;
00861 else if ( au == "false" )
00862 accentunder = false;
00863 else {
00864
00865
00866 QDomElement mo;
00867
00868 if ( isEmbellishedOperator( element.childNodes().item( 1 ), &mo, oasisFormat ) ) {
00869 if ( mo.attribute( "accent" ) == "true" )
00870 accentunder = true;
00871 else
00872 accentunder = false;
00873 }
00874 else
00875 accentunder = false;
00876 }
00877
00878 QDomNode n = element.firstChild();
00879 int i = 0;
00880 QDomElement root = doc.createElement( "INDEX" );
00881
00882 while ( !n.isNull() && i < 2 ) {
00883 if ( n.isElement() ) {
00884 ++i;
00885 if ( i == 1 ) {
00886 QDomElement content = doc.createElement( "CONTENT" );
00887 QDomElement sequence = doc.createElement( "SEQUENCE" );
00888 content.appendChild( sequence );
00889 QDomElement e = n.toElement();
00890 filter->processElement( e, doc, sequence );
00891
00892 root.appendChild( content );
00893 }
00894 else {
00895 MathStyle previousStyle( style );
00896 style.displaystyle = false;
00897 if ( !accentunder ) {
00898 style.scriptlevel += 1;
00899 style.styleChange();
00900 }
00901
00902 QDomElement mo; QDomElement index;
00903 if ( isEmbellishedOperator( n.previousSibling(), &mo, oasisFormat ) &&
00904 !previousStyle.displaystyle &&
00905 mo.attribute( "movablelimits" ) == "true" )
00906 {
00907 index = doc.createElement( "LOWERRIGHT" );
00908 }
00909 else {
00910 index = doc.createElement( "LOWERMIDDLE" );
00911 }
00912
00913 QDomElement sequence = doc.createElement( "SEQUENCE" );
00914 index.appendChild( sequence );
00915 QDomElement e = n.toElement();
00916 filter->processElement( e, doc, sequence );
00917 root.appendChild( index );
00918
00919 style = previousStyle;
00920 }
00921 }
00922 else {
00923 kdDebug( DEBUGID ) << "<" << element.tagName() << "> child: "
00924 << n.nodeName() << endl;
00925 }
00926 n = n.nextSibling();
00927 }
00928
00929 docnode.appendChild( root );
00930 }
00931
00932 void MathML2KFormulaPrivate::mover( QDomElement element, QDomNode docnode, bool oasisFormat )
00933 {
00934 bool accent;
00935
00936 QString ac = element.attribute( "accent" );
00937 if ( ac == "true" )
00938 accent = true;
00939 else if ( ac == "false" )
00940 accent = false;
00941 else {
00942
00943
00944 QDomElement mo;
00945
00946 if ( isEmbellishedOperator( element.childNodes().item( 1 ), &mo, oasisFormat ) ) {
00947 if ( mo.attribute( "accent" ) == "true" )
00948 accent = true;
00949 else
00950 accent = false;
00951 }
00952 else
00953 accent = false;
00954 }
00955
00956 QDomNode n = element.firstChild();
00957 int i = 0;
00958 QDomElement root = doc.createElement( "INDEX" );
00959
00960 while ( !n.isNull() && i < 2 ) {
00961 if ( n.isElement() ) {
00962 ++i;
00963 if ( i == 1 ) {
00964 QDomElement content = doc.createElement( "CONTENT" );
00965 QDomElement sequence = doc.createElement( "SEQUENCE" );
00966 content.appendChild( sequence );
00967 QDomElement e = n.toElement();
00968 filter->processElement( e, doc, sequence );
00969
00970 root.appendChild( content );
00971 }
00972 else {
00973 MathStyle previousStyle( style );
00974 style.displaystyle = false;
00975 if ( !accent ) {
00976 style.scriptlevel += 1;
00977 style.styleChange();
00978 }
00979
00980 QDomElement mo; QDomElement index;
00981 if ( isEmbellishedOperator( n.previousSibling(), &mo, oasisFormat ) &&
00982 !previousStyle.displaystyle &&
00983 mo.attribute( "movablelimits" ) == "true" )
00984 {
00985 index = doc.createElement( "UPPERRIGHT" );
00986 }
00987 else {
00988 index = doc.createElement( "UPPERMIDDLE" );
00989 }
00990
00991 QDomElement sequence = doc.createElement( "SEQUENCE" );
00992 index.appendChild( sequence );
00993 QDomElement e = n.toElement();
00994 filter->processElement( e, doc, sequence );
00995 root.appendChild( index );
00996
00997 style = previousStyle;
00998 }
00999 }
01000 else {
01001 kdDebug( DEBUGID ) << "<" << element.tagName() << "> child: "
01002 << n.nodeName() << endl;
01003 }
01004 n = n.nextSibling();
01005 }
01006
01007 docnode.appendChild( root );
01008 }
01009
01010 void MathML2KFormulaPrivate::munderover( QDomElement element, QDomNode docnode, bool oasisFormat )
01011 {
01012 bool accent;
01013 bool accentunder;
01014
01015 QString value = element.attribute( "accentunder" );
01016 if ( value == "true" )
01017 accentunder = true;
01018 else if ( value == "false" )
01019 accentunder = false;
01020 else {
01021
01022
01023 QDomElement mo;
01024
01025 if ( isEmbellishedOperator( element.childNodes().item( 1 ), &mo, oasisFormat ) ) {
01026 if ( mo.attribute( "accent" ) == "true" )
01027 accentunder = true;
01028 else
01029 accentunder = false;
01030 }
01031 else
01032 accentunder = false;
01033 }
01034 value = element.attribute( "accent" );
01035 if ( value == "true" )
01036 accent = true;
01037 else if ( value == "false" )
01038 accent = false;
01039 else {
01040
01041
01042 QDomElement mo;
01043
01044 if ( isEmbellishedOperator( element.childNodes().item( 2 ), &mo,oasisFormat ) ) {
01045 kdDebug( DEBUGID ) << "embellished operator" << endl;
01046 if ( mo.attribute( "accent" ) == "true" )
01047 accent = true;
01048 else
01049 accent = false;
01050 }
01051 else
01052 accent = false;
01053 }
01054 kdDebug( DEBUGID ) << "munderover:\n accentunder = " << accentunder
01055 << "\n accent = " << accent << endl;
01056
01057 QDomNode n = element.firstChild();
01058 int i = 0;
01059 QDomElement root = doc.createElement( "INDEX" );
01060
01061 while ( !n.isNull() && i < 3 ) {
01062 if ( n.isElement() ) {
01063 ++i;
01064 if ( i == 1 ) {
01065 QDomElement content = doc.createElement( "CONTENT" );
01066 QDomElement sequence = doc.createElement( "SEQUENCE" );
01067 content.appendChild( sequence );
01068 QDomElement e = n.toElement();
01069 filter->processElement( e, doc, sequence );
01070
01071 root.appendChild( content );
01072 }
01073 else if ( i == 2 ) {
01074 MathStyle previousStyle( style );
01075 style.displaystyle = false;
01076 if ( !accentunder ) {
01077 style.scriptlevel += 1;
01078 style.styleChange();
01079 }
01080
01081 QDomElement mo; QDomElement index;
01082
01083 if ( isEmbellishedOperator( element.firstChild(), &mo, oasisFormat ) &&
01084 !previousStyle.displaystyle &&
01085 mo.attribute( "movablelimits" ) == "true" )
01086 {
01087 index = doc.createElement( "LOWERRIGHT" );
01088 }
01089 else {
01090 index = doc.createElement( "LOWERMIDDLE" );
01091 }
01092
01093 QDomElement sequence = doc.createElement( "SEQUENCE" );
01094 index.appendChild( sequence );
01095 QDomElement e = n.toElement();
01096 filter->processElement( e, doc, sequence );
01097 root.appendChild( index );
01098
01099 style = previousStyle;
01100 }
01101 else {
01102 MathStyle previousStyle( style );
01103 style.displaystyle = false;
01104 if ( !accent ) {
01105 style.scriptlevel += 1;
01106 style.styleChange();
01107 }
01108
01109 QDomElement mo; QDomElement index;
01110 if ( isEmbellishedOperator( element.firstChild(), &mo, oasisFormat ) &&
01111 !previousStyle.displaystyle &&
01112 mo.attribute( "movablelimits" ) == "true" )
01113 {
01114 index = doc.createElement( "UPPERRIGHT" );
01115 }
01116 else {
01117 index = doc.createElement( "UPPERMIDDLE" );
01118 }
01119
01120 QDomElement sequence = doc.createElement( "SEQUENCE" );
01121 index.appendChild( sequence );
01122 QDomElement e = n.toElement();
01123 filter->processElement( e, doc, sequence );
01124 root.appendChild( index );
01125
01126 style = previousStyle;
01127 }
01128 }
01129 else {
01130 kdDebug( DEBUGID ) << "<" << element.tagName() << "> child: "
01131 << n.nodeName() << endl;
01132 }
01133 n = n.nextSibling();
01134 }
01135
01136 docnode.appendChild( root );
01137 }
01138
01139 void MathML2KFormulaPrivate::msubsup( QDomElement element, QDomNode docnode )
01140 {
01141 QDomNode n = element.firstChild();
01142 int i = 0;
01143 QDomElement root = doc.createElement("INDEX");
01144 MathStyle previousStyle( style );
01145
01146 while ( !n.isNull() && i < 2 ) {
01147 if ( n.isElement() ) {
01148 ++i;
01149 if ( i == 1 ) {
01150 QDomElement content = doc.createElement( "CONTENT" );
01151 QDomElement sequence = doc.createElement( "SEQUENCE" );
01152 content.appendChild( sequence );
01153 QDomElement e = n.toElement();
01154 filter->processElement( e, doc, sequence );
01155
01156 root.appendChild( content );
01157 }
01158 else if ( i == 2 ) {
01159 style.scriptlevel += 1;
01160 style.displaystyle = false;
01161 style.styleChange();
01162
01163 QDomElement index;
01164 index = doc.createElement( "LOWERRIGHT" );
01165
01166 QDomElement sequence = doc.createElement( "SEQUENCE" );
01167 index.appendChild( sequence );
01168 QDomElement e = n.toElement();
01169 filter->processElement( e, doc, sequence );
01170 root.appendChild( index );
01171 }
01172 else {
01173 QDomElement index;
01174 index = doc.createElement( "UPPERRIGHT" );
01175
01176 QDomElement sequence = doc.createElement( "SEQUENCE" );
01177 index.appendChild( sequence );
01178 QDomElement e = n.toElement();
01179 filter->processElement( e, doc, sequence );
01180 root.appendChild( index );
01181
01182 style = previousStyle;
01183
01184 }
01185 }
01186 else {
01187 kdDebug( DEBUGID ) << "<msubsup> child: " << n.nodeName() << endl;
01188 }
01189 n = n.nextSibling();
01190 }
01191 docnode.appendChild( root );
01192 }
01193
01194 void MathML2KFormulaPrivate::createTextElements( QString text, QDomNode docnode )
01195 {
01196 for ( uint i = 0; i < text.length(); ++i ) {
01197 QDomElement textelement = doc.createElement( "TEXT" );
01198 textelement.setAttribute( "CHAR", QString( text.at( i ) ) );
01199 style.setStyles( textelement );
01200 if ( context.symbolTable().inTable( text.at( i ) ) ) {
01201
01202 textelement.setAttribute( "SYMBOL", "3" );
01203 }
01204 docnode.appendChild( textelement );
01205 }
01206 }
01207
01208 void MathML2KFormulaPrivate::createNameSequence( QString text, QDomNode docnode )
01209 {
01210 QDomElement namesequence = doc.createElement( "NAMESEQUENCE" );
01211 for ( uint i = 0; i < text.length(); ++i ) {
01212 QDomElement textelement = doc.createElement( "TEXT" );
01213 textelement.setAttribute( "CHAR", QString( text.at( i ) ) );
01214 style.setStyles( textelement );
01215 if ( context.symbolTable().inTable( text.at( i ) ) ) {
01216
01217 textelement.setAttribute( "SYMBOL", "3" );
01218 }
01219 namesequence.appendChild( textelement );
01220 }
01221 docnode.appendChild( namesequence );
01222 }
01223
01224 double MathML2KFormulaPrivate::convertToPoint( QString value, bool* ok )
01225 {
01226 double pt = 0;
01227
01228 if ( value.endsWith( "em" ) ) {
01229
01230 pt = context.getDefaultFont().pointSize();
01231 if ( pt == -1 ) {
01232 QFontMetrics fm( context.getDefaultFont() );
01233 pt = fm.width( 'M' );
01234
01235 }
01236 pt = pt * value.remove( value.length() - 2, 2 ).toDouble( ok );
01237 }
01238 else if ( value.endsWith( "ex" ) ) {
01239 QFontMetrics fm( context.getDefaultFont() );
01240 pt = fm.height();
01241
01242 }
01243 else if ( value.endsWith( "px" ) ) {
01244 pt = value.remove( value.length() - 2, 2 ).toDouble( ok );
01245
01246 }
01247 else if ( value.endsWith( "in" ) ) {
01248 pt = value.remove( value.length() - 2, 2 ).toDouble( ok );
01249 pt *= 72;
01250 }
01251 else if ( value.endsWith( "cm" ) ) {
01252 pt = value.remove( value.length() - 2, 2 ).toDouble( ok );
01253 pt *= 1/2.54 * 72;
01254 }
01255 else if ( value.endsWith( "mm" ) ) {
01256 pt = value.remove( value.length() - 2, 2 ).toDouble( ok );
01257 pt *= 1/25.4 * 72;
01258 }
01259 else if ( value.endsWith( "pt" ) ) {
01260 pt = value.remove( value.length() - 2, 2 ).toDouble( ok );
01261 }
01262 else if ( value.endsWith( "pc" ) ) {
01263 pt = value.remove( value.length() - 2, 2 ).toDouble( ok );
01264 pt /= 12;
01265 }
01266 else {
01267 pt = value.toDouble( ok );
01268 }
01269
01270 return pt;
01271 }
01272
01273 bool MathML2KFormulaPrivate::isEmbellishedOperator( QDomNode node,
01274 QDomElement* mo, bool oasisFormat )
01275 {
01276
01277
01278 if ( !node.isElement() )
01279 return false;
01280
01281 QDomElement element = node.toElement();
01282 QString tag = element.tagName();
01283
01284 if ( tag == "mo" )
01285 {
01286 *mo = element;
01287 return true;
01288 }
01289 if ( tag == "msub" || tag == "msup" || tag == "msubsup" ||
01290 tag == "munder" || tag == "mover" || tag == "munderover" ||
01291 tag == "mmultiscripts" || tag == "mfrac" || tag == "semantics" )
01292 {
01293 return isEmbellishedOperator( element.firstChild(), mo,oasisFormat );
01294 }
01295 if ( tag == "maction" )
01296 {
01297 return false;
01298 }
01299 if ( tag == "mrow" || tag == "mstyle" || tag == "mphantom" || tag == "mpadded" ) {
01300 QDomNode n = element.firstChild();
01301 int i = 0;
01302
01303 while ( !n.isNull() ) {
01304 if ( isEmbellishedOperator( n, mo,oasisFormat ) ) {
01305 if ( ++i > 1 )
01306 return false;
01307 }
01308 else if ( !isSpaceLike( n, oasisFormat ) ) {
01309 return false;
01310 }
01311 n = n.nextSibling();
01312 }
01313 return ( i == 1 );
01314 }
01315 return false;
01316 }
01317
01318 bool MathML2KFormulaPrivate::isSpaceLike( QDomNode node, bool oasisFormat )
01319 {
01320
01321
01322 if ( !node.isElement() )
01323 return false;
01324
01325 QDomElement element = node.toElement();
01326 QString tag = element.tagName();
01327
01328 if ( tag == "mtext" || tag == "mspace" ||
01329 tag == "maligngroup" || tag == "malignmark" ) {
01330 return true;
01331 }
01332 if ( tag == "mstyle" || tag == "mphantom" || tag == "mpadded" || tag == "mrow" ) {
01333 QDomNode n = element.firstChild();
01334 while ( !n.isNull() ) {
01335 if ( isSpaceLike( n,oasisFormat ) )
01336 n = n.nextSibling();
01337 else
01338 return false;
01339 }
01340 return true;
01341 }
01342 if ( tag == "maction" ) {
01343 return false;
01344 }
01345
01346 return false;
01347 }
01348
01349
01350 MathML2KFormula::MathML2KFormula( const QDomDocument& mmldoc, const ContextStyle &contextStyle, bool _oasisFormat )
01351 : m_error( false ), oasisFormat( _oasisFormat ), context( contextStyle )
01352 {
01353 orig_element = mmldoc.documentElement();
01354 done = false;
01355 }
01356
01357 MathML2KFormula::MathML2KFormula( const QDomElement& mmlelm, const ContextStyle &contextStyle, bool _oasisFormat )
01358 : m_error( false ), orig_element( mmlelm ), oasisFormat( _oasisFormat ), context( contextStyle )
01359 {
01360 done = false;
01361 }
01362
01363 QDomDocument MathML2KFormula::getKFormulaDom()
01364 {
01365 return formuladoc;
01366 }
01367
01368
01369
01370 void MathML2KFormula::startConversion()
01371 {
01372
01373
01374 done = false;
01375 formuladoc = QDomDocument( "KFORMULA" );
01376 impl = new MathML2KFormulaPrivate( this, context, formuladoc );
01377 if ( orig_element.tagName() == "math" ) {
01378 impl->math( orig_element );
01379 m_error = false;
01380 }
01381 else {
01382 kdError() << "Not a MathML document!" << endl;
01383 KMessageBox::error( 0, i18n( "The document does not seem to be MathML." ), i18n( "MathML Import Error" ) );
01384 m_error = true;
01385 }
01386 done = true;
01387 }
01388
01389 bool MathML2KFormula::processElement( QDomNode node, QDomDocument& doc, QDomNode docnode )
01390 {
01391
01392
01393 Type type = UNKNOWN;
01394
01395 if ( node.isElement() ) {
01396 QDomElement element = node.toElement();
01397 QString tag = element.tagName();
01398
01399 if ( tag == "mi" ) {
01400 type = TOKEN;
01401 impl->mi( element, docnode );
01402 }
01403 else if ( tag == "mo" ) {
01404 type = TOKEN;
01405 impl->mo( element, docnode );
01406 }
01407 else if ( tag == "mn" ) {
01408 type = TOKEN;
01409 impl->mn( element, docnode );
01410 }
01411 else if ( tag == "mtext" ) {
01412 type = TOKEN;
01413 impl->mtext( element, docnode );
01414 }
01415 else if ( tag == "ms" ) {
01416 type = TOKEN;
01417 impl->ms( element, docnode );
01418 }
01419 else if ( tag == "mspace" ) {
01420 type = TOKEN;
01421 impl->mspace( element, docnode );
01422 }
01423 else if ( tag == "mrow" ) {
01424 type = LAYOUT;
01425 impl->mrow( element, docnode );
01426 }
01427 else if ( tag == "mfrac" ) {
01428 type = LAYOUT;
01429 impl->mfrac( element, docnode );
01430 }
01431 else if ( tag == "mroot" ) {
01432 type = LAYOUT;
01433 impl->mroot( element, docnode );
01434 }
01435 else if ( tag == "msqrt" ) {
01436 type = LAYOUT;
01437 impl->msqrt( element, docnode );
01438 }
01439 else if ( tag == "mstyle" ) {
01440 type = LAYOUT;
01441 impl->mstyle( element, docnode );
01442 }
01443 else if ( tag == "mfenced" ) {
01444 type = LAYOUT;
01445 impl->mfenced( element, docnode );
01446 }
01447 else if ( tag == "mtable" ) {
01448 type = TABLE;
01449 impl->mtable( element, docnode );
01450 }
01451 else if ( tag == "msub" || tag == "msup" ) {
01452 type = SCRIPT;
01453 impl->msub_msup( element, docnode );
01454 }
01455 else if ( tag == "munder" ) {
01456 type = SCRIPT;
01457 impl->munder( element, docnode,oasisFormat );
01458 }
01459 else if ( tag == "mover" ) {
01460 type = SCRIPT;
01461 impl->mover( element, docnode,oasisFormat );
01462 }
01463 else if ( tag == "munderover" ) {
01464 type = SCRIPT;
01465 impl->munderover( element, docnode, oasisFormat );
01466 }
01467 else if ( tag == "msubsup" ) {
01468 type = SCRIPT;
01469 impl->msubsup( element, docnode );
01470 }
01471
01472
01473 else if ( tag == "apply" ) {
01474 type = CONTENT;
01475 QDomNode n = element.firstChild();
01476 QDomElement op = n.toElement();
01477 uint count = element.childNodes().count();
01478
01479 QDomElement brackets = doc.createElement("BRACKET");
01480 brackets.setAttribute("RIGHT", "41");
01481 brackets.setAttribute("LEFT", "40");
01482 QDomElement content = doc.createElement("CONTENT");
01483 brackets.appendChild(content);
01484 QDomElement base = doc.createElement("SEQUENCE");
01485 content.appendChild(base);
01486 docnode.appendChild(brackets);
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516 if ( op.tagName() == "plus" || op.tagName() == "times" ||
01517 op.tagName() == "and" || op.tagName() == "or" ||
01518 op.tagName() == "xor" ) {
01519
01520 n = n.nextSibling();
01521 bool first = true;
01522
01523 while ( !n.isNull() ) {
01524 if ( n.isElement() ) {
01525 if ( !first ) {
01526 QDomElement text = doc.createElement( "TEXT" );
01527 QString value;
01528
01529 if ( op.tagName() == "plus" )
01530 value = "+";
01531 else if ( op.tagName() == "times" )
01532 value = "*";
01533 else if ( op.tagName() == "and" )
01534 value = "&";
01535 else if ( op.tagName() == "or" )
01536 value = "|";
01537 else if ( op.tagName() == "xor" )
01538 value = "^";
01539
01540 text.setAttribute( "CHAR", value );
01541 base.appendChild( text );
01542 }
01543 first = false;
01544 QDomElement e = n.toElement();
01545 processElement( e, doc, base );
01546 }
01547 n = n.nextSibling();
01548 }
01549 }
01550
01551 else if ( op.tagName() == "factorial" ) {
01552 QDomElement e = n.nextSibling().toElement();
01553 processElement( e, doc, docnode );
01554 impl->createTextElements( "!", base );
01555 }
01556 else if ( op.tagName() == "minus" ) {
01557 n = n.nextSibling();
01558 if ( count == 2 ) {
01559 impl->createTextElements( "-", base );
01560 QDomElement e = n.toElement();
01561 processElement( e, doc, base );
01562 }
01563 else if ( count == 3 ) {
01564 QDomElement e = n.toElement();
01565 processElement( e, doc, base );
01566 impl->createTextElements( "-", base );
01567 n = n.nextSibling();
01568 e = n.toElement();
01569 processElement( e, doc, base );
01570 }
01571 }
01572
01573 else if ( op.tagName() == "divide" && count == 3 ) {
01574 n = n.nextSibling();
01575 QDomElement e = n.toElement();
01576 processElement( e, doc, base );
01577 impl->createTextElements("/", base);
01578 n = n.nextSibling();
01579 e = n.toElement();
01580 processElement( e, doc, base );
01581 }
01582 else if ( op.tagName() == "power" && count == 3 ) {
01583
01584 n = n.nextSibling();
01585 QDomElement e = n.toElement();
01586 QDomElement index = doc.createElement("INDEX");
01587 base.appendChild(index);
01588 QDomElement content = doc.createElement("CONTENT");
01589 index.appendChild(content);
01590 QDomElement sequence = doc.createElement("SEQUENCE");
01591 content.appendChild(sequence);
01592 processElement(e, doc, sequence);
01593 QDomElement upper = doc.createElement("UPPERRIGHT");
01594 index.appendChild(upper);
01595 sequence = doc.createElement("SEQUENCE");
01596 upper.appendChild(sequence);
01597 n = n.nextSibling();
01598 e = n.toElement();
01599 processElement(e, doc, sequence);
01600 }
01601 else if ( op.tagName() == "abs" && count == 2) {
01602 n = n.nextSibling();
01603 QDomElement e = n.toElement();
01604 QDomElement bracket = doc.createElement("BRACKET");
01605 bracket.setAttribute("RIGHT", "257");
01606 bracket.setAttribute("LEFT", "256");
01607 base.appendChild(bracket);
01608 QDomElement content = doc.createElement("CONTENT");
01609 bracket.appendChild(content);
01610 QDomElement sequence = doc.createElement("SEQUENCE");
01611 content.appendChild(sequence);
01612 processElement(e, doc, sequence);
01613 }
01614 else if ( op.tagName() == "not" && count == 2) {
01615 n = n.nextSibling();
01616 QDomElement e = n.toElement();
01617 impl->createTextElements(QString(QChar(0xAC)), base);
01618 processElement(e, doc, base);
01619 }
01620 else if ( op.tagName() == "implies" && count == 3 ) {
01621 n = n.nextSibling();
01622 QDomElement e = n.toElement();
01623 processElement( e, doc, base );
01624 impl->createTextElements(QString(QChar(0x21D2)), base);
01625 n = n.nextSibling();
01626 e = n.toElement();
01627 processElement( e, doc, base );
01628 }
01629
01630
01631 }
01632
01633 else if ( tag == "cn" ) {
01634 type = CONTENT;
01635 QString type = element.attribute( "type", "real" );
01636
01637 if ( type == "real" || type == "constant" ) {
01638 impl->createTextElements( element.text().stripWhiteSpace(),
01639 docnode );
01640 }
01641 else if ( type == "integer" ) {
01642 QString base = element.attribute( "base" );
01643 if ( !base ) {
01644 impl->createTextElements( element.text().stripWhiteSpace(),
01645 docnode );
01646 }
01647 else {
01648 QDomElement index = doc.createElement( "INDEX" );
01649 QDomElement content = doc.createElement( "CONTENT" );
01650 QDomElement sequence = doc.createElement( "SEQUENCE" );
01651 impl->createTextElements( element.text().stripWhiteSpace(),
01652 sequence );
01653 content.appendChild( sequence );
01654 index.appendChild( content );
01655
01656 QDomElement lowerright = doc.createElement( "LOWERRIGHT" );
01657 sequence = doc.createElement( "SEQUENCE" );
01658
01659 impl->createTextElements( base, sequence );
01660
01661 lowerright.appendChild( sequence );
01662 index.appendChild( lowerright );
01663
01664 docnode.appendChild( index );
01665 }
01666 }
01667 else if ( type == "rational" ) {
01668 QDomNode n = element.firstChild();
01669 impl->createTextElements( n.toText().data().stripWhiteSpace(),
01670 docnode );
01671
01672 n = n.nextSibling();
01673 impl->createTextElements( "/", docnode );
01674
01675 n = n.nextSibling();
01676 impl->createTextElements( n.toText().data().stripWhiteSpace(),
01677 docnode );
01678 }
01679 else if ( type == "complex-cartesian" ) {
01680 QDomNode n = element.firstChild();
01681 impl->createTextElements( n.toText().data().stripWhiteSpace(),
01682 docnode );
01683
01684 n = n.nextSibling();
01685 impl->createTextElements( "+", docnode );
01686
01687 n = n.nextSibling();
01688 impl->createTextElements( n.toText().data().stripWhiteSpace(),
01689 docnode );
01690
01691 impl->createTextElements( "i", docnode );
01692 }
01693
01694 else if ( type == "complex-polar" ) {
01695 QDomNode n = element.firstChild();
01696 impl->createTextElements( n.toText().data().stripWhiteSpace(),
01697 docnode );
01698
01699 n = n.nextSibling();
01700 QDomElement index = doc.createElement( "INDEX" );
01701 QDomElement content = doc.createElement( "CONTENT" );
01702 QDomElement sequence = doc.createElement( "SEQUENCE" );
01703 QDomElement textelement = doc.createElement( "TEXT" );
01704 textelement.setAttribute( "CHAR", "e" );
01705 sequence.appendChild( textelement );
01706 content.appendChild( sequence );
01707 index.appendChild( content );
01708
01709 QDomElement upperright = doc.createElement( "UPPERRIGHT" );
01710 sequence = doc.createElement( "SEQUENCE" );
01711 textelement = doc.createElement( "TEXT" );
01712 textelement.setAttribute( "CHAR", "i" );
01713 sequence.appendChild( textelement );
01714
01715 n = n.nextSibling();
01716 impl->createTextElements( n.toText().data().stripWhiteSpace(),
01717 sequence );
01718
01719 upperright.appendChild( sequence );
01720 index.appendChild( upperright );
01721
01722 docnode.appendChild( index );
01723 }
01724 }
01725
01726 else if ( tag == "ci" ) {
01727 type = CONTENT;
01728 QDomNode n = element.firstChild();
01729
01730 if ( n.isText() ) {
01731 impl->createTextElements( n.toText().data().stripWhiteSpace(),
01732 docnode );
01733 }
01734 else if ( n.isElement() ) {
01735 QDomElement e = n.toElement();
01736 processElement( e, doc, docnode );
01737 }
01738 else if ( n.isEntityReference() ) {
01739 kdDebug( DEBUGID ) << "isEntityReference: "
01740 << n.toEntityReference().nodeName().latin1()
01741 << endl;
01742 }
01743 else
01744 kdDebug( DEBUGID ) << "ci: " << n.nodeName().latin1() << endl;
01745 }
01746
01747 else if ( tag == "list" ) {
01748 type = CONTENT;
01749 QDomNode n = element.firstChild();
01750
01751 QDomElement bracket = doc.createElement( "BRACKET" );
01752 bracket.setAttribute( "LEFT", 91 );
01753 bracket.setAttribute( "RIGHT", 93 );
01754 QDomElement content = doc.createElement( "CONTENT" );
01755 QDomElement sequence = doc.createElement( "SEQUENCE" );
01756
01757 bool first = true;
01758
01759 while ( !n.isNull() ) {
01760 if ( n.isElement() ) {
01761 if ( !first ) {
01762 QDomElement textelement = doc.createElement( "TEXT" );
01763 textelement.setAttribute( "CHAR", "," );
01764 sequence.appendChild( textelement );
01765 }
01766 first = false;
01767 QDomElement e = n.toElement();
01768 processElement( e, doc, sequence );
01769 }
01770 n = n.nextSibling();
01771 }
01772
01773 content.appendChild( sequence );
01774 bracket.appendChild( content );
01775 docnode.appendChild( bracket );
01776 }
01777 }
01778
01779 if ( type == UNKNOWN && node.nodeType() != QDomNode::AttributeNode ) {
01780 kdDebug() << "Not an element: " << node.nodeName() << endl;
01781 QDomNode n = node.firstChild();
01782 while ( !n.isNull() ) {
01783 processElement( n, doc, docnode );
01784 n = n.nextSibling();
01785 }
01786 }
01787
01788 return true;
01789 }
01790
01791 KFORMULA_NAMESPACE_END
01792
01793 using namespace KFormula;
01794 #include "kformulamathmlread.moc"