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