diff options
author | Michele Calgaro <michele.calgaro@yahoo.it> | 2021-05-23 20:48:35 +0900 |
---|---|---|
committer | Michele Calgaro <michele.calgaro@yahoo.it> | 2021-05-29 15:16:28 +0900 |
commit | 8b78a8791bc539bcffe7159f9d9714d577cb3d7d (patch) | |
tree | 1328291f966f19a22d7b13657d3f01a588eb1083 /lib/kformula/sequenceelement.cpp | |
parent | 95834e2bdc5e01ae1bd21ac0dfa4fa1d2417fae9 (diff) | |
download | koffice-8b78a8791bc539bcffe7159f9d9714d577cb3d7d.tar.gz koffice-8b78a8791bc539bcffe7159f9d9714d577cb3d7d.zip |
Renaming of files in preparation for code style tools.
Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it>
Diffstat (limited to 'lib/kformula/sequenceelement.cpp')
-rw-r--r-- | lib/kformula/sequenceelement.cpp | 1934 |
1 files changed, 1934 insertions, 0 deletions
diff --git a/lib/kformula/sequenceelement.cpp b/lib/kformula/sequenceelement.cpp new file mode 100644 index 00000000..187bcd65 --- /dev/null +++ b/lib/kformula/sequenceelement.cpp @@ -0,0 +1,1934 @@ +/* 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 <stdlib.h> +#include <math.h> + +#include <tqpainter.h> +#include <tqpaintdevice.h> +#include <tqvaluestack.h> + +#include <kcommand.h> +#include <kdebug.h> +#include <tdelocale.h> + +//#include <boost/spirit.hpp> + +#include "MatrixDialog.h" +#include "bracketelement.h" +#include "creationstrategy.h" +#include "elementtype.h" +#include "elementvisitor.h" +#include "formulacursor.h" +#include "formulaelement.h" +#include "fractionelement.h" +#include "indexelement.h" +#include "kformulacommand.h" +#include "kformulacontainer.h" +#include "kformuladocument.h" +#include "matrixelement.h" +#include "rootelement.h" +#include "sequenceelement.h" +#include "sequenceparser.h" +#include "spaceelement.h" +#include "symbolelement.h" +#include "symboltable.h" +#include "textelement.h" +#include "numberelement.h" +#include "identifierelement.h" +#include "operatorelement.h" + +#include <assert.h> + +KFORMULA_NAMESPACE_BEGIN +//using namespace std; + +ElementCreationStrategy* SequenceElement::creationStrategy = 0; + +void SequenceElement::setCreationStrategy( ElementCreationStrategy* strategy ) +{ + creationStrategy = strategy; +} + +void SequenceElement::setStyle( StyleElement *st ) +{ + style = st; +} + +SequenceElement::SequenceElement(BasicElement* parent) + : BasicElement(parent), parseTree(0), textSequence(true),singlePipe(true), style(0) +{ + assert( creationStrategy != 0 ); + children.setAutoDelete(true); +} + + +SequenceElement::~SequenceElement() +{ + delete parseTree; +} + +SequenceElement::SequenceElement( const SequenceElement& other ) + : BasicElement( other ) +{ + children.setAutoDelete(true); + uint count = other.children.count(); + for (uint i = 0; i < count; i++) { + BasicElement* child = children.at(i)->clone(); + child->setParent( this ); + children.append( child ); + } +} + + +bool SequenceElement::accept( ElementVisitor* visitor ) +{ + return visitor->visit( this ); +} + + +bool SequenceElement::readOnly( const FormulaCursor* ) const +{ + return getParent()->readOnly( this ); +} + + +/** + * Returns the element the point is in. + */ +BasicElement* SequenceElement::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()); + + uint count = children.count(); + for (uint i = 0; i < count; i++) { + BasicElement* child = children.at(i); + e = child->goToPos(cursor, handled, point, myPos); + if (e != 0) { + if (!handled) { + handled = true; + if ((point.x() - myPos.x()) < (e->getX() + e->getWidth()*2/3)) { + cursor->setTo(this, children.find(e)); + } + else { + cursor->setTo(this, children.find(e)+1); + } + } + return e; + } + } + + luPixel dx = point.x() - myPos.x(); + //int dy = point.y() - myPos.y(); + + for (uint i = 0; i < count; i++) { + BasicElement* child = children.at(i); + if (dx < child->getX()) { + cursor->setTo( this, i ); + handled = true; + return children.at( i ); + } + } + + cursor->setTo(this, countChildren()); + handled = true; + return this; + } + return 0; +} + + +bool SequenceElement::isEmpty() +{ + uint count = children.count(); + for (uint i = 0; i < count; i++) { + BasicElement* child = children.at(i); + if (!child->isInvisible()) { + return false; + } + } + return true; +} + + +/** + * Calculates our width and height and + * our children's parentPosition. + */ +void SequenceElement::calcSizes( const ContextStyle& context, + ContextStyle::TextStyle tstyle, + ContextStyle::IndexStyle istyle, + StyleAttributes& style ) +{ + double factor = style.sizeFactor(); + if (!isEmpty()) { + luPixel width = 0; + luPixel toBaseline = 0; + luPixel fromBaseline = 0; + + width += context.ptToPixelX( getSpaceBefore( context, tstyle, factor ) ); + + // Let's do all normal elements that have a base line. + TQPtrListIterator<BasicElement> it( children ); + for ( ; it.current(); ++it ) { + BasicElement* child = it.current(); + + if ( !child->isInvisible() ) { + child->calcSizes( context, tstyle, istyle, style ); + child->setX( width ); + width += child->getWidth(); + + luPixel childBaseline = child->getBaseline(); + if ( childBaseline > -1 ) { + toBaseline = TQMAX( toBaseline, childBaseline ); + fromBaseline = TQMAX( fromBaseline, + child->getHeight() - childBaseline ); + } + else { + luPixel bl = child->getHeight()/2 + context.axisHeight( tstyle, factor ); + toBaseline = TQMAX( toBaseline, bl ); + fromBaseline = TQMAX( fromBaseline, child->getHeight() - bl ); + } + } + else { + child->setX( width ); + } + } + + width += context.ptToPixelX( getSpaceAfter( context, tstyle, factor ) ); + + setWidth(width); + setHeight(toBaseline+fromBaseline); + setBaseline(toBaseline); + + setChildrenPositions(); + } + else { + luPixel w = context.getEmptyRectWidth( factor ); + luPixel h = context.getEmptyRectHeight( factor ); + setWidth( w ); + setHeight( h ); + setBaseline( h ); + //setMidline( h*.5 ); + } +} + + +void SequenceElement::setChildrenPositions() +{ + TQPtrListIterator<BasicElement> it( children ); + for ( ; it.current(); ++it ) { + BasicElement* child = it.current(); + child->setY(getBaseline() - child->getBaseline()); + } +} + + +/** + * 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 SequenceElement::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() ); + // There might be zero sized elements that still want to be drawn at least + // in edit mode. (EmptyElement) + //if ( !LuPixelRect( myPos.x(), myPos.y(), getWidth(), getHeight() ).intersects( r ) ) + // return; + + if (!isEmpty()) { + TQPtrListIterator<BasicElement> it( children ); + for (int i = 0 ; it.current(); i++) { + BasicElement* child = it.current(); + if (!child->isInvisible()) { + child->draw(painter, r, context, tstyle, istyle, style, myPos); + + // Each starting element draws the whole token + // This only concerns TextElements. + /* + ElementType* token = child->getElementType(); + if ( token != 0 ) { + it += token->end() - token->start(); + } + else { + ++it; + } + */ + } +// else { + ++it; +// } + } + } + else { + drawEmptyRect( painter, context, style.sizeFactor(), myPos ); + } + // Debug + //painter.setPen(TQt::green); + //painter.drawRect(parentOrigin.x() + getX(), parentOrigin.y() + getY(), + // getWidth(), getHeight()); +// painter.drawLine( context.layoutUnitToPixelX( parentOrigin.x() + getX() ), +// context.layoutUnitToPixelY( parentOrigin.y() + getY() + axis( context, tstyle ) ), +// context.layoutUnitToPixelX( parentOrigin.x() + getX() + getWidth() ), +// context.layoutUnitToPixelY( parentOrigin.y() + getY() + axis( context, tstyle ) ) ); +// painter.setPen(TQt::red); +// painter.drawLine( context.layoutUnitToPixelX( parentOrigin.x() + getX() ), +// context.layoutUnitToPixelY( parentOrigin.y() + getY() + getBaseline() ), +// context.layoutUnitToPixelX( parentOrigin.x() + getX() + getWidth() ), +// context.layoutUnitToPixelY( parentOrigin.y() + getY() + getBaseline() ) ); +} + + +void SequenceElement::dispatchFontCommand( FontCommand* cmd ) +{ + TQPtrListIterator<BasicElement> it( children ); + for ( ; it.current(); ++it ) { + BasicElement* child = it.current(); + child->dispatchFontCommand( cmd ); + } +} + + +void SequenceElement::drawEmptyRect( TQPainter& painter, const ContextStyle& context, + double factor, const LuPixelPoint& upperLeft ) +{ + if ( context.edit() ) { + painter.setBrush(TQt::NoBrush); + painter.setPen( TQPen( context.getEmptyColor(), + context.layoutUnitToPixelX( context.getLineWidth( factor ) ) ) ); + painter.drawRect( context.layoutUnitToPixelX( upperLeft.x() ), + context.layoutUnitToPixelY( upperLeft.y() ), + context.layoutUnitToPixelX( getWidth() ), + context.layoutUnitToPixelY( getHeight() ) ); + } +} + +void SequenceElement::calcCursorSize( const ContextStyle& context, + FormulaCursor* cursor, bool smallCursor ) +{ + LuPixelPoint point = widgetPos(); + uint pos = cursor->getPos(); + + luPixel posX = getChildPosition( context, pos ); + luPixel height = getHeight(); + + luPixel unitX = context.ptToLayoutUnitPixX( 1 ); + luPixel unitY = context.ptToLayoutUnitPixY( 1 ); + + // Here are those evil constants that describe the cursor size. + + if ( cursor->isSelection() ) { + uint mark = cursor->getMark(); + luPixel markX = getChildPosition( context, mark ); + luPixel x = TQMIN(posX, markX); + luPixel width = abs(posX - markX); + + if ( smallCursor ) { + cursor->cursorSize.setRect( point.x()+x, point.y(), width, height ); + } + else { + cursor->cursorSize.setRect( point.x()+x, point.y() - 2*unitY, + width + unitX, height + 4*unitY ); + } + } + else { + if ( smallCursor ) { + cursor->cursorSize.setRect( point.x()+posX, point.y(), + unitX, height ); + } + else { + cursor->cursorSize.setRect( point.x(), point.y() - 2*unitY, + getWidth() + unitX, height + 4*unitY ); + } + } + + cursor->cursorPoint.setX( point.x()+posX ); + cursor->cursorPoint.setY( point.y()+getHeight()/2 ); +} + + +/** + * If the cursor is inside a sequence it needs to be drawn. + */ +void SequenceElement::drawCursor( TQPainter& painter, const ContextStyle& context, + StyleAttributes& style, FormulaCursor* cursor, + bool smallCursor, bool activeCursor ) +{ + painter.setRasterOp( TQt::XorROP ); + if ( cursor->isSelection() ) { + const LuPixelRect& r = cursor->cursorSize; + painter.fillRect( context.layoutUnitToPixelX( r.x() ), + context.layoutUnitToPixelY( r.y() ), + context.layoutUnitToPixelX( r.width() ), + context.layoutUnitToPixelY( r.height() ), + TQt::white ); + } + painter.setPen( TQPen( TQt::white, + context.layoutUnitToPixelX( context.getLineWidth( style.sizeFactor() )/2 ) ) ); + const LuPixelPoint& point = cursor->getCursorPoint(); + const LuPixelRect& size = cursor->getCursorSize(); + if ( activeCursor ) + { + int offset = 0; + if ( cursor->isSelection() && cursor->getPos() > cursor->getMark() ) + offset = -1; + painter.drawLine( context.layoutUnitToPixelX( point.x() ) + offset, + context.layoutUnitToPixelY( size.top() ), + context.layoutUnitToPixelX( point.x() ) + offset, + context.layoutUnitToPixelY( size.bottom() )-1 ); + painter.drawLine( context.layoutUnitToPixelX( point.x() ) + offset + 1, + context.layoutUnitToPixelY( size.top() ), + context.layoutUnitToPixelX( point.x() ) + offset + 1, + context.layoutUnitToPixelY( size.bottom() )-1 ); + } + if ( !smallCursor && !cursor->isSelection() ) + painter.drawLine( context.layoutUnitToPixelX( size.left() ), + context.layoutUnitToPixelY( size.bottom() )-1, + context.layoutUnitToPixelX( size.right() )-1, + context.layoutUnitToPixelY( size.bottom() )-1 ); + // This might be wrong but probably isn't. + painter.setRasterOp( TQt::CopyROP ); +} + + +luPixel SequenceElement::getChildPosition( const ContextStyle& context, uint child ) +{ + if (child < children.count()) { + return children.at(child)->getX(); + } + else { + if (children.count() > 0) { + return children.at(child-1)->getX() + children.at(child-1)->getWidth(); + } + else { + return context.ptToLayoutUnitPixX( 2 ); + } + } +} + + +// 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 SequenceElement::moveLeft(FormulaCursor* cursor, BasicElement* from) +{ + // Our parent asks us for a cursor position. Found. + if (from == getParent()) { + cursor->setTo(this, children.count()); + if ( cursor->isSelectionMode() ) { + cursor->setMark( children.count() ); + } + from->entered( this ); + } + + // We already owned the cursor. Ask next child then. + else if (from == this) { + if (cursor->getPos() > 0) { + cursor->setTo(this, cursor->getPos()-1); + + // invisible elements are not visible so we move on. + if (children.at(cursor->getPos())->isInvisible()) { + moveLeft(cursor, this); + } + } + else { + // Needed because FormulaElement derives this. + if (getParent() != 0) { + getParent()->moveLeft(cursor, this); + } + else { + formula()->moveOutLeft( cursor ); + } + } + } + + // The cursor came from one of our children or + // something is wrong. + else { + int fromPos = children.find(from); + if ( fromPos > 0 ) { + children.at( fromPos - 1)->moveLeft( cursor, this ); + } + + // invisible elements are not visible so we move on. + if (from->isInvisible()) { + moveLeft(cursor, this); + } + formula()->tell( "" ); + } +} + +/** + * 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 SequenceElement::moveRight(FormulaCursor* cursor, BasicElement* from) +{ + // Our parent asks us for a cursor position. Found. + if (from == getParent()) { + cursor->setTo(this, 0); + from->entered( this ); + } + + // We already owned the cursor. Ask next child then. + else if (from == this) { + uint pos = cursor->getPos(); + if (pos < children.count()) { + cursor->setTo(this, pos+1); + + // invisible elements are not visible so we move on. + if (children.at(pos)->isInvisible()) { + moveRight(cursor, this); + } + } + else { + // Needed because FormulaElement derives this. + if (getParent() != 0) { + getParent()->moveRight(cursor, this); + } + else { + formula()->moveOutRight( cursor ); + } + } + } + + // The cursor came from one of our children or + // something is wrong. + else { + int fromPos = children.find(from); + if ( fromPos < children.count() - 1 ) { + children.at( fromPos + 1 )->moveDown( cursor, this ); + } + else { + cursor->setTo(this, fromPos+1); + } + if (cursor->isSelectionMode()) { + cursor->setMark(fromPos); + } + + // invisible elements are not visible so we move on. + if (from->isInvisible()) { + moveRight(cursor, this); + } + formula()->tell( "" ); + } +} + + +void SequenceElement::moveWordLeft(FormulaCursor* cursor) +{ + uint pos = cursor->getPos(); + if (pos > 0) { + ElementType* type = children.at(pos-1)->getElementType(); + if (type != 0) { + cursor->setTo(this, type->start()); + } + } + else { + moveLeft(cursor, this); + } +} + + +void SequenceElement::moveWordRight(FormulaCursor* cursor) +{ + uint pos = cursor->getPos(); + if (pos < children.count()) { + ElementType* type = children.at(pos)->getElementType(); + if (type != 0) { + cursor->setTo(this, type->end()); + } + } + else { + 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 SequenceElement::moveUp(FormulaCursor* cursor, BasicElement* from) +{ + if (from == getParent()) { + moveRight(cursor, this); + } + else if ( from == this ) { + if ( getParent() != 0 ) { + uint pos = cursor->getPos(); + if ( pos < (children.count() - 1) / 2 ) { + getParent()->moveLeft( cursor, this ); + } + else { + getParent()->moveRight( cursor, this ); + } + } + else { + formula()->moveOutAbove( cursor ); + } + } + else { + if (getParent() != 0) { + getParent()->moveUp(cursor, this); + } + else { + formula()->moveOutAbove( cursor ); + } + } +} + +/** + * Enters this element while moving down starting inside + * the element `from'. Searches for a cursor position inside + * this element or below it. + */ +void SequenceElement::moveDown(FormulaCursor* cursor, BasicElement* from) +{ + if (from == getParent()) { + cursor->setTo(this, 0); + from->entered( this ); + } + else if (from == this) { + uint pos = cursor->getPos(); + if (pos < children.count()) { + children.at(pos)->moveDown(cursor, this); + } + } + else { + if (getParent() != 0) { + getParent()->moveDown(cursor, this); + } + else { + cursor->setTo( this, children.count() ); + from->entered( this ); +// formula()->moveOutBelow( cursor ); + } + } +} + +/** + * Moves the cursor to the first position in this sequence. + * (That is before the first child.) + */ +void SequenceElement::moveHome(FormulaCursor* cursor) +{ + if (cursor->isSelectionMode()) { + BasicElement* element = cursor->getElement(); + if (element != this) { + while (element->getParent() != this) { + element = element->getParent(); + } + cursor->setMark(children.find(element)+1); + } + } + cursor->setTo(this, 0); +} + +/** + * Moves the cursor to the last position in this sequence. + * (That is behind the last child.) + */ +void SequenceElement::moveEnd(FormulaCursor* cursor) +{ + if (cursor->isSelectionMode()) { + BasicElement* element = cursor->getElement(); + if (element != this) { + while (element->getParent() != this) { + element = element->getParent(); + if (element == 0) { + cursor->setMark(children.count()); + break; + } + } + if (element != 0) { + cursor->setMark(children.find(element)); + } + } + } + cursor->setTo(this, children.count()); +} + +/** + * Sets the cursor inside this element to its start position. + * For most elements that is the main child. + */ +void SequenceElement::goInside(FormulaCursor* cursor) +{ + cursor->setSelection(false); + cursor->setTo(this, 0); +} + +/** + * Sets the cursor inside this element to its end position. + * For most elements that is the main child. + */ +void SequenceElement::goInsideLast(FormulaCursor* cursor) +{ + cursor->setSelection(false); + cursor->setTo(this, children.count()); +} + + +// children + + /** + * Insert a new child in the sequence + * + * @returns true if succesful, i.e. if index is in range, otherwise returns + * false. The valid range is 0 to count(). The child is appended if index == count(). + * + * @param index position in the sequence to insert the child + * @param child the child to insert in the sequence + */ + +bool SequenceElement::insert( uint index, BasicElement *child ) +{ + return children.insert( index, child ); +} + +/** + * Removes the child. If this was the main child this element might + * request its own removal. + * The cursor is the one that caused the removal. It has to be moved + * to the place any user expects the cursor after that particular + * element has been removed. + */ +// void SequenceElement::removeChild(FormulaCursor* cursor, BasicElement* child) +// { +// int pos = children.find(child); +// formula()->elementRemoval(child, pos); +// cursor->setTo(this, pos); +// children.remove(pos); +// /* +// if len(self.children) == 0: +// if self.parent != None: +// self.parent.removeChild(cursor, self) +// return +// */ +// formula()->changed(); +// } + + +/** + * Inserts all new children at the cursor position. Places the + * cursor according to the direction. The inserted elements will + * be selected. + * + * The list will be emptied but stays the property of the caller. + */ +void SequenceElement::insert(FormulaCursor* cursor, + TQPtrList<BasicElement>& newChildren, + Direction direction) +{ + int pos = cursor->getPos(); + uint count = newChildren.count(); + for (uint i = 0; i < count; i++) { + BasicElement* child = newChildren.take(0); + child->setParent(this); + children.insert(pos+i, child); + } + if (direction == beforeCursor) { + cursor->setTo(this, pos+count, pos); + } + else { + cursor->setTo(this, pos, pos+count); + } + + formula()->changed(); + parse(); +} + + +/** + * Removes all selected children and returns them. Places the + * cursor to where the children have been. + * + * The ownership of the list is passed to the caller. + */ +void SequenceElement::remove(FormulaCursor* cursor, + TQPtrList<BasicElement>& removedChildren, + Direction direction) +{ + if (cursor->isSelection()) { + int from = cursor->getSelectionStart(); + int to = cursor->getSelectionEnd(); + for (int i = from; i < to; i++) { + removeChild(removedChildren, from); + } + cursor->setTo(this, from); + cursor->setSelection(false); + } + else { + if (direction == beforeCursor) { + int pos = cursor->getPos() - 1; + if (pos >= 0) { + while (pos >= 0) { + BasicElement* child = children.at(pos); + formula()->elementRemoval(child); + children.take(pos); + removedChildren.prepend(child); + if (!child->isInvisible()) { + break; + } + pos--; + } + cursor->setTo(this, pos); + formula()->changed(); + } + } + else { + uint pos = cursor->getPos(); + if (pos < children.count()) { + while (pos < children.count()) { + BasicElement* child = children.at(pos); + formula()->elementRemoval(child); + children.take(pos); + removedChildren.append(child); + if (!child->isInvisible()) { + break; + } + } + // It is necessary to set the cursor to its old + // position because it got a notification and + // moved to the beginning of this sequence. + cursor->setTo(this, pos); + formula()->changed(); + } + } + } + parse(); +} + + +/** + * Removes the children at pos and appends it to the list. + */ +void SequenceElement::removeChild(TQPtrList<BasicElement>& removedChildren, int pos) +{ + BasicElement* child = children.at(pos); + formula()->elementRemoval(child); + children.take(pos); + removedChildren.append(child); + //cerr << *removedChildren.at(0) << endl; + formula()->changed(); +} + + +/** + * Moves the cursor to a normal place where new elements + * might be inserted. + */ +void SequenceElement::normalize(FormulaCursor* cursor, Direction) +{ + cursor->setSelection(false); +} + + +/** + * Returns the child at the cursor. + * Does not care about the selection. + */ +BasicElement* SequenceElement::getChild( FormulaCursor* cursor, Direction direction ) +{ + if ( direction == beforeCursor ) { + if ( cursor->getPos() > 0 ) { + return children.at( cursor->getPos() - 1 ); + } + } + else { + if ( cursor->getPos() < tqRound( children.count() ) ) { + return children.at( cursor->getPos() ); + } + } + return 0; +} + + +/** + * Sets the cursor to select the child. The mark is placed before, + * the position behind it. + */ +void SequenceElement::selectChild(FormulaCursor* cursor, BasicElement* child) +{ + int pos = children.find(child); + if (pos > -1) { + cursor->setTo(this, pos+1, pos); + } +} + +void SequenceElement::childWillVanish(FormulaCursor* cursor, BasicElement* child) +{ + int childPos = children.find(child); + if (childPos > -1) { + int pos = cursor->getPos(); + if (pos > childPos) { + pos--; + } + int mark = cursor->getMark(); + if (mark > childPos) { + mark--; + } + cursor->setTo(this, pos, mark); + } +} + + +/** + * Selects all children. The cursor is put behind, the mark before them. + */ +void SequenceElement::selectAllChildren(FormulaCursor* cursor) +{ + cursor->setTo(this, children.count(), 0); +} + +bool SequenceElement::onlyTextSelected( FormulaCursor* cursor ) +{ + if ( cursor->isSelection() ) { + uint from = TQMIN( cursor->getPos(), cursor->getMark() ); + uint to = TQMAX( cursor->getPos(), cursor->getMark() ); + for ( uint i = from; i < to; i++ ) { + BasicElement* element = getChild( i ); + if ( element->getCharacter() == TQChar::null ) { + return false; + } + } + } + return true; +} + + +KCommand* SequenceElement::buildCommand( Container* container, Request* request ) +{ + FormulaCursor* cursor = container->activeCursor(); + if ( cursor->isReadOnly() ) { + formula()->tell( i18n( "write protection" ) ); + return 0; + } + + switch ( *request ) { + case req_addText: { + KFCReplaceToken* command = new KFCReplaceToken( i18n("Add Text"), container ); + TextRequest* tr = static_cast<TextRequest*>( request ); + IdentifierElement* id = creationStrategy->createIdentifierElement(); + command->addToken( id ); + for ( uint i = 0; i < tr->text().length(); i++ ) { + TextElement* text = creationStrategy->createTextElement( tr->text()[i] ); + command->addContent( id, text ); + } + return command; + } + case req_addTextChar: { + KFCReplaceToken* command = new KFCReplaceToken( i18n("Add Text"), container ); + TextCharRequest* tr = static_cast<TextCharRequest*>( request ); + IdentifierElement* id = creationStrategy->createIdentifierElement(); + TextElement* text = creationStrategy->createTextElement( tr->ch() ); + command->addToken( id ); + command->addContent( id, text ); + return command; + } + + case req_addOperator: { + KFCReplaceToken* command = new KFCReplaceToken( i18n("Add Operator"), container ); + OperatorRequest* opr = static_cast<OperatorRequest*>( request ); + OperatorElement* op = creationStrategy->createOperatorElement(); + TextElement* text = creationStrategy->createTextElement( opr->ch() ); + command->addToken( op ); + command->addContent( op, text ); + return command; + } + + case req_addNumber: { + KFCReplaceToken* command = new KFCReplaceToken( i18n("Add Number"), container ); + NumberRequest* nr = static_cast<NumberRequest*>( request ); + NumberElement* num = creationStrategy->createNumberElement(); + num->setParent( this ); + TextElement* text = creationStrategy->createTextElement( nr->ch() ); + text->setParent( num ); + command->addToken( num ); + command->addContent( num, text ); + return command; + } + + case req_addEmptyBox: { + EmptyElement* element = creationStrategy->createEmptyElement(); + if ( element != 0 ) { + KFCReplace* command = new KFCReplace( i18n("Add Empty Box"), container ); + command->addElement( element ); + return command; + } + break; + } + case req_addNameSequence: + if ( onlyTextSelected( container->activeCursor() ) ) { + NameSequence* nameSequence = creationStrategy->createNameSequence(); + if ( nameSequence != 0 ) { + KFCAddReplacing* command = new KFCAddReplacing( i18n( "Add Name" ), container ); + command->setElement( nameSequence ); + return command; + } + } + break; + case req_addBracket: { + BracketRequest* br = static_cast<BracketRequest*>( request ); + BracketElement* bracketElement = + creationStrategy->createBracketElement( br->left(), br->right() ); + if ( bracketElement != 0 ) { + KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Bracket"), container); + command->setElement( bracketElement ); + return command; + } + break; + } + case req_addOverline: { + OverlineElement* overline = creationStrategy->createOverlineElement(); + if ( overline != 0 ) { + KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Overline"), container); + command->setElement( overline ); + return command; + } + break; + } + case req_addUnderline: { + UnderlineElement* underline = creationStrategy->createUnderlineElement(); + if ( underline != 0 ) { + KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Underline"), container); + command->setElement( underline ); + return command; + } + break; + } + case req_addMultiline: { + MultilineElement* multiline = creationStrategy->createMultilineElement(); + if ( multiline != 0 ) { + KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Multiline"), container); + command->setElement( multiline ); + return command; + } + break; + } + case req_addSpace: { + SpaceRequest* sr = static_cast<SpaceRequest*>( request ); + SpaceElement* element = creationStrategy->createSpaceElement( sr->space() ); + if ( element != 0 ) { + KFCReplace* command = new KFCReplace( i18n("Add Space"), container ); + command->addElement( element ); + return command; + } + break; + } + case req_addFraction: { + FractionElement* fraction = creationStrategy->createFractionElement(); + if ( fraction != 0 ) { + KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Fraction"), container); + command->setElement( fraction ); + return command; + } + break; + } + case req_addRoot: { + RootElement* root = creationStrategy->createRootElement(); + if ( root != 0 ) { + KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Root"), container); + command->setElement( root ); + return command; + } + break; + } + case req_addSymbol: { + SymbolRequest* sr = static_cast<SymbolRequest*>( request ); + SymbolElement* symbol = creationStrategy->createSymbolElement( sr->type() ); + if ( symbol != 0 ) { + KFCAddReplacing* command = new KFCAddReplacing( i18n( "Add Symbol" ), container ); + command->setElement( symbol ); + return command; + } + break; + } + case req_addOneByTwoMatrix: { + FractionElement* element = creationStrategy->createFractionElement(); + if ( element != 0 ) { + KFCAddReplacing* command = new KFCAddReplacing( i18n("Add 1x2 Matrix"), container ); + element->showLine(false); + command->setElement(element); + return command; + } + } + case req_addMatrix: { + MatrixRequest* mr = static_cast<MatrixRequest*>( request ); + uint rows = mr->rows(), cols = mr->columns(); + if ( ( rows == 0 ) || ( cols == 0 ) ) { + MatrixDialog* dialog = new MatrixDialog( 0 ); + if ( dialog->exec() ) { + rows = dialog->h; + cols = dialog->w; + } + delete dialog; + } + + if ( ( rows != 0 ) && ( cols != 0 ) ) { + KFCAddReplacing* command = new KFCAddReplacing( i18n( "Add Matrix" ), container ); + command->setElement( creationStrategy->createMatrixElement( rows, cols ) ); + return command; + } + else + return 0L; + } + case req_addIndex: { + if ( cursor->getPos() > 0 && !cursor->isSelection() ) { + IndexElement* element = + dynamic_cast<IndexElement*>( children.at( cursor->getPos()-1 ) ); + if ( element != 0 ) { + element->goInside( cursor ); + return element->buildCommand( container, request ); + } + } + IndexElement* element = creationStrategy->createIndexElement(); + if ( element != 0 ) { + if ( !cursor->isSelection() ) { + cursor->moveLeft( SelectMovement | WordMovement ); + } + IndexRequest* ir = static_cast<IndexRequest*>( request ); + KFCAddIndex* command = new KFCAddIndex( container, element, + element->getIndex( ir->index() ) ); + return command; + } + break; + } + case req_removeEnclosing: { + if ( !cursor->isSelection() ) { + DirectedRemove* dr = static_cast<DirectedRemove*>( request ); + KFCRemoveEnclosing* command = new KFCRemoveEnclosing( container, dr->direction() ); + return command; + } + } + case req_remove: { + SequenceElement* sequence = cursor->normal(); + if ( sequence && + ( sequence == sequence->formula() ) && + ( sequence->countChildren() == 0 ) ) { + sequence->formula()->removeFormula( cursor ); + return 0; + } + else { + DirectedRemove* dr = static_cast<DirectedRemove*>( request ); + + // empty removes are not legal! + if ( !cursor->isSelection() ) { + if ( countChildren() > 0 ) { + if ( ( cursor->getPos() == 0 ) && ( dr->direction() == beforeCursor ) ) { + return 0; + } + if ( ( cursor->getPos() == countChildren() ) && ( dr->direction() == afterCursor ) ) { + return 0; + } + } + else if ( getParent() == 0 ) { + return 0; + } + } + + KFCRemove* command = new KFCRemove( container, dr->direction() ); + return command; + } + } + case req_compactExpression: { + cursor->moveEnd(); + cursor->moveRight(); + formula()->cursorHasMoved( cursor ); + break; + } + case req_makeGreek: { + TextElement* element = cursor->getActiveTextElement(); + if ((element != 0) && !element->isSymbol()) { + cursor->selectActiveElement(); + const SymbolTable& table = container->document()->getSymbolTable(); + if (table.greekLetters().find(element->getCharacter()) != -1) { + KFCReplace* command = new KFCReplace( i18n( "Change Char to Symbol" ), container ); + TextElement* symbol = creationStrategy->createTextElement( table.unicodeFromSymbolFont( element->getCharacter() ), true ); + command->addElement( symbol ); + return command; + } + cursor->setSelection( false ); + } + break; + } + case req_paste: + case req_copy: + case req_cut: + break; + case req_formatBold: + case req_formatItalic: { + if ( cursor->isSelection() ) { + CharStyleRequest* csr = static_cast<CharStyleRequest*>( request ); + CharStyle cs = normalChar; + if ( csr->bold() ) cs = static_cast<CharStyle>( cs | boldChar ); + if ( csr->italic() ) cs = static_cast<CharStyle>( cs | italicChar ); + CharStyleCommand* cmd = new CharStyleCommand( cs, i18n( "Change Char Style" ), container ); + int end = cursor->getSelectionEnd(); + for ( int i = cursor->getSelectionStart(); i<end; ++i ) { + cmd->addElement( children.at( i ) ); + } + return cmd; + } + break; + } + case req_formatFamily: { + if ( cursor->isSelection() ) { + CharFamilyRequest* cfr = static_cast<CharFamilyRequest*>( request ); + CharFamily cf = cfr->charFamily(); + CharFamilyCommand* cmd = new CharFamilyCommand( cf, i18n( "Change Char Family" ), container ); + int end = cursor->getSelectionEnd(); + for ( int i = cursor->getSelectionStart(); i<end; ++i ) { + cmd->addElement( children.at( i ) ); + } + return cmd; + } + break; + } + default: + break; + } + return 0; +} + + +KCommand* SequenceElement::input( Container* container, TQKeyEvent* event ) +{ + TQChar ch = event->text().at( 0 ); + if ( ch.isPrint() ) { + return input( container, ch ); + } + else { + int action = event->key(); + int state = event->state(); + MoveFlag flag = movementFlag(state); + + switch ( action ) { + case TQt::Key_BackSpace: { + DirectedRemove r( req_remove, beforeCursor ); + return buildCommand( container, &r ); + } + case TQt::Key_Delete: { + DirectedRemove r( req_remove, afterCursor ); + return buildCommand( container, &r ); + } + case TQt::Key_Left: { + FormulaCursor* cursor = container->activeCursor(); + cursor->moveLeft( flag ); + formula()->cursorHasMoved( cursor ); + break; + } + case TQt::Key_Right: { + FormulaCursor* cursor = container->activeCursor(); + cursor->moveRight( flag ); + formula()->cursorHasMoved( cursor ); + break; + } + case TQt::Key_Up: { + FormulaCursor* cursor = container->activeCursor(); + cursor->moveUp( flag ); + formula()->cursorHasMoved( cursor ); + break; + } + case TQt::Key_Down: { + FormulaCursor* cursor = container->activeCursor(); + cursor->moveDown( flag ); + formula()->cursorHasMoved( cursor ); + break; + } + case TQt::Key_Home: { + FormulaCursor* cursor = container->activeCursor(); + cursor->moveHome( flag ); + formula()->cursorHasMoved( cursor ); + break; + } + case TQt::Key_End: { + FormulaCursor* cursor = container->activeCursor(); + cursor->moveEnd( flag ); + formula()->cursorHasMoved( cursor ); + break; + } + default: + if ( state & TQt::ControlButton ) { + switch ( event->key() ) { + case TQt::Key_AsciiCircum: { + IndexRequest r( upperLeftPos ); + return buildCommand( container, &r ); + } + case TQt::Key_Underscore: { + IndexRequest r( lowerLeftPos ); + return buildCommand( container, &r ); + } + default: + break; + } + } + } + } + return 0; +} + + +KCommand* SequenceElement::input( Container* container, TQChar ch ) +{ + int unicode = ch.unicode(); + switch (unicode) { + case '(': { + BracketRequest r( container->document()->leftBracketChar(), + container->document()->rightBracketChar() ); + singlePipe = true; + return buildCommand( container, &r ); + } + case '[': { + BracketRequest r( LeftSquareBracket, RightSquareBracket ); + singlePipe = true; + return buildCommand( container, &r ); + } + case '{': { + BracketRequest r( LeftCurlyBracket, RightCurlyBracket ); + singlePipe = true; + return buildCommand( container, &r ); + } + case '|': { + if (!singlePipe) { // We have had 2 '|' in a row so we want brackets + + DirectedRemove rDelete( req_remove, beforeCursor ); //Delete the previous '|' we dont need it any more + KCommand* command = buildCommand( container, &rDelete ); + command->execute(); + + BracketRequest rBracket( LeftLineBracket , RightLineBracket); + singlePipe = true; //the next '|' will be a single pipe again + return buildCommand( container, &rBracket ); + } + else { // We really do only want 1 '|' + TextCharRequest r(ch); + + //in case another '|' character is entered right after this one, '| |' brackets are made; see above + singlePipe = false; + + return buildCommand( container, &r ); + } + } + case '^': { + IndexRequest r( upperRightPos ); + singlePipe = true; + return buildCommand( container, &r ); + } + case '_': { + IndexRequest r( lowerRightPos ); + singlePipe = true; + return buildCommand( container, &r ); + } + /* + case ' ': { + Request r( req_compactExpression ); + singlePipe = true; + return buildCommand( container, &r ); + }*/ + case '}': { + Request r( req_addEmptyBox ); + singlePipe = true; + return buildCommand( container, &r ); + } + case ']': + case ')': + singlePipe = true; + break; + case '\\': { + Request r( req_addNameSequence ); + singlePipe = true; + return buildCommand( container, &r ); + } + default: { + singlePipe = true; + if ( ch.isPunct() || ch.isSymbol() ) { + OperatorRequest r( ch ); + return buildCommand( container, &r ); + } + if ( ch.isNumber() ) { + NumberRequest r( ch ); + return buildCommand( container, &r ); + } + TextCharRequest r( ch ); + return buildCommand( container, &r ); + } + } + return 0; +} + +/** + * Stores the given childrens dom in the element. + */ +void SequenceElement::getChildrenDom( TQDomDocument& doc, TQDomElement elem, + uint from, uint to) +{ + for (uint i = from; i < to; i++) { + TQDomElement tmpEleDom=children.at(i)->getElementDom(doc); + elem.appendChild(tmpEleDom); + } +} + +/** + * Stores the given childrens MathML dom in the element. + */ +void SequenceElement::getChildrenMathMLDom( TQDomDocument& doc, TQDomNode& parent, + uint from, uint to) +{ + for ( uint i = from; i < to; i++ ) { + children.at( i )->writeMathML( doc, parent, false ); + } +} + + +/** + * Builds elements from the given node and its siblings and + * puts them into the list. + * Returns false if an error occures. + */ +bool SequenceElement::buildChildrenFromDom(TQPtrList<BasicElement>& list, TQDomNode n) +{ + while (!n.isNull()) { + if (n.isElement()) { + TQDomElement e = n.toElement(); + BasicElement* child = 0; + TQString tag = e.tagName().upper(); + + child = createElement(tag, e); + if (child != 0) { + child->setParent(this); + if (child->buildFromDom(e)) { + list.append(child); + } + else { + delete child; + return false; + } + } + else { + return false; + } + } + n = n.nextSibling(); + } + parse(); + return true; +} + + +BasicElement* SequenceElement::createElement( TQString type, const TQDomElement& element ) +{ + return creationStrategy->createElement( type, element ); +} + +/** + * Appends our attributes to the dom element. + */ +void SequenceElement::writeDom(TQDomElement element) +{ + BasicElement::writeDom(element); + + uint count = children.count(); + TQDomDocument doc = element.ownerDocument(); + getChildrenDom(doc, element, 0, count); +} + +/** + * Reads our attributes from the element. + * Returns false if it failed. + */ +bool SequenceElement::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 SequenceElement::readContentFromDom(TQDomNode& node) +{ + if (!BasicElement::readContentFromDom(node)) { + return false; + } + + return buildChildrenFromDom(children, node); +} + + +void SequenceElement::parse() +{ + delete parseTree; + + textSequence = true; + for (BasicElement* element = children.first(); + element != 0; + element = children.next()) { + + // Those types are gone. Make sure they won't + // be used. + element->setElementType(0); + + if (element->getCharacter().isNull()) { + textSequence = false; + } + } + + const SymbolTable& symbols = formula()->getSymbolTable(); + SequenceParser parser(symbols); + parseTree = parser.parse(children); + + // With the IndexElement dynamically changing its text/non-text + // behaviour we need to reparse your parent, too. Hacky! + BasicElement* p = getParent(); + if ( p != 0 ) { + SequenceElement* seq = dynamic_cast<SequenceElement*>( p->getParent() ); + if ( seq != 0 ) { + seq->parse(); + } + } + // debug + //parseTree->output(); +} + + +bool SequenceElement::isFirstOfToken( BasicElement* child ) +{ + return ( child->getElementType() != 0 ) && isChildNumber( child->getElementType()->start(), child ); +} + + +TQString SequenceElement::toLatex() +{ + TQString content; + uint count = children.count(); + for ( uint i = 0; i < count; i++ ) { + BasicElement* child = children.at( i ); +// if ( isFirstOfToken( child ) ) { +// content += ""; +// } + content += child->toLatex(); + } + return content; +} + + +TQString SequenceElement::formulaString() +{ + TQString content; + uint count = children.count(); + for ( uint i = 0; i < count; i++ ) { + BasicElement* child = children.at( i ); + //if ( isFirstOfToken( child ) ) { + // content += " "; + //} + content += child->formulaString(); + } + return content; +} + + +void SequenceElement::writeMathMLContent( TQDomDocument& doc, TQDomElement& element, bool oasisFormat ) const +{ + for ( TQPtrListIterator<BasicElement> it( children ); it.current(); ++it ) { + it.current()->writeMathML( doc, element, oasisFormat ); + } +} + + +const BasicElement* SequenceElement::getChild( uint i ) const +{ + TQPtrListIterator<BasicElement> it( children ); + it += i; + return it.current(); +} + + +int SequenceElement::childPos( const BasicElement* child ) const +{ + TQPtrListIterator<BasicElement> it( children ); + uint count = it.count(); + for ( uint i=0; i<count; ++i, ++it ) { + if ( it.current() == child ) { + return i; + } + } + return -1; +} + + +NameSequence::NameSequence( BasicElement* parent ) + : SequenceElement( parent ) +{ +} + + +bool NameSequence::accept( ElementVisitor* visitor ) +{ + return visitor->visit( this ); +} + + +void NameSequence::calcCursorSize( const ContextStyle& context, + FormulaCursor* cursor, bool smallCursor ) +{ + inherited::calcCursorSize( context, cursor, smallCursor ); + LuPixelPoint point = widgetPos(); + luPixel unitX = context.ptToLayoutUnitPixX( 1 ); + luPixel unitY = context.ptToLayoutUnitPixY( 1 ); + cursor->addCursorSize( LuPixelRect( point.x()-unitX, point.y()-unitY, + getWidth()+2*unitX, getHeight()+2*unitY ) ); +} + +void NameSequence::drawCursor( TQPainter& painter, const ContextStyle& context, + StyleAttributes& style, FormulaCursor* cursor, + bool smallCursor, bool activeCursor ) +{ + LuPixelPoint point = widgetPos(); + painter.setPen( TQPen( context.getEmptyColor(), + context.layoutUnitToPixelX( context.getLineWidth( style.sizeFactor() )/2 ) ) ); + luPixel unitX = context.ptToLayoutUnitPixX( 1 ); + luPixel unitY = context.ptToLayoutUnitPixY( 1 ); + painter.drawRect( context.layoutUnitToPixelX( point.x()-unitX ), + context.layoutUnitToPixelY( point.y()-unitY ), + context.layoutUnitToPixelX( getWidth()+2*unitX ), + context.layoutUnitToPixelY( getHeight()+2*unitY ) ); + + inherited::drawCursor( painter, context, style, cursor, smallCursor, activeCursor ); +} + +void NameSequence::moveWordLeft( FormulaCursor* cursor ) +{ + uint pos = cursor->getPos(); + if ( pos > 0 ) { + cursor->setTo( this, 0 ); + } + else { + moveLeft( cursor, this ); + } +} + +void NameSequence::moveWordRight( FormulaCursor* cursor ) +{ + int pos = cursor->getPos(); + if ( pos < countChildren() ) { + cursor->setTo( this, countChildren() ); + } + else { + moveRight( cursor, this ); + } +} + + +KCommand* NameSequence::compactExpressionCmd( Container* container ) +{ + BasicElement* element = replaceElement( container->document()->getSymbolTable() ); + if ( element != 0 ) { + getParent()->selectChild( container->activeCursor(), this ); + + KFCReplace* command = new KFCReplace( i18n( "Add Element" ), container ); + command->addElement( element ); + return command; + } + return 0; +} + +KCommand* NameSequence::buildCommand( Container* container, Request* request ) +{ + switch ( *request ) { + case req_compactExpression: + return compactExpressionCmd( container ); + case req_addSpace: + case req_addIndex: + case req_addMatrix: + case req_addOneByTwoMatrix: + case req_addSymbol: + case req_addRoot: + case req_addFraction: + case req_addBracket: + case req_addNameSequence: + return 0; + default: + break; + } + return inherited::buildCommand( container, request ); +} + + +KCommand* NameSequence::input( Container* container, TQChar ch ) +{ + int unicode = ch.unicode(); + switch (unicode) { + case '(': + case '[': + case '|': + case '^': + case '_': + case '}': + case ']': + case ')': + case '\\': { +// KCommand* compact = compactExpressionCmd( container ); +// KCommand* cmd = static_cast<SequenceElement*>( getParent() )->input( container, ch ); +// if ( compact != 0 ) { +// KMacroCommand* macro = new KMacroCommand( cmd->name() ); +// macro->addCommand( compact ); +// macro->addCommand( cmd ); +// return macro; +// } +// else { +// return cmd; +// } + break; + } + case '{': + case ' ': { + Request r( req_compactExpression ); + return buildCommand( container, &r ); + } + default: { + TextCharRequest r( ch ); + return buildCommand( container, &r ); + } + } + return 0; +} + +void NameSequence::setElementType( ElementType* t ) +{ + inherited::setElementType( t ); + parse(); +} + +BasicElement* NameSequence::replaceElement( const SymbolTable& table ) +{ + TQString name = buildName(); + TQChar ch = table.unicode( name ); + if ( !ch.isNull() ) { + return new TextElement( ch, true ); + } + else { + ch = table.unicode( i18n( name.latin1() ) ); + if ( !ch.isNull() ) { + return new TextElement( ch, true ); + } + } + + if ( name == "!" ) return new SpaceElement( NEGTHIN ); + if ( name == "," ) return new SpaceElement( THIN ); + if ( name == ">" ) return new SpaceElement( MEDIUM ); + if ( name == ";" ) return new SpaceElement( THICK ); + if ( name == "quad" ) return new SpaceElement( QUAD ); + + if ( name == "frac" ) return new FractionElement(); + if ( name == "atop" ) { + FractionElement* frac = new FractionElement(); + frac->showLine( false ); + return frac; + } + if ( name == "sqrt" ) return new RootElement(); + + return 0; +} + +BasicElement* NameSequence::createElement( TQString type ) +{ + if ( type == "TEXT" ) return new TextElement(); + return 0; +} + +// void NameSequence::parse() +// { +// // A name sequence is known as name and so are its children. +// // Caution: this is fake! +// for ( int i = 0; i < countChildren(); i++ ) { +// getChild( i )->setElementType( getElementType() ); +// } +// } + +TQString NameSequence::buildName() +{ + TQString name; + for ( uint i = 0; i < countChildren(); i++ ) { + name += getChild( i )->getCharacter(); + } + return name; +} + +bool NameSequence::isValidSelection( FormulaCursor* cursor ) +{ + SequenceElement* sequence = cursor->normal(); + if ( sequence == 0 ) { + return false; + } + return sequence->onlyTextSelected( cursor ); +} + +int SequenceElement::buildChildrenFromMathMLDom(TQPtrList<BasicElement>& list, TQDomNode n) +{ + while (!n.isNull()) { + int nodeNumber = 1; + if (n.isElement()) { + TQDomElement e = n.toElement(); + BasicElement* child = 0; + TQString tag = e.tagName().lower(); + + kdDebug( DEBUGID ) << "Sequence Tag: " << tag << endl; + if ( tag == "semantics" ) { // Special case, just pick the first child + TQDomNode node = e.firstChild(); + while( ! node.isElement() ) { + node = node.nextSibling(); + if ( node.isNull() ) { + return -1; + } + } + e = node.toElement(); + tag = e.tagName().lower(); + } + child = creationStrategy->createElement(tag, e); + if (child != 0) { + child->setParent(this); + if (style != 0) { + child->setStyle(style); + } + nodeNumber = child->buildFromMathMLDom( e ); + if ( nodeNumber != -1 ) { + list.append(child); + } + else { + delete child; + return -1; + } + } + else { + kdWarning() << "Unsupported MathML element: " << tag << endl; + } + } + for (int i = 0; i < nodeNumber; i++ ) { + if ( n.isNull() ) { + return -1; + } + n = n.nextSibling(); + } + } + // Operator elements inside a sequence have to be parsed to get proper form + // value. Form value is needed to access operator dictionary and has to be + // obtained after sequence parsing since its value depends on position + // inside the sequence. + + // If the sequence contains more than one element, if the first or last + // element are operators, they have to be marked differently + if ( list.count() > 1 ) { + if ( list.getFirst()->getElementName() == "mo" ) { + static_cast<OperatorElement*>( list.getFirst() )->setForm( PrefixForm ); + } + if ( list.getLast()->getElementName() == "mo" ) { + static_cast<OperatorElement*>( list.getLast() )->setForm( PostfixForm ); + } + for ( uint i = 1; i < list.count() - 1; i++ ) { + if ( list.at( i )->getElementName() == "mo" ) { + static_cast<OperatorElement*>( list.at( i ) )->setForm( InfixForm ); + } + } + } + else if ( list.count() == 1 ) { + if ( list.getFirst()->getElementName() == "mo" ) { + static_cast<OperatorElement*>( list.getFirst() )->setForm( InfixForm ); + } + } + parse(); + return 1; +} + +/** + */ +int SequenceElement::readContentFromMathMLDom(TQDomNode& node) +{ + if ( BasicElement::readContentFromMathMLDom(node) == -1 ) { + return -1; + } + + return buildChildrenFromMathMLDom(children, node); +} + +int SequenceElement::buildMathMLChild( TQDomNode node ) +{ + int nodeCounter = 1; + while ( ! node.isElement() ) { + node = node.nextSibling(); + nodeCounter++; + if ( node.isNull() ) { + return -1; + } + } + TQDomElement e = node.toElement(); + BasicElement* child = 0; + TQString tag = e.tagName().lower(); + + child = creationStrategy->createElement(tag, e); + if (child != 0) { + child->setParent(this); + if (style != 0) { + child->setStyle(style); + } + if (child->buildFromMathMLDom(e) != -1) { + children.append(child); + } + else { + delete child; + return -1; + } + } + else { + return -1; + } + parse(); + return nodeCounter; +} + + + +KFORMULA_NAMESPACE_END |