diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
commit | 8362bf63dea22bbf6736609b0f49c152f975eb63 (patch) | |
tree | 0eea3928e39e50fae91d4e68b21b1e6cbae25604 /lib/kformula/symbolelement.cc | |
download | koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.tar.gz koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.zip |
Added old abandoned KDE3 version of koffice
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'lib/kformula/symbolelement.cc')
-rw-r--r-- | lib/kformula/symbolelement.cc | 906 |
1 files changed, 906 insertions, 0 deletions
diff --git a/lib/kformula/symbolelement.cc b/lib/kformula/symbolelement.cc new file mode 100644 index 00000000..49932bee --- /dev/null +++ b/lib/kformula/symbolelement.cc @@ -0,0 +1,906 @@ +/* This file is part of the KDE project + Copyright (C) 2001 Andrea Rizzi <[email protected]> + Ulrich Kuettler <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include <qpainter.h> + +#include <kdebug.h> + +#include "elementvisitor.h" +#include "formulacursor.h" +#include "formulaelement.h" +#include "kformulacommand.h" +#include "sequenceelement.h" +#include "symbolelement.h" + +KFORMULA_NAMESPACE_BEGIN + + +class SymbolSequenceElement : public SequenceElement { + typedef SequenceElement inherited; +public: + + SymbolSequenceElement( BasicElement* parent = 0 ) : SequenceElement( parent ) {} + + /** + * This is called by the container to get a command depending on + * the current cursor position (this is how the element gets chosen) + * and the request. + * + * @returns the command that performs the requested action with + * the containers active cursor. + */ + virtual KCommand* buildCommand( Container*, Request* ); +}; + + +KCommand* SymbolSequenceElement::buildCommand( Container* container, Request* request ) +{ + FormulaCursor* cursor = container->activeCursor(); + if ( cursor->isReadOnly() ) { + return 0; + } + + switch ( *request ) { + case req_addIndex: { + FormulaCursor* cursor = container->activeCursor(); + if ( cursor->isSelection() || + ( cursor->getPos() > 0 && cursor->getPos() < countChildren() ) ) { + break; + } + IndexRequest* ir = static_cast<IndexRequest*>( request ); + if ( ( ir->index() == upperMiddlePos ) || ( ir->index() == lowerMiddlePos ) ) { + SymbolElement* element = static_cast<SymbolElement*>( getParent() ); + ElementIndexPtr index = element->getIndex( ir->index() ); + if ( !index->hasIndex() ) { + KFCAddGenericIndex* command = new KFCAddGenericIndex( container, index ); + return command; + } + else { + index->moveToIndex( cursor, afterCursor ); + cursor->setSelection( false ); + formula()->cursorHasMoved( cursor ); + return 0; + } + } + } + default: + break; + } + return inherited::buildCommand( container, request ); +} + + +SymbolElement::SymbolElement(SymbolType type, BasicElement* parent) + : BasicElement(parent), symbol( 0 ), symbolType( type ) +{ + content = new SymbolSequenceElement( this ); + upper = 0; + lower = 0; +} + +SymbolElement::~SymbolElement() +{ + delete lower; + delete upper; + delete content; + delete symbol; +} + + +SymbolElement::SymbolElement( const SymbolElement& other ) + : BasicElement( other ), symbol( 0 ), symbolType( other.symbolType ) +{ + content = new SymbolSequenceElement( *dynamic_cast<SymbolSequenceElement*>( other.content ) ); + content->setParent( this ); + + if ( other.upper ) { + upper = new SequenceElement( *( other.upper ) ); + upper->setParent( this ); + } + else { + upper = 0; + } + if ( other.lower ) { + lower = new SequenceElement( *( other.lower ) ); + lower->setParent( this ); + } + else { + lower = 0; + } +} + + +bool SymbolElement::accept( ElementVisitor* visitor ) +{ + return visitor->visit( this ); +} + + +BasicElement* SymbolElement::goToPos( FormulaCursor* cursor, bool& handled, + const LuPixelPoint& point, const LuPixelPoint& parentOrigin ) +{ + BasicElement* e = BasicElement::goToPos(cursor, handled, point, parentOrigin); + if (e != 0) { + LuPixelPoint myPos(parentOrigin.x() + getX(), + parentOrigin.y() + getY()); + + e = content->goToPos(cursor, handled, point, myPos); + if (e != 0) { + return e; + } + if (hasLower()) { + e = lower->goToPos(cursor, handled, point, myPos); + if (e != 0) { + return e; + } + } + if (hasUpper()) { + e = upper->goToPos(cursor, handled, point, myPos); + if (e != 0) { + return e; + } + } + + // the positions after the indexes. + luPixel dx = point.x() - myPos.x(); + luPixel dy = point.y() - myPos.y(); + if (dy < symbol->getY()) { + if (hasUpper() && (dx > upper->getX())) { + upper->moveLeft(cursor, this); + handled = true; + return upper; + } + } + else if (dy > symbol->getY()+symbol->getHeight()) { + if (hasLower() && (dx > lower->getX())) { + lower->moveLeft(cursor, this); + handled = true; + return lower; + } + } + + // Have the cursor jump behind the integral. + if ( ( dx < symbol->getX()+symbol->getWidth() ) && + ( dx > symbol->getX()+symbol->getWidth()/2 ) ) { + content->moveRight( cursor, this ); + handled = true; + return content; + } + + return this; + } + return 0; +} + + +/** + * Calculates our width and height and + * our children's parentPosition. + */ +void SymbolElement::calcSizes( const ContextStyle& context, + ContextStyle::TextStyle tstyle, + ContextStyle::IndexStyle istyle, + StyleAttributes& style ) +{ + double factor = style.sizeFactor(); + luPt mySize = context.getAdjustedSize( tstyle, factor ); + luPixel distX = context.ptToPixelX( context.getThinSpace( tstyle, factor ) ); + luPixel distY = context.ptToPixelY( context.getThinSpace( tstyle, factor ) ); + + //if ( symbol == 0 ) { + delete symbol; + symbol = context.fontStyle().createArtwork( symbolType ); + //} + + symbol->calcSizes(context, tstyle, factor, mySize); + content->calcSizes( context, tstyle, istyle, style ); + + //symbol->scale(((double)parentSize)/symbol->getHeight()*2); + + luPixel upperWidth = 0; + luPixel upperHeight = 0; + if (hasUpper()) { + upper->calcSizes( context, context.convertTextStyleIndex( tstyle ), + context.convertIndexStyleUpper( istyle ), style ); + upperWidth = upper->getWidth(); + upperHeight = upper->getHeight() + distY; + } + + luPixel lowerWidth = 0; + luPixel lowerHeight = 0; + if (hasLower()) { + lower->calcSizes( context, context.convertTextStyleIndex( tstyle ), + context.convertIndexStyleLower( istyle ), style ); + lowerWidth = lower->getWidth(); + lowerHeight = lower->getHeight() + distY; + } + + // widths + luPixel xOffset = QMAX(symbol->getWidth(), QMAX(upperWidth, lowerWidth)); + if (context.getCenterSymbol()) { + symbol->setX((xOffset - symbol->getWidth()) / 2); + } + else { + symbol->setX(xOffset - symbol->getWidth()); + } + // ??? + content->setX(xOffset + + static_cast<luPixel>( symbol->slant()*symbol->getHeight()/2 ) + + distX/2); + + setWidth(QMAX(content->getX() + content->getWidth(), + QMAX(upperWidth, lowerWidth))); + + // heights + //int toMidline = QMAX(content->getHeight() / 2, + luPixel toMidline = QMAX(content->axis( context, tstyle, factor ), + upperHeight + symbol->getHeight()/2); + //int fromMidline = QMAX(content->getHeight() / 2, + luPixel fromMidline = QMAX(content->getHeight() - content->axis( context, tstyle, factor ), + lowerHeight + symbol->getHeight()/2); + setHeight(toMidline + fromMidline); + //setMidline(toMidline); + + symbol->setY(toMidline - symbol->getHeight()/2); + //content->setY(toMidline - content->getHeight()/2); + content->setY(toMidline - content->axis( context, tstyle, factor )); + + if (hasUpper()) { + luPixel slant = + static_cast<luPixel>( symbol->slant()*( symbol->getHeight()+distY ) ); + if (context.getCenterSymbol()) { + upper->setX((xOffset - upperWidth) / 2 + slant ); + } + else { + if (upperWidth < symbol->getWidth()) { + upper->setX(symbol->getX() + + (symbol->getWidth() - upperWidth) / 2 + slant ); + } + else { + upper->setX(xOffset - upperWidth); + } + } + upper->setY(toMidline - upperHeight - symbol->getHeight()/2); + } + if (hasLower()) { + luPixel slant = static_cast<luPixel>( -symbol->slant()*distY ); + if (context.getCenterSymbol()) { + lower->setX((xOffset - lowerWidth) / 2 + slant); + } + else { + if (lowerWidth < symbol->getWidth()) { + lower->setX(symbol->getX() + + (symbol->getWidth() - lowerWidth) / 2 + slant ); + } + else { + lower->setX(xOffset - lowerWidth); + } + } + lower->setY(toMidline + symbol->getHeight()/2 + distY); + } + setBaseline(content->getBaseline() + content->getY()); +} + +/** + * Draws the whole element including its children. + * The `parentOrigin' is the point this element's parent starts. + * We can use our parentPosition to get our own origin then. + */ +void SymbolElement::draw( QPainter& painter, const LuPixelRect& r, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + ContextStyle::IndexStyle istyle, + StyleAttributes& style, + const LuPixelPoint& parentOrigin ) +{ + LuPixelPoint myPos( parentOrigin.x()+getX(), parentOrigin.y()+getY() ); + //if ( !LuPixelRect( myPos.x(), myPos.y(), getWidth(), getHeight() ).intersects( r ) ) + // return; + + luPt mySize = context.getAdjustedSize( tstyle, style.sizeFactor() ); + symbol->draw( painter, r, context, tstyle, style, mySize, myPos ); + content->draw( painter, r, context, tstyle, istyle, style, myPos ); + if ( hasUpper() ) { + upper->draw( painter, r, context, context.convertTextStyleIndex( tstyle ), + context.convertIndexStyleUpper( istyle ), style, myPos ); + } + if ( hasLower() ) { + lower->draw( painter, r, context, context.convertTextStyleIndex( tstyle ), + context.convertIndexStyleLower( istyle ), style, myPos ); + } + + // Debug +#if 0 + painter.setBrush(Qt::NoBrush); + painter.setPen(Qt::red); +// painter.drawRect( context.layoutUnitToPixelX( myPos.x() ), +// context.layoutUnitToPixelY( myPos.y() ), +// context.layoutUnitToPixelX( getWidth() ), +// context.layoutUnitToPixelY( getHeight() ) ); + painter.drawRect( context.layoutUnitToPixelX( myPos.x()+symbol->getX() ), + context.layoutUnitToPixelY( myPos.y()+symbol->getY() ), + context.layoutUnitToPixelX( symbol->getWidth() ), + context.layoutUnitToPixelY( symbol->getHeight() ) ); + painter.setPen(Qt::green); + painter.drawLine( context.layoutUnitToPixelX( myPos.x() ), + context.layoutUnitToPixelY( myPos.y()+axis(context, tstyle) ), + context.layoutUnitToPixelX( myPos.x()+getWidth() ), + context.layoutUnitToPixelY( myPos.y()+axis(context, tstyle) ) ); +#endif +} + + +void SymbolElement::dispatchFontCommand( FontCommand* cmd ) +{ + content->dispatchFontCommand( cmd ); + if ( hasUpper() ) { + upper->dispatchFontCommand( cmd ); + } + if ( hasLower() ) { + lower->dispatchFontCommand( cmd ); + } +} + +// navigation +// +// The elements are responsible to handle cursor movement themselves. +// To do this they need to know the direction the cursor moves and +// the element it comes from. +// +// The cursor might be in normal or in selection mode. + +/** + * Enters this element while moving to the left starting inside + * the element `from'. Searches for a cursor position inside + * this element or to the left of it. + */ +void SymbolElement::moveLeft(FormulaCursor* cursor, BasicElement* from) +{ + if (cursor->isSelectionMode()) { + getParent()->moveLeft(cursor, this); + } + else { + bool linear = cursor->getLinearMovement(); + if (from == getParent()) { + content->moveLeft(cursor, this); + } + else if (from == content) { + if (linear && hasLower()) { + lower->moveLeft(cursor, this); + } + else if (linear && hasUpper()) { + upper->moveLeft(cursor, this); + } + else { + getParent()->moveLeft(cursor, this); + } + } + else if (from == lower) { + if (linear && hasUpper()) { + upper->moveLeft(cursor, this); + } + else { + getParent()->moveLeft(cursor, this); + } + } + else if (from == upper) { + getParent()->moveLeft(cursor, this); + } + } +} + +/** + * Enters this element while moving to the right starting inside + * the element `from'. Searches for a cursor position inside + * this element or to the right of it. + */ +void SymbolElement::moveRight(FormulaCursor* cursor, BasicElement* from) +{ + if (cursor->isSelectionMode()) { + getParent()->moveRight(cursor, this); + } + else { + bool linear = cursor->getLinearMovement(); + if (from == getParent()) { + if (linear && hasUpper()) { + upper->moveRight(cursor, this); + } + else if (linear && hasLower()) { + lower->moveRight(cursor, this); + } + else { + content->moveRight(cursor, this); + } + } + else if (from == upper) { + if (linear && hasLower()) { + lower->moveRight(cursor, this); + } + else { + content->moveRight(cursor, this); + } + } + else if (from == lower) { + content->moveRight(cursor, this); + } + else if (from == content) { + getParent()->moveRight(cursor, this); + } + } +} + +/** + * Enters this element while moving up starting inside + * the element `from'. Searches for a cursor position inside + * this element or above it. + */ +void SymbolElement::moveUp(FormulaCursor* cursor, BasicElement* from) +{ + if (cursor->isSelectionMode()) { + getParent()->moveUp(cursor, this); + } + else { + if (from == content) { + if (hasUpper()) { + upper->moveLeft(cursor, this); + } + else { + getParent()->moveUp(cursor, this); + } + } + else if (from == upper) { + getParent()->moveUp(cursor, this); + } + else if ((from == getParent()) || (from == lower)) { + content->moveRight(cursor, this); + } + } +} + +/** + * Enters this element while moving down starting inside + * the element `from'. Searches for a cursor position inside + * this element or below it. + */ +void SymbolElement::moveDown(FormulaCursor* cursor, BasicElement* from) +{ + if (cursor->isSelectionMode()) { + getParent()->moveDown(cursor, this); + } + else { + if (from == content) { + if (hasLower()) { + lower->moveLeft(cursor, this); + } + else { + getParent()->moveDown(cursor, this); + } + } + else if (from == lower) { + getParent()->moveDown(cursor, this); + } + else if ((from == getParent()) || (from == upper)) { + content->moveRight(cursor, this); + } + } +} + +// children + +// main child +// +// If an element has children one has to become the main one. + +// void SymbolElement::setMainChild(SequenceElement* child) +// { +// formula()->elementRemoval(content); +// content = child; +// content->setParent(this); +// formula()->changed(); +// } + + +/** + * Inserts all new children at the cursor position. Places the + * cursor according to the direction. + * + * You only can insert one index at a time. So the list must contain + * exactly on SequenceElement. And the index you want to insert + * must not exist already. + * + * The list will be emptied but stays the property of the caller. + */ +void SymbolElement::insert(FormulaCursor* cursor, + QPtrList<BasicElement>& newChildren, + Direction direction) +{ + SequenceElement* index = static_cast<SequenceElement*>(newChildren.take(0)); + index->setParent(this); + + switch (cursor->getPos()) { + case upperMiddlePos: + upper = index; + break; + case lowerMiddlePos: + lower = index; + break; + default: + // this is an error! + return; + } + + if (direction == beforeCursor) { + index->moveLeft(cursor, this); + } + else { + index->moveRight(cursor, this); + } + cursor->setSelection(false); + formula()->changed(); +} + +/** + * Removes all selected children and returns them. Places the + * cursor to where the children have been. + * + * The cursor has to be inside one of our indexes which is supposed + * to be empty. The index will be removed and the cursor will + * be placed to the removed index so it can be inserted again. + * This methode is called by SequenceElement::remove only. + * + * The ownership of the list is passed to the caller. + */ +void SymbolElement::remove(FormulaCursor* cursor, + QPtrList<BasicElement>& removedChildren, + Direction direction) +{ + int pos = cursor->getPos(); + switch (pos) { + case upperMiddlePos: + removedChildren.append(upper); + formula()->elementRemoval(upper); + upper = 0; + setToUpper(cursor); + break; + case lowerMiddlePos: + removedChildren.append(lower); + formula()->elementRemoval(lower); + lower = 0; + setToLower(cursor); + break; + case contentPos: { + BasicElement* parent = getParent(); + parent->selectChild(cursor, this); + parent->remove(cursor, removedChildren, direction); + break; + } + } + formula()->changed(); +} + +/** + * Moves the cursor to a normal place where new elements + * might be inserted. + */ +void SymbolElement::normalize(FormulaCursor* cursor, Direction direction) +{ + if (direction == beforeCursor) { + content->moveLeft(cursor, this); + } + else { + content->moveRight(cursor, this); + } +} + +/** + * Returns the child at the cursor. + */ +BasicElement* SymbolElement::getChild(FormulaCursor* cursor, Direction) +{ + int pos = cursor->getPos(); + switch (pos) { + case contentPos: + return content; + case upperMiddlePos: + return upper; + case lowerMiddlePos: + return lower; + } + return 0; +} + +/** + * Sets the cursor to select the child. The mark is placed before, + * the position behind it. + */ +void SymbolElement::selectChild(FormulaCursor* cursor, BasicElement* child) +{ + if (child == content) { + setToContent(cursor); + } + else if (child == upper) { + setToUpper(cursor); + } + else if (child == lower) { + setToLower(cursor); + } +} + +void SymbolElement::setToUpper(FormulaCursor* cursor) +{ + cursor->setTo(this, upperMiddlePos); +} + +void SymbolElement::setToLower(FormulaCursor* cursor) +{ + cursor->setTo(this, lowerMiddlePos); +} + +/** + * Sets the cursor to point to the place where the content is. + * There always is a content so this is not a useful place. + * No insertion or removal will succeed as long as the cursor is + * there. + */ +void SymbolElement::setToContent(FormulaCursor* cursor) +{ + cursor->setTo(this, contentPos); +} + + +void SymbolElement::moveToUpper(FormulaCursor* cursor, Direction direction) +{ + if (hasUpper()) { + if (direction == beforeCursor) { + upper->moveLeft(cursor, this); + } + else { + upper->moveRight(cursor, this); + } + } +} + +void SymbolElement::moveToLower(FormulaCursor* cursor, Direction direction) +{ + if (hasLower()) { + if (direction == beforeCursor) { + lower->moveLeft(cursor, this); + } + else { + lower->moveRight(cursor, this); + } + } +} + + +ElementIndexPtr SymbolElement::getIndex( int position ) +{ + switch ( position ) { + case lowerMiddlePos: + return getLowerIndex(); + case upperMiddlePos: + return getUpperIndex(); + } + return getUpperIndex(); +} + + +/** + * Appends our attributes to the dom element. + */ +void SymbolElement::writeDom(QDomElement element) +{ + BasicElement::writeDom(element); + + element.setAttribute("TYPE", symbolType); + + QDomDocument doc = element.ownerDocument(); + + QDomElement con = doc.createElement("CONTENT"); + con.appendChild(content->getElementDom(doc)); + element.appendChild(con); + + if(hasLower()) { + QDomElement ind = doc.createElement("LOWER"); + ind.appendChild(lower->getElementDom(doc)); + element.appendChild(ind); + } + if(hasUpper()) { + QDomElement ind = doc.createElement("UPPER"); + ind.appendChild(upper->getElementDom(doc)); + element.appendChild(ind); + } +} + +/** + * Reads our attributes from the element. + * Returns false if it failed. + */ +bool SymbolElement::readAttributesFromDom(QDomElement element) +{ + if (!BasicElement::readAttributesFromDom(element)) { + return false; + } + + QString typeStr = element.attribute("TYPE"); + if(!typeStr.isNull()) { + symbolType = static_cast<SymbolType>(typeStr.toInt()); + } + + return true; +} + +/** + * Reads our content from the node. Sets the node to the next node + * that needs to be read. + * Returns false if it failed. + */ +bool SymbolElement::readContentFromDom(QDomNode& node) +{ + if (!BasicElement::readContentFromDom(node)) { + return false; + } + + if ( !buildChild( content, node, "CONTENT" ) ) { + kdWarning( DEBUGID ) << "Empty content in SymbolElement." << endl; + return false; + } + node = node.nextSibling(); + + bool lowerRead = false; + bool upperRead = false; + + while (!node.isNull() && !(upperRead && lowerRead)) { + + if (!lowerRead && (node.nodeName().upper() == "LOWER")) { + lowerRead = buildChild( lower=new SequenceElement( this ), node, "LOWER" ); + if ( !lowerRead ) return false; + } + + if (!upperRead && (node.nodeName().upper() == "UPPER")) { + upperRead = buildChild( upper=new SequenceElement( this ), node, "UPPER" ); + if ( !upperRead ) return false; + } + + node = node.nextSibling(); + } + return true; +} + +QString SymbolElement::toLatex() +{ + QString sym; + + switch(symbolType) { + + case 1001: + sym="\\int"; + break; + case 1002: + sym="\\sum"; + break; + case 1003: + sym="\\prod"; + break; + + default: + sym=" "; + + } + + + if(hasLower()) { + sym+="_{"; + sym+=lower->toLatex(); + sym+="}"; + } + + if(hasUpper()) { + sym+="^{"; + sym+=upper->toLatex(); + sym+="} "; + } + + sym += " "; + + sym+=content->toLatex(); + + + return sym; +} + +QString SymbolElement::formulaString() +{ + QString sym; + switch ( symbolType ) { + case 1001: + sym="int("; + break; + case 1002: + sym="sum("; + break; + case 1003: + sym="prod("; + break; + default: + sym="("; + } + sym += content->formulaString(); + if ( hasLower() ) { + sym += ", " + lower->formulaString(); + } + if ( hasUpper() ) { + sym += ", " + upper->formulaString(); + } + return sym + ")"; +} + +void SymbolElement::writeMathML( QDomDocument& doc, QDomNode& parent, bool oasisFormat ) const +{ + QDomElement de = doc.createElement( oasisFormat ? "math:mrow" : "mrow" ); + QDomElement mo = doc.createElement( oasisFormat ? "math:mo" : "mo" ); + + QString value; + + switch( symbolType ) + { + case EmptyBracket: break; + case LeftLineBracket: case RightLineBracket: + mo.appendChild( doc.createTextNode( "|" ) ); break; + case Integral: + mo.appendChild( doc.createEntityReference( "int" ) ); break; + case Sum: + mo.appendChild( doc.createEntityReference( "sum" ) ); break; + case Product: + mo.appendChild( doc.createEntityReference( "prod" ) ); break; + default: + mo.appendChild( doc.createTextNode( QChar( symbolType ) ) ); + } + + QDomElement between; + if ( hasUpper() && hasLower() ) + { + between = doc.createElement( oasisFormat ? "math:msubsup" : "msubsup" ); + between.appendChild( mo ); + lower->writeMathML( doc, between, oasisFormat ); + upper->writeMathML( doc, between, oasisFormat ); + } + else if ( hasUpper() ) + { + between = doc.createElement( oasisFormat ? "math:msup" : "msup" ); + between.appendChild( mo ); + upper->writeMathML( doc, between, oasisFormat ); + } + else if ( hasLower() ) + { + between = doc.createElement( oasisFormat ? "math:msub" : "msub" ); + between.appendChild( mo ); + lower->writeMathML( doc, between, oasisFormat ); + } + else + between = mo; + + de.appendChild( between ); + content->writeMathML( doc, de, oasisFormat ); + + parent.appendChild( de ); +} + +KFORMULA_NAMESPACE_END |