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