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"