summaryrefslogtreecommitdiffstats
path: root/lib/kformula/kformulamathmlread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kformula/kformulamathmlread.cpp')
-rw-r--r--lib/kformula/kformulamathmlread.cpp1794
1 files changed, 1794 insertions, 0 deletions
diff --git a/lib/kformula/kformulamathmlread.cpp b/lib/kformula/kformulamathmlread.cpp
new file mode 100644
index 000000000..ff941d6f3
--- /dev/null
+++ b/lib/kformula/kformulamathmlread.cpp
@@ -0,0 +1,1794 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 Andrea Rizzi <rizzi@kde.org>
+ Ulrich Kuettler <ulrich.kuettler@mailbox.tu-dresden.de>
+
+ 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"