diff options
Diffstat (limited to 'lib/kformula/kformulamathmlread.cpp')
-rw-r--r-- | lib/kformula/kformulamathmlread.cpp | 1794 |
1 files changed, 1794 insertions, 0 deletions
diff --git a/lib/kformula/kformulamathmlread.cpp b/lib/kformula/kformulamathmlread.cpp new file mode 100644 index 00000000..ff941d6f --- /dev/null +++ b/lib/kformula/kformulamathmlread.cpp @@ -0,0 +1,1794 @@ +/* This file is part of the KDE project + Copyright (C) 2001 Andrea Rizzi <[email protected]> + Ulrich Kuettler <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include <iostream> +#include <tqstring.h> +#include <tqfontmetrics.h> + +#include <tdelocale.h> +#include <tdemessagebox.h> + +//#include <KoUnit.h> + +#include "kformulamathmlread.h" +#include "symboltable.h" + +KFORMULA_NAMESPACE_BEGIN +using namespace std; + +class MathML2KFormulaPrivate +{ + friend class MathML2KFormula; + +public: + MathML2KFormulaPrivate( MathML2KFormula* mml_filter, + const ContextStyle& contextStyle, + const TQDomDocument& formuladoc ); + ~MathML2KFormulaPrivate(); + + void math( TQDomElement element ); + + // Token Elements + void mi( TQDomElement element, TQDomNode docnode ); + void mn( TQDomElement element, TQDomNode docnode ); + void mo( TQDomElement element, TQDomNode docnode ); + void mtext( TQDomElement element, TQDomNode docnode ); + void mspace( TQDomElement element, TQDomNode docnode ); + void ms( TQDomElement element, TQDomNode docnode ); + // mglyph not supported + + // General Layout Schemata + void mrow( TQDomElement element, TQDomNode docnode ); + void mfrac( TQDomElement element, TQDomNode docnode ); + void msqrt( TQDomElement element, TQDomNode docnode ); + void mroot( TQDomElement element, TQDomNode docnode ); + void mstyle( TQDomElement element, TQDomNode docnode ); + // merror not supported + // mpadded not supported + // mphantom not supported + void mfenced( TQDomElement element, TQDomNode docnode ); + // menclose not supported + + // Script and Limit Schemata + void msub_msup( TQDomElement element, TQDomNode docnode ); + void msubsup( TQDomElement element, TQDomNode docnode ); + void munder( TQDomElement element, TQDomNode docnode, bool oasisFormat ); + void mover( TQDomElement element, TQDomNode docnode, bool oasisFormat ); + void munderover( TQDomElement element, TQDomNode docnode, bool oasisFormat ); + // mmultiscripts not supported + + // Tables and Matrices + void mtable( TQDomElement element, TQDomNode docnode ); + // not much supported + + // Enlivening Expressions + // maction not supported + +protected: + void createTextElements( TQString text, TQDomNode docnode ); + void createNameSequence( TQString text, TQDomNode docnode ); + double convertToPoint( TQString value, bool* ok ); + bool isEmbellishedOperator( TQDomNode node, TQDomElement* mo, bool oasisFormat ); + bool isSpaceLike( TQDomNode node, bool oasisFormat ); + + enum MathVariant { + normal, + bold, + italic, + bold_italic, + double_struck, + bold_fraktur, + script, + bold_script, + fraktur, + sans_serif, + bold_sans_serif, + sans_serif_italic, + sans_serif_bold_italic, + monospace + }; + + struct MathStyle { + MathStyle() + : scriptsizemultiplier( 0.71 ), + scriptminsize( 8 ), + veryverythinmathspace( 1.0/18.0 ), + verythinmathspace( 2.0/18.0 ), + thinmathspace( 3.0/18.0 ), + mediummathspace( 4.0/18.0 ), + thickmathspace( 5.0/18.0 ), + verythickmathspace( 6.0/18.0 ), + veryverythickmathspace( 7.0/18.0 ), + + useVariant( false ) + { + } + + void styleChange() + { + kdDebug( DEBUGID ) << "Style Change:" + << "\n scriptlevel = " << scriptlevel + << "\n displaystyle = " << displaystyle + << "\n scriptsizemultiplier = " + << scriptsizemultiplier + << "\n scriptminsize = " << scriptminsize + << endl; + } + + void setStyles( TQDomElement element ) + { + if ( !useVariant ) + return; + + switch ( mathvariant ) + { + case normal: + element.setAttribute( "STYLE", "normal" ); + break; + case bold: + element.setAttribute( "STYLE", "bold" ); + break; + + case bold_italic: + element.setAttribute( "STYLE", "bolditalic" ); + break; + case italic: + element.setAttribute( "STYLE", "italic" ); + break; + + case double_struck: + element.setAttribute( "FAMILY", "doublestruck" ); + break; + + case bold_fraktur: + element.setAttribute( "STYLE", "bold" ); + case fraktur: + element.setAttribute( "FAMILY", "fraktur" ); + break; + + case bold_script: + element.setAttribute( "STYLE", "bold" ); + case script: + element.setAttribute( "FAMILY", "script" ); + break; + + case bold_sans_serif: + element.setAttribute( "STYLE", "bold" ); + case sans_serif: + element.setAttribute( "FAMILY", "normal" ); + break; + case sans_serif_bold_italic: + element.setAttribute( "STYLE", "bolditalic" ); + element.setAttribute( "FAMILY", "normal" ); + break; + case sans_serif_italic: + element.setAttribute( "STYLE", "italic" ); + element.setAttribute( "FAMILY", "normal" ); + break; + + //case monospace: + default: + break; + } + } + + void readStyles( TQDomElement mmlElement ) + { + if ( mmlElement.hasAttribute( "mathvariant" ) ) + { + useVariant = true; + + if ( mmlElement.attribute( "mathvariant" ) == "normal" ) + mathvariant = normal; + else if ( mmlElement.attribute( "mathvariant" ) == "bold" ) + mathvariant = bold; + else if ( mmlElement.attribute( "mathvariant" ) == "italic" ) + mathvariant = italic; + else if ( mmlElement.attribute( "mathvariant" ) == "bold-italic" ) + mathvariant = bold_italic; + else if ( mmlElement.attribute( "mathvariant" ) == "double-struck" ) + mathvariant = double_struck; + else if ( mmlElement.attribute( "mathvariant" ) == "bold-fraktur" ) + mathvariant = bold_fraktur; + else if ( mmlElement.attribute( "mathvariant" ) == "script" ) + mathvariant = script; + else if ( mmlElement.attribute( "mathvariant" ) == "bold-script" ) + mathvariant = bold_script; + else if ( mmlElement.attribute( "mathvariant" ) == "fraktur" ) + mathvariant = fraktur; + else if ( mmlElement.attribute( "mathvariant" ) == "sans-serif" ) + mathvariant = sans_serif; + else if ( mmlElement.attribute( "mathvariant" ) == "bold-sans-serif" ) + mathvariant = bold_sans_serif; + else if ( mmlElement.attribute( "mathvariant" ) == "sans-serif-italic" ) + mathvariant = sans_serif_italic; + else if ( mmlElement.attribute( "mathvariant" ) == "sans-serif-bold-italic" ) + mathvariant = sans_serif_bold_italic; + else if ( mmlElement.attribute( "mathvariant" ) == "monospace" ) + mathvariant = monospace; + } + } + + // Styles, set by <mstyle> // default + + int scriptlevel; // inherited + bool displaystyle; // inherited + double scriptsizemultiplier; // 0.71 + double scriptminsize; // 8pt + // color + // background + double veryverythinmathspace; // 1/18em = 0.0555556em + double verythinmathspace; // 2/18em = 0.111111em + double thinmathspace; // 3/18em = 0.166667em + double mediummathspace; // 4/18em = 0.222222em + double thickmathspace; // 5/18em = 0.277778em + double verythickmathspace; // 6/18em = 0.333333em + double veryverythickmathspace; // 7/18em = 0.388889em + + // 'Local' styles + + MathVariant mathvariant; + bool useVariant; + //int mathsize; + }; + + MathStyle style; + TQDomDocument doc; + +private: + const ContextStyle& context; + MathML2KFormula* filter; +}; + +MathML2KFormulaPrivate::MathML2KFormulaPrivate( MathML2KFormula* mml_filter, const ContextStyle& cs, const TQDomDocument& formuladoc ) + : doc( formuladoc ), context( cs ), filter( mml_filter ) +{ +} + +MathML2KFormulaPrivate::~MathML2KFormulaPrivate() +{ +} + +void MathML2KFormulaPrivate::math( TQDomElement element ) +{ + TQDomElement formula = doc.createElement( "FORMULA" ); + TQDomNode n = element.firstChild(); + + TQString display = element.attribute( "display" ); + + if ( display == "block" ) { + style.displaystyle = true; + } + else { + // if display == "inline" (default) or illegal (then use default) + style.displaystyle = false; + } + + style.scriptlevel = 0; + + /*kdDebug( DEBUGID ) << "<math> element:\n displaystyle = " + << style.displaystyle << "\n scriptlevel = " + << style.scriptlevel << endl;*/ + + while ( !n.isNull() ) { + filter->processElement( n, doc, formula ); + n = n.nextSibling(); + } + + doc.appendChild( formula ); +} + +void MathML2KFormulaPrivate::mi( TQDomElement element, TQDomNode docnode ) +{ + MathStyle previousStyle( style ); + TQString text = element.text().stripWhiteSpace(); + if ( text.length() == 1 ) { // Default italic, only when content is one char + style.mathvariant = italic; + style.useVariant = true; + style.readStyles( element ); + createTextElements( text, docnode ); + } else { // If length is 0 or >1, it should be a text sequence + style.readStyles( element ); + createNameSequence( text, docnode ); + } + style = previousStyle; +} + +void MathML2KFormulaPrivate::mo( TQDomElement element, TQDomNode docnode ) +{ + MathStyle previousStyle( style ); + style.readStyles( element ); + + TQString text = element.text().stripWhiteSpace(); + createTextElements( text, docnode ); + + style = previousStyle; +} + +void MathML2KFormulaPrivate::mn( TQDomElement element, TQDomNode docnode ) +{ + MathStyle previousStyle( style ); + style.readStyles( element ); + + TQString text = element.text().stripWhiteSpace(); + createTextElements( text, docnode ); + + style = previousStyle; +} + +void MathML2KFormulaPrivate::mtext( TQDomElement element, TQDomNode docnode ) +{ + MathStyle previousStyle( style ); + style.readStyles( element ); + + TQDomNode n = element.firstChild(); + + while ( !n.isNull() ) { + if ( n.isText() ) { + TQString text = n.toText().data().stripWhiteSpace(); + createTextElements( text, docnode ); + } + else if ( n.isElement() ) { + filter->processElement( n, doc, docnode ); + } + else { + kdDebug( DEBUGID ) << "<mtext> child: " << n.nodeName() << endl; + } + + n = n.nextSibling(); + } + + style = previousStyle; +} + +void MathML2KFormulaPrivate::ms( TQDomElement element, TQDomNode docnode ) +{ + TQString lquote = element.attribute( "lquote", "\"" ); + TQString rquote = element.attribute( "rquote", "\"" ); + TQString text; + + text = lquote; + text += element.text().stripWhiteSpace(); + text += rquote; + + createTextElements( text, docnode ); +} + +void MathML2KFormulaPrivate::mspace( TQDomElement element, TQDomNode docnode ) +{ + // we support only horizontal space + TQString width = element.attribute( "width" ); + + TQDomElement spaceelement = doc.createElement( "SPACE" ); + + // check for namedspace. We don't support much... + if ( width == "veryverythinmathspace" ) { + spaceelement.setAttribute( "WIDTH", "thin" ); + } + else if ( width == "verythinmathspace" ) { + spaceelement.setAttribute( "WIDTH", "thin" ); + } + else if ( width == "thinmathspace" ) { + spaceelement.setAttribute( "WIDTH", "thin" ); + } + else if ( width == "mediummathspace" ) { + spaceelement.setAttribute( "WIDTH", "medium" ); + } + else if ( width == "thickmathspace" ) { + spaceelement.setAttribute( "WIDTH", "thick" ); + } + else if ( width == "verythickmathspace" ) { + spaceelement.setAttribute( "WIDTH", "thick" ); + } + else if ( width == "veryverythickmathspace" ) { + spaceelement.setAttribute( "WIDTH", "quad" ); + } + + else { + // units + + double w = 0; + bool ok; + + if ( width.endsWith( "em" ) ) { + // See MathML specification, Appendix H + w = context.getDefaultFont().pointSize(); + if ( w == -1 ) { + TQFontMetrics fm( context.getDefaultFont() ); + w = fm.width( 'm' ); + } + w = w * width.remove( width.length() - 2, 2 ).toDouble( &ok ); + // w in points? + } + else if ( width.endsWith( "px" ) ) { + w = width.remove( width.length() - 2, 2 ).toDouble( &ok ); + // w in pixels + } + else if ( width.endsWith( "in" ) ) { + w = width.remove( width.length() - 2, 2 ).toDouble( &ok ); + w *= 72; // w in points + } + else if ( width.endsWith( "cm" ) ) { + w = width.remove( width.length() - 2, 2 ).toDouble( &ok ); + w *= 1/2.54 * 72; // w in points + } + else if ( width.endsWith( "mm" ) ) { + w = width.remove( width.length() - 2, 2 ).toDouble( &ok ); + w *= 1/25.4 * 72; // w in points + } + else if ( width.endsWith( "pt" ) ) { + w = width.remove( width.length() - 2, 2 ).toDouble( &ok ); + // w in points + } + else if ( width.endsWith( "pc" ) ) { + w = width.remove( width.length() - 2, 2 ).toDouble( &ok ); + w /= 12; // w in points + } + else { + w = width.toDouble( &ok ); + } + + if ( !ok ) + return; + + if ( w < 20 ) + spaceelement.setAttribute( "WIDTH", "thin" ); + else if ( w < 40 ) + spaceelement.setAttribute( "WIDTH", "medium" ); + else if ( w < 80 ) + spaceelement.setAttribute( "WIDTH", "thick" ); + else + spaceelement.setAttribute( "WIDTH", "quad" ); + } + + docnode.appendChild( spaceelement ); +} + +void MathML2KFormulaPrivate::mrow( TQDomElement element, TQDomNode docnode ) +{ + TQDomNode n = element.firstChild(); + while ( !n.isNull() ) { + if ( n.isElement () ) { + TQDomElement e = n.toElement(); + // We do not allow sequence inside sequence + filter->processElement( e, doc, docnode ); + } + else { + kdDebug( DEBUGID ) << "<mrow> child: " << n.nodeName() << endl; + } + n = n.nextSibling(); + } +} + +void MathML2KFormulaPrivate::mfrac( TQDomElement element, TQDomNode docnode ) +{ + TQDomNode n = element.firstChild(); + TQDomElement fraction = doc.createElement( "FRACTION" ); + + MathStyle previousStyle( style ); + style.displaystyle ? style.displaystyle = false : style.scriptlevel += 1; + style.styleChange(); + + int i = 0; + while ( !n.isNull() && i < 2 ) { + if ( n.isElement() ) { + ++i; + if ( i == 1 ) { //first is numerator + TQDomElement numerator = + doc.createElement( "NUMERATOR" ); + TQDomElement sequence = doc.createElement( "SEQUENCE" ); + numerator.appendChild( sequence ); + TQDomElement e = n.toElement(); + filter->processElement( e, doc, sequence ); + fraction.appendChild( numerator ); + + } + else { + TQDomElement denominator = + doc.createElement( "DENOMINATOR" ); + TQDomElement sequence = doc.createElement( "SEQUENCE" ); + denominator.appendChild( sequence ); + TQDomElement e = n.toElement(); + filter->processElement( e, doc, sequence ); + fraction.appendChild( denominator ); + + } + } + else { + kdDebug( DEBUGID ) << "<mfrac> child: " << n.nodeName() << endl; + } + n = n.nextSibling(); + } + + style = previousStyle; + docnode.appendChild( fraction ); +} + +void MathML2KFormulaPrivate::mroot( TQDomElement element, TQDomNode docnode ) +{ + TQDomNode n = element.firstChild(); + int i = 0; + TQDomElement root = doc.createElement( "ROOT" ); + + while ( !n.isNull() && i < 2 ) { + if ( n.isElement() ) { + ++i; + if ( i == 1 ) { //first is content (base) + TQDomElement content = doc.createElement( "CONTENT" ); + TQDomElement sequence = doc.createElement( "SEQUENCE" ); + content.appendChild( sequence ); + TQDomElement e = n.toElement(); + filter->processElement( e, doc, sequence ); + + root.appendChild(content); + } + else { // index + MathStyle previousStyle( style ); + style.scriptlevel += 2; + style.displaystyle = false; + style.styleChange(); + + TQDomElement index = doc.createElement( "INDEX" ); + TQDomElement sequence = doc.createElement( "SEQUENCE" ); + index.appendChild( sequence ); + TQDomElement e = n.toElement(); + filter->processElement( e, doc, sequence ); + root.appendChild( index ); + + style = previousStyle; + } + } + else { + kdDebug( DEBUGID ) << "<mroot> child: " << n.nodeName() << endl; + } + n = n.nextSibling(); + } + docnode.appendChild( root ); +} + +void MathML2KFormulaPrivate::msqrt( TQDomElement element, TQDomNode docnode ) +{ + TQDomNode n = element.firstChild(); + TQDomElement root = doc.createElement( "ROOT" ); + + TQDomElement content = doc.createElement( "CONTENT" ); + TQDomElement sequence = doc.createElement( "SEQUENCE" ); + content.appendChild( sequence ); + root.appendChild( content ); + + while ( !n.isNull() ) { + if ( n.isElement() ) { + filter->processElement( n.toElement(), doc, sequence ); + } + else { + kdDebug( DEBUGID ) << "<msqrt> child: " << n.nodeName() << endl; + } + n = n.nextSibling(); + } + + docnode.appendChild( root ); +} + +void MathML2KFormulaPrivate::mstyle( TQDomElement element, TQDomNode docnode ) +{ + bool ok; + + MathStyle previousStyle( style ); + style.readStyles( element ); + + if ( element.hasAttribute( "scriptlevel" ) ) { + TQString scriptlevel = element.attribute( "scriptlevel" ); + if ( scriptlevel.startsWith( "+" ) || scriptlevel.startsWith( "-" ) ) + style.scriptlevel += scriptlevel.toInt( &ok ); + else + style.scriptlevel = scriptlevel.toInt( &ok ); + if ( !ok ) + style.scriptlevel = previousStyle.scriptlevel; + } + if ( element.hasAttribute( "displaystyle" ) ) { + TQString displaystyle = element.attribute( "displaystyle" ); + if ( displaystyle == "true" ) + style.displaystyle = true; + else if ( displaystyle == "false" ) + style.displaystyle = false; + } + if ( element.hasAttribute( "scriptsizemultiplier" ) ) { + style.scriptsizemultiplier = + element.attribute( "scriptsizemultiplier" ).toDouble( &ok ); + if ( !ok ) + style.scriptsizemultiplier = previousStyle.scriptsizemultiplier; + } + if ( element.hasAttribute( "scriptminsize" ) ) { + TQString scriptminsize = element.attribute( "scriptminsize" ); + style.scriptminsize = convertToPoint( scriptminsize, &ok ); + if ( !ok ) + style.scriptminsize = previousStyle.scriptminsize; + } + + if ( element.hasAttribute( "veryverythinmathspace" ) ) { + TQString vvthinmspace = element.attribute( "veryverythinmathspace" ); + style.veryverythinmathspace = convertToPoint( vvthinmspace, &ok ); + if ( !ok ) + style.veryverythinmathspace = previousStyle.veryverythinmathspace; + } + if ( element.hasAttribute( "verythinmathspace" ) ) { + TQString vthinmspace = element.attribute( "verythinmathspace" ); + style.verythinmathspace = convertToPoint( vthinmspace, &ok ); + if ( !ok ) + style.verythinmathspace = previousStyle.verythinmathspace; + } + if ( element.hasAttribute( "thinmathspace" ) ) { + TQString thinmathspace = element.attribute( "thinmathspace" ); + style.thinmathspace = convertToPoint( thinmathspace, &ok ); + if ( !ok ) + style.thinmathspace = previousStyle.thinmathspace; + } + if ( element.hasAttribute( "mediummathspace" ) ) { + TQString mediummathspace = element.attribute( "mediummathspace" ); + style.mediummathspace = convertToPoint( mediummathspace, &ok ); + if ( !ok ) + style.mediummathspace = previousStyle.mediummathspace; + } + if ( element.hasAttribute( "thickmathspace" ) ) { + TQString thickmathspace = element.attribute( "thickmathspace" ); + style.thickmathspace = convertToPoint( thickmathspace, &ok ); + if ( !ok ) + style.thickmathspace = previousStyle.thickmathspace; + } + if ( element.hasAttribute( "verythickmathspace" ) ) { + TQString vthickmspace = element.attribute( "verythickmathspace" ); + style.verythickmathspace = convertToPoint( vthickmspace, &ok ); + if ( !ok ) + style.verythickmathspace = previousStyle.verythickmathspace; + } + if ( element.hasAttribute( "veryverythickmathspace" ) ) { + TQString vvthickmspace = element.attribute( "veryverythickmathspace" ); + style.veryverythickmathspace = convertToPoint( vvthickmspace, &ok ); + if ( !ok ) + style.veryverythickmathspace = + previousStyle.veryverythickmathspace; + } + + style.styleChange(); + + TQDomNode n = element.firstChild(); + while ( !n.isNull() ) { + filter->processElement( n, doc, docnode ); + n = n.nextSibling(); + } + + style = previousStyle; +} + +void MathML2KFormulaPrivate::mfenced( TQDomElement element, TQDomNode docnode ) +{ + TQDomElement bracket = doc.createElement( "BRACKET" ); + TQString value = element.attribute( "open", "(" ); + bracket.setAttribute( "LEFT", TQString::number( value.at( 0 ).latin1() ) ); + value = element.attribute( "close", ")" ); + bracket.setAttribute( "RIGHT", TQString::number( value.at( 0 ).latin1() ) ); + + TQDomElement content = doc.createElement( "CONTENT" ); + TQDomElement sequence = doc.createElement( "SEQUENCE" ); + content.appendChild( sequence ); + + TQString separators = element.attribute( "separators", "," ); + + TQDomNode n = element.firstChild(); + uint i = 0; + while ( !n.isNull() ) { + if ( n.isElement() ) { + if ( i != 0 && !separators.isEmpty() ) { + TQDomElement textelement = doc.createElement( "TEXT" ); + if ( i > separators.length() ) + i = separators.length(); + textelement.setAttribute( "CHAR", TQString( separators.at( i - 1 ) ) ); + //style.setStyles( textelement ); + sequence.appendChild( textelement ); + } + ++i; + TQDomElement e = n.toElement(); + filter->processElement( e, doc, sequence ); + } + else { + kdDebug( DEBUGID ) << "<mfenced> child: " << n.nodeName() << endl; + } + n = n.nextSibling(); + } + bracket.appendChild( content ); + docnode.appendChild( bracket ); +} + +void MathML2KFormulaPrivate::mtable( TQDomElement element, TQDomNode docnode ) +{ + MathStyle previousStyle( style ); + TQString displaystyle = element.attribute( "displaystyle", "false" ); + if ( displaystyle == "true" ) { + style.displaystyle = true; + } + else { + // false is default and also used for illegal values + style.displaystyle = false; + } + style.styleChange(); + + TQString subtag; + int rows = 0; int cols = 0; + TQDomNode n = element.firstChild(); + + while ( !n.isNull() ) { + if ( n.isElement() ) { + TQDomElement e = n.toElement(); + subtag = e.tagName(); + if (subtag == "mtr") + { + ++rows; + + /* Determins the number of columns */ + + TQDomNode cellnode = e.firstChild(); + int cc = 0; + + while ( !cellnode.isNull() ) { + if ( cellnode.isElement() ) + cc++; + cellnode = cellnode.nextSibling(); + } + + if ( cc > cols ) + cols = cc; + + } + } + else { + kdDebug( DEBUGID ) << "<mtable> child: " << n.nodeName() << endl; + } + n = n.nextSibling(); + } + + /* Again createing elements, I need to know the number + of rows and cols to leave empty spaces */ + + n = element.firstChild(); + TQDomElement matrix = doc.createElement( "MATRIX" ); + matrix.setAttribute( "COLUMNS", cols ); + matrix.setAttribute( "ROWS", rows ); + + while ( !n.isNull() ) { + if ( n.isElement() ) { + TQDomElement e = n.toElement(); + subtag = e.tagName(); + if ( subtag == "mtr" ) { + TQDomNode cellnode = e.firstChild(); + int cc = 0; + while ( !cellnode.isNull() ) { + if ( cellnode.isElement() ) { + ++cc; + TQDomElement cell = doc.createElement( "SEQUENCE" ); + TQDomElement cellelement = cellnode.toElement(); + filter->processElement( cellelement, doc, cell ); + matrix.appendChild( cell ); + } + cellnode = cellnode.nextSibling(); + } + + /* Add empty elements */ + for(; cc < cols; cc++ ) { + TQDomElement cell = doc.createElement( "SEQUENCE" ); + matrix.appendChild( cell ); + } + } + } + n = n.nextSibling(); + } + + style = previousStyle; + docnode.appendChild(matrix); +} + +void MathML2KFormulaPrivate::msub_msup( TQDomElement element, TQDomNode docnode ) +{ + TQDomNode n = element.firstChild(); + int i = 0; + TQDomElement root = doc.createElement( "INDEX" ); + + while ( !n.isNull() && i < 2 ) { + if ( n.isElement() ) { + ++i; + if ( i == 1 ) { // first is content (base) + TQDomElement content = doc.createElement( "CONTENT" ); + TQDomElement sequence = doc.createElement( "SEQUENCE" ); + content.appendChild( sequence ); + TQDomElement e = n.toElement(); + filter->processElement( e, doc, sequence ); + + root.appendChild( content ); + } + else { + TQDomElement index; + if ( element.tagName() == "msup" ) + index = doc.createElement( "UPPERRIGHT" ); + else + index = doc.createElement( "LOWERRIGHT" ); + + MathStyle previousStyle( style ); + style.scriptlevel += 1; + style.displaystyle = false; + style.styleChange(); + + TQDomElement sequence = doc.createElement( "SEQUENCE" ); + index.appendChild( sequence ); + TQDomElement e = n.toElement(); + filter->processElement( e, doc, sequence ); + root.appendChild( index ); + + style = previousStyle; + } + } + else { + kdDebug( DEBUGID ) << "<" << element.tagName() << "> child: " + << n.nodeName() << endl; + } + n = n.nextSibling(); + } + docnode.appendChild( root ); +} + +void MathML2KFormulaPrivate::munder( TQDomElement element, TQDomNode docnode, bool oasisFormat ) +{ + bool accentunder; + + TQString au = element.attribute( "accentunder" ); + if ( au == "true" ) + accentunder = true; + else if ( au == "false" ) + accentunder = false; + else { + // use default + + TQDomElement mo; + // is underscript an embellished operator? + if ( isEmbellishedOperator( element.childNodes().item( 1 ), &mo, oasisFormat ) ) { + if ( mo.attribute( "accent" ) == "true" ) + accentunder = true; + else + accentunder = false; + } + else + accentunder = false; + } + + TQDomNode n = element.firstChild(); + int i = 0; + TQDomElement root = doc.createElement( "INDEX" ); + + while ( !n.isNull() && i < 2 ) { + if ( n.isElement() ) { + ++i; + if ( i == 1 ) { // first is content (base) + TQDomElement content = doc.createElement( "CONTENT" ); + TQDomElement sequence = doc.createElement( "SEQUENCE" ); + content.appendChild( sequence ); + TQDomElement e = n.toElement(); + filter->processElement( e, doc, sequence ); + + root.appendChild( content ); + } + else { // underscript + MathStyle previousStyle( style ); + style.displaystyle = false; + if ( !accentunder ) { + style.scriptlevel += 1; + style.styleChange(); + } + + TQDomElement mo; TQDomElement index; + if ( isEmbellishedOperator( n.previousSibling(), &mo, oasisFormat ) && + !previousStyle.displaystyle && + mo.attribute( "movablelimits" ) == "true" ) + { + index = doc.createElement( "LOWERRIGHT" ); + } + else { + index = doc.createElement( "LOWERMIDDLE" ); + } + + TQDomElement sequence = doc.createElement( "SEQUENCE" ); + index.appendChild( sequence ); + TQDomElement e = n.toElement(); + filter->processElement( e, doc, sequence ); + root.appendChild( index ); + + style = previousStyle; + } + } + else { + kdDebug( DEBUGID ) << "<" << element.tagName() << "> child: " + << n.nodeName() << endl; + } + n = n.nextSibling(); + } + + docnode.appendChild( root ); +} + +void MathML2KFormulaPrivate::mover( TQDomElement element, TQDomNode docnode, bool oasisFormat ) +{ + bool accent; + + TQString ac = element.attribute( "accent" ); + if ( ac == "true" ) + accent = true; + else if ( ac == "false" ) + accent = false; + else { + // use default + + TQDomElement mo; + // is overscript an embellished operator? + if ( isEmbellishedOperator( element.childNodes().item( 1 ), &mo, oasisFormat ) ) { + if ( mo.attribute( "accent" ) == "true" ) + accent = true; + else + accent = false; + } + else + accent = false; + } + + TQDomNode n = element.firstChild(); + int i = 0; + TQDomElement root = doc.createElement( "INDEX" ); + + while ( !n.isNull() && i < 2 ) { + if ( n.isElement() ) { + ++i; + if ( i == 1 ) { // first is content (base) + TQDomElement content = doc.createElement( "CONTENT" ); + TQDomElement sequence = doc.createElement( "SEQUENCE" ); + content.appendChild( sequence ); + TQDomElement e = n.toElement(); + filter->processElement( e, doc, sequence ); + + root.appendChild( content ); + } + else { // overscript + MathStyle previousStyle( style ); + style.displaystyle = false; + if ( !accent ) { + style.scriptlevel += 1; + style.styleChange(); + } + + TQDomElement mo; TQDomElement index; + if ( isEmbellishedOperator( n.previousSibling(), &mo, oasisFormat ) && + !previousStyle.displaystyle && + mo.attribute( "movablelimits" ) == "true" ) + { + index = doc.createElement( "UPPERRIGHT" ); + } + else { + index = doc.createElement( "UPPERMIDDLE" ); + } + + TQDomElement sequence = doc.createElement( "SEQUENCE" ); + index.appendChild( sequence ); + TQDomElement e = n.toElement(); + filter->processElement( e, doc, sequence ); + root.appendChild( index ); + + style = previousStyle; + } + } + else { + kdDebug( DEBUGID ) << "<" << element.tagName() << "> child: " + << n.nodeName() << endl; + } + n = n.nextSibling(); + } + + docnode.appendChild( root ); +} + +void MathML2KFormulaPrivate::munderover( TQDomElement element, TQDomNode docnode, bool oasisFormat ) +{ + bool accent; + bool accentunder; + + TQString value = element.attribute( "accentunder" ); + if ( value == "true" ) + accentunder = true; + else if ( value == "false" ) + accentunder = false; + else { + // use default + + TQDomElement mo; + // is underscript an embellished operator? + if ( isEmbellishedOperator( element.childNodes().item( 1 ), &mo, oasisFormat ) ) { + if ( mo.attribute( "accent" ) == "true" ) + accentunder = true; + else + accentunder = false; + } + else + accentunder = false; + } + value = element.attribute( "accent" ); + if ( value == "true" ) + accent = true; + else if ( value == "false" ) + accent = false; + else { + // use default + + TQDomElement mo; + // is overscript an embellished operator? + if ( isEmbellishedOperator( element.childNodes().item( 2 ), &mo,oasisFormat ) ) { + kdDebug( DEBUGID ) << "embellished operator" << endl; + if ( mo.attribute( "accent" ) == "true" ) + accent = true; + else + accent = false; + } + else + accent = false; + } + kdDebug( DEBUGID ) << "munderover:\n accentunder = " << accentunder + << "\n accent = " << accent << endl; + + TQDomNode n = element.firstChild(); + int i = 0; + TQDomElement root = doc.createElement( "INDEX" ); + + while ( !n.isNull() && i < 3 ) { + if ( n.isElement() ) { + ++i; + if ( i == 1 ) { // base + TQDomElement content = doc.createElement( "CONTENT" ); + TQDomElement sequence = doc.createElement( "SEQUENCE" ); + content.appendChild( sequence ); + TQDomElement e = n.toElement(); + filter->processElement( e, doc, sequence ); + + root.appendChild( content ); + } + else if ( i == 2 ) { // underscript + MathStyle previousStyle( style ); + style.displaystyle = false; + if ( !accentunder ) { + style.scriptlevel += 1; + style.styleChange(); + } + + TQDomElement mo; TQDomElement index; + // is the base an embellished operator? + if ( isEmbellishedOperator( element.firstChild(), &mo, oasisFormat ) && + !previousStyle.displaystyle && + mo.attribute( "movablelimits" ) == "true" ) + { + index = doc.createElement( "LOWERRIGHT" ); + } + else { + index = doc.createElement( "LOWERMIDDLE" ); + } + + TQDomElement sequence = doc.createElement( "SEQUENCE" ); + index.appendChild( sequence ); + TQDomElement e = n.toElement(); + filter->processElement( e, doc, sequence ); + root.appendChild( index ); + + style = previousStyle; + } + else { // overscript + MathStyle previousStyle( style ); + style.displaystyle = false; + if ( !accent ) { + style.scriptlevel += 1; + style.styleChange(); + } + + TQDomElement mo; TQDomElement index; + if ( isEmbellishedOperator( element.firstChild(), &mo, oasisFormat ) && + !previousStyle.displaystyle && + mo.attribute( "movablelimits" ) == "true" ) + { + index = doc.createElement( "UPPERRIGHT" ); + } + else { + index = doc.createElement( "UPPERMIDDLE" ); + } + + TQDomElement sequence = doc.createElement( "SEQUENCE" ); + index.appendChild( sequence ); + TQDomElement e = n.toElement(); + filter->processElement( e, doc, sequence ); + root.appendChild( index ); + + style = previousStyle; + } + } + else { + kdDebug( DEBUGID ) << "<" << element.tagName() << "> child: " + << n.nodeName() << endl; + } + n = n.nextSibling(); + } + + docnode.appendChild( root ); +} + +void MathML2KFormulaPrivate::msubsup( TQDomElement element, TQDomNode docnode ) +{ + TQDomNode n = element.firstChild(); + int i = 0; + TQDomElement root = doc.createElement("INDEX"); + MathStyle previousStyle( style ); + + while ( !n.isNull() && i < 2 ) { + if ( n.isElement() ) { + ++i; + if ( i == 1 ) { // base + TQDomElement content = doc.createElement( "CONTENT" ); + TQDomElement sequence = doc.createElement( "SEQUENCE" ); + content.appendChild( sequence ); + TQDomElement e = n.toElement(); + filter->processElement( e, doc, sequence ); + + root.appendChild( content ); + } + else if ( i == 2 ) { // subscript + style.scriptlevel += 1; + style.displaystyle = false; + style.styleChange(); + + TQDomElement index; + index = doc.createElement( "LOWERRIGHT" ); + + TQDomElement sequence = doc.createElement( "SEQUENCE" ); + index.appendChild( sequence ); + TQDomElement e = n.toElement(); + filter->processElement( e, doc, sequence ); + root.appendChild( index ); + } + else { // superscript + TQDomElement index; + index = doc.createElement( "UPPERRIGHT" ); + + TQDomElement sequence = doc.createElement( "SEQUENCE" ); + index.appendChild( sequence ); + TQDomElement e = n.toElement(); + filter->processElement( e, doc, sequence ); + root.appendChild( index ); + + style = previousStyle; + + } + } + else { + kdDebug( DEBUGID ) << "<msubsup> child: " << n.nodeName() << endl; + } + n = n.nextSibling(); + } + docnode.appendChild( root ); +} + +void MathML2KFormulaPrivate::createTextElements( TQString text, TQDomNode docnode ) +{ + for ( uint i = 0; i < text.length(); ++i ) { + TQDomElement textelement = doc.createElement( "TEXT" ); + textelement.setAttribute( "CHAR", TQString( text.at( i ) ) ); + style.setStyles( textelement ); + if ( context.symbolTable().inTable( text.at( i ) ) ) { + // The element is a symbol. + textelement.setAttribute( "SYMBOL", "3" ); + } + docnode.appendChild( textelement ); + } +} + +void MathML2KFormulaPrivate::createNameSequence( TQString text, TQDomNode docnode ) +{ + TQDomElement namesequence = doc.createElement( "NAMESEQUENCE" ); + for ( uint i = 0; i < text.length(); ++i ) { + TQDomElement textelement = doc.createElement( "TEXT" ); + textelement.setAttribute( "CHAR", TQString( text.at( i ) ) ); + style.setStyles( textelement ); + if ( context.symbolTable().inTable( text.at( i ) ) ) { + // The element is a symbol. + textelement.setAttribute( "SYMBOL", "3" ); + } + namesequence.appendChild( textelement ); + } + docnode.appendChild( namesequence ); +} + +double MathML2KFormulaPrivate::convertToPoint( TQString value, bool* ok ) +{ + double pt = 0; + + if ( value.endsWith( "em" ) ) { + // See MathML specification, Appendix H + pt = context.getDefaultFont().pointSize(); + if ( pt == -1 ) { + TQFontMetrics fm( context.getDefaultFont() ); + pt = fm.width( 'M' ); + // PIXELS! + } + pt = pt * value.remove( value.length() - 2, 2 ).toDouble( ok ); + } + else if ( value.endsWith( "ex" ) ) { + TQFontMetrics fm( context.getDefaultFont() ); + pt = fm.height(); + // PIXELS, and totally wrong! + } + else if ( value.endsWith( "px" ) ) { + pt = value.remove( value.length() - 2, 2 ).toDouble( ok ); + // PIXELS! + } + else if ( value.endsWith( "in" ) ) { + pt = value.remove( value.length() - 2, 2 ).toDouble( ok ); + pt *= 72; + } + else if ( value.endsWith( "cm" ) ) { + pt = value.remove( value.length() - 2, 2 ).toDouble( ok ); + pt *= 1/2.54 * 72; + } + else if ( value.endsWith( "mm" ) ) { + pt = value.remove( value.length() - 2, 2 ).toDouble( ok ); + pt *= 1/25.4 * 72; + } + else if ( value.endsWith( "pt" ) ) { + pt = value.remove( value.length() - 2, 2 ).toDouble( ok ); + } + else if ( value.endsWith( "pc" ) ) { + pt = value.remove( value.length() - 2, 2 ).toDouble( ok ); + pt /= 12; + } + else { + pt = value.toDouble( ok ); + } + + return pt; +} + +bool MathML2KFormulaPrivate::isEmbellishedOperator( TQDomNode node, + TQDomElement* mo, bool oasisFormat ) +{ + // See MathML 2.0 specification: 3.2.5.7 + + if ( !node.isElement() ) + return false; + + TQDomElement element = node.toElement(); + TQString tag = element.tagName(); + + if ( tag == "mo" ) + { + *mo = element; + return true; + } + if ( tag == "msub" || tag == "msup" || tag == "msubsup" || + tag == "munder" || tag == "mover" || tag == "munderover" || + tag == "mmultiscripts" || tag == "mfrac" || tag == "semantics" ) + { + return isEmbellishedOperator( element.firstChild(), mo,oasisFormat ); + } + if ( tag == "maction" ) + { + return false; // not supported + } + if ( tag == "mrow" || tag == "mstyle" || tag == "mphantom" || tag == "mpadded" ) { + TQDomNode n = element.firstChild(); + int i = 0; + + while ( !n.isNull() ) { + if ( isEmbellishedOperator( n, mo,oasisFormat ) ) { + if ( ++i > 1 ) // one (only one) embellished operator + return false; + } + else if ( !isSpaceLike( n, oasisFormat ) ) { // zero or more space-like elements + return false; + } + n = n.nextSibling(); + } + return ( i == 1 ); + } + return false; +} + +bool MathML2KFormulaPrivate::isSpaceLike( TQDomNode node, bool oasisFormat ) +{ + // See MathML 2.0 specification: 3.2.7.3 + + if ( !node.isElement() ) + return false; + + TQDomElement element = node.toElement(); + TQString tag = element.tagName(); + + if ( tag == "mtext" || tag == "mspace" || + tag == "maligngroup" || tag == "malignmark" ) { + return true; + } + if ( tag == "mstyle" || tag == "mphantom" || tag == "mpadded" || tag == "mrow" ) { + TQDomNode n = element.firstChild(); + while ( !n.isNull() ) { + if ( isSpaceLike( n,oasisFormat ) ) + n = n.nextSibling(); + else + return false; + } + return true; + } + if ( tag == "maction" ) { + return false; // not supported + } + + return false; +} + + +MathML2KFormula::MathML2KFormula( const TQDomDocument& mmldoc, const ContextStyle &contextStyle, bool _oasisFormat ) + : m_error( false ), oasisFormat( _oasisFormat ), context( contextStyle ) +{ + orig_element = mmldoc.documentElement(); + done = false; +} + +MathML2KFormula::MathML2KFormula( const TQDomElement& mmlelm, const ContextStyle &contextStyle, bool _oasisFormat ) + : m_error( false ), orig_element( mmlelm ), oasisFormat( _oasisFormat ), context( contextStyle ) +{ + done = false; +} + +TQDomDocument MathML2KFormula::getKFormulaDom() +{ + return formuladoc; +} + + + +void MathML2KFormula::startConversion() +{ + //TODO:let it be async + //kdDebug() << origdoc.toString() << endl; + done = false; + formuladoc = TQDomDocument( "KFORMULA" ); + impl = new MathML2KFormulaPrivate( this, context, formuladoc ); + if ( orig_element.tagName() == "math" ) { + impl->math( orig_element ); + m_error = false; + } + else { + kdError() << "Not a MathML document!" << endl; + KMessageBox::error( 0, i18n( "The document does not seem to be MathML." ), i18n( "MathML Import Error" ) ); + m_error = true; + } + done = true; +} + +bool MathML2KFormula::processElement( TQDomNode node, TQDomDocument& doc, TQDomNode docnode ) +{ + + //TQDomElement *element; + Type type = UNKNOWN; + + if ( node.isElement() ) { + TQDomElement element = node.toElement(); + TQString tag = element.tagName(); + + if ( tag == "mi" ) { + type = TOKEN; + impl->mi( element, docnode ); + } + else if ( tag == "mo" ) { + type = TOKEN; + impl->mo( element, docnode ); + } + else if ( tag == "mn" ) { + type = TOKEN; + impl->mn( element, docnode ); + } + else if ( tag == "mtext" ) { + type = TOKEN; + impl->mtext( element, docnode ); + } + else if ( tag == "ms" ) { + type = TOKEN; + impl->ms( element, docnode ); + } + else if ( tag == "mspace" ) { + type = TOKEN; + impl->mspace( element, docnode ); + } + else if ( tag == "mrow" ) { + type = LAYOUT; + impl->mrow( element, docnode ); + } + else if ( tag == "mfrac" ) { + type = LAYOUT; + impl->mfrac( element, docnode ); + } + else if ( tag == "mroot" ) { + type = LAYOUT; + impl->mroot( element, docnode ); + } + else if ( tag == "msqrt" ) { + type = LAYOUT; + impl->msqrt( element, docnode ); + } + else if ( tag == "mstyle" ) { + type = LAYOUT; + impl->mstyle( element, docnode ); + } + else if ( tag == "mfenced" ) { + type = LAYOUT; + impl->mfenced( element, docnode ); + } + else if ( tag == "mtable" ) { + type = TABLE; + impl->mtable( element, docnode ); + } + else if ( tag == "msub" || tag == "msup" ) { + type = SCRIPT; + impl->msub_msup( element, docnode ); + } + else if ( tag == "munder" ) { + type = SCRIPT; + impl->munder( element, docnode,oasisFormat ); + } + else if ( tag == "mover" ) { + type = SCRIPT; + impl->mover( element, docnode,oasisFormat ); + } + else if ( tag == "munderover" ) { + type = SCRIPT; + impl->munderover( element, docnode, oasisFormat ); + } + else if ( tag == "msubsup" ) { + type = SCRIPT; + impl->msubsup( element, docnode ); + } + + // content markup (not yet complete) + else if ( tag == "apply" ) { + type = CONTENT; + TQDomNode n = element.firstChild(); + TQDomElement op = n.toElement(); + uint count = element.childNodes().count(); + //adding explicit brackets to replace "apply"s implicit ones + TQDomElement brackets = doc.createElement("BRACKET"); + brackets.setAttribute("RIGHT", "41"); + brackets.setAttribute("LEFT", "40"); + TQDomElement content = doc.createElement("CONTENT"); + brackets.appendChild(content); + TQDomElement base = doc.createElement("SEQUENCE"); + content.appendChild(base); + docnode.appendChild(brackets); + //Arithmetic, Algebra and Logic operators status + // quotient X + // factorial O + // divide O + // max, min X + // minus O + // plus O + // power O + // rem X + // times O + // root X + // gcd X + // and O + // or O + // xor O + // not O + // implies O + // forall X + // exists X + // abs O + // conjugate X + // arg X + // real X + // imaginary X + // lcm X + // floor X + // ceiling X + + // n-ary + if ( op.tagName() == "plus" || op.tagName() == "times" || + op.tagName() == "and" || op.tagName() == "or" || + op.tagName() == "xor" ) { + + n = n.nextSibling(); + bool first = true; + + while ( !n.isNull() ) { + if ( n.isElement() ) { + if ( !first ) { + TQDomElement text = doc.createElement( "TEXT" ); + TQString value; + + if ( op.tagName() == "plus" ) + value = "+"; + else if ( op.tagName() == "times" ) + value = "*"; + else if ( op.tagName() == "and" ) + value = "&"; + else if ( op.tagName() == "or" ) + value = "|"; + else if ( op.tagName() == "xor" ) + value = "^"; // ??? + + text.setAttribute( "CHAR", value ); //switch to createTextElements? + base.appendChild( text ); + } + first = false; + TQDomElement e = n.toElement(); + processElement( e, doc, base ); + } + n = n.nextSibling(); + } + } + + else if ( op.tagName() == "factorial" ) { + TQDomElement e = n.nextSibling().toElement(); + processElement( e, doc, docnode ); + impl->createTextElements( "!", base ); + } + else if ( op.tagName() == "minus" ) { + n = n.nextSibling(); + if ( count == 2 ) { // unary + impl->createTextElements( "-", base ); + TQDomElement e = n.toElement(); + processElement( e, doc, base ); + } + else if ( count == 3 ) { // binary + TQDomElement e = n.toElement(); + processElement( e, doc, base ); + impl->createTextElements( "-", base ); + n = n.nextSibling(); + e = n.toElement(); + processElement( e, doc, base ); + } + } + + else if ( op.tagName() == "divide" && count == 3 ) { + n = n.nextSibling(); + TQDomElement e = n.toElement(); + processElement( e, doc, base ); + impl->createTextElements("/", base); + n = n.nextSibling(); + e = n.toElement(); + processElement( e, doc, base ); + } + else if ( op.tagName() == "power" && count == 3 ) { + //code duplication of msub_sup(), but I can't find a way to cleanly call it + n = n.nextSibling(); + TQDomElement e = n.toElement(); + TQDomElement index = doc.createElement("INDEX"); + base.appendChild(index); + TQDomElement content = doc.createElement("CONTENT"); + index.appendChild(content); + TQDomElement sequence = doc.createElement("SEQUENCE"); + content.appendChild(sequence); + processElement(e, doc, sequence); + TQDomElement upper = doc.createElement("UPPERRIGHT"); + index.appendChild(upper); + sequence = doc.createElement("SEQUENCE"); + upper.appendChild(sequence); + n = n.nextSibling(); + e = n.toElement(); + processElement(e, doc, sequence); + } + else if ( op.tagName() == "abs" && count == 2) { + n = n.nextSibling(); + TQDomElement e = n.toElement(); + TQDomElement bracket = doc.createElement("BRACKET"); + bracket.setAttribute("RIGHT", "257"); + bracket.setAttribute("LEFT", "256"); + base.appendChild(bracket); + TQDomElement content = doc.createElement("CONTENT"); + bracket.appendChild(content); + TQDomElement sequence = doc.createElement("SEQUENCE"); + content.appendChild(sequence); + processElement(e, doc, sequence); + } + else if ( op.tagName() == "not" && count == 2) { + n = n.nextSibling(); + TQDomElement e = n.toElement(); + impl->createTextElements(TQString(TQChar(0xAC)), base); + processElement(e, doc, base); + } + else if ( op.tagName() == "implies" && count == 3 ) { + n = n.nextSibling(); + TQDomElement e = n.toElement(); + processElement( e, doc, base ); + impl->createTextElements(TQString(TQChar(0x21D2)), base); + n = n.nextSibling(); + e = n.toElement(); + processElement( e, doc, base ); + } + // many, many more... + + } + + else if ( tag == "cn" ) { + type = CONTENT; + TQString type = element.attribute( "type", "real" ); + + if ( type == "real" || type == "constant" ) { + impl->createTextElements( element.text().stripWhiteSpace(), + docnode ); + } + else if ( type == "integer" ) { + TQString base = element.attribute( "base" ); + if ( !base ) { + impl->createTextElements( element.text().stripWhiteSpace(), + docnode ); + } + else { + TQDomElement index = doc.createElement( "INDEX" ); + TQDomElement content = doc.createElement( "CONTENT" ); + TQDomElement sequence = doc.createElement( "SEQUENCE" ); + impl->createTextElements( element.text().stripWhiteSpace(), + sequence ); + content.appendChild( sequence ); + index.appendChild( content ); + + TQDomElement lowerright = doc.createElement( "LOWERRIGHT" ); + sequence = doc.createElement( "SEQUENCE" ); + + impl->createTextElements( base, sequence ); + + lowerright.appendChild( sequence ); + index.appendChild( lowerright ); + + docnode.appendChild( index ); + } + } + else if ( type == "rational" ) { + TQDomNode n = element.firstChild(); + impl->createTextElements( n.toText().data().stripWhiteSpace(), + docnode ); + + n = n.nextSibling(); // <sep/> + impl->createTextElements( "/", docnode ); + + n = n.nextSibling(); + impl->createTextElements( n.toText().data().stripWhiteSpace(), + docnode ); + } + else if ( type == "complex-cartesian" ) { + TQDomNode n = element.firstChild(); + impl->createTextElements( n.toText().data().stripWhiteSpace(), + docnode ); + + n = n.nextSibling(); // <sep/> + impl->createTextElements( "+", docnode ); + + n = n.nextSibling(); + impl->createTextElements( n.toText().data().stripWhiteSpace(), + docnode ); + + impl->createTextElements( "i", docnode ); + } + + else if ( type == "complex-polar" ) { + TQDomNode n = element.firstChild(); + impl->createTextElements( n.toText().data().stripWhiteSpace(), + docnode ); + + n = n.nextSibling(); // <sep/> + TQDomElement index = doc.createElement( "INDEX" ); + TQDomElement content = doc.createElement( "CONTENT" ); + TQDomElement sequence = doc.createElement( "SEQUENCE" ); + TQDomElement textelement = doc.createElement( "TEXT" ); + textelement.setAttribute( "CHAR", "e" ); + sequence.appendChild( textelement ); + content.appendChild( sequence ); + index.appendChild( content ); + + TQDomElement upperright = doc.createElement( "UPPERRIGHT" ); + sequence = doc.createElement( "SEQUENCE" ); + textelement = doc.createElement( "TEXT" ); + textelement.setAttribute( "CHAR", "i" ); + sequence.appendChild( textelement ); + + n = n.nextSibling(); + impl->createTextElements( n.toText().data().stripWhiteSpace(), + sequence ); + + upperright.appendChild( sequence ); + index.appendChild( upperright ); + + docnode.appendChild( index ); + } + } + + else if ( tag == "ci" ) { + type = CONTENT; + TQDomNode n = element.firstChild(); + + if ( n.isText() ) { + impl->createTextElements( n.toText().data().stripWhiteSpace(), + docnode ); + } + else if ( n.isElement() ) { + TQDomElement e = n.toElement(); + processElement( e, doc, docnode ); + } + else if ( n.isEntityReference() ) { + kdDebug( DEBUGID ) << "isEntityReference: " + << n.toEntityReference().nodeName().latin1() + << endl; + } + else + kdDebug( DEBUGID ) << "ci: " << n.nodeName().latin1() << endl; + } + + else if ( tag == "list" ) { + type = CONTENT; + TQDomNode n = element.firstChild(); + + TQDomElement bracket = doc.createElement( "BRACKET" ); + bracket.setAttribute( "LEFT", 91 ); // [ + bracket.setAttribute( "RIGHT", 93 ); // ] + TQDomElement content = doc.createElement( "CONTENT" ); + TQDomElement sequence = doc.createElement( "SEQUENCE" ); + + bool first = true; + + while ( !n.isNull() ) { + if ( n.isElement() ) { + if ( !first ) { + TQDomElement textelement = doc.createElement( "TEXT" ); + textelement.setAttribute( "CHAR", "," ); + sequence.appendChild( textelement ); + } + first = false; + TQDomElement e = n.toElement(); + processElement( e, doc, sequence ); + } + n = n.nextSibling(); + } + + content.appendChild( sequence ); + bracket.appendChild( content ); + docnode.appendChild( bracket ); + } + } + + if ( type == UNKNOWN && node.nodeType() != TQDomNode::AttributeNode ) { + kdDebug() << "Not an element: " << node.nodeName() << endl; + TQDomNode n = node.firstChild(); + while ( !n.isNull() ) { + processElement( n, doc, docnode ); + n = n.nextSibling(); + } + } + + return true; +} + +KFORMULA_NAMESPACE_END + +using namespace KFormula; +#include "kformulamathmlread.moc" |