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