lib

sequenceelement.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2001 Andrea Rizzi <rizzi@kde.org>
00003                   Ulrich Kuettler <ulrich.kuettler@mailbox.tu-dresden.de>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include <stdlib.h>
00022 #include <math.h>
00023 
00024 #include <qpainter.h>
00025 #include <qpaintdevice.h>
00026 #include <qvaluestack.h>
00027 
00028 #include <kcommand.h>
00029 #include <kdebug.h>
00030 #include <klocale.h>
00031 
00032 //#include <boost/spirit.hpp>
00033 
00034 #include "MatrixDialog.h"
00035 #include "bracketelement.h"
00036 #include "creationstrategy.h"
00037 #include "elementtype.h"
00038 #include "elementvisitor.h"
00039 #include "formulacursor.h"
00040 #include "formulaelement.h"
00041 #include "fractionelement.h"
00042 #include "indexelement.h"
00043 #include "kformulacommand.h"
00044 #include "kformulacontainer.h"
00045 #include "kformuladocument.h"
00046 #include "matrixelement.h"
00047 #include "rootelement.h"
00048 #include "sequenceelement.h"
00049 #include "sequenceparser.h"
00050 #include "spaceelement.h"
00051 #include "symbolelement.h"
00052 #include "symboltable.h"
00053 #include "textelement.h"
00054 #include "numberelement.h"
00055 #include "identifierelement.h"
00056 #include "operatorelement.h"
00057 
00058 #include <assert.h>
00059 
00060 KFORMULA_NAMESPACE_BEGIN
00061 //using namespace std;
00062 
00063 ElementCreationStrategy* SequenceElement::creationStrategy = 0;
00064 
00065 void SequenceElement::setCreationStrategy( ElementCreationStrategy* strategy )
00066 {
00067     creationStrategy = strategy;
00068 }
00069 
00070 void SequenceElement::setStyle( StyleElement *st ) 
00071 {
00072     style = st;
00073 }
00074 
00075 SequenceElement::SequenceElement(BasicElement* parent)
00076         : BasicElement(parent), parseTree(0), textSequence(true),singlePipe(true), style(0)
00077 {
00078     assert( creationStrategy != 0 );
00079     children.setAutoDelete(true);
00080 }
00081 
00082 
00083 SequenceElement::~SequenceElement()
00084 {
00085     delete parseTree;
00086 }
00087 
00088 SequenceElement::SequenceElement( const SequenceElement& other )
00089     : BasicElement( other )
00090 {
00091     children.setAutoDelete(true);
00092     uint count = other.children.count();
00093     for (uint i = 0; i < count; i++) {
00094         BasicElement* child = children.at(i)->clone();
00095         child->setParent( this );
00096         children.append( child );
00097     }
00098 }
00099 
00100 
00101 bool SequenceElement::accept( ElementVisitor* visitor )
00102 {
00103     return visitor->visit( this );
00104 }
00105 
00106 
00107 bool SequenceElement::readOnly( const FormulaCursor* ) const
00108 {
00109     return getParent()->readOnly( this );
00110 }
00111 
00112 
00116 BasicElement* SequenceElement::goToPos( FormulaCursor* cursor, bool& handled,
00117                                         const LuPixelPoint& point, const LuPixelPoint& parentOrigin )
00118 {
00119     BasicElement* e = BasicElement::goToPos(cursor, handled, point, parentOrigin);
00120     if (e != 0) {
00121         LuPixelPoint myPos(parentOrigin.x() + getX(),
00122                            parentOrigin.y() + getY());
00123 
00124         uint count = children.count();
00125         for (uint i = 0; i < count; i++) {
00126             BasicElement* child = children.at(i);
00127             e = child->goToPos(cursor, handled, point, myPos);
00128             if (e != 0) {
00129                 if (!handled) {
00130                     handled = true;
00131                     if ((point.x() - myPos.x()) < (e->getX() + e->getWidth()*2/3)) {
00132                         cursor->setTo(this, children.find(e));
00133                     }
00134                     else {
00135                         cursor->setTo(this, children.find(e)+1);
00136                     }
00137                 }
00138                 return e;
00139             }
00140         }
00141 
00142         luPixel dx = point.x() - myPos.x();
00143         //int dy = point.y() - myPos.y();
00144 
00145         for (uint i = 0; i < count; i++) {
00146             BasicElement* child = children.at(i);
00147             if (dx < child->getX()) {
00148                 cursor->setTo( this, i );
00149                 handled = true;
00150                 return children.at( i );
00151             }
00152         }
00153 
00154         cursor->setTo(this, countChildren());
00155         handled = true;
00156         return this;
00157     }
00158     return 0;
00159 }
00160 
00161 
00162 bool SequenceElement::isEmpty()
00163 {
00164     uint count = children.count();
00165     for (uint i = 0; i < count; i++) {
00166         BasicElement* child = children.at(i);
00167         if (!child->isInvisible()) {
00168             return false;
00169         }
00170     }
00171     return true;
00172 }
00173 
00174 
00179 void SequenceElement::calcSizes( const ContextStyle& context,
00180                                  ContextStyle::TextStyle tstyle,
00181                                  ContextStyle::IndexStyle istyle,
00182                                  StyleAttributes& style )
00183 {
00184     double factor = style.sizeFactor();
00185     if (!isEmpty()) {
00186         luPixel width = 0;
00187         luPixel toBaseline = 0;
00188         luPixel fromBaseline = 0;
00189 
00190         width += context.ptToPixelX( getSpaceBefore( context, tstyle, factor ) );
00191 
00192         // Let's do all normal elements that have a base line.
00193         QPtrListIterator<BasicElement> it( children );
00194         for ( ; it.current(); ++it ) {
00195             BasicElement* child = it.current();
00196 
00197             if ( !child->isInvisible() ) {
00198                 child->calcSizes( context, tstyle, istyle, style );
00199                 child->setX( width );
00200                 width += child->getWidth();
00201 
00202                 luPixel childBaseline = child->getBaseline();
00203                 if ( childBaseline > -1 ) {
00204                     toBaseline = QMAX( toBaseline, childBaseline );
00205                     fromBaseline = QMAX( fromBaseline,
00206                                          child->getHeight() - childBaseline );
00207                 }
00208                 else {
00209                     luPixel bl = child->getHeight()/2 + context.axisHeight( tstyle, factor );
00210                     toBaseline = QMAX( toBaseline, bl );
00211                     fromBaseline = QMAX( fromBaseline, child->getHeight() - bl );
00212                 }
00213             }
00214             else {
00215                 child->setX( width );
00216             }
00217         }
00218 
00219         width += context.ptToPixelX( getSpaceAfter( context, tstyle, factor ) );
00220 
00221         setWidth(width);
00222         setHeight(toBaseline+fromBaseline);
00223         setBaseline(toBaseline);
00224 
00225         setChildrenPositions();
00226     }
00227     else {
00228         luPixel w = context.getEmptyRectWidth( factor );
00229         luPixel h = context.getEmptyRectHeight( factor );
00230         setWidth( w );
00231         setHeight( h );
00232         setBaseline( h );
00233         //setMidline( h*.5 );
00234     }
00235 }
00236 
00237 
00238 void SequenceElement::setChildrenPositions()
00239 {
00240     QPtrListIterator<BasicElement> it( children );
00241     for ( ; it.current(); ++it ) {
00242         BasicElement* child = it.current();
00243         child->setY(getBaseline() - child->getBaseline());
00244     }
00245 }
00246 
00247 
00253 void SequenceElement::draw( QPainter& painter, const LuPixelRect& r,
00254                             const ContextStyle& context,
00255                             ContextStyle::TextStyle tstyle,
00256                             ContextStyle::IndexStyle istyle,
00257                             StyleAttributes& style,
00258                             const LuPixelPoint& parentOrigin )
00259 {
00260     LuPixelPoint myPos( parentOrigin.x() + getX(), parentOrigin.y() + getY() );
00261     // There might be zero sized elements that still want to be drawn at least
00262     // in edit mode. (EmptyElement)
00263     //if ( !LuPixelRect( myPos.x(), myPos.y(), getWidth(), getHeight() ).intersects( r ) )
00264     //    return;
00265 
00266     if (!isEmpty()) {
00267         QPtrListIterator<BasicElement> it( children );
00268         for (int i = 0 ; it.current(); i++) {
00269             BasicElement* child = it.current();
00270             if (!child->isInvisible()) {
00271                 child->draw(painter, r, context, tstyle, istyle, style, myPos);
00272 
00273                 // Each starting element draws the whole token
00274                 // This only concerns TextElements.
00275                 /*
00276                 ElementType* token = child->getElementType();
00277                 if ( token != 0 ) {
00278                     it += token->end() - token->start();
00279                 }
00280                 else {
00281                     ++it;
00282                 }
00283                 */
00284             }
00285 //            else {
00286                 ++it;
00287 //            }
00288         }
00289     }
00290     else {
00291         drawEmptyRect( painter, context, style.sizeFactor(), myPos );
00292     }
00293     // Debug
00294     //painter.setPen(Qt::green);
00295     //painter.drawRect(parentOrigin.x() + getX(), parentOrigin.y() + getY(),
00296     //                 getWidth(), getHeight());
00297 //     painter.drawLine( context.layoutUnitToPixelX( parentOrigin.x() + getX() ),
00298 //                       context.layoutUnitToPixelY( parentOrigin.y() + getY() + axis( context, tstyle ) ),
00299 //                       context.layoutUnitToPixelX( parentOrigin.x() + getX() + getWidth() ),
00300 //                       context.layoutUnitToPixelY( parentOrigin.y() + getY() + axis( context, tstyle ) ) );
00301 //     painter.setPen(Qt::red);
00302 //     painter.drawLine( context.layoutUnitToPixelX( parentOrigin.x() + getX() ),
00303 //                       context.layoutUnitToPixelY( parentOrigin.y() + getY() + getBaseline() ),
00304 //                       context.layoutUnitToPixelX( parentOrigin.x() + getX() + getWidth() ),
00305 //                       context.layoutUnitToPixelY( parentOrigin.y() + getY() + getBaseline() ) );
00306 }
00307 
00308 
00309 void SequenceElement::dispatchFontCommand( FontCommand* cmd )
00310 {
00311     QPtrListIterator<BasicElement> it( children );
00312     for ( ; it.current(); ++it ) {
00313         BasicElement* child = it.current();
00314         child->dispatchFontCommand( cmd );
00315     }
00316 }
00317 
00318 
00319 void SequenceElement::drawEmptyRect( QPainter& painter, const ContextStyle& context,
00320                                      double factor, const LuPixelPoint& upperLeft )
00321 {
00322     if ( context.edit() ) {
00323         painter.setBrush(Qt::NoBrush);
00324         painter.setPen( QPen( context.getEmptyColor(),
00325                               context.layoutUnitToPixelX( context.getLineWidth( factor ) ) ) );
00326         painter.drawRect( context.layoutUnitToPixelX( upperLeft.x() ),
00327                           context.layoutUnitToPixelY( upperLeft.y() ),
00328                           context.layoutUnitToPixelX( getWidth() ),
00329                           context.layoutUnitToPixelY( getHeight() ) );
00330     }
00331 }
00332 
00333 void SequenceElement::calcCursorSize( const ContextStyle& context,
00334                                       FormulaCursor* cursor, bool smallCursor )
00335 {
00336     LuPixelPoint point = widgetPos();
00337     uint pos = cursor->getPos();
00338 
00339     luPixel posX = getChildPosition( context, pos );
00340     luPixel height = getHeight();
00341 
00342     luPixel unitX = context.ptToLayoutUnitPixX( 1 );
00343     luPixel unitY = context.ptToLayoutUnitPixY( 1 );
00344 
00345     // Here are those evil constants that describe the cursor size.
00346 
00347     if ( cursor->isSelection() ) {
00348         uint mark = cursor->getMark();
00349         luPixel markX = getChildPosition( context, mark );
00350         luPixel x = QMIN(posX, markX);
00351         luPixel width = abs(posX - markX);
00352 
00353         if ( smallCursor ) {
00354             cursor->cursorSize.setRect( point.x()+x, point.y(), width, height );
00355         }
00356         else {
00357             cursor->cursorSize.setRect( point.x()+x, point.y() - 2*unitY,
00358                                         width + unitX, height + 4*unitY );
00359         }
00360     }
00361     else {
00362         if ( smallCursor ) {
00363             cursor->cursorSize.setRect( point.x()+posX, point.y(),
00364                                         unitX, height );
00365         }
00366         else {
00367             cursor->cursorSize.setRect( point.x(), point.y() - 2*unitY,
00368                                         getWidth() + unitX, height + 4*unitY );
00369         }
00370     }
00371 
00372     cursor->cursorPoint.setX( point.x()+posX );
00373     cursor->cursorPoint.setY( point.y()+getHeight()/2 );
00374 }
00375 
00376 
00380 void SequenceElement::drawCursor( QPainter& painter, const ContextStyle& context,
00381                                   StyleAttributes& style, FormulaCursor* cursor,
00382                                   bool smallCursor, bool activeCursor )
00383 {
00384     painter.setRasterOp( Qt::XorROP );
00385     if ( cursor->isSelection() ) {
00386         const LuPixelRect& r = cursor->cursorSize;
00387         painter.fillRect( context.layoutUnitToPixelX( r.x() ),
00388                           context.layoutUnitToPixelY( r.y() ),
00389                           context.layoutUnitToPixelX( r.width() ),
00390                           context.layoutUnitToPixelY( r.height() ),
00391                           Qt::white );
00392     }
00393     painter.setPen( QPen( Qt::white,
00394                           context.layoutUnitToPixelX( context.getLineWidth( style.sizeFactor() )/2 ) ) );
00395     const LuPixelPoint& point = cursor->getCursorPoint();
00396     const LuPixelRect& size = cursor->getCursorSize();
00397     if ( activeCursor )
00398     {
00399         int offset = 0;
00400         if ( cursor->isSelection() && cursor->getPos() > cursor->getMark() )
00401             offset = -1;
00402         painter.drawLine( context.layoutUnitToPixelX( point.x() ) + offset,
00403                           context.layoutUnitToPixelY( size.top() ),
00404                           context.layoutUnitToPixelX( point.x() ) + offset,
00405                           context.layoutUnitToPixelY( size.bottom() )-1 );
00406         painter.drawLine( context.layoutUnitToPixelX( point.x() ) + offset + 1,
00407                           context.layoutUnitToPixelY( size.top() ),
00408                           context.layoutUnitToPixelX( point.x() ) + offset + 1,
00409                           context.layoutUnitToPixelY( size.bottom() )-1 );
00410     }
00411     if ( !smallCursor && !cursor->isSelection() )
00412         painter.drawLine( context.layoutUnitToPixelX( size.left() ),
00413                           context.layoutUnitToPixelY( size.bottom() )-1,
00414                           context.layoutUnitToPixelX( size.right() )-1,
00415                           context.layoutUnitToPixelY( size.bottom() )-1 );
00416     // This might be wrong but probably isn't.
00417     painter.setRasterOp( Qt::CopyROP );
00418 }
00419 
00420 
00421 luPixel SequenceElement::getChildPosition( const ContextStyle& context, uint child )
00422 {
00423     if (child < children.count()) {
00424         return children.at(child)->getX();
00425     }
00426     else {
00427         if (children.count() > 0) {
00428             return children.at(child-1)->getX() + children.at(child-1)->getWidth();
00429         }
00430         else {
00431             return context.ptToLayoutUnitPixX( 2 );
00432         }
00433     }
00434 }
00435 
00436 
00437 // navigation
00438 //
00439 // The elements are responsible to handle cursor movement themselves.
00440 // To do this they need to know the direction the cursor moves and
00441 // the element it comes from.
00442 //
00443 // The cursor might be in normal or in selection mode.
00444 
00450 void SequenceElement::moveLeft(FormulaCursor* cursor, BasicElement* from)
00451 {
00452     // Our parent asks us for a cursor position. Found.
00453     if (from == getParent()) {
00454         cursor->setTo(this, children.count());
00455         if ( cursor->isSelectionMode() ) {
00456             cursor->setMark( children.count() );
00457         }
00458         from->entered( this );
00459     }
00460 
00461     // We already owned the cursor. Ask next child then.
00462     else if (from == this) {
00463         if (cursor->getPos() > 0) {
00464             cursor->setTo(this, cursor->getPos()-1);
00465 
00466             // invisible elements are not visible so we move on.
00467             if (children.at(cursor->getPos())->isInvisible()) {
00468                 moveLeft(cursor, this);
00469             }
00470         }
00471         else {
00472             // Needed because FormulaElement derives this.
00473             if (getParent() != 0) {
00474                 getParent()->moveLeft(cursor, this);
00475             }
00476             else {
00477                 formula()->moveOutLeft( cursor );
00478             }
00479         }
00480     }
00481 
00482     // The cursor came from one of our children or
00483     // something is wrong.
00484     else {
00485         int fromPos = children.find(from);
00486         if ( fromPos > 0 ) {
00487             children.at( fromPos - 1)->moveLeft( cursor, this );
00488         }
00489         else {
00490             cursor->setTo(this, fromPos);
00491         }
00492 
00493         // invisible elements are not visible so we move on.
00494         if (from->isInvisible()) {
00495             moveLeft(cursor, this);
00496         }
00497         formula()->tell( "" );
00498     }
00499 }
00500 
00506 void SequenceElement::moveRight(FormulaCursor* cursor, BasicElement* from)
00507 {
00508     // Our parent asks us for a cursor position. Found.
00509     if (from == getParent()) {
00510         cursor->setTo(this, 0);
00511         from->entered( this );
00512     }
00513 
00514     // We already owned the cursor. Ask next child then.
00515     else if (from == this) {
00516         uint pos = cursor->getPos();
00517         if (pos < children.count()) {
00518             cursor->setTo(this, pos+1);
00519             
00520             // invisible elements are not visible so we move on.
00521             if (children.at(pos)->isInvisible()) {
00522                 moveRight(cursor, this);
00523             }
00524         }
00525         else {
00526             // Needed because FormulaElement derives this.
00527             if (getParent() != 0) {
00528                 getParent()->moveRight(cursor, this);
00529             }
00530             else {
00531                 formula()->moveOutRight( cursor );
00532             }
00533         }
00534     }
00535 
00536     // The cursor came from one of our children or
00537     // something is wrong.
00538     else {
00539         int fromPos = children.find(from);
00540         if ( fromPos < children.count() - 1 ) {
00541             children.at( fromPos + 1 )->moveDown( cursor, this );
00542         }
00543         else {
00544             cursor->setTo(this, fromPos+1);
00545         }
00546         if (cursor->isSelectionMode()) {
00547             cursor->setMark(fromPos);
00548         }
00549 
00550         // invisible elements are not visible so we move on.
00551         if (from->isInvisible()) {
00552             moveRight(cursor, this);
00553         }
00554         formula()->tell( "" );
00555     }
00556 }
00557 
00558 
00559 void SequenceElement::moveWordLeft(FormulaCursor* cursor)
00560 {
00561     uint pos = cursor->getPos();
00562     if (pos > 0) {
00563         ElementType* type = children.at(pos-1)->getElementType();
00564         if (type != 0) {
00565             cursor->setTo(this, type->start());
00566         }
00567     }
00568     else {
00569         moveLeft(cursor, this);
00570     }
00571 }
00572 
00573 
00574 void SequenceElement::moveWordRight(FormulaCursor* cursor)
00575 {
00576     uint pos = cursor->getPos();
00577     if (pos < children.count()) {
00578         ElementType* type = children.at(pos)->getElementType();
00579         if (type != 0) {
00580             cursor->setTo(this, type->end());
00581         }
00582     }
00583     else {
00584         moveRight(cursor, this);
00585     }
00586 }
00587 
00588 
00594 void SequenceElement::moveUp(FormulaCursor* cursor, BasicElement* from)
00595 {
00596     if (from == getParent()) {
00597         moveRight(cursor, this);
00598     }
00599     else if ( from == this ) {
00600         if ( getParent() != 0 ) {
00601             uint pos = cursor->getPos();
00602             if ( pos < (children.count() - 1) / 2 ) {
00603                 getParent()->moveLeft( cursor, this );
00604             }
00605             else {
00606                 getParent()->moveRight( cursor, this );
00607             }
00608         }
00609         else {
00610                 formula()->moveOutAbove( cursor );
00611         }
00612     }
00613     else {
00614         if (getParent() != 0) {
00615             getParent()->moveUp(cursor, this);
00616         }
00617         else {
00618             formula()->moveOutAbove( cursor );
00619         }
00620     }
00621 }
00622 
00628 void SequenceElement::moveDown(FormulaCursor* cursor, BasicElement* from)
00629 {
00630     if (from == getParent()) {
00631         cursor->setTo(this, 0);
00632         from->entered( this );
00633     }
00634     else if (from == this) {
00635         uint pos = cursor->getPos();
00636         if (pos < children.count()) {
00637                 children.at(pos)->moveDown(cursor, this);
00638         }
00639     }
00640     else {
00641         if (getParent() != 0) {
00642             getParent()->moveDown(cursor, this);
00643         }
00644         else {
00645             cursor->setTo( this, children.count() );
00646             from->entered( this );
00647 //            formula()->moveOutBelow( cursor );
00648         }
00649     }
00650 }
00651 
00656 void SequenceElement::moveHome(FormulaCursor* cursor)
00657 {
00658     if (cursor->isSelectionMode()) {
00659         BasicElement* element = cursor->getElement();
00660         if (element != this) {
00661             while (element->getParent() != this) {
00662                 element = element->getParent();
00663             }
00664             cursor->setMark(children.find(element)+1);
00665         }
00666     }
00667     cursor->setTo(this, 0);
00668 }
00669 
00674 void SequenceElement::moveEnd(FormulaCursor* cursor)
00675 {
00676     if (cursor->isSelectionMode()) {
00677         BasicElement* element = cursor->getElement();
00678         if (element != this) {
00679             while (element->getParent() != this) {
00680                 element = element->getParent();
00681                 if (element == 0) {
00682                     cursor->setMark(children.count());
00683                     break;
00684                 }
00685             }
00686             if (element != 0) {
00687                 cursor->setMark(children.find(element));
00688             }
00689         }
00690     }
00691     cursor->setTo(this, children.count());
00692 }
00693 
00698 void SequenceElement::goInside(FormulaCursor* cursor)
00699 {
00700     cursor->setSelection(false);
00701     cursor->setTo(this, 0);
00702 }
00703 
00708 void SequenceElement::goInsideLast(FormulaCursor* cursor)
00709 {
00710     cursor->setSelection(false);
00711     cursor->setTo(this, children.count());
00712 }
00713 
00714 
00715 // children
00716 
00727 bool SequenceElement::insert( uint index, BasicElement *child )
00728 {
00729     return children.insert( index, child );
00730 }
00731 
00739 // void SequenceElement::removeChild(FormulaCursor* cursor, BasicElement* child)
00740 // {
00741 //     int pos = children.find(child);
00742 //     formula()->elementRemoval(child, pos);
00743 //     cursor->setTo(this, pos);
00744 //     children.remove(pos);
00745 //     /*
00746 //         if len(self.children) == 0:
00747 //             if self.parent != None:
00748 //                 self.parent.removeChild(cursor, self)
00749 //                 return
00750 //     */
00751 //     formula()->changed();
00752 // }
00753 
00754 
00762 void SequenceElement::insert(FormulaCursor* cursor,
00763                              QPtrList<BasicElement>& newChildren,
00764                              Direction direction)
00765 {
00766     int pos = cursor->getPos();
00767     uint count = newChildren.count();
00768     for (uint i = 0; i < count; i++) {
00769         BasicElement* child = newChildren.take(0);
00770         child->setParent(this);
00771         children.insert(pos+i, child);
00772     }
00773     if (direction == beforeCursor) {
00774         cursor->setTo(this, pos+count, pos);
00775     }
00776     else {
00777         cursor->setTo(this, pos, pos+count);
00778     }
00779 
00780     formula()->changed();
00781     parse();
00782 }
00783 
00784 
00791 void SequenceElement::remove(FormulaCursor* cursor,
00792                              QPtrList<BasicElement>& removedChildren,
00793                              Direction direction)
00794 {
00795     if (cursor->isSelection()) {
00796         int from = cursor->getSelectionStart();
00797         int to = cursor->getSelectionEnd();
00798         for (int i = from; i < to; i++) {
00799             removeChild(removedChildren, from);
00800         }
00801         cursor->setTo(this, from);
00802         cursor->setSelection(false);
00803     }
00804     else {
00805         if (direction == beforeCursor) {
00806             int pos = cursor->getPos() - 1;
00807             if (pos >= 0) {
00808                 while (pos >= 0) {
00809                     BasicElement* child = children.at(pos);
00810                     formula()->elementRemoval(child);
00811                     children.take(pos);
00812                     removedChildren.prepend(child);
00813                     if (!child->isInvisible()) {
00814                         break;
00815                     }
00816                     pos--;
00817                 }
00818                 cursor->setTo(this, pos);
00819                 formula()->changed();
00820             }
00821         }
00822         else {
00823             uint pos = cursor->getPos();
00824             if (pos < children.count()) {
00825                 while (pos < children.count()) {
00826                     BasicElement* child = children.at(pos);
00827                     formula()->elementRemoval(child);
00828                     children.take(pos);
00829                     removedChildren.append(child);
00830                     if (!child->isInvisible()) {
00831                         break;
00832                     }
00833                 }
00834                 // It is necessary to set the cursor to its old
00835                 // position because it got a notification and
00836                 // moved to the beginning of this sequence.
00837                 cursor->setTo(this, pos);
00838                 formula()->changed();
00839             }
00840         }
00841     }
00842     parse();
00843 }
00844 
00845 
00849 void SequenceElement::removeChild(QPtrList<BasicElement>& removedChildren, int pos)
00850 {
00851     BasicElement* child = children.at(pos);
00852     formula()->elementRemoval(child);
00853     children.take(pos);
00854     removedChildren.append(child);
00855     //cerr << *removedChildren.at(0) << endl;
00856     formula()->changed();
00857 }
00858 
00859 
00864 void SequenceElement::normalize(FormulaCursor* cursor, Direction)
00865 {
00866     cursor->setSelection(false);
00867 }
00868 
00869 
00874 BasicElement* SequenceElement::getChild( FormulaCursor* cursor, Direction direction )
00875 {
00876     if ( direction == beforeCursor ) {
00877         if ( cursor->getPos() > 0 ) {
00878             return children.at( cursor->getPos() - 1 );
00879         }
00880     }
00881     else {
00882         if ( cursor->getPos() < qRound( children.count() ) ) {
00883             return children.at( cursor->getPos() );
00884         }
00885     }
00886     return 0;
00887 }
00888 
00889 
00894 void SequenceElement::selectChild(FormulaCursor* cursor, BasicElement* child)
00895 {
00896     int pos = children.find(child);
00897     if (pos > -1) {
00898         cursor->setTo(this, pos+1, pos);
00899     }
00900 }
00901 
00902 void SequenceElement::childWillVanish(FormulaCursor* cursor, BasicElement* child)
00903 {
00904     int childPos = children.find(child);
00905     if (childPos > -1) {
00906         int pos = cursor->getPos();
00907         if (pos > childPos) {
00908             pos--;
00909         }
00910         int mark = cursor->getMark();
00911         if (mark > childPos) {
00912             mark--;
00913         }
00914         cursor->setTo(this, pos, mark);
00915     }
00916 }
00917 
00918 
00922 void SequenceElement::selectAllChildren(FormulaCursor* cursor)
00923 {
00924     cursor->setTo(this, children.count(), 0);
00925 }
00926 
00927 bool SequenceElement::onlyTextSelected( FormulaCursor* cursor )
00928 {
00929     if ( cursor->isSelection() ) {
00930         uint from = QMIN( cursor->getPos(), cursor->getMark() );
00931         uint to = QMAX( cursor->getPos(), cursor->getMark() );
00932         for ( uint i = from; i < to; i++ ) {
00933             BasicElement* element = getChild( i );
00934             if ( element->getCharacter() == QChar::null ) {
00935                 return false;
00936             }
00937         }
00938     }
00939     return true;
00940 }
00941 
00942 
00943 KCommand* SequenceElement::buildCommand( Container* container, Request* request )
00944 {
00945     FormulaCursor* cursor = container->activeCursor();
00946     if ( cursor->isReadOnly() ) {
00947         formula()->tell( i18n( "write protection" ) );
00948         return 0;
00949     }
00950 
00951     switch ( *request ) {
00952     case req_addText: {
00953         KFCReplaceToken* command = new KFCReplaceToken( i18n("Add Text"), container );
00954         TextRequest* tr = static_cast<TextRequest*>( request );
00955         IdentifierElement* id = creationStrategy->createIdentifierElement();
00956         command->addToken( id );
00957         for ( uint i = 0; i < tr->text().length(); i++ ) {
00958             TextElement* text = creationStrategy->createTextElement( tr->text()[i] );
00959             command->addContent( id, text );
00960         }
00961         return command;
00962     }
00963     case req_addTextChar: {
00964         KFCReplaceToken* command = new KFCReplaceToken( i18n("Add Text"), container );
00965         TextCharRequest* tr = static_cast<TextCharRequest*>( request );
00966         IdentifierElement* id = creationStrategy->createIdentifierElement();
00967         TextElement* text = creationStrategy->createTextElement( tr->ch() );
00968         command->addToken( id );
00969         command->addContent( id, text );
00970         return command;
00971     }
00972 
00973     case req_addOperator: {
00974         KFCReplaceToken* command = new KFCReplaceToken( i18n("Add Operator"), container );
00975         OperatorRequest* opr = static_cast<OperatorRequest*>( request );
00976         OperatorElement* op = creationStrategy->createOperatorElement();
00977         TextElement* text = creationStrategy->createTextElement( opr->ch() );
00978         command->addToken( op );
00979         command->addContent( op, text );
00980         return command;
00981     }
00982 
00983     case req_addNumber: {
00984         KFCReplaceToken* command = new KFCReplaceToken( i18n("Add Number"), container );
00985         NumberRequest* nr = static_cast<NumberRequest*>( request );
00986         NumberElement* num = creationStrategy->createNumberElement();
00987         num->setParent( this );
00988         TextElement* text = creationStrategy->createTextElement( nr->ch() );
00989         text->setParent( num );
00990         command->addToken( num );
00991         command->addContent( num, text );
00992         return command;
00993     }
00994 
00995     case req_addEmptyBox: {
00996         EmptyElement* element = creationStrategy->createEmptyElement();
00997         if ( element != 0 ) {
00998             KFCReplace* command = new KFCReplace( i18n("Add Empty Box"), container );
00999             command->addElement( element );
01000             return command;
01001         }
01002         break;
01003     }
01004     case req_addNameSequence:
01005         if ( onlyTextSelected( container->activeCursor() ) ) {
01006             NameSequence* nameSequence = creationStrategy->createNameSequence();
01007             if ( nameSequence != 0 ) {
01008                 KFCAddReplacing* command = new KFCAddReplacing( i18n( "Add Name" ), container );
01009                 command->setElement( nameSequence );
01010                 return command;
01011             }
01012         }
01013         break;
01014     case req_addBracket: {
01015         BracketRequest* br = static_cast<BracketRequest*>( request );
01016         BracketElement* bracketElement =
01017             creationStrategy->createBracketElement( br->left(), br->right() );
01018         if ( bracketElement != 0 ) {
01019             KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Bracket"), container);
01020             command->setElement( bracketElement );
01021             return command;
01022         }
01023         break;
01024     }
01025     case req_addOverline: {
01026         OverlineElement* overline = creationStrategy->createOverlineElement();
01027         if ( overline != 0 ) {
01028             KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Overline"), container);
01029             command->setElement( overline );
01030             return command;
01031         }
01032         break;
01033     }
01034     case req_addUnderline: {
01035         UnderlineElement* underline = creationStrategy->createUnderlineElement();
01036         if ( underline != 0 ) {
01037             KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Underline"), container);
01038             command->setElement( underline );
01039             return command;
01040         }
01041         break;
01042     }
01043     case req_addMultiline: {
01044         MultilineElement* multiline = creationStrategy->createMultilineElement();
01045         if ( multiline != 0 ) {
01046             KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Multiline"), container);
01047             command->setElement( multiline );
01048             return command;
01049         }
01050         break;
01051     }
01052     case req_addSpace: {
01053         SpaceRequest* sr = static_cast<SpaceRequest*>( request );
01054         SpaceElement* element = creationStrategy->createSpaceElement( sr->space() );
01055         if ( element != 0 ) {
01056             KFCReplace* command = new KFCReplace( i18n("Add Space"), container );
01057             command->addElement( element );
01058             return command;
01059         }
01060         break;
01061     }
01062     case req_addFraction: {
01063         FractionElement* fraction = creationStrategy->createFractionElement();
01064         if ( fraction != 0 ) {
01065             KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Fraction"), container);
01066             command->setElement( fraction );
01067             return command;
01068         }
01069         break;
01070     }
01071     case req_addRoot: {
01072         RootElement* root = creationStrategy->createRootElement();
01073         if ( root != 0 ) {
01074             KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Root"), container);
01075             command->setElement( root );
01076             return command;
01077         }
01078         break;
01079     }
01080     case req_addSymbol: {
01081         SymbolRequest* sr = static_cast<SymbolRequest*>( request );
01082         SymbolElement* symbol = creationStrategy->createSymbolElement( sr->type() );
01083         if ( symbol != 0 ) {
01084             KFCAddReplacing* command = new KFCAddReplacing( i18n( "Add Symbol" ), container );
01085             command->setElement( symbol );
01086             return command;
01087         }
01088         break;
01089     }
01090     case req_addOneByTwoMatrix: {
01091         FractionElement* element = creationStrategy->createFractionElement();
01092         if ( element != 0 ) {
01093             KFCAddReplacing* command = new KFCAddReplacing( i18n("Add 1x2 Matrix"), container );
01094             element->showLine(false);
01095             command->setElement(element);
01096             return command;
01097         }
01098     }
01099     case req_addMatrix: {
01100         MatrixRequest* mr = static_cast<MatrixRequest*>( request );
01101         uint rows = mr->rows(), cols = mr->columns();
01102         if ( ( rows == 0 ) || ( cols == 0 ) ) {
01103             MatrixDialog* dialog = new MatrixDialog( 0 );
01104             if ( dialog->exec() ) {
01105                 rows = dialog->h;
01106                 cols = dialog->w;
01107             }
01108             delete dialog;
01109         }
01110 
01111         if ( ( rows != 0 ) && ( cols != 0 ) ) {
01112             KFCAddReplacing* command = new KFCAddReplacing( i18n( "Add Matrix" ), container );
01113             command->setElement( creationStrategy->createMatrixElement( rows, cols ) );
01114             return command;
01115         }
01116         else
01117             return 0L;
01118     }
01119     case req_addIndex: {
01120         if ( cursor->getPos() > 0 && !cursor->isSelection() ) {
01121             IndexElement* element =
01122                 dynamic_cast<IndexElement*>( children.at( cursor->getPos()-1 ) );
01123             if ( element != 0 ) {
01124                 element->goInside( cursor );
01125                 return element->buildCommand( container, request );
01126             }
01127         }
01128         IndexElement* element = creationStrategy->createIndexElement();
01129         if ( element != 0 ) {
01130             if ( !cursor->isSelection() ) {
01131                 cursor->moveLeft( SelectMovement | WordMovement );
01132             }
01133             IndexRequest* ir = static_cast<IndexRequest*>( request );
01134             KFCAddIndex* command = new KFCAddIndex( container, element,
01135                                                     element->getIndex( ir->index() ) );
01136             return command;
01137         }
01138         break;
01139     }
01140     case req_removeEnclosing: {
01141         if ( !cursor->isSelection() ) {
01142             DirectedRemove* dr = static_cast<DirectedRemove*>( request );
01143             KFCRemoveEnclosing* command = new KFCRemoveEnclosing( container, dr->direction() );
01144             return command;
01145         }
01146     }
01147     case req_remove: {
01148         SequenceElement* sequence = cursor->normal();
01149         if ( sequence &&
01150              ( sequence == sequence->formula() ) &&
01151              ( sequence->countChildren() == 0 ) ) {
01152             sequence->formula()->removeFormula( cursor );
01153             return 0;
01154         }
01155         else {
01156             DirectedRemove* dr = static_cast<DirectedRemove*>( request );
01157 
01158             // empty removes are not legal!
01159             if ( !cursor->isSelection() ) {
01160                 if ( countChildren() > 0 ) {
01161                     if ( ( cursor->getPos() == 0 ) && ( dr->direction() == beforeCursor ) ) {
01162                         return 0;
01163                     }
01164                     if ( ( cursor->getPos() == countChildren() ) && ( dr->direction() == afterCursor ) ) {
01165                         return 0;
01166                     }
01167                 }
01168                 else if ( getParent() == 0 ) {
01169                     return 0;
01170                 }
01171             }
01172 
01173             KFCRemove* command = new KFCRemove( container, dr->direction() );
01174             return command;
01175         }
01176     }
01177     case req_compactExpression: {
01178         cursor->moveEnd();
01179         cursor->moveRight();
01180         formula()->cursorHasMoved( cursor );
01181         break;
01182     }
01183     case req_makeGreek: {
01184         TextElement* element = cursor->getActiveTextElement();
01185         if ((element != 0) && !element->isSymbol()) {
01186             cursor->selectActiveElement();
01187             const SymbolTable& table = container->document()->getSymbolTable();
01188             if (table.greekLetters().find(element->getCharacter()) != -1) {
01189                 KFCReplace* command = new KFCReplace( i18n( "Change Char to Symbol" ), container );
01190                 TextElement* symbol = creationStrategy->createTextElement( table.unicodeFromSymbolFont( element->getCharacter() ), true );
01191                 command->addElement( symbol );
01192                 return command;
01193             }
01194             cursor->setSelection( false );
01195         }
01196         break;
01197     }
01198     case req_paste:
01199     case req_copy:
01200     case req_cut:
01201         break;
01202     case req_formatBold:
01203     case req_formatItalic: {
01204         if ( cursor->isSelection() ) {
01205             CharStyleRequest* csr = static_cast<CharStyleRequest*>( request );
01206             CharStyle cs = normalChar;
01207             if ( csr->bold() ) cs = static_cast<CharStyle>( cs | boldChar );
01208             if ( csr->italic() ) cs = static_cast<CharStyle>( cs | italicChar );
01209             CharStyleCommand* cmd = new CharStyleCommand( cs, i18n( "Change Char Style" ), container );
01210             int end = cursor->getSelectionEnd();
01211             for ( int i = cursor->getSelectionStart(); i<end; ++i ) {
01212                 cmd->addElement( children.at( i ) );
01213             }
01214             return cmd;
01215         }
01216         break;
01217     }
01218     case req_formatFamily: {
01219         if ( cursor->isSelection() ) {
01220             CharFamilyRequest* cfr = static_cast<CharFamilyRequest*>( request );
01221             CharFamily cf = cfr->charFamily();
01222             CharFamilyCommand* cmd = new CharFamilyCommand( cf, i18n( "Change Char Family" ), container );
01223             int end = cursor->getSelectionEnd();
01224             for ( int i = cursor->getSelectionStart(); i<end; ++i ) {
01225                 cmd->addElement( children.at( i ) );
01226             }
01227             return cmd;
01228         }
01229         break;
01230     }
01231     default:
01232         break;
01233     }
01234     return 0;
01235 }
01236 
01237 
01238 KCommand* SequenceElement::input( Container* container, QKeyEvent* event )
01239 {
01240     QChar ch = event->text().at( 0 );
01241     if ( ch.isPrint() ) {
01242         return input( container, ch );
01243     }
01244     else {
01245         int action = event->key();
01246         int state = event->state();
01247         MoveFlag flag = movementFlag(state);
01248 
01249     switch ( action ) {
01250         case Qt::Key_BackSpace: {
01251             DirectedRemove r( req_remove, beforeCursor );
01252             return buildCommand( container, &r );
01253         }
01254         case Qt::Key_Delete: {
01255             DirectedRemove r( req_remove, afterCursor );
01256             return buildCommand( container, &r );
01257         }
01258     case Qt::Key_Left: {
01259             FormulaCursor* cursor = container->activeCursor();
01260             cursor->moveLeft( flag );
01261             formula()->cursorHasMoved( cursor );
01262             break;
01263         }
01264         case Qt::Key_Right: {
01265             FormulaCursor* cursor = container->activeCursor();
01266             cursor->moveRight( flag );
01267             formula()->cursorHasMoved( cursor );
01268             break;
01269         }
01270         case Qt::Key_Up: {
01271             FormulaCursor* cursor = container->activeCursor();
01272             cursor->moveUp( flag );
01273             formula()->cursorHasMoved( cursor );
01274             break;
01275         }
01276         case Qt::Key_Down: {
01277             FormulaCursor* cursor = container->activeCursor();
01278             cursor->moveDown( flag );
01279             formula()->cursorHasMoved( cursor );
01280             break;
01281         }
01282         case Qt::Key_Home: {
01283             FormulaCursor* cursor = container->activeCursor();
01284             cursor->moveHome( flag );
01285             formula()->cursorHasMoved( cursor );
01286             break;
01287         }
01288         case Qt::Key_End: {
01289             FormulaCursor* cursor = container->activeCursor();
01290             cursor->moveEnd( flag );
01291             formula()->cursorHasMoved( cursor );
01292             break;
01293         }
01294         default:
01295             if ( state & Qt::ControlButton ) {
01296                 switch ( event->key() ) {
01297                 case Qt::Key_AsciiCircum: {
01298                     IndexRequest r( upperLeftPos );
01299                     return buildCommand( container, &r );
01300                 }
01301                 case Qt::Key_Underscore: {
01302                     IndexRequest r( lowerLeftPos );
01303                     return buildCommand( container, &r );
01304                 }
01305                 default:
01306                     break;
01307                 }
01308             }
01309         }
01310     }
01311     return 0;
01312 }
01313 
01314 
01315 KCommand* SequenceElement::input( Container* container, QChar ch )
01316 {
01317     int unicode = ch.unicode();
01318     switch (unicode) {
01319     case '(': {
01320         BracketRequest r( container->document()->leftBracketChar(),
01321                           container->document()->rightBracketChar() );
01322         singlePipe = true;
01323         return buildCommand( container, &r );
01324     }
01325     case '[': {
01326         BracketRequest r( LeftSquareBracket, RightSquareBracket );
01327         singlePipe = true;
01328         return buildCommand( container, &r );
01329     }
01330     case '{': {
01331         BracketRequest r( LeftCurlyBracket, RightCurlyBracket );
01332         singlePipe = true;
01333         return buildCommand( container, &r );
01334     }
01335     case '|': { 
01336         if (!singlePipe) { // We have had 2 '|' in a row so we want brackets
01337 
01338           DirectedRemove rDelete( req_remove, beforeCursor ); //Delete the previous '|' we dont need it any more
01339           KCommand* command = buildCommand( container, &rDelete );
01340           command->execute();
01341           
01342           BracketRequest rBracket( LeftLineBracket , RightLineBracket);
01343           singlePipe = true;  //the next '|' will be a single pipe again
01344           return buildCommand( container, &rBracket );    
01345         }
01346         else { // We really do only want 1 '|'
01347           TextCharRequest r(ch);
01348 
01349           //in case another '|' character is entered right after this one, '| |' brackets are made; see above
01350           singlePipe = false;
01351 
01352           return buildCommand( container, &r );   
01353         }
01354     }
01355     case '^': {
01356         IndexRequest r( upperRightPos );
01357         singlePipe = true;
01358         return buildCommand( container, &r );
01359     }
01360     case '_': {
01361         IndexRequest r( lowerRightPos );
01362         singlePipe = true;
01363         return buildCommand( container, &r );
01364     }
01365         /*
01366     case ' ': {
01367         Request r( req_compactExpression );
01368         singlePipe = true;
01369         return buildCommand( container, &r );
01370         }*/
01371     case '}': {
01372         Request r( req_addEmptyBox );
01373         singlePipe = true;
01374         return buildCommand( container, &r );
01375     }
01376     case ']':
01377     case ')':
01378         singlePipe = true; 
01379         break;
01380     case '\\': {
01381         Request r( req_addNameSequence );
01382         singlePipe = true;
01383         return buildCommand( container, &r );
01384     }
01385     default: {
01386         singlePipe = true;
01387         if ( ch.isPunct() || ch.isSymbol() ) {
01388             OperatorRequest r( ch );
01389             return buildCommand( container, &r );
01390         }
01391         if ( ch.isNumber() ) {
01392             NumberRequest r( ch );
01393             return buildCommand( container, &r );
01394         }
01395         TextCharRequest r( ch );
01396         return buildCommand( container, &r );
01397     }
01398     }
01399     return 0;
01400 }
01401 
01405 void SequenceElement::getChildrenDom( QDomDocument& doc, QDomElement elem,
01406                                      uint from, uint to)
01407 {
01408     for (uint i = from; i < to; i++) {
01409         QDomElement tmpEleDom=children.at(i)->getElementDom(doc);
01410         elem.appendChild(tmpEleDom);
01411     }
01412 }
01413 
01417 void SequenceElement::getChildrenMathMLDom( QDomDocument& doc, QDomNode& parent,
01418                                             uint from, uint to)
01419 {
01420     for ( uint i = from; i < to; i++ ) {
01421         children.at( i )->writeMathML( doc, parent, false );
01422     }
01423 }
01424 
01425 
01431 bool SequenceElement::buildChildrenFromDom(QPtrList<BasicElement>& list, QDomNode n)
01432 {
01433     while (!n.isNull()) {
01434         if (n.isElement()) {
01435             QDomElement e = n.toElement();
01436             BasicElement* child = 0;
01437             QString tag = e.tagName().upper();
01438 
01439             child = createElement(tag, e);
01440             if (child != 0) {
01441                 child->setParent(this);
01442                 if (child->buildFromDom(e)) {
01443                     list.append(child);
01444                 }
01445                 else {
01446                     delete child;
01447                     return false;
01448                 }
01449             }
01450             else {
01451                 return false;
01452             }
01453         }
01454         n = n.nextSibling();
01455     }
01456     parse();
01457     return true;
01458 }
01459 
01460 
01461 BasicElement* SequenceElement::createElement( QString type, const QDomElement& element )
01462 {
01463     return creationStrategy->createElement( type, element );
01464 }
01465 
01469 void SequenceElement::writeDom(QDomElement element)
01470 {
01471     BasicElement::writeDom(element);
01472 
01473     uint count = children.count();
01474     QDomDocument doc = element.ownerDocument();
01475     getChildrenDom(doc, element, 0, count);
01476 }
01477 
01482 bool SequenceElement::readAttributesFromDom(QDomElement element)
01483 {
01484     if (!BasicElement::readAttributesFromDom(element)) {
01485         return false;
01486     }
01487     return true;
01488 }
01489 
01495 bool SequenceElement::readContentFromDom(QDomNode& node)
01496 {
01497     if (!BasicElement::readContentFromDom(node)) {
01498         return false;
01499     }
01500 
01501     return buildChildrenFromDom(children, node);
01502 }
01503 
01504 
01505 void SequenceElement::parse()
01506 {
01507     delete parseTree;
01508 
01509     textSequence = true;
01510     for (BasicElement* element = children.first();
01511          element != 0;
01512          element = children.next()) {
01513 
01514         // Those types are gone. Make sure they won't
01515         // be used.
01516         element->setElementType(0);
01517 
01518         if (element->getCharacter().isNull()) {
01519             textSequence = false;
01520         }
01521     }
01522 
01523     const SymbolTable& symbols = formula()->getSymbolTable();
01524     SequenceParser parser(symbols);
01525     parseTree = parser.parse(children);
01526 
01527     // With the IndexElement dynamically changing its text/non-text
01528     // behaviour we need to reparse your parent, too. Hacky!
01529     BasicElement* p = getParent();
01530     if ( p != 0 ) {
01531         SequenceElement* seq = dynamic_cast<SequenceElement*>( p->getParent() );
01532         if ( seq != 0 ) {
01533             seq->parse();
01534         }
01535     }
01536     // debug
01537     //parseTree->output();
01538 }
01539 
01540 
01541 bool SequenceElement::isFirstOfToken( BasicElement* child )
01542 {
01543     return ( child->getElementType() != 0 ) && isChildNumber( child->getElementType()->start(), child );
01544 }
01545 
01546 
01547 QString SequenceElement::toLatex()
01548 {
01549     QString content;
01550     uint count = children.count();
01551     for ( uint i = 0; i < count; i++ ) {
01552         BasicElement* child = children.at( i );
01553 //         if ( isFirstOfToken( child ) ) {
01554 //             content += "";
01555 //         }
01556         content += child->toLatex();
01557     }
01558     return content;
01559 }
01560 
01561 
01562 QString SequenceElement::formulaString()
01563 {
01564     QString content;
01565     uint count = children.count();
01566     for ( uint i = 0; i < count; i++ ) {
01567         BasicElement* child = children.at( i );
01568         //if ( isFirstOfToken( child ) ) {
01569         //    content += " ";
01570         //}
01571         content += child->formulaString();
01572     }
01573     return content;
01574 }
01575 
01576 
01577 void SequenceElement::writeMathMLContent( QDomDocument& doc, QDomElement& element, bool oasisFormat ) const
01578 {
01579     for ( QPtrListIterator<BasicElement> it( children ); it.current(); ++it ) {
01580         it.current()->writeMathML( doc, element, oasisFormat );
01581     }
01582 }
01583 
01584 
01585 const BasicElement* SequenceElement::getChild( uint i ) const
01586 {
01587     QPtrListIterator<BasicElement> it( children );
01588     it += i;
01589     return it.current();
01590 }
01591 
01592 
01593 int SequenceElement::childPos( const BasicElement* child ) const
01594 {
01595     QPtrListIterator<BasicElement> it( children );
01596     uint count = it.count();
01597     for ( uint i=0; i<count; ++i, ++it ) {
01598         if ( it.current() == child ) {
01599             return i;
01600         }
01601     }
01602     return -1;
01603 }
01604 
01605 
01606 NameSequence::NameSequence( BasicElement* parent )
01607     : SequenceElement( parent )
01608 {
01609 }
01610 
01611 
01612 bool NameSequence::accept( ElementVisitor* visitor )
01613 {
01614     return visitor->visit( this );
01615 }
01616 
01617 
01618 void NameSequence::calcCursorSize( const ContextStyle& context,
01619                                    FormulaCursor* cursor, bool smallCursor )
01620 {
01621     inherited::calcCursorSize( context, cursor, smallCursor );
01622     LuPixelPoint point = widgetPos();
01623     luPixel unitX = context.ptToLayoutUnitPixX( 1 );
01624     luPixel unitY = context.ptToLayoutUnitPixY( 1 );
01625     cursor->addCursorSize( LuPixelRect( point.x()-unitX, point.y()-unitY,
01626                                         getWidth()+2*unitX, getHeight()+2*unitY ) );
01627 }
01628 
01629 void NameSequence::drawCursor( QPainter& painter, const ContextStyle& context,
01630                                StyleAttributes& style, FormulaCursor* cursor,
01631                                bool smallCursor, bool activeCursor )
01632 {
01633     LuPixelPoint point = widgetPos();
01634     painter.setPen( QPen( context.getEmptyColor(),
01635                           context.layoutUnitToPixelX( context.getLineWidth( style.sizeFactor() )/2 ) ) );
01636     luPixel unitX = context.ptToLayoutUnitPixX( 1 );
01637     luPixel unitY = context.ptToLayoutUnitPixY( 1 );
01638     painter.drawRect( context.layoutUnitToPixelX( point.x()-unitX ),
01639                       context.layoutUnitToPixelY( point.y()-unitY ),
01640                       context.layoutUnitToPixelX( getWidth()+2*unitX ),
01641                       context.layoutUnitToPixelY( getHeight()+2*unitY ) );
01642 
01643     inherited::drawCursor( painter, context, style, cursor, smallCursor, activeCursor );
01644 }
01645 
01646 void NameSequence::moveWordLeft( FormulaCursor* cursor )
01647 {
01648     uint pos = cursor->getPos();
01649     if ( pos > 0 ) {
01650         cursor->setTo( this, 0 );
01651     }
01652     else {
01653         moveLeft( cursor, this );
01654     }
01655 }
01656 
01657 void NameSequence::moveWordRight( FormulaCursor* cursor )
01658 {
01659     int pos = cursor->getPos();
01660     if ( pos < countChildren() ) {
01661         cursor->setTo( this, countChildren() );
01662     }
01663     else {
01664         moveRight( cursor, this );
01665     }
01666 }
01667 
01668 
01669 KCommand* NameSequence::compactExpressionCmd( Container* container )
01670 {
01671     BasicElement* element = replaceElement( container->document()->getSymbolTable() );
01672     if ( element != 0 ) {
01673         getParent()->selectChild( container->activeCursor(), this );
01674 
01675         KFCReplace* command = new KFCReplace( i18n( "Add Element" ), container );
01676         command->addElement( element );
01677         return command;
01678     }
01679     return 0;
01680 }
01681 
01682 KCommand* NameSequence::buildCommand( Container* container, Request* request )
01683 {
01684     switch ( *request ) {
01685     case req_compactExpression:
01686         return compactExpressionCmd( container );
01687     case req_addSpace:
01688     case req_addIndex:
01689     case req_addMatrix:
01690     case req_addOneByTwoMatrix:
01691     case req_addSymbol:
01692     case req_addRoot:
01693     case req_addFraction:
01694     case req_addBracket:
01695     case req_addNameSequence:
01696         return 0;
01697     default:
01698         break;
01699     }
01700     return inherited::buildCommand( container, request );
01701 }
01702 
01703 
01704 KCommand* NameSequence::input( Container* container, QChar ch )
01705 {
01706     int unicode = ch.unicode();
01707     switch (unicode) {
01708     case '(':
01709     case '[':
01710     case '|':
01711     case '^':
01712     case '_':
01713     case '}':
01714     case ']':
01715     case ')':
01716     case '\\': {
01717 //         KCommand* compact = compactExpressionCmd( container );
01718 //         KCommand* cmd = static_cast<SequenceElement*>( getParent() )->input( container, ch );
01719 //         if ( compact != 0 ) {
01720 //             KMacroCommand* macro = new KMacroCommand( cmd->name() );
01721 //             macro->addCommand( compact );
01722 //             macro->addCommand( cmd );
01723 //             return macro;
01724 //         }
01725 //         else {
01726 //             return cmd;
01727 //         }
01728         break;
01729     }
01730     case '{':
01731     case ' ': {
01732         Request r( req_compactExpression );
01733         return buildCommand( container, &r );
01734     }
01735     default: {
01736         TextCharRequest r( ch );
01737         return buildCommand( container, &r );
01738     }
01739     }
01740     return 0;
01741 }
01742 
01743 void NameSequence::setElementType( ElementType* t )
01744 {
01745     inherited::setElementType( t );
01746     parse();
01747 }
01748 
01749 BasicElement* NameSequence::replaceElement( const SymbolTable& table )
01750 {
01751     QString name = buildName();
01752     QChar ch = table.unicode( name );
01753     if ( !ch.isNull() ) {
01754         return new TextElement( ch, true );
01755     }
01756     else {
01757         ch = table.unicode( i18n( name.latin1() ) );
01758         if ( !ch.isNull() ) {
01759             return new TextElement( ch, true );
01760         }
01761     }
01762 
01763     if ( name == "!" )    return new SpaceElement( NEGTHIN );
01764     if ( name == "," )    return new SpaceElement( THIN );
01765     if ( name == ">" )    return new SpaceElement( MEDIUM );
01766     if ( name == ";" )    return new SpaceElement( THICK );
01767     if ( name == "quad" ) return new SpaceElement( QUAD );
01768 
01769     if ( name == "frac" ) return new FractionElement();
01770     if ( name == "atop" ) {
01771         FractionElement* frac = new FractionElement();
01772         frac->showLine( false );
01773         return frac;
01774     }
01775     if ( name == "sqrt" ) return new RootElement();
01776 
01777     return 0;
01778 }
01779 
01780 BasicElement* NameSequence::createElement( QString type )
01781 {
01782     if      ( type == "TEXT" )         return new TextElement();
01783     return 0;
01784 }
01785 
01786 // void NameSequence::parse()
01787 // {
01788 //     // A name sequence is known as name and so are its children.
01789 //     // Caution: this is fake!
01790 //     for ( int i = 0; i < countChildren(); i++ ) {
01791 //         getChild( i )->setElementType( getElementType() );
01792 //     }
01793 // }
01794 
01795 QString NameSequence::buildName()
01796 {
01797     QString name;
01798     for ( uint i = 0; i < countChildren(); i++ ) {
01799         name += getChild( i )->getCharacter();
01800     }
01801     return name;
01802 }
01803 
01804 bool NameSequence::isValidSelection( FormulaCursor* cursor )
01805 {
01806     SequenceElement* sequence = cursor->normal();
01807     if ( sequence == 0 ) {
01808         return false;
01809     }
01810     return sequence->onlyTextSelected( cursor );
01811 }
01812 
01813 int SequenceElement::buildChildrenFromMathMLDom(QPtrList<BasicElement>& list, QDomNode n) 
01814 {
01815     while (!n.isNull()) {
01816         int nodeNumber = 1;
01817         if (n.isElement()) {
01818             QDomElement e = n.toElement();
01819             BasicElement* child = 0;
01820             QString tag = e.tagName().lower();
01821 
01822             kdDebug( DEBUGID ) << "Sequence Tag: " << tag << endl;
01823             if ( tag == "semantics" ) { // Special case, just pick the first child
01824                 QDomNode node = e.firstChild();
01825                 while( ! node.isElement() ) {
01826                     node = node.nextSibling();
01827                     if ( node.isNull() ) {
01828                         return -1;
01829                     }
01830                 }
01831                 e = node.toElement();
01832                 tag = e.tagName().lower();
01833             }
01834             child = creationStrategy->createElement(tag, e);
01835             if (child != 0) {
01836                 child->setParent(this);
01837                 if (style != 0) {
01838                     child->setStyle(style);
01839                 }
01840                 nodeNumber = child->buildFromMathMLDom( e );
01841                 if ( nodeNumber != -1 ) {
01842                     list.append(child);
01843                 }
01844                 else {
01845                     delete child;
01846                     return -1;
01847                 }
01848             }
01849             else {
01850                 kdWarning() << "Unsupported MathML element: " << tag << endl;
01851             }
01852         }
01853         for (int i = 0; i < nodeNumber; i++ ) {
01854             if ( n.isNull() ) {
01855                 return -1;
01856             }
01857             n = n.nextSibling();
01858         }
01859     }
01860     // Operator elements inside a sequence have to be parsed to get proper form
01861     // value. Form value is needed to access operator dictionary and has to be
01862     // obtained after sequence parsing since its value depends on position
01863     // inside the sequence.
01864 
01865     // If the sequence contains more than one element, if the first or last
01866     // element are operators, they have to be marked differently
01867     if ( list.count() > 1 ) {
01868         if ( list.getFirst()->getElementName() == "mo" ) {
01869             static_cast<OperatorElement*>( list.getFirst() )->setForm( PrefixForm );
01870         }
01871         if ( list.getLast()->getElementName() == "mo" ) {
01872             static_cast<OperatorElement*>( list.getLast() )->setForm( PostfixForm );
01873         }
01874         for ( uint i = 1; i < list.count() - 1; i++ ) {
01875             if ( list.at( i )->getElementName() == "mo" ) {
01876                 static_cast<OperatorElement*>( list.at( i ) )->setForm( InfixForm );
01877             }
01878         }
01879     }
01880     else if ( list.count() == 1 ) {
01881         if ( list.getFirst()->getElementName() == "mo" ) {
01882             static_cast<OperatorElement*>( list.getFirst() )->setForm( InfixForm );
01883         }
01884     }
01885     parse();
01886     return 1;
01887 }
01888 
01891 int SequenceElement::readContentFromMathMLDom(QDomNode& node)
01892 {
01893     if ( BasicElement::readContentFromMathMLDom(node) == -1 ) {
01894         return -1;
01895     }
01896 
01897     return buildChildrenFromMathMLDom(children, node);
01898 }
01899 
01900 int SequenceElement::buildMathMLChild( QDomNode node )
01901 {
01902     int nodeCounter = 1;
01903     while ( ! node.isElement() ) {
01904         node = node.nextSibling();
01905         nodeCounter++;
01906         if ( node.isNull() ) {
01907             return -1;
01908         }
01909     }
01910     QDomElement e = node.toElement();
01911     BasicElement* child = 0;
01912     QString tag = e.tagName().lower();
01913 
01914     child = creationStrategy->createElement(tag, e);
01915     if (child != 0) {
01916         child->setParent(this);
01917         if (style != 0) {
01918             child->setStyle(style);
01919         }
01920         if (child->buildFromMathMLDom(e) != -1) {
01921             children.append(child);
01922         }
01923         else {
01924             delete child;
01925             return -1;
01926         }
01927     }
01928     else {
01929         return -1;
01930     }
01931     parse();
01932     return nodeCounter;
01933 }
01934 
01935 
01936 
01937 KFORMULA_NAMESPACE_END
KDE Home | KDE Accessibility Home | Description of Access Keys