You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koffice/lib/kformula/kformulamathmlread.cpp

1795 lines
60 KiB

/* 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"