/* 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 <tqpainter.h>

#include <kdebug.h>
#include <tdelocale.h>

#include "elementvisitor.h"
#include "indexelement.h"
#include "formulacursor.h"
#include "formulaelement.h"
#include "kformulacommand.h"
#include "sequenceelement.h"


KFORMULA_NAMESPACE_BEGIN


class IndexSequenceElement : public SequenceElement {
    typedef SequenceElement inherited;
public:

    IndexSequenceElement( BasicElement* parent = 0 ) : SequenceElement( parent ) {}
    virtual IndexSequenceElement* clone() {
        return new IndexSequenceElement( *this );
    }

    /**
     * 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* IndexSequenceElement::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;
        }
        IndexElement* element = static_cast<IndexElement*>( getParent() );
        IndexRequest* ir = static_cast<IndexRequest*>( request );
        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 );
}


IndexElement::IndexElement(BasicElement* parent)
    : BasicElement(parent),
      m_subScriptShiftType( NoSize ),
      m_superScriptShiftType( NoSize ),
      m_customAccentUnder( false ),
      m_customAccent ( false )
{
    content = new IndexSequenceElement( this );

    upperLeft   = 0;
    upperMiddle = 0;
    upperRight  = 0;
    lowerLeft   = 0;
    lowerMiddle = 0;
    lowerRight  = 0;
}

IndexElement::~IndexElement()
{
    delete content;
    delete upperLeft;
    delete upperMiddle;
    delete upperRight;
    delete lowerLeft;
    delete lowerMiddle;
    delete lowerRight;
}


IndexElement::IndexElement( const IndexElement& other )
    : BasicElement( other ),
      m_subScriptShiftType( other.m_subScriptShiftType ),
      m_subScriptShift( other.m_subScriptShift ),
      m_superScriptShiftType( other.m_superScriptShiftType ),
      m_superScriptShift( other.m_superScriptShift ),
      m_customAccentUnder( other.m_customAccentUnder ),
      m_accentUnder( other.m_accentUnder ),
      m_customAccent ( other.m_customAccent ),
      m_accent( other.m_accent )      
{
    content = new IndexSequenceElement( *dynamic_cast<IndexSequenceElement*>( other.content ) );

    if ( other.upperLeft ) {
        upperLeft = new SequenceElement( *( other.upperLeft ) );
        upperLeft->setParent( this );
    }
    else {
        upperLeft = 0;
    }
    if ( other.upperMiddle ) {
        upperMiddle = new SequenceElement( *( other.upperMiddle ) );
        upperMiddle->setParent( this );
    }
    else {
        upperMiddle = 0;
    }
    if ( other.upperRight ) {
        upperRight = new SequenceElement( *( other.upperRight ) );
        upperRight->setParent( this );
    }
    else {
        upperRight = 0;
    }

    if ( other.lowerLeft ) {
        lowerLeft = new SequenceElement( *( other.lowerLeft ) );
        lowerLeft->setParent( this );
    }
    else {
        lowerLeft = 0;
    }
    if ( other.lowerMiddle ) {
        lowerMiddle = new SequenceElement( *( other.lowerMiddle ) );
        lowerMiddle->setParent( this );
    }
    else {
        lowerMiddle = 0;
    }
    if ( other.lowerRight ) {
        lowerRight = new SequenceElement( *( other.lowerRight ) );
        lowerRight->setParent( this );
    }
    else {
        lowerRight = 0;
    }
}


bool IndexElement::accept( ElementVisitor* visitor )
{
    return visitor->visit( this );
}


TQChar IndexElement::getCharacter() const
{
    if ( !content->isTextOnly() ) {
        return TQChar::null;
    }

    if ( hasUpperRight() && !upperRight->isTextOnly() ) {
        return TQChar::null;
    }
    if ( hasUpperMiddle() && !upperMiddle->isTextOnly() ) {
        return TQChar::null;
    }
    if ( hasUpperLeft() && !upperLeft->isTextOnly() ) {
        return TQChar::null;
    }
    if ( hasLowerRight() && !lowerRight->isTextOnly() ) {
        return TQChar::null;
    }
    if ( hasLowerMiddle() && !lowerMiddle->isTextOnly() ) {
        return TQChar::null;
    }
    if ( hasLowerLeft() && !lowerLeft->isTextOnly() ) {
        return TQChar::null;
    }

    return ' ';
}

void IndexElement::entered( SequenceElement* child )
{
    if ( child == content ) {
        formula()->tell( i18n( "Indexed list" ) );
    }
    else {
        formula()->tell( i18n( "Index" ) );
    }
}


/**
 * Returns the element the point is in.
 */
BasicElement* IndexElement::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 (hasUpperRight()) {
            e = upperRight->goToPos(cursor, handled, point, myPos);
            if (e != 0) return e;
        }
        if (hasUpperMiddle()) {
            e = upperMiddle->goToPos(cursor, handled, point, myPos);
            if (e != 0) return e;
        }
        if (hasUpperLeft()) {
            e = upperLeft->goToPos(cursor, handled, point, myPos);
            if (e != 0) return e;
        }
        if (hasLowerRight()) {
            e = lowerRight->goToPos(cursor, handled, point, myPos);
            if (e != 0) return e;
        }
        if (hasLowerMiddle()) {
            e = lowerMiddle->goToPos(cursor, handled, point, myPos);
            if (e != 0) return e;
        }
        if (hasLowerLeft()) {
            e = lowerLeft->goToPos(cursor, handled, point, myPos);
            if (e != 0) return e;
        }

        luPixel dx = point.x() - myPos.x();
        luPixel dy = point.y() - myPos.y();

        // the positions after the left indexes
        if (dx < content->getX()+content->getWidth()) {
            if (dy < content->getY()) {
                if (hasUpperMiddle() && (dx > upperMiddle->getX())) {
                    upperMiddle->moveLeft(cursor, this);
                    handled = true;
                    return upperMiddle;
                }
                if (hasUpperLeft() && (dx > upperLeft->getX())) {
                    upperLeft->moveLeft(cursor, this);
                    handled = true;
                    return upperLeft;
                }
            }
            else if (dy > content->getY()+content->getHeight()) {
                if (hasLowerMiddle() && (dx > lowerMiddle->getX())) {
                    lowerMiddle->moveLeft(cursor, this);
                    handled = true;
                    return lowerMiddle;
                }
                if (hasLowerLeft() && (dx > lowerLeft->getX())) {
                    lowerLeft->moveLeft(cursor, this);
                    handled = true;
                    return lowerLeft;
                }
            }
        }
        // the positions after the left indexes
        else {
            if (dy < content->getY()) {
                if (hasUpperRight()) {
                    upperRight->moveLeft(cursor, this);
                    handled = true;
                    return upperRight;
                }
            }
            else if (dy > content->getY()+content->getHeight()) {
                if (hasLowerRight()) {
                    lowerRight->moveLeft(cursor, this);
                    handled = true;
                    return lowerRight;
                }
            }
            else {
                content->moveLeft(cursor, this);
                handled = true;
                return content;
            }
        }

        return this;
    }
    return 0;
}


// drawing
//
// Drawing depends on a context which knows the required properties like
// fonts, spaces and such.
// It is essential to calculate elements size with the same context
// before you draw.


void IndexElement::setMiddleX(int xOffset, int middleWidth)
{
    content->setX(xOffset + (middleWidth - content->getWidth()) / 2);
    if (hasUpperMiddle()) {
        upperMiddle->setX(xOffset + (middleWidth - upperMiddle->getWidth()) / 2);
    }
    if (hasLowerMiddle()) {
        lowerMiddle->setX(xOffset + (middleWidth - lowerMiddle->getWidth()) / 2);
    }
}


/**
 * Calculates our width and height and
 * our children's parentPosition.
 */
void IndexElement::calcSizes(const ContextStyle& context, 
							 ContextStyle::TextStyle tstyle,
							 ContextStyle::IndexStyle istyle,
							 StyleAttributes& style )
{
    double factor = style.sizeFactor();
    luPixel distY = context.ptToPixelY( context.getThinSpace( tstyle, factor ) );

    ContextStyle::TextStyle i_tstyle = context.convertTextStyleIndex(tstyle);
    ContextStyle::IndexStyle u_istyle = context.convertIndexStyleUpper( istyle );
    ContextStyle::IndexStyle l_istyle = context.convertIndexStyleLower( istyle );

    // get the indexes size
    luPixel ulWidth = 0, ulHeight = 0, ulMidline = 0;
    if (hasUpperLeft()) {
	  upperLeft->calcSizes( context, i_tstyle, u_istyle, style );
        ulWidth = upperLeft->getWidth();
        ulHeight = upperLeft->getHeight();
        ulMidline = upperLeft->axis( context, i_tstyle, factor );
    }

    luPixel umWidth = 0, umHeight = 0, umMidline = 0;
    if (hasUpperMiddle()) {
        upperMiddle->calcSizes( context, i_tstyle, u_istyle, style );
        umWidth = upperMiddle->getWidth();
        umHeight = upperMiddle->getHeight() + distY;
        umMidline = upperMiddle->axis( context, i_tstyle, factor );
    }

    luPixel urWidth = 0, urHeight = 0, urMidline = 0;
    if (hasUpperRight()) {
        upperRight->calcSizes( context, i_tstyle, u_istyle, style );
        urWidth = upperRight->getWidth();
        urHeight = upperRight->getHeight();
        urMidline = upperRight->axis( context, i_tstyle, factor );
    }

    luPixel llWidth = 0, llHeight = 0, llMidline = 0;
    if (hasLowerLeft()) {
        lowerLeft->calcSizes( context, i_tstyle, l_istyle, style );
        llWidth = lowerLeft->getWidth();
        llHeight = lowerLeft->getHeight();
        llMidline = lowerLeft->axis( context, i_tstyle, factor );
    }

    luPixel lmWidth = 0, lmHeight = 0, lmMidline = 0;
    if (hasLowerMiddle()) {
        lowerMiddle->calcSizes( context, i_tstyle, l_istyle, style );
        lmWidth = lowerMiddle->getWidth();
        lmHeight = lowerMiddle->getHeight() + distY;
        lmMidline = lowerMiddle->axis( context, i_tstyle, factor );
    }

    luPixel lrWidth = 0, lrHeight = 0, lrMidline = 0;
    if (hasLowerRight()) {
        lowerRight->calcSizes( context, i_tstyle, l_istyle, style );
        lrWidth = lowerRight->getWidth();
        lrHeight = lowerRight->getHeight();
        lrMidline = lowerRight->axis( context, i_tstyle, factor );
    }

    // get the contents size
    content->calcSizes( context, tstyle, istyle, style );
    luPixel width = TQMAX(content->getWidth(), TQMAX(umWidth, lmWidth));
    luPixel toMidline = content->axis( context, tstyle, factor );
    luPixel fromMidline = content->getHeight() - toMidline;

    // calculate the x offsets
    if (ulWidth > llWidth) {
        upperLeft->setX(0);
        if (hasLowerLeft()) {
            lowerLeft->setX(ulWidth - llWidth);
        }
        setMiddleX(ulWidth, width);
        width += ulWidth;
    }
    else {
        if (hasUpperLeft()) {
            upperLeft->setX(llWidth - ulWidth);
        }
        if (hasLowerLeft()) {
            lowerLeft->setX(0);
        }
        setMiddleX(llWidth, width);
        width += llWidth;
    }

    if (hasUpperRight()) {
        upperRight->setX(width);
    }
    if (hasLowerRight()) {
        lowerRight->setX(width);
    }
    width += TQMAX(urWidth, lrWidth);

    // calculate the y offsets
    luPixel ulOffset = 0;
    luPixel urOffset = 0;
    luPixel llOffset = 0;
    luPixel lrOffset = 0;
    if (content->isTextOnly()) {
        luPt mySize = context.getAdjustedSize( tstyle, factor );
        TQFont font = context.getDefaultFont();
        font.setPointSizeFloat( context.layoutUnitPtToPt( mySize ) );

        TQFontMetrics fm(font);
        LuPixelRect bound = fm.boundingRect('x');

        luPixel exBaseline = context.ptToLayoutUnitPt( -bound.top() );

        // the upper half
        ulOffset = ulHeight + exBaseline - content->getBaseline();
        urOffset = urHeight + exBaseline - content->getBaseline();

        // the lower half
        llOffset = lrOffset = content->getBaseline();
    }
    else {

        // the upper half
        ulOffset = TQMAX(ulMidline, ulHeight-toMidline);
        urOffset = TQMAX(urMidline, urHeight-toMidline);

        // the lower half
        llOffset = TQMAX(content->getHeight()-llMidline, toMidline);
        lrOffset = TQMAX(content->getHeight()-lrMidline, toMidline);
    }

    // Add more offset if defined in attributes
    switch ( m_superScriptShiftType ) {
    case AbsoluteSize:
        urOffset += context.ptToLayoutUnitPt( m_superScriptShift );
        break;
    case RelativeSize:
        urOffset += urOffset * m_superScriptShift;
        break;
    case PixelSize:
        urOffset += context.pixelToLayoutUnitY( m_superScriptShift );
        break;
    default:
        break;
    }

    switch ( m_subScriptShiftType ) {
    case AbsoluteSize:
        lrOffset += context.ptToLayoutUnitPt( m_subScriptShift );
        break;
    case RelativeSize:
        lrOffset += lrOffset * m_subScriptShift;
        break;
    case PixelSize:
        lrOffset += context.pixelToLayoutUnitY( m_subScriptShift );
        break;
    default:
        break;
    }

    luPixel height = TQMAX(umHeight, TQMAX(ulOffset, urOffset));

    // the upper half
    content->setY(height);
    toMidline += height;
    if (hasUpperLeft()) {
        upperLeft->setY(height-ulOffset);
    }
    if (hasUpperMiddle()) {
        upperMiddle->setY(height-umHeight);
    }
    if (hasUpperRight()) {
        upperRight->setY( height - urOffset );
    }

    // the lower half
    if (hasLowerLeft()) {
        lowerLeft->setY(height+llOffset);
    }
    if (hasLowerMiddle()) {
        lowerMiddle->setY(height+content->getHeight()+distY);
    }
    if (hasLowerRight()) {
        lowerRight->setY( height + lrOffset );
    }

    fromMidline += TQMAX(TQMAX(llHeight+llOffset, lrHeight+lrOffset) - content->getHeight(), lmHeight);

    // set the result
    setWidth(width);
    setHeight(toMidline+fromMidline);
    if (content->isTextOnly()) {
        setBaseline(content->getY() + content->getBaseline());
        //setMidline(content->getY() + content->getMidline());
    }
    else {
        //setMidline(toMidline);
        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 IndexElement::draw( TQPainter& 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;

    ContextStyle::TextStyle i_tstyle = context.convertTextStyleIndex(tstyle);
    ContextStyle::IndexStyle u_istyle = context.convertIndexStyleUpper( istyle );
    ContextStyle::IndexStyle l_istyle = context.convertIndexStyleLower( istyle );

    content->draw(painter, r, context, tstyle, istyle, style, myPos);
    if (hasUpperLeft()) {
        upperLeft->draw(painter, r, context, i_tstyle, u_istyle, style, myPos);
    }
    if (hasUpperMiddle()) {
        upperMiddle->draw(painter, r, context, i_tstyle, u_istyle, style, myPos);
    }
    if (hasUpperRight()) {
        upperRight->draw(painter, r, context, i_tstyle, u_istyle, style, myPos);
    }
    if (hasLowerLeft()) {
        lowerLeft->draw(painter, r, context, i_tstyle, l_istyle, style, myPos);
    }
    if (hasLowerMiddle()) {
        lowerMiddle->draw(painter, r, context, i_tstyle, l_istyle, style, myPos);
    }
    if (hasLowerRight()) {
        lowerRight->draw(painter, r, context, i_tstyle, l_istyle, style, myPos);
    }

    // Debug
    //painter.setBrush(TQt::NoBrush);
    //painter.setPen(TQt::red);
    //painter.drawRect(myPos.x(), myPos.y(), getWidth(), getHeight());
    //painter.drawLine(myPos.x(), myPos.y()+getMidline(),
    //                 myPos.x()+getWidth(), myPos.y()+getMidline());
}


void IndexElement::dispatchFontCommand( FontCommand* cmd )
{
    content->dispatchFontCommand( cmd );
    if (hasUpperLeft()) {
        upperLeft->dispatchFontCommand( cmd );
    }
    if (hasUpperMiddle()) {
        upperMiddle->dispatchFontCommand( cmd );
    }
    if (hasUpperRight()) {
        upperRight->dispatchFontCommand( cmd );
    }
    if (hasLowerLeft()) {
        lowerLeft->dispatchFontCommand( cmd );
    }
    if (hasLowerMiddle()) {
        lowerMiddle->dispatchFontCommand( cmd );
    }
    if (hasLowerRight()) {
        lowerRight->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.

int IndexElement::getFromPos(BasicElement* from)
{
    if (from == lowerRight) {
        return lowerRightPos;
    }
    else if (from == upperRight) {
        return upperRightPos;
    }
    else if (from == lowerMiddle) {
        return lowerMiddlePos;
    }
    else if (from == content) {
        return contentPos;
    }
    else if (from == upperMiddle) {
        return upperMiddlePos;
    }
    else if (from == lowerLeft) {
        return lowerLeftPos;
    }
    else if (from == upperLeft) {
        return upperLeftPos;
    }
    return parentPos;
}

/**
 * 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 IndexElement::moveLeft(FormulaCursor* cursor, BasicElement* from)
{
    if (cursor->isSelectionMode()) {
        getParent()->moveLeft(cursor, this);
    }
    else {
        bool linear = cursor->getLinearMovement();
        int fromPos = getFromPos(from);
        if (!linear) {
            if ((fromPos == lowerRightPos) && hasLowerMiddle()) {
                lowerMiddle->moveLeft(cursor, this);
                return;
            }
            else if ((fromPos == upperRightPos) && hasUpperMiddle()) {
                upperMiddle->moveLeft(cursor, this);
                return;
            }
            else if ((fromPos == lowerMiddlePos) && hasLowerLeft()) {
                lowerLeft->moveLeft(cursor, this);
                return;
            }
            else if ((fromPos == upperMiddlePos) && hasUpperLeft()) {
                upperLeft->moveLeft(cursor, this);
                return;
            }
        }
        switch (fromPos) {
            case parentPos:
                if (hasLowerRight() && linear) {
                    lowerRight->moveLeft(cursor, this);
                    break;
                }
            case lowerRightPos:
                if (hasUpperRight() && linear) {
                    upperRight->moveLeft(cursor, this);
                    break;
                }
            case upperRightPos:
                if (hasLowerMiddle() && linear) {
                    lowerMiddle->moveLeft(cursor, this);
                    break;
                }
            case lowerMiddlePos:
                content->moveLeft(cursor, this);
                break;
            case contentPos:
                if (hasUpperMiddle() && linear) {
                    upperMiddle->moveLeft(cursor, this);
                    break;
                }
            case upperMiddlePos:
                if (hasLowerLeft() && linear) {
                    lowerLeft->moveLeft(cursor, this);
                    break;
                }
            case lowerLeftPos:
                if (hasUpperLeft() && linear) {
                    upperLeft->moveLeft(cursor, this);
                    break;
                }
            case upperLeftPos:
                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 IndexElement::moveRight(FormulaCursor* cursor, BasicElement* from)
{
    if (cursor->isSelectionMode()) {
        getParent()->moveRight(cursor, this);
    }
    else {
        bool linear = cursor->getLinearMovement();
        int fromPos = getFromPos(from);
        if (!linear) {
            if ((fromPos == lowerLeftPos) && hasLowerMiddle()) {
                lowerMiddle->moveRight(cursor, this);
                return;
            }
            else if ((fromPos == upperLeftPos) && hasUpperMiddle()) {
                upperMiddle->moveRight(cursor, this);
                return;
            }
            else if ((fromPos == lowerMiddlePos) && hasLowerRight()) {
                lowerRight->moveRight(cursor, this);
                return;
            }
            else if ((fromPos == upperMiddlePos) && hasUpperRight()) {
                upperRight->moveRight(cursor, this);
                return;
            }
        }
        switch (fromPos) {
            case parentPos:
                if (hasUpperLeft() && linear) {
                    upperLeft->moveRight(cursor, this);
                    break;
                }
            case upperLeftPos:
                if (hasLowerLeft() && linear) {
                    lowerLeft->moveRight(cursor, this);
                    break;
                }
            case lowerLeftPos:
                if (hasUpperMiddle() && linear) {
                    upperMiddle->moveRight(cursor, this);
                    break;
                }
            case upperMiddlePos:
                content->moveRight(cursor, this);
                break;
            case contentPos:
                if (hasLowerMiddle() && linear) {
                    lowerMiddle->moveRight(cursor, this);
                    break;
                }
            case lowerMiddlePos:
                if (hasUpperRight() && linear) {
                    upperRight->moveRight(cursor, this);
                    break;
                }
            case upperRightPos:
                if (hasLowerRight() && linear) {
                    lowerRight->moveRight(cursor, this);
                    break;
                }
            case lowerRightPos:
                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 IndexElement::moveUp(FormulaCursor* cursor, BasicElement* from)
{
    if (cursor->isSelectionMode()) {
        getParent()->moveUp(cursor, this);
    }
    else {
        if (from == content) {
            if ((cursor->getPos() == 0) && (cursor->getElement() == from)) {
                if (hasUpperLeft()) {
                    upperLeft->moveLeft(cursor, this);
                    return;
                }
                else if (hasUpperMiddle()) {
                    upperMiddle->moveRight(cursor, this);
                    return;
                }
            }
            if (hasUpperRight()) {
                upperRight->moveRight(cursor, this);
            }
            else if (hasUpperMiddle()) {
                upperMiddle->moveLeft(cursor, this);
            }
            else if (hasUpperLeft()) {
                upperLeft->moveLeft(cursor, this);
            }
            else {
                getParent()->moveUp(cursor, this);
            }
        }
        else if ((from == upperLeft) || (from == upperMiddle) || (from == upperRight)) {
            getParent()->moveUp(cursor, this);
        }
        else if ((from == getParent()) || (from == lowerLeft) || (from == lowerMiddle)) {
            content->moveRight(cursor, this);
        }
        else if (from == lowerRight) {
            content->moveLeft(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 IndexElement::moveDown(FormulaCursor* cursor, BasicElement* from)
{
    if (cursor->isSelectionMode()) {
        getParent()->moveDown(cursor, this);
    }
    else {
        if (from == content) {
            if ((cursor->getPos() == 0) && (cursor->getElement() == from)) {
                if (hasLowerLeft()) {
                    lowerLeft->moveLeft(cursor, this);
                    return;
                }
                else if (hasLowerMiddle()) {
                    lowerMiddle->moveRight(cursor, this);
                    return;
                }
            }
            if (hasLowerRight()) {
                lowerRight->moveRight(cursor, this);
            }
            else if (hasLowerMiddle()) {
                lowerMiddle->moveLeft(cursor, this);
            }
            else if (hasLowerLeft()) {
                lowerLeft->moveLeft(cursor, this);
            }
            else {
                getParent()->moveDown(cursor, this);
            }
        }
        else if ((from == lowerLeft) || (from == lowerMiddle) || (from == lowerRight)) {
            getParent()->moveDown(cursor, this);
        }
        else if ((from == getParent()) || (from == upperLeft) || (from == upperMiddle)) {
            content->moveRight(cursor, this);
        }
        if (from == upperRight) {
            content->moveLeft(cursor, this);
        }
    }
}


// children


// main child
//
// If an element has children one has to become the main one.

// void IndexElement::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 IndexElement::insert(FormulaCursor* cursor,
                          TQPtrList<BasicElement>& newChildren,
                          Direction direction)
{
    SequenceElement* index = static_cast<SequenceElement*>(newChildren.take(0));
    index->setParent(this);

    switch (cursor->getPos()) {
    case upperLeftPos:
        upperLeft = index;
        break;
    case lowerLeftPos:
        lowerLeft = index;
        break;
    case upperMiddlePos:
        upperMiddle = index;
        break;
    case lowerMiddlePos:
        lowerMiddle = index;
        break;
    case upperRightPos:
        upperRight = index;
        break;
    case lowerRightPos:
        lowerRight = 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 IndexElement::remove(FormulaCursor* cursor,
                          TQPtrList<BasicElement>& removedChildren,
                          Direction direction)
{
    int pos = cursor->getPos();
    switch (pos) {
    case upperLeftPos:
        removedChildren.append(upperLeft);
        formula()->elementRemoval(upperLeft);
        upperLeft = 0;
        setToUpperLeft(cursor);
        break;
    case lowerLeftPos:
        removedChildren.append(lowerLeft);
        formula()->elementRemoval(lowerLeft);
        lowerLeft = 0;
        setToLowerLeft(cursor);
        break;
    case contentPos: {
        BasicElement* parent = getParent();
        parent->selectChild(cursor, this);
        parent->remove(cursor, removedChildren, direction);
        break;
    }
    case upperMiddlePos:
        removedChildren.append(upperMiddle);
        formula()->elementRemoval(upperMiddle);
        upperMiddle = 0;
        setToUpperMiddle(cursor);
        break;
    case lowerMiddlePos:
        removedChildren.append(lowerMiddle);
        formula()->elementRemoval(lowerMiddle);
        lowerMiddle = 0;
        setToLowerMiddle(cursor);
        break;
    case upperRightPos:
        removedChildren.append(upperRight);
        formula()->elementRemoval(upperRight);
        upperRight = 0;
        setToUpperRight(cursor);
        break;
    case lowerRightPos:
        removedChildren.append(lowerRight);
        formula()->elementRemoval(lowerRight);
        lowerRight = 0;
        setToLowerRight(cursor);
        break;
    }
    formula()->changed();
}

/**
 * Moves the cursor to a normal place where new elements
 * might be inserted.
 */
void IndexElement::normalize(FormulaCursor* cursor, Direction direction)
{
    if (direction == beforeCursor) {
        content->moveLeft(cursor, this);
    }
    else {
        content->moveRight(cursor, this);
    }
}

/**
 * Returns wether the element has no more useful
 * children (except its main child) and should therefore
 * be replaced by its main child's content.
 */
bool IndexElement::isSenseless()
{
    return !hasUpperLeft() && !hasUpperRight() && !hasUpperMiddle() &&
        !hasLowerLeft() && !hasLowerRight() && !hasLowerMiddle();
}


/**
 * Returns the child at the cursor.
 */
BasicElement* IndexElement::getChild(FormulaCursor* cursor, Direction)
{
    int pos = cursor->getPos();
    /*
      It makes no sense to care for the direction.
    if (direction == beforeCursor) {
        pos -= 1;
    }
    */
    switch (pos) {
    case contentPos:
        return content;
    case upperLeftPos:
        return upperLeft;
    case lowerLeftPos:
        return lowerLeft;
    case upperMiddlePos:
        return upperMiddle;
    case lowerMiddlePos:
        return lowerMiddle;
    case upperRightPos:
        return upperRight;
    case lowerRightPos:
        return lowerRight;
    }
    return 0;
}


/**
 * Sets the cursor to select the child. The mark is placed before,
 * the position behind it.
 */
void IndexElement::selectChild(FormulaCursor* cursor, BasicElement* child)
{
    if (child == content) {
        setToContent(cursor);
    }
    else if (child == upperLeft) {
        setToUpperLeft(cursor);
    }
    else if (child == lowerLeft) {
        setToLowerLeft(cursor);
    }
    else if (child == upperMiddle) {
        setToUpperMiddle(cursor);
    }
    else if (child == lowerMiddle) {
        setToLowerMiddle(cursor);
    }
    else if (child == upperRight) {
        setToUpperRight(cursor);
    }
    else if (child == lowerRight) {
        setToLowerRight(cursor);
    }
}


/**
 * 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 IndexElement::setToContent(FormulaCursor* cursor)
{
    cursor->setTo(this, contentPos);
}

// point the cursor to a gap where an index is to be inserted.
// this makes no sense if there is such an index already.

void IndexElement::setToUpperLeft(FormulaCursor* cursor)
{
    cursor->setTo(this, upperLeftPos);
}

void IndexElement::setToUpperMiddle(FormulaCursor* cursor)
{
    cursor->setTo(this, upperMiddlePos);
}

void IndexElement::setToUpperRight(FormulaCursor* cursor)
{
    cursor->setTo(this, upperRightPos);
}

void IndexElement::setToLowerLeft(FormulaCursor* cursor)
{
    cursor->setTo(this, lowerLeftPos);
}

void IndexElement::setToLowerMiddle(FormulaCursor* cursor)
{
    cursor->setTo(this, lowerMiddlePos);
}

void IndexElement::setToLowerRight(FormulaCursor* cursor)
{
    cursor->setTo(this, lowerRightPos);
}


// move inside an index that exists already.

void IndexElement::moveToUpperLeft(FormulaCursor* cursor, Direction direction)
{
    if (hasUpperLeft()) {
        if (direction == beforeCursor) {
            upperLeft->moveLeft(cursor, this);
        }
        else {
            upperLeft->moveRight(cursor, this);
        }
    }
}

void IndexElement::moveToUpperMiddle(FormulaCursor* cursor, Direction direction)
{
    if (hasUpperMiddle()) {
        if (direction == beforeCursor) {
            upperMiddle->moveLeft(cursor, this);
        }
        else {
            upperMiddle->moveRight(cursor, this);
        }
    }
}

void IndexElement::moveToUpperRight(FormulaCursor* cursor, Direction direction)
{
    if (hasUpperRight()) {
        if (direction == beforeCursor) {
            upperRight->moveLeft(cursor, this);
        }
        else {
            upperRight->moveRight(cursor, this);
        }
    }
}

void IndexElement::moveToLowerLeft(FormulaCursor* cursor, Direction direction)
{
    if (hasLowerLeft()) {
        if (direction == beforeCursor) {
            lowerLeft->moveLeft(cursor, this);
        }
        else {
            lowerLeft->moveRight(cursor, this);
        }
    }
}

void IndexElement::moveToLowerMiddle(FormulaCursor* cursor, Direction direction)
{
    if (hasLowerMiddle()) {
        if (direction == beforeCursor) {
            lowerMiddle->moveLeft(cursor, this);
        }
        else {
            lowerMiddle->moveRight(cursor, this);
        }
    }
}

void IndexElement::moveToLowerRight(FormulaCursor* cursor, Direction direction)
{
    if (hasLowerRight()) {
        if (direction == beforeCursor) {
            lowerRight->moveLeft(cursor, this);
        }
        else {
            lowerRight->moveRight(cursor, this);
        }
    }
}


/**
 * Appends our attributes to the dom element.
 */
void IndexElement::writeDom(TQDomElement element)
{
    BasicElement::writeDom(element);

    TQDomDocument doc = element.ownerDocument();

    TQDomElement cont = doc.createElement("CONTENT");
    cont.appendChild(content->getElementDom(doc));
    element.appendChild(cont);

    if (hasUpperLeft()) {
        TQDomElement ind = doc.createElement("UPPERLEFT");
        ind.appendChild(upperLeft->getElementDom(doc));
        element.appendChild(ind);
    }
    if (hasUpperMiddle()) {
        TQDomElement ind = doc.createElement("UPPERMIDDLE");
        ind.appendChild(upperMiddle->getElementDom(doc));
        element.appendChild(ind);
    }
    if (hasUpperRight()) {
        TQDomElement ind = doc.createElement("UPPERRIGHT");
        ind.appendChild(upperRight->getElementDom(doc));
        element.appendChild(ind);
    }
    if (hasLowerLeft()) {
        TQDomElement ind = doc.createElement("LOWERLEFT");
        ind.appendChild(lowerLeft->getElementDom(doc));
        element.appendChild(ind);
    }
    if (hasLowerMiddle()) {
        TQDomElement ind = doc.createElement("LOWERMIDDLE");
        ind.appendChild(lowerMiddle->getElementDom(doc));
        element.appendChild(ind);
    }
    if (hasLowerRight()) {
        TQDomElement ind = doc.createElement("LOWERRIGHT");
        ind.appendChild(lowerRight->getElementDom(doc));
        element.appendChild(ind);
    }
}

/**
 * Reads our attributes from the element.
 * Returns false if it failed.
 */
bool IndexElement::readAttributesFromDom(TQDomElement element)
{
    if (!BasicElement::readAttributesFromDom(element)) {
        return false;
    }
    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 IndexElement::readContentFromDom(TQDomNode& node)
{
    if (!BasicElement::readContentFromDom(node)) {
        return false;
    }

    if ( !buildChild( content, node, "CONTENT" ) ) {
        kdWarning( DEBUGID ) << "Empty content in IndexElement." << endl;
        return false;
    }
    node = node.nextSibling();

    bool upperLeftRead = false;
    bool upperMiddleRead = false;
    bool upperRightRead = false;
    bool lowerLeftRead = false;
    bool lowerMiddleRead = false;
    bool lowerRightRead = false;

    while (!node.isNull() &&
           !(upperLeftRead && upperMiddleRead && upperRightRead &&
             lowerLeftRead && lowerMiddleRead && lowerRightRead)) {

        if (!upperLeftRead && (node.nodeName().upper() == "UPPERLEFT")) {
            upperLeftRead = buildChild( upperLeft=new SequenceElement( this ), node, "UPPERLEFT" );
            if ( !upperLeftRead ) return false;
        }

        if (!upperMiddleRead && (node.nodeName().upper() == "UPPERMIDDLE")) {
            upperMiddleRead = buildChild( upperMiddle=new SequenceElement( this ), node, "UPPERMIDDLE" );
            if ( !upperMiddleRead ) return false;
        }

        if (!upperRightRead && (node.nodeName().upper() == "UPPERRIGHT")) {
            upperRightRead = buildChild( upperRight=new SequenceElement( this ), node, "UPPERRIGHT" );
            if ( !upperRightRead ) return false;
        }

        if (!lowerLeftRead && (node.nodeName().upper() == "LOWERLEFT")) {
            lowerLeftRead = buildChild( lowerLeft=new SequenceElement( this ), node, "LOWERLEFT" );
            if ( !lowerLeftRead ) return false;
        }

        if (!lowerMiddleRead && (node.nodeName().upper() == "LOWERMIDDLE")) {
            lowerMiddleRead = buildChild( lowerMiddle=new SequenceElement( this ), node, "LOWERMIDDLE" );
            if ( !lowerMiddleRead ) return false;
        }

        if (!lowerRightRead && (node.nodeName().upper() == "LOWERRIGHT")) {
            lowerRightRead = buildChild( lowerRight=new SequenceElement( this ), node, "LOWERRIGHT" );
            if ( !lowerRightRead ) return false;
        }

        node = node.nextSibling();
    }
    return upperLeftRead || upperMiddleRead || upperRightRead ||
        lowerLeftRead || lowerMiddleRead || lowerRightRead;
}

bool IndexElement::readAttributesFromMathMLDom( const TQDomElement& element )
{
    if ( !BasicElement::readAttributesFromMathMLDom( element ) ) {
        return false;
    }

    TQString tag = element.tagName().stripWhiteSpace().lower();
    if ( tag == "msub" || tag == "msubsup" ) {
        TQString subscriptshiftStr = element.attribute( "subscriptshift" ).stripWhiteSpace().lower();
        if ( ! subscriptshiftStr.isNull() ) {
            m_subScriptShift = getSize( subscriptshiftStr, &m_subScriptShiftType );
        }
    }
    if ( tag == "msup" || tag == "msubsup" ) {
        TQString superscriptshiftStr = element.attribute( "superscriptshift" ).stripWhiteSpace().lower();
        if ( ! superscriptshiftStr.isNull() ) {
            m_superScriptShift = getSize( superscriptshiftStr, &m_superScriptShiftType );
        }
    }

    if ( tag == "munder" || tag == "munderover" ) {
        TQString accentunderStr = element.attribute( "accentunder" ).stripWhiteSpace().lower();
        if ( ! accentunderStr.isNull() ) {
            if ( accentunderStr == "true" ) {
                m_customAccentUnder = true;
                m_accentUnder = true;
            }
            else if ( accentunderStr == "false" ) {
                m_customAccentUnder = true;
                m_accentUnder = false;
            }
            else {
                kdWarning( DEBUGID ) << "Invalid value for attribute `accentunder': " 
                                     << accentunderStr << endl;
            }
        }
    }
    if ( tag == "mover" || tag == "munderover" ) {
        TQString accentStr = element.attribute( "accent" ).stripWhiteSpace().lower();
        if ( ! accentStr.isNull() ) {
            if ( accentStr == "true" ) {
                m_customAccent = true;
                m_accent = true;
            }
            else if ( accentStr == "false" ) {
                m_customAccent = true;
                m_accent = false;
            }
            else {
                kdWarning( DEBUGID ) << "Invalid value for attribute `accent': " 
                                     << accentStr << endl;
            }
        }
    }
    return true;
}

/**
 * Reads our content from the MathML node. Sets the node to the next node
 * that needs to be read. It is sometimes needed to read more than one node
 * (e. g. for fence operators).
 * Returns the number of nodes processed or -1 if it failed.
 */
int IndexElement::readContentFromMathMLDom( TQDomNode& node )
{
    if ( BasicElement::readContentFromMathMLDom( node ) == -1 ) {
        return -1;
    }

    int contentNumber = content->buildMathMLChild( node );
    if ( contentNumber == -1 ) {
        kdWarning( DEBUGID ) << "Empty base in Script" << endl;
        return -1;
    }
    for (int i = 0; i < contentNumber; i++ ) {
        if ( node.isNull() ) {
            return -1;
        }
        node = node.nextSibling();
    }

    TQString indexType = node.parentNode().toElement().tagName().lower();
    if ( indexType == "msub" ) {
        lowerRight = new SequenceElement( this );
        int lowerRightNumber = lowerRight->buildMathMLChild( node );
        if ( lowerRightNumber == -1 ) {
            kdWarning( DEBUGID ) << "Empty subscript in Script" << endl;
            return -1;
        }
        for (int i = 0; i < lowerRightNumber; i++ ) {
            if ( node.isNull() ) {
                return -1;
            }
            node = node.nextSibling();
        }

        return 1;
    }

    if ( indexType == "msup" ) {
        upperRight = new SequenceElement( this );
        int upperRightNumber = upperRight->buildMathMLChild( node );
        if ( upperRightNumber == -1 ) {
            kdWarning( DEBUGID ) << "Empty superscript in Script" << endl;
            return -1;
        }
        for (int i = 0; i < upperRightNumber; i++ ) {
            if ( node.isNull() ) {
                return -1;
            }
            node = node.nextSibling();
        }

        return 1;
    }

    if ( indexType == "msubsup" ) {
        lowerRight = new SequenceElement( this );
        int lowerRightNumber = lowerRight->buildMathMLChild( node );
        if ( lowerRightNumber == -1 ) {
            kdWarning( DEBUGID ) << "Empty subscript in Script" << endl;
            return -1;
        }
        for (int i = 0; i < lowerRightNumber; i++ ) {
            if ( node.isNull() ) {
                return -1;
            }
            node = node.nextSibling();
        }

        upperRight = new SequenceElement( this );
        int upperRightNumber = upperRight->buildMathMLChild( node );
        if ( upperRightNumber == -1 ) {
            kdWarning( DEBUGID ) << "Empty superscript in Script" << endl;
            return -1;
        }
        for (int i = 0; i < upperRightNumber; i++ ) {
            if ( node.isNull() ) {
                return -1;
            }
            node = node.nextSibling();
        }

        return 1;
    }
    if ( indexType == "munder" ) {
        lowerMiddle = new SequenceElement( this );
        int lowerMiddleNumber = lowerMiddle->buildMathMLChild( node );
        if ( lowerMiddleNumber == -1 ) {
            kdWarning( DEBUGID ) << "Empty underscript in Script" << endl;
            return -1;
        }
        for (int i = 0; i < lowerMiddleNumber; i++ ) {
            if ( node.isNull() ) {
                return -1;
            }
            node = node.nextSibling();
        }

        return 1;
    }

    if ( indexType == "mover" ) {
        upperMiddle = new SequenceElement( this );
        int upperMiddleNumber = upperMiddle->buildMathMLChild( node );
        if ( upperMiddleNumber == -1 ) {
            kdWarning( DEBUGID ) << "Empty overscript in Script" << endl;
            return -1;
        }
        for (int i = 0; i < upperMiddleNumber; i++ ) {
            if ( node.isNull() ) {
                return -1;
            }
            node = node.nextSibling();
        }

        return 1;
    }

    if ( indexType == "munderover" ) {
        lowerMiddle = new SequenceElement( this );
        int lowerMiddleNumber = lowerMiddle->buildMathMLChild( node );
        if ( lowerMiddleNumber == -1 ) {
            kdWarning( DEBUGID ) << "Empty underscript in Script" << endl;
            return -1;
        }
        for (int i = 0; i < lowerMiddleNumber; i++ ) {
            if ( node.isNull() ) {
                return -1;
            }
            node = node.nextSibling();
        }


        upperMiddle = new SequenceElement( this );
        int upperMiddleNumber = upperMiddle->buildMathMLChild( node );
        if ( upperMiddleNumber == -1 ) {
            kdWarning( DEBUGID ) << "Empty overscript in Script" << endl;
            return -1;
        }
        for (int i = 0; i < upperMiddleNumber; i++ ) {
            if ( node.isNull() ) {
                return -1;
            }
            node = node.nextSibling();
        }

        return 1;
    }
    // TODO: mmultiscripts, section 3.4.7
    return 1;
}


ElementIndexPtr IndexElement::getIndex( int position )
{
    switch (position) {
	case upperRightPos:
	    return getUpperRight();
	case lowerRightPos:
	    return getLowerRight();
	case lowerMiddlePos:
	    return getLowerMiddle();
	case upperMiddlePos:
	    return getUpperMiddle();
	case lowerLeftPos:
	    return getLowerLeft();
	case upperLeftPos:
	    return getUpperLeft();
    }
    return getUpperRight();
}



TQString IndexElement::toLatex()
{
    TQString index;

    if ( hasUpperMiddle() ) {
        index += "\\overset{" + upperMiddle->toLatex() + "}{";
    }

    if ( hasLowerMiddle() ) {
        index += "\\underset{" + lowerMiddle->toLatex() + "}{";
    }

    if ( hasUpperLeft() || hasUpperRight() ) { //Not sure that this is possible in Latex!
        /*index += "{}";
        if ( hasUpperLeft() )
            index += "^" + upperLeft->toLatex();
        if ( hasLowerLeft() )
            index += "_" + lowerLeft->toLatex();
        */
    }

    index += content->toLatex();

    if ( hasUpperRight() || hasLowerRight() ) {
        if ( hasUpperRight() )
            index += "^{" + upperRight->toLatex() + "}";
        if ( hasLowerRight() )
            index += "_{" + lowerRight->toLatex() + "}";
        index += " ";
    }

    if ( hasLowerMiddle() ) {
        index += "}";
    }

    if ( hasUpperMiddle() ) {
        index += "}";
    }

    return index;
}

TQString IndexElement::formulaString()
{
    TQString index = "(" + content->formulaString() + ")";
    if ( hasLowerRight() ) {
        index += "_(" + lowerRight->formulaString() + ")";
    }
    if ( hasUpperRight() ) {
        index += "**(" + upperRight->formulaString() + ")";
    }
    return index;
}

TQString IndexElement::getElementName() const
{
    if ( hasUpperMiddle() && hasLowerMiddle() )
        return "munderover";
    if ( hasUpperMiddle() )
        return "mover";
    if ( hasLowerMiddle() )
        return "munder";
    if ( hasLowerLeft() || hasUpperLeft() )
        return "mmultiscripts";
    if ( hasLowerRight() || hasUpperRight() ) {
        if ( ! hasUpperRight() )
            return "msub";
        if ( ! hasLowerRight() )
            return "msup";
    }
    return "msubsup";
}

void IndexElement::writeMathMLAttributes( TQDomElement& element ) const
{
    TQString tag = getElementName();
    if ( tag == "msub" || tag == "msubsup" ) {
        switch ( m_subScriptShiftType ) {
        case AbsoluteSize:
            element.setAttribute( "subscriptshift", TQString( "%1pt" ).arg( m_subScriptShift ) );
            break;
        case RelativeSize:
            element.setAttribute( "subscriptshift", TQString( "%1%" ).arg( m_subScriptShift * 100.0 ) );
            break;
        case PixelSize:
            element.setAttribute( "subscriptshift", TQString( "%1px" ).arg( m_subScriptShift ) );
            break;
        default:
            break;
        }
    }
    if ( tag == "msup" || tag == "msubsup" ) {
        switch ( m_superScriptShiftType ) {
        case AbsoluteSize:
            element.setAttribute( "superscriptshift", TQString( "%1pt" ).arg( m_superScriptShift ) );
            break;
        case RelativeSize:
            element.setAttribute( "superscriptshift", TQString( "%1%" ).arg( m_superScriptShift * 100.0 ) );
            break;
        case PixelSize:
            element.setAttribute( "superscriptshift", TQString( "%1px" ).arg( m_superScriptShift ) );
            break;
        default:
            break;
        }
    }
    if ( tag == "munder" || tag == "munderover" ) {
        if ( m_customAccentUnder ) {
            element.setAttribute( "accentunder", m_accentUnder ? "true" : "false" );
        }
    }
    if ( tag == "mover" || tag == "munderover" ) {
        if ( m_customAccent ) {
            element.setAttribute( "accent", m_accent ? "true" : "false" );
        }
    }
}


void IndexElement::writeMathMLContent( TQDomDocument& doc, 
                                       TQDomElement& element,
                                       bool oasisFormat ) const
{
    TQDomElement de;

    content->writeMathML( doc, element, oasisFormat ); // base
    if ( hasUpperMiddle() && hasLowerMiddle() )
    {
        lowerMiddle->writeMathML( doc, element, oasisFormat );
        upperMiddle->writeMathML( doc, element,oasisFormat );
    }
    else if ( hasUpperMiddle() )
    {
        upperMiddle->writeMathML( doc, element,oasisFormat );
    }
    else if ( hasLowerMiddle() )
    {
        lowerMiddle->writeMathML( doc, element,oasisFormat );
    }

    if ( hasLowerLeft() || hasUpperLeft() )
    {
        if ( hasLowerRight() )
            lowerRight->writeMathML( doc, element, oasisFormat );
        else
            element.appendChild( doc.createElement( "none" ) );

        if ( hasUpperRight() )
            upperRight->writeMathML( doc, element, oasisFormat );
        else
            element.appendChild( doc.createElement( "none" ) );
        
        element.appendChild( doc.createElement( "mprescripts" ) );

        if ( hasLowerLeft() )
            lowerLeft->writeMathML( doc, element, oasisFormat );
        else
            element.appendChild( doc.createElement( "none" ) );

        if ( hasUpperLeft() )
            upperLeft->writeMathML( doc, element, oasisFormat );
        else
            element.appendChild( doc.createElement( "none" ) );
    }
    else if ( hasLowerRight() || hasUpperRight() )
    {
        if ( !hasUpperRight() ) {
            lowerRight->writeMathML( doc, element, oasisFormat );
        }
        else if ( !hasLowerRight() ) {
            upperRight->writeMathML( doc, element, oasisFormat );
        }
        else // both
        {
            lowerRight->writeMathML( doc, element, oasisFormat );
            upperRight->writeMathML( doc, element,oasisFormat );
        }
    }
}

KFORMULA_NAMESPACE_END
