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