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

1935 lines
59 KiB

/* This file is part of the KDE project
Copyright (C) 2001 Andrea Rizzi <rizzi@kde.org>
Ulrich Kuettler <ulrich.kuettler@mailbox.tu-dresden.de>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <stdlib.h>
#include <math.h>
#include <tqpainter.h>
#include <tqpaintdevice.h>
#include <tqvaluestack.h>
#include <kcommand.h>
#include <kdebug.h>
#include <klocale.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* tqparent)
: BasicElement(tqparent), parseTree(0), textSequence(true),singlePipe(true), style(0)
{
assert( creationStrategy != 0 );
tqchildren.setAutoDelete(true);
}
SequenceElement::~SequenceElement()
{
delete parseTree;
}
SequenceElement::SequenceElement( const SequenceElement& other )
: BasicElement( other )
{
tqchildren.setAutoDelete(true);
uint count = other.tqchildren.count();
for (uint i = 0; i < count; i++) {
BasicElement* child = tqchildren.at(i)->clone();
child->setParent( this );
tqchildren.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 = tqchildren.count();
for (uint i = 0; i < count; i++) {
BasicElement* child = tqchildren.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, tqchildren.find(e));
}
else {
cursor->setTo(this, tqchildren.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 = tqchildren.at(i);
if (dx < child->getX()) {
cursor->setTo( this, i );
handled = true;
return tqchildren.at( i );
}
}
cursor->setTo(this, countChildren());
handled = true;
return this;
}
return 0;
}
bool SequenceElement::isEmpty()
{
uint count = tqchildren.count();
for (uint i = 0; i < count; i++) {
BasicElement* child = tqchildren.at(i);
if (!child->isInvisible()) {
return false;
}
}
return true;
}
/**
* Calculates our width and height and
* our tqchildren'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( tqchildren );
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( tqchildren );
for ( ; it.current(); ++it ) {
BasicElement* child = it.current();
child->setY(getBaseline() - child->getBaseline());
}
}
/**
* Draws the whole element including its tqchildren.
* The `parentOrigin' is the point this element's tqparent 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( tqchildren );
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( tqchildren );
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 < tqchildren.count()) {
return tqchildren.at(child)->getX();
}
else {
if (tqchildren.count() > 0) {
return tqchildren.at(child-1)->getX() + tqchildren.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 tqparent asks us for a cursor position. Found.
if (from == getParent()) {
cursor->setTo(this, tqchildren.count());
if ( cursor->isSelectionMode() ) {
cursor->setMark( tqchildren.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 (tqchildren.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 tqchildren or
// something is wrong.
else {
int fromPos = tqchildren.find(from);
if ( fromPos > 0 ) {
tqchildren.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 tqparent 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 < tqchildren.count()) {
cursor->setTo(this, pos+1);
// invisible elements are not visible so we move on.
if (tqchildren.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 tqchildren or
// something is wrong.
else {
int fromPos = tqchildren.find(from);
if ( fromPos < tqchildren.count() - 1 ) {
tqchildren.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 = tqchildren.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 < tqchildren.count()) {
ElementType* type = tqchildren.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 < (tqchildren.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 < tqchildren.count()) {
tqchildren.at(pos)->moveDown(cursor, this);
}
}
else {
if (getParent() != 0) {
getParent()->moveDown(cursor, this);
}
else {
cursor->setTo( this, tqchildren.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(tqchildren.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(tqchildren.count());
break;
}
}
if (element != 0) {
cursor->setMark(tqchildren.find(element));
}
}
}
cursor->setTo(this, tqchildren.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, tqchildren.count());
}
// tqchildren
/**
* 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 tqchildren.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 = tqchildren.find(child);
// formula()->elementRemoval(child, pos);
// cursor->setTo(this, pos);
// tqchildren.remove(pos);
// /*
// if len(self.tqchildren) == 0:
// if self.tqparent != None:
// self.tqparent.removeChild(cursor, self)
// return
// */
// formula()->changed();
// }
/**
* Inserts all new tqchildren 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);
tqchildren.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 tqchildren and returns them. Places the
* cursor to where the tqchildren 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 = tqchildren.at(pos);
formula()->elementRemoval(child);
tqchildren.take(pos);
removedChildren.prepend(child);
if (!child->isInvisible()) {
break;
}
pos--;
}
cursor->setTo(this, pos);
formula()->changed();
}
}
else {
uint pos = cursor->getPos();
if (pos < tqchildren.count()) {
while (pos < tqchildren.count()) {
BasicElement* child = tqchildren.at(pos);
formula()->elementRemoval(child);
tqchildren.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 tqchildren at pos and appends it to the list.
*/
void SequenceElement::removeChild(TQPtrList<BasicElement>& removedChildren, int pos)
{
BasicElement* child = tqchildren.at(pos);
formula()->elementRemoval(child);
tqchildren.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 tqchildren.at( cursor->getPos() - 1 );
}
}
else {
if ( cursor->getPos() < tqRound( tqchildren.count() ) ) {
return tqchildren.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 = tqchildren.find(child);
if (pos > -1) {
cursor->setTo(this, pos+1, pos);
}
}
void SequenceElement::childWillVanish(FormulaCursor* cursor, BasicElement* child)
{
int childPos = tqchildren.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 tqchildren. The cursor is put behind, the mark before them.
*/
void SequenceElement::selectAllChildren(FormulaCursor* cursor)
{
cursor->setTo(this, tqchildren.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*>( tqchildren.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.tqunicodeFromSymbolFont( 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( tqchildren.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( tqchildren.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 tqunicode = ch.tqunicode();
switch (tqunicode) {
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 tqchildrens dom in the element.
*/
void SequenceElement::getChildrenDom( TQDomDocument& doc, TQDomElement elem,
uint from, uint to)
{
for (uint i = from; i < to; i++) {
TQDomElement tmpEleDom=tqchildren.at(i)->getElementDom(doc);
elem.appendChild(tmpEleDom);
}
}
/**
* Stores the given tqchildrens MathML dom in the element.
*/
void SequenceElement::getChildrenMathMLDom( TQDomDocument& doc, TQDomNode& tqparent,
uint from, uint to)
{
for ( uint i = from; i < to; i++ ) {
tqchildren.at( i )->writeMathML( doc, tqparent, 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 = tqchildren.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(tqchildren, node);
}
void SequenceElement::parse()
{
delete parseTree;
textSequence = true;
for (BasicElement* element = tqchildren.first();
element != 0;
element = tqchildren.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(tqchildren);
// With the IndexElement dynamically changing its text/non-text
// behaviour we need to reparse your tqparent, 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 = tqchildren.count();
for ( uint i = 0; i < count; i++ ) {
BasicElement* child = tqchildren.at( i );
// if ( isFirstOfToken( child ) ) {
// content += "";
// }
content += child->toLatex();
}
return content;
}
TQString SequenceElement::formulaString()
{
TQString content;
uint count = tqchildren.count();
for ( uint i = 0; i < count; i++ ) {
BasicElement* child = tqchildren.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( tqchildren ); it.current(); ++it ) {
it.current()->writeMathML( doc, element, oasisFormat );
}
}
const BasicElement* SequenceElement::getChild( uint i ) const
{
TQPtrListIterator<BasicElement> it( tqchildren );
it += i;
return it.current();
}
int SequenceElement::childPos( const BasicElement* child ) const
{
TQPtrListIterator<BasicElement> it( tqchildren );
uint count = it.count();
for ( uint i=0; i<count; ++i, ++it ) {
if ( it.current() == child ) {
return i;
}
}
return -1;
}
NameSequence::NameSequence( BasicElement* tqparent )
: SequenceElement( tqparent )
{
}
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 tqunicode = ch.tqunicode();
switch (tqunicode) {
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.tqunicode( name );
if ( !ch.isNull() ) {
return new TextElement( ch, true );
}
else {
ch = table.tqunicode( 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( TQUAD );
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 tqchildren.
// // 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(tqchildren, 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) {
tqchildren.append(child);
}
else {
delete child;
return -1;
}
}
else {
return -1;
}
parse();
return nodeCounter;
}
KFORMULA_NAMESPACE_END