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 
00490         // invisible elements are not visible so we move on.
00491         if (from->isInvisible()) {
00492             moveLeft(cursor, this);
00493         }
00494         formula()->tell( "" );
00495     }
00496 }
00497 
00503 void SequenceElement::moveRight(FormulaCursor* cursor, BasicElement* from)
00504 {
00505     // Our parent asks us for a cursor position. Found.
00506     if (from == getParent()) {
00507         cursor->setTo(this, 0);
00508         from->entered( this );
00509     }
00510 
00511     // We already owned the cursor. Ask next child then.
00512     else if (from == this) {
00513         uint pos = cursor->getPos();
00514         if (pos < children.count()) {
00515             cursor->setTo(this, pos+1);
00516             
00517             // invisible elements are not visible so we move on.
00518             if (children.at(pos)->isInvisible()) {
00519                 moveRight(cursor, this);
00520             }
00521         }
00522         else {
00523             // Needed because FormulaElement derives this.
00524             if (getParent() != 0) {
00525                 getParent()->moveRight(cursor, this);
00526             }
00527             else {
00528                 formula()->moveOutRight( cursor );
00529             }
00530         }
00531     }
00532 
00533     // The cursor came from one of our children or
00534     // something is wrong.
00535     else {
00536         int fromPos = children.find(from);
00537         if ( fromPos < children.count() - 1 ) {
00538             children.at( fromPos + 1 )->moveDown( cursor, this );
00539         }
00540         else {
00541             cursor->setTo(this, fromPos+1);
00542         }
00543         if (cursor->isSelectionMode()) {
00544             cursor->setMark(fromPos);
00545         }
00546 
00547         // invisible elements are not visible so we move on.
00548         if (from->isInvisible()) {
00549             moveRight(cursor, this);
00550         }
00551         formula()->tell( "" );
00552     }
00553 }
00554 
00555 
00556 void SequenceElement::moveWordLeft(FormulaCursor* cursor)
00557 {
00558     uint pos = cursor->getPos();
00559     if (pos > 0) {
00560         ElementType* type = children.at(pos-1)->getElementType();
00561         if (type != 0) {
00562             cursor->setTo(this, type->start());
00563         }
00564     }
00565     else {
00566         moveLeft(cursor, this);
00567     }
00568 }
00569 
00570 
00571 void SequenceElement::moveWordRight(FormulaCursor* cursor)
00572 {
00573     uint pos = cursor->getPos();
00574     if (pos < children.count()) {
00575         ElementType* type = children.at(pos)->getElementType();
00576         if (type != 0) {
00577             cursor->setTo(this, type->end());
00578         }
00579     }
00580     else {
00581         moveRight(cursor, this);
00582     }
00583 }
00584 
00585 
00591 void SequenceElement::moveUp(FormulaCursor* cursor, BasicElement* from)
00592 {
00593     if (from == getParent()) {
00594         moveRight(cursor, this);
00595     }
00596     else if ( from == this ) {
00597         if ( getParent() != 0 ) {
00598             uint pos = cursor->getPos();
00599             if ( pos < (children.count() - 1) / 2 ) {
00600                 getParent()->moveLeft( cursor, this );
00601             }
00602             else {
00603                 getParent()->moveRight( cursor, this );
00604             }
00605         }
00606         else {
00607                 formula()->moveOutAbove( cursor );
00608         }
00609     }
00610     else {
00611         if (getParent() != 0) {
00612             getParent()->moveUp(cursor, this);
00613         }
00614         else {
00615             formula()->moveOutAbove( cursor );
00616         }
00617     }
00618 }
00619 
00625 void SequenceElement::moveDown(FormulaCursor* cursor, BasicElement* from)
00626 {
00627     if (from == getParent()) {
00628         cursor->setTo(this, 0);
00629         from->entered( this );
00630     }
00631     else if (from == this) {
00632         uint pos = cursor->getPos();
00633         if (pos < children.count()) {
00634                 children.at(pos)->moveDown(cursor, this);
00635         }
00636     }
00637     else {
00638         if (getParent() != 0) {
00639             getParent()->moveDown(cursor, this);
00640         }
00641         else {
00642             cursor->setTo( this, children.count() );
00643             from->entered( this );
00644 //            formula()->moveOutBelow( cursor );
00645         }
00646     }
00647 }
00648 
00653 void SequenceElement::moveHome(FormulaCursor* cursor)
00654 {
00655     if (cursor->isSelectionMode()) {
00656         BasicElement* element = cursor->getElement();
00657         if (element != this) {
00658             while (element->getParent() != this) {
00659                 element = element->getParent();
00660             }
00661             cursor->setMark(children.find(element)+1);
00662         }
00663     }
00664     cursor->setTo(this, 0);
00665 }
00666 
00671 void SequenceElement::moveEnd(FormulaCursor* cursor)
00672 {
00673     if (cursor->isSelectionMode()) {
00674         BasicElement* element = cursor->getElement();
00675         if (element != this) {
00676             while (element->getParent() != this) {
00677                 element = element->getParent();
00678                 if (element == 0) {
00679                     cursor->setMark(children.count());
00680                     break;
00681                 }
00682             }
00683             if (element != 0) {
00684                 cursor->setMark(children.find(element));
00685             }
00686         }
00687     }
00688     cursor->setTo(this, children.count());
00689 }
00690 
00695 void SequenceElement::goInside(FormulaCursor* cursor)
00696 {
00697     cursor->setSelection(false);
00698     cursor->setTo(this, 0);
00699 }
00700 
00705 void SequenceElement::goInsideLast(FormulaCursor* cursor)
00706 {
00707     cursor->setSelection(false);
00708     cursor->setTo(this, children.count());
00709 }
00710 
00711 
00712 // children
00713 
00724 bool SequenceElement::insert( uint index, BasicElement *child )
00725 {
00726     return children.insert( index, child );
00727 }
00728 
00736 // void SequenceElement::removeChild(FormulaCursor* cursor, BasicElement* child)
00737 // {
00738 //     int pos = children.find(child);
00739 //     formula()->elementRemoval(child, pos);
00740 //     cursor->setTo(this, pos);
00741 //     children.remove(pos);
00742 //     /*
00743 //         if len(self.children) == 0:
00744 //             if self.parent != None:
00745 //                 self.parent.removeChild(cursor, self)
00746 //                 return
00747 //     */
00748 //     formula()->changed();
00749 // }
00750 
00751 
00759 void SequenceElement::insert(FormulaCursor* cursor,
00760                              QPtrList<BasicElement>& newChildren,
00761                              Direction direction)
00762 {
00763     int pos = cursor->getPos();
00764     uint count = newChildren.count();
00765     for (uint i = 0; i < count; i++) {
00766         BasicElement* child = newChildren.take(0);
00767         child->setParent(this);
00768         children.insert(pos+i, child);
00769     }
00770     if (direction == beforeCursor) {
00771         cursor->setTo(this, pos+count, pos);
00772     }
00773     else {
00774         cursor->setTo(this, pos, pos+count);
00775     }
00776 
00777     formula()->changed();
00778     parse();
00779 }
00780 
00781 
00788 void SequenceElement::remove(FormulaCursor* cursor,
00789                              QPtrList<BasicElement>& removedChildren,
00790                              Direction direction)
00791 {
00792     if (cursor->isSelection()) {
00793         int from = cursor->getSelectionStart();
00794         int to = cursor->getSelectionEnd();
00795         for (int i = from; i < to; i++) {
00796             removeChild(removedChildren, from);
00797         }
00798         cursor->setTo(this, from);
00799         cursor->setSelection(false);
00800     }
00801     else {
00802         if (direction == beforeCursor) {
00803             int pos = cursor->getPos() - 1;
00804             if (pos >= 0) {
00805                 while (pos >= 0) {
00806                     BasicElement* child = children.at(pos);
00807                     formula()->elementRemoval(child);
00808                     children.take(pos);
00809                     removedChildren.prepend(child);
00810                     if (!child->isInvisible()) {
00811                         break;
00812                     }
00813                     pos--;
00814                 }
00815                 cursor->setTo(this, pos);
00816                 formula()->changed();
00817             }
00818         }
00819         else {
00820             uint pos = cursor->getPos();
00821             if (pos < children.count()) {
00822                 while (pos < children.count()) {
00823                     BasicElement* child = children.at(pos);
00824                     formula()->elementRemoval(child);
00825                     children.take(pos);
00826                     removedChildren.append(child);
00827                     if (!child->isInvisible()) {
00828                         break;
00829                     }
00830                 }
00831                 // It is necessary to set the cursor to its old
00832                 // position because it got a notification and
00833                 // moved to the beginning of this sequence.
00834                 cursor->setTo(this, pos);
00835                 formula()->changed();
00836             }
00837         }
00838     }
00839     parse();
00840 }
00841 
00842 
00846 void SequenceElement::removeChild(QPtrList<BasicElement>& removedChildren, int pos)
00847 {
00848     BasicElement* child = children.at(pos);
00849     formula()->elementRemoval(child);
00850     children.take(pos);
00851     removedChildren.append(child);
00852     //cerr << *removedChildren.at(0) << endl;
00853     formula()->changed();
00854 }
00855 
00856 
00861 void SequenceElement::normalize(FormulaCursor* cursor, Direction)
00862 {
00863     cursor->setSelection(false);
00864 }
00865 
00866 
00871 BasicElement* SequenceElement::getChild( FormulaCursor* cursor, Direction direction )
00872 {
00873     if ( direction == beforeCursor ) {
00874         if ( cursor->getPos() > 0 ) {
00875             return children.at( cursor->getPos() - 1 );
00876         }
00877     }
00878     else {
00879         if ( cursor->getPos() < qRound( children.count() ) ) {
00880             return children.at( cursor->getPos() );
00881         }
00882     }
00883     return 0;
00884 }
00885 
00886 
00891 void SequenceElement::selectChild(FormulaCursor* cursor, BasicElement* child)
00892 {
00893     int pos = children.find(child);
00894     if (pos > -1) {
00895         cursor->setTo(this, pos+1, pos);
00896     }
00897 }
00898 
00899 void SequenceElement::childWillVanish(FormulaCursor* cursor, BasicElement* child)
00900 {
00901     int childPos = children.find(child);
00902     if (childPos > -1) {
00903         int pos = cursor->getPos();
00904         if (pos > childPos) {
00905             pos--;
00906         }
00907         int mark = cursor->getMark();
00908         if (mark > childPos) {
00909             mark--;
00910         }
00911         cursor->setTo(this, pos, mark);
00912     }
00913 }
00914 
00915 
00919 void SequenceElement::selectAllChildren(FormulaCursor* cursor)
00920 {
00921     cursor->setTo(this, children.count(), 0);
00922 }
00923 
00924 bool SequenceElement::onlyTextSelected( FormulaCursor* cursor )
00925 {
00926     if ( cursor->isSelection() ) {
00927         uint from = QMIN( cursor->getPos(), cursor->getMark() );
00928         uint to = QMAX( cursor->getPos(), cursor->getMark() );
00929         for ( uint i = from; i < to; i++ ) {
00930             BasicElement* element = getChild( i );
00931             if ( element->getCharacter() == QChar::null ) {
00932                 return false;
00933             }
00934         }
00935     }
00936     return true;
00937 }
00938 
00939 
00940 KCommand* SequenceElement::buildCommand( Container* container, Request* request )
00941 {
00942     FormulaCursor* cursor = container->activeCursor();
00943     if ( cursor->isReadOnly() ) {
00944         formula()->tell( i18n( "write protection" ) );
00945         return 0;
00946     }
00947 
00948     switch ( *request ) {
00949     case req_addText: {
00950         KFCReplaceToken* command = new KFCReplaceToken( i18n("Add Text"), container );
00951         TextRequest* tr = static_cast<TextRequest*>( request );
00952         IdentifierElement* id = creationStrategy->createIdentifierElement();
00953         command->addToken( id );
00954         for ( uint i = 0; i < tr->text().length(); i++ ) {
00955             TextElement* text = creationStrategy->createTextElement( tr->text()[i] );
00956             command->addContent( id, text );
00957         }
00958         return command;
00959     }
00960     case req_addTextChar: {
00961         KFCReplaceToken* command = new KFCReplaceToken( i18n("Add Text"), container );
00962         TextCharRequest* tr = static_cast<TextCharRequest*>( request );
00963         IdentifierElement* id = creationStrategy->createIdentifierElement();
00964         TextElement* text = creationStrategy->createTextElement( tr->ch() );
00965         command->addToken( id );
00966         command->addContent( id, text );
00967         return command;
00968     }
00969 
00970     case req_addOperator: {
00971         KFCReplaceToken* command = new KFCReplaceToken( i18n("Add Operator"), container );
00972         OperatorRequest* opr = static_cast<OperatorRequest*>( request );
00973         OperatorElement* op = creationStrategy->createOperatorElement();
00974         TextElement* text = creationStrategy->createTextElement( opr->ch() );
00975         command->addToken( op );
00976         command->addContent( op, text );
00977         return command;
00978     }
00979 
00980     case req_addNumber: {
00981         KFCReplaceToken* command = new KFCReplaceToken( i18n("Add Number"), container );
00982         NumberRequest* nr = static_cast<NumberRequest*>( request );
00983         NumberElement* num = creationStrategy->createNumberElement();
00984         num->setParent( this );
00985         TextElement* text = creationStrategy->createTextElement( nr->ch() );
00986         text->setParent( num );
00987         command->addToken( num );
00988         command->addContent( num, text );
00989         return command;
00990     }
00991 
00992     case req_addEmptyBox: {
00993         EmptyElement* element = creationStrategy->createEmptyElement();
00994         if ( element != 0 ) {
00995             KFCReplace* command = new KFCReplace( i18n("Add Empty Box"), container );
00996             command->addElement( element );
00997             return command;
00998         }
00999         break;
01000     }
01001     case req_addNameSequence:
01002         if ( onlyTextSelected( container->activeCursor() ) ) {
01003             NameSequence* nameSequence = creationStrategy->createNameSequence();
01004             if ( nameSequence != 0 ) {
01005                 KFCAddReplacing* command = new KFCAddReplacing( i18n( "Add Name" ), container );
01006                 command->setElement( nameSequence );
01007                 return command;
01008             }
01009         }
01010         break;
01011     case req_addBracket: {
01012         BracketRequest* br = static_cast<BracketRequest*>( request );
01013         BracketElement* bracketElement =
01014             creationStrategy->createBracketElement( br->left(), br->right() );
01015         if ( bracketElement != 0 ) {
01016             KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Bracket"), container);
01017             command->setElement( bracketElement );
01018             return command;
01019         }
01020         break;
01021     }
01022     case req_addOverline: {
01023         OverlineElement* overline = creationStrategy->createOverlineElement();
01024         if ( overline != 0 ) {
01025             KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Overline"), container);
01026             command->setElement( overline );
01027             return command;
01028         }
01029         break;
01030     }
01031     case req_addUnderline: {
01032         UnderlineElement* underline = creationStrategy->createUnderlineElement();
01033         if ( underline != 0 ) {
01034             KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Underline"), container);
01035             command->setElement( underline );
01036             return command;
01037         }
01038         break;
01039     }
01040     case req_addMultiline: {
01041         MultilineElement* multiline = creationStrategy->createMultilineElement();
01042         if ( multiline != 0 ) {
01043             KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Multiline"), container);
01044             command->setElement( multiline );
01045             return command;
01046         }
01047         break;
01048     }
01049     case req_addSpace: {
01050         SpaceRequest* sr = static_cast<SpaceRequest*>( request );
01051         SpaceElement* element = creationStrategy->createSpaceElement( sr->space() );
01052         if ( element != 0 ) {
01053             KFCReplace* command = new KFCReplace( i18n("Add Space"), container );
01054             command->addElement( element );
01055             return command;
01056         }
01057         break;
01058     }
01059     case req_addFraction: {
01060         FractionElement* fraction = creationStrategy->createFractionElement();
01061         if ( fraction != 0 ) {
01062             KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Fraction"), container);
01063             command->setElement( fraction );
01064             return command;
01065         }
01066         break;
01067     }
01068     case req_addRoot: {
01069         RootElement* root = creationStrategy->createRootElement();
01070         if ( root != 0 ) {
01071             KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Root"), container);
01072             command->setElement( root );
01073             return command;
01074         }
01075         break;
01076     }
01077     case req_addSymbol: {
01078         SymbolRequest* sr = static_cast<SymbolRequest*>( request );
01079         SymbolElement* symbol = creationStrategy->createSymbolElement( sr->type() );
01080         if ( symbol != 0 ) {
01081             KFCAddReplacing* command = new KFCAddReplacing( i18n( "Add Symbol" ), container );
01082             command->setElement( symbol );
01083             return command;
01084         }
01085         break;
01086     }
01087     case req_addOneByTwoMatrix: {
01088         FractionElement* element = creationStrategy->createFractionElement();
01089         if ( element != 0 ) {
01090             KFCAddReplacing* command = new KFCAddReplacing( i18n("Add 1x2 Matrix"), container );
01091             element->showLine(false);
01092             command->setElement(element);
01093             return command;
01094         }
01095     }
01096     case req_addMatrix: {
01097         MatrixRequest* mr = static_cast<MatrixRequest*>( request );
01098         uint rows = mr->rows(), cols = mr->columns();
01099         if ( ( rows == 0 ) || ( cols == 0 ) ) {
01100             MatrixDialog* dialog = new MatrixDialog( 0 );
01101             if ( dialog->exec() ) {
01102                 rows = dialog->h;
01103                 cols = dialog->w;
01104             }
01105             delete dialog;
01106         }
01107 
01108         if ( ( rows != 0 ) && ( cols != 0 ) ) {
01109             KFCAddReplacing* command = new KFCAddReplacing( i18n( "Add Matrix" ), container );
01110             command->setElement( creationStrategy->createMatrixElement( rows, cols ) );
01111             return command;
01112         }
01113         else
01114             return 0L;
01115     }
01116     case req_addIndex: {
01117         if ( cursor->getPos() > 0 && !cursor->isSelection() ) {
01118             IndexElement* element =
01119                 dynamic_cast<IndexElement*>( children.at( cursor->getPos()-1 ) );
01120             if ( element != 0 ) {
01121                 element->goInside( cursor );
01122                 return element->buildCommand( container, request );
01123             }
01124         }
01125         IndexElement* element = creationStrategy->createIndexElement();
01126         if ( element != 0 ) {
01127             if ( !cursor->isSelection() ) {
01128                 cursor->moveLeft( SelectMovement | WordMovement );
01129             }
01130             IndexRequest* ir = static_cast<IndexRequest*>( request );
01131             KFCAddIndex* command = new KFCAddIndex( container, element,
01132                                                     element->getIndex( ir->index() ) );
01133             return command;
01134         }
01135         break;
01136     }
01137     case req_removeEnclosing: {
01138         if ( !cursor->isSelection() ) {
01139             DirectedRemove* dr = static_cast<DirectedRemove*>( request );
01140             KFCRemoveEnclosing* command = new KFCRemoveEnclosing( container, dr->direction() );
01141             return command;
01142         }
01143     }
01144     case req_remove: {
01145         SequenceElement* sequence = cursor->normal();
01146         if ( sequence &&
01147              ( sequence == sequence->formula() ) &&
01148              ( sequence->countChildren() == 0 ) ) {
01149             sequence->formula()->removeFormula( cursor );
01150             return 0;
01151         }
01152         else {
01153             DirectedRemove* dr = static_cast<DirectedRemove*>( request );
01154 
01155             // empty removes are not legal!
01156             if ( !cursor->isSelection() ) {
01157                 if ( countChildren() > 0 ) {
01158                     if ( ( cursor->getPos() == 0 ) && ( dr->direction() == beforeCursor ) ) {
01159                         return 0;
01160                     }
01161                     if ( ( cursor->getPos() == countChildren() ) && ( dr->direction() == afterCursor ) ) {
01162                         return 0;
01163                     }
01164                 }
01165                 else if ( getParent() == 0 ) {
01166                     return 0;
01167                 }
01168             }
01169 
01170             KFCRemove* command = new KFCRemove( container, dr->direction() );
01171             return command;
01172         }
01173     }
01174     case req_compactExpression: {
01175         cursor->moveEnd();
01176         cursor->moveRight();
01177         formula()->cursorHasMoved( cursor );
01178         break;
01179     }
01180     case req_makeGreek: {
01181         TextElement* element = cursor->getActiveTextElement();
01182         if ((element != 0) && !element->isSymbol()) {
01183             cursor->selectActiveElement();
01184             const SymbolTable& table = container->document()->getSymbolTable();
01185             if (table.greekLetters().find(element->getCharacter()) != -1) {
01186                 KFCReplace* command = new KFCReplace( i18n( "Change Char to Symbol" ), container );
01187                 TextElement* symbol = creationStrategy->createTextElement( table.unicodeFromSymbolFont( element->getCharacter() ), true );
01188                 command->addElement( symbol );
01189                 return command;
01190             }
01191             cursor->setSelection( false );
01192         }
01193         break;
01194     }
01195     case req_paste:
01196     case req_copy:
01197     case req_cut:
01198         break;
01199     case req_formatBold:
01200     case req_formatItalic: {
01201         if ( cursor->isSelection() ) {
01202             CharStyleRequest* csr = static_cast<CharStyleRequest*>( request );
01203             CharStyle cs = normalChar;
01204             if ( csr->bold() ) cs = static_cast<CharStyle>( cs | boldChar );
01205             if ( csr->italic() ) cs = static_cast<CharStyle>( cs | italicChar );
01206             CharStyleCommand* cmd = new CharStyleCommand( cs, i18n( "Change Char Style" ), container );
01207             int end = cursor->getSelectionEnd();
01208             for ( int i = cursor->getSelectionStart(); i<end; ++i ) {
01209                 cmd->addElement( children.at( i ) );
01210             }
01211             return cmd;
01212         }
01213         break;
01214     }
01215     case req_formatFamily: {
01216         if ( cursor->isSelection() ) {
01217             CharFamilyRequest* cfr = static_cast<CharFamilyRequest*>( request );
01218             CharFamily cf = cfr->charFamily();
01219             CharFamilyCommand* cmd = new CharFamilyCommand( cf, i18n( "Change Char Family" ), container );
01220             int end = cursor->getSelectionEnd();
01221             for ( int i = cursor->getSelectionStart(); i<end; ++i ) {
01222                 cmd->addElement( children.at( i ) );
01223             }
01224             return cmd;
01225         }
01226         break;
01227     }
01228     default:
01229         break;
01230     }
01231     return 0;
01232 }
01233 
01234 
01235 KCommand* SequenceElement::input( Container* container, QKeyEvent* event )
01236 {
01237     QChar ch = event->text().at( 0 );
01238     if ( ch.isPrint() ) {
01239         return input( container, ch );
01240     }
01241     else {
01242         int action = event->key();
01243         int state = event->state();
01244         MoveFlag flag = movementFlag(state);
01245 
01246     switch ( action ) {
01247         case Qt::Key_BackSpace: {
01248             DirectedRemove r( req_remove, beforeCursor );
01249             return buildCommand( container, &r );
01250         }
01251         case Qt::Key_Delete: {
01252             DirectedRemove r( req_remove, afterCursor );
01253             return buildCommand( container, &r );
01254         }
01255     case Qt::Key_Left: {
01256             FormulaCursor* cursor = container->activeCursor();
01257             cursor->moveLeft( flag );
01258             formula()->cursorHasMoved( cursor );
01259             break;
01260         }
01261         case Qt::Key_Right: {
01262             FormulaCursor* cursor = container->activeCursor();
01263             cursor->moveRight( flag );
01264             formula()->cursorHasMoved( cursor );
01265             break;
01266         }
01267         case Qt::Key_Up: {
01268             FormulaCursor* cursor = container->activeCursor();
01269             cursor->moveUp( flag );
01270             formula()->cursorHasMoved( cursor );
01271             break;
01272         }
01273         case Qt::Key_Down: {
01274             FormulaCursor* cursor = container->activeCursor();
01275             cursor->moveDown( flag );
01276             formula()->cursorHasMoved( cursor );
01277             break;
01278         }
01279         case Qt::Key_Home: {
01280             FormulaCursor* cursor = container->activeCursor();
01281             cursor->moveHome( flag );
01282             formula()->cursorHasMoved( cursor );
01283             break;
01284         }
01285         case Qt::Key_End: {
01286             FormulaCursor* cursor = container->activeCursor();
01287             cursor->moveEnd( flag );
01288             formula()->cursorHasMoved( cursor );
01289             break;
01290         }
01291         default:
01292             if ( state & Qt::ControlButton ) {
01293                 switch ( event->key() ) {
01294                 case Qt::Key_AsciiCircum: {
01295                     IndexRequest r( upperLeftPos );
01296                     return buildCommand( container, &r );
01297                 }
01298                 case Qt::Key_Underscore: {
01299                     IndexRequest r( lowerLeftPos );
01300                     return buildCommand( container, &r );
01301                 }
01302                 default:
01303                     break;
01304                 }
01305             }
01306         }
01307     }
01308     return 0;
01309 }
01310 
01311 
01312 KCommand* SequenceElement::input( Container* container, QChar ch )
01313 {
01314     int unicode = ch.unicode();
01315     switch (unicode) {
01316     case '(': {
01317         BracketRequest r( container->document()->leftBracketChar(),
01318                           container->document()->rightBracketChar() );
01319         singlePipe = true;
01320         return buildCommand( container, &r );
01321     }
01322     case '[': {
01323         BracketRequest r( LeftSquareBracket, RightSquareBracket );
01324         singlePipe = true;
01325         return buildCommand( container, &r );
01326     }
01327     case '{': {
01328         BracketRequest r( LeftCurlyBracket, RightCurlyBracket );
01329         singlePipe = true;
01330         return buildCommand( container, &r );
01331     }
01332     case '|': { 
01333         if (!singlePipe) { // We have had 2 '|' in a row so we want brackets
01334 
01335           DirectedRemove rDelete( req_remove, beforeCursor ); //Delete the previous '|' we dont need it any more
01336           KCommand* command = buildCommand( container, &rDelete );
01337           command->execute();
01338           
01339           BracketRequest rBracket( LeftLineBracket , RightLineBracket);
01340           singlePipe = true;  //the next '|' will be a single pipe again
01341           return buildCommand( container, &rBracket );    
01342         }
01343         else { // We really do only want 1 '|'
01344           TextCharRequest r(ch);
01345 
01346           //in case another '|' character is entered right after this one, '| |' brackets are made; see above
01347           singlePipe = false;
01348 
01349           return buildCommand( container, &r );   
01350         }
01351     }
01352     case '^': {
01353         IndexRequest r( upperRightPos );
01354         singlePipe = true;
01355         return buildCommand( container, &r );
01356     }
01357     case '_': {
01358         IndexRequest r( lowerRightPos );
01359         singlePipe = true;
01360         return buildCommand( container, &r );
01361     }
01362         /*
01363     case ' ': {
01364         Request r( req_compactExpression );
01365         singlePipe = true;
01366         return buildCommand( container, &r );
01367         }*/
01368     case '}': {
01369         Request r( req_addEmptyBox );
01370         singlePipe = true;
01371         return buildCommand( container, &r );
01372     }
01373     case ']':
01374     case ')':
01375         singlePipe = true; 
01376         break;
01377     case '\\': {
01378         Request r( req_addNameSequence );
01379         singlePipe = true;
01380         return buildCommand( container, &r );
01381     }
01382     default: {
01383         singlePipe = true;
01384         if ( ch.isPunct() || ch.isSymbol() ) {
01385             OperatorRequest r( ch );
01386             return buildCommand( container, &r );
01387         }
01388         if ( ch.isNumber() ) {
01389             NumberRequest r( ch );
01390             return buildCommand( container, &r );
01391         }
01392         TextCharRequest r( ch );
01393         return buildCommand( container, &r );
01394     }
01395     }
01396     return 0;
01397 }
01398 
01402 void SequenceElement::getChildrenDom( QDomDocument& doc, QDomElement elem,
01403                                      uint from, uint to)
01404 {
01405     for (uint i = from; i < to; i++) {
01406         QDomElement tmpEleDom=children.at(i)->getElementDom(doc);
01407         elem.appendChild(tmpEleDom);
01408     }
01409 }
01410 
01414 void SequenceElement::getChildrenMathMLDom( QDomDocument& doc, QDomNode& parent,
01415                                             uint from, uint to)
01416 {
01417     for ( uint i = from; i < to; i++ ) {
01418         children.at( i )->writeMathML( doc, parent, false );
01419     }
01420 }
01421 
01422 
01428 bool SequenceElement::buildChildrenFromDom(QPtrList<BasicElement>& list, QDomNode n)
01429 {
01430     while (!n.isNull()) {
01431         if (n.isElement()) {
01432             QDomElement e = n.toElement();
01433             BasicElement* child = 0;
01434             QString tag = e.tagName().upper();
01435 
01436             child = createElement(tag, e);
01437             if (child != 0) {
01438                 child->setParent(this);
01439                 if (child->buildFromDom(e)) {
01440                     list.append(child);
01441                 }
01442                 else {
01443                     delete child;
01444                     return false;
01445                 }
01446             }
01447             else {
01448                 return false;
01449             }
01450         }
01451         n = n.nextSibling();
01452     }
01453     parse();
01454     return true;
01455 }
01456 
01457 
01458 BasicElement* SequenceElement::createElement( QString type, const QDomElement& element )
01459 {
01460     return creationStrategy->createElement( type, element );
01461 }
01462 
01466 void SequenceElement::writeDom(QDomElement element)
01467 {
01468     BasicElement::writeDom(element);
01469 
01470     uint count = children.count();
01471     QDomDocument doc = element.ownerDocument();
01472     getChildrenDom(doc, element, 0, count);
01473 }
01474 
01479 bool SequenceElement::readAttributesFromDom(QDomElement element)
01480 {
01481     if (!BasicElement::readAttributesFromDom(element)) {
01482         return false;
01483     }
01484     return true;
01485 }
01486 
01492 bool SequenceElement::readContentFromDom(QDomNode& node)
01493 {
01494     if (!BasicElement::readContentFromDom(node)) {
01495         return false;
01496     }
01497 
01498     return buildChildrenFromDom(children, node);
01499 }
01500 
01501 
01502 void SequenceElement::parse()
01503 {
01504     delete parseTree;
01505 
01506     textSequence = true;
01507     for (BasicElement* element = children.first();
01508          element != 0;
01509          element = children.next()) {
01510 
01511         // Those types are gone. Make sure they won't
01512         // be used.
01513         element->setElementType(0);
01514 
01515         if (element->getCharacter().isNull()) {
01516             textSequence = false;
01517         }
01518     }
01519 
01520     const SymbolTable& symbols = formula()->getSymbolTable();
01521     SequenceParser parser(symbols);
01522     parseTree = parser.parse(children);
01523 
01524     // With the IndexElement dynamically changing its text/non-text
01525     // behaviour we need to reparse your parent, too. Hacky!
01526     BasicElement* p = getParent();
01527     if ( p != 0 ) {
01528         SequenceElement* seq = dynamic_cast<SequenceElement*>( p->getParent() );
01529         if ( seq != 0 ) {
01530             seq->parse();
01531         }
01532     }
01533     // debug
01534     //parseTree->output();
01535 }
01536 
01537 
01538 bool SequenceElement::isFirstOfToken( BasicElement* child )
01539 {
01540     return ( child->getElementType() != 0 ) && isChildNumber( child->getElementType()->start(), child );
01541 }
01542 
01543 
01544 QString SequenceElement::toLatex()
01545 {
01546     QString content;
01547     uint count = children.count();
01548     for ( uint i = 0; i < count; i++ ) {
01549         BasicElement* child = children.at( i );
01550 //         if ( isFirstOfToken( child ) ) {
01551 //             content += "";
01552 //         }
01553         content += child->toLatex();
01554     }
01555     return content;
01556 }
01557 
01558 
01559 QString SequenceElement::formulaString()
01560 {
01561     QString content;
01562     uint count = children.count();
01563     for ( uint i = 0; i < count; i++ ) {
01564         BasicElement* child = children.at( i );
01565         //if ( isFirstOfToken( child ) ) {
01566         //    content += " ";
01567         //}
01568         content += child->formulaString();
01569     }
01570     return content;
01571 }
01572 
01573 
01574 void SequenceElement::writeMathMLContent( QDomDocument& doc, QDomElement& element, bool oasisFormat ) const
01575 {
01576     for ( QPtrListIterator<BasicElement> it( children ); it.current(); ++it ) {
01577         it.current()->writeMathML( doc, element, oasisFormat );
01578     }
01579 }
01580 
01581 
01582 const BasicElement* SequenceElement::getChild( uint i ) const
01583 {
01584     QPtrListIterator<BasicElement> it( children );
01585     it += i;
01586     return it.current();
01587 }
01588 
01589 
01590 int SequenceElement::childPos( const BasicElement* child ) const
01591 {
01592     QPtrListIterator<BasicElement> it( children );
01593     uint count = it.count();
01594     for ( uint i=0; i<count; ++i, ++it ) {
01595         if ( it.current() == child ) {
01596             return i;
01597         }
01598     }
01599     return -1;
01600 }
01601 
01602 
01603 NameSequence::NameSequence( BasicElement* parent )
01604     : SequenceElement( parent )
01605 {
01606 }
01607 
01608 
01609 bool NameSequence::accept( ElementVisitor* visitor )
01610 {
01611     return visitor->visit( this );
01612 }
01613 
01614 
01615 void NameSequence::calcCursorSize( const ContextStyle& context,
01616                                    FormulaCursor* cursor, bool smallCursor )
01617 {
01618     inherited::calcCursorSize( context, cursor, smallCursor );
01619     LuPixelPoint point = widgetPos();
01620     luPixel unitX = context.ptToLayoutUnitPixX( 1 );
01621     luPixel unitY = context.ptToLayoutUnitPixY( 1 );
01622     cursor->addCursorSize( LuPixelRect( point.x()-unitX, point.y()-unitY,
01623                                         getWidth()+2*unitX, getHeight()+2*unitY ) );
01624 }
01625 
01626 void NameSequence::drawCursor( QPainter& painter, const ContextStyle& context,
01627                                StyleAttributes& style, FormulaCursor* cursor,
01628                                bool smallCursor, bool activeCursor )
01629 {
01630     LuPixelPoint point = widgetPos();
01631     painter.setPen( QPen( context.getEmptyColor(),
01632                           context.layoutUnitToPixelX( context.getLineWidth( style.sizeFactor() )/2 ) ) );
01633     luPixel unitX = context.ptToLayoutUnitPixX( 1 );
01634     luPixel unitY = context.ptToLayoutUnitPixY( 1 );
01635     painter.drawRect( context.layoutUnitToPixelX( point.x()-unitX ),
01636                       context.layoutUnitToPixelY( point.y()-unitY ),
01637                       context.layoutUnitToPixelX( getWidth()+2*unitX ),
01638                       context.layoutUnitToPixelY( getHeight()+2*unitY ) );
01639 
01640     inherited::drawCursor( painter, context, style, cursor, smallCursor, activeCursor );
01641 }
01642 
01643 void NameSequence::moveWordLeft( FormulaCursor* cursor )
01644 {
01645     uint pos = cursor->getPos();
01646     if ( pos > 0 ) {
01647         cursor->setTo( this, 0 );
01648     }
01649     else {
01650         moveLeft( cursor, this );
01651     }
01652 }
01653 
01654 void NameSequence::moveWordRight( FormulaCursor* cursor )
01655 {
01656     int pos = cursor->getPos();
01657     if ( pos < countChildren() ) {
01658         cursor->setTo( this, countChildren() );
01659     }
01660     else {
01661         moveRight( cursor, this );
01662     }
01663 }
01664 
01665 
01666 KCommand* NameSequence::compactExpressionCmd( Container* container )
01667 {
01668     BasicElement* element = replaceElement( container->document()->getSymbolTable() );
01669     if ( element != 0 ) {
01670         getParent()->selectChild( container->activeCursor(), this );
01671 
01672         KFCReplace* command = new KFCReplace( i18n( "Add Element" ), container );
01673         command->addElement( element );
01674         return command;
01675     }
01676     return 0;
01677 }
01678 
01679 KCommand* NameSequence::buildCommand( Container* container, Request* request )
01680 {
01681     switch ( *request ) {
01682     case req_compactExpression:
01683         return compactExpressionCmd( container );
01684     case req_addSpace:
01685     case req_addIndex:
01686     case req_addMatrix:
01687     case req_addOneByTwoMatrix:
01688     case req_addSymbol:
01689     case req_addRoot:
01690     case req_addFraction:
01691     case req_addBracket:
01692     case req_addNameSequence:
01693         return 0;
01694     default:
01695         break;
01696     }
01697     return inherited::buildCommand( container, request );
01698 }
01699 
01700 
01701 KCommand* NameSequence::input( Container* container, QChar ch )
01702 {
01703     int unicode = ch.unicode();
01704     switch (unicode) {
01705     case '(':
01706     case '[':
01707     case '|':
01708     case '^':
01709     case '_':
01710     case '}':
01711     case ']':
01712     case ')':
01713     case '\\': {
01714 //         KCommand* compact = compactExpressionCmd( container );
01715 //         KCommand* cmd = static_cast<SequenceElement*>( getParent() )->input( container, ch );
01716 //         if ( compact != 0 ) {
01717 //             KMacroCommand* macro = new KMacroCommand( cmd->name() );
01718 //             macro->addCommand( compact );
01719 //             macro->addCommand( cmd );
01720 //             return macro;
01721 //         }
01722 //         else {
01723 //             return cmd;
01724 //         }
01725         break;
01726     }
01727     case '{':
01728     case ' ': {
01729         Request r( req_compactExpression );
01730         return buildCommand( container, &r );
01731     }
01732     default: {
01733         TextCharRequest r( ch );
01734         return buildCommand( container, &r );
01735     }
01736     }
01737     return 0;
01738 }
01739 
01740 void NameSequence::setElementType( ElementType* t )
01741 {
01742     inherited::setElementType( t );
01743     parse();
01744 }
01745 
01746 BasicElement* NameSequence::replaceElement( const SymbolTable& table )
01747 {
01748     QString name = buildName();
01749     QChar ch = table.unicode( name );
01750     if ( !ch.isNull() ) {
01751         return new TextElement( ch, true );
01752     }
01753     else {
01754         ch = table.unicode( i18n( name.latin1() ) );
01755         if ( !ch.isNull() ) {
01756             return new TextElement( ch, true );
01757         }
01758     }
01759 
01760     if ( name == "!" )    return new SpaceElement( NEGTHIN );
01761     if ( name == "," )    return new SpaceElement( THIN );
01762     if ( name == ">" )    return new SpaceElement( MEDIUM );
01763     if ( name == ";" )    return new SpaceElement( THICK );
01764     if ( name == "quad" ) return new SpaceElement( QUAD );
01765 
01766     if ( name == "frac" ) return new FractionElement();
01767     if ( name == "atop" ) {
01768         FractionElement* frac = new FractionElement();
01769         frac->showLine( false );
01770         return frac;
01771     }
01772     if ( name == "sqrt" ) return new RootElement();
01773 
01774     return 0;
01775 }
01776 
01777 BasicElement* NameSequence::createElement( QString type )
01778 {
01779     if      ( type == "TEXT" )         return new TextElement();
01780     return 0;
01781 }
01782 
01783 // void NameSequence::parse()
01784 // {
01785 //     // A name sequence is known as name and so are its children.
01786 //     // Caution: this is fake!
01787 //     for ( int i = 0; i < countChildren(); i++ ) {
01788 //         getChild( i )->setElementType( getElementType() );
01789 //     }
01790 // }
01791 
01792 QString NameSequence::buildName()
01793 {
01794     QString name;
01795     for ( uint i = 0; i < countChildren(); i++ ) {
01796         name += getChild( i )->getCharacter();
01797     }
01798     return name;
01799 }
01800 
01801 bool NameSequence::isValidSelection( FormulaCursor* cursor )
01802 {
01803     SequenceElement* sequence = cursor->normal();
01804     if ( sequence == 0 ) {
01805         return false;
01806     }
01807     return sequence->onlyTextSelected( cursor );
01808 }
01809 
01810 int SequenceElement::buildChildrenFromMathMLDom(QPtrList<BasicElement>& list, QDomNode n) 
01811 {
01812     while (!n.isNull()) {
01813         int nodeNumber = 1;
01814         if (n.isElement()) {
01815             QDomElement e = n.toElement();
01816             BasicElement* child = 0;
01817             QString tag = e.tagName().lower();
01818 
01819             kdDebug( DEBUGID ) << "Sequence Tag: " << tag << endl;
01820             if ( tag == "semantics" ) { // Special case, just pick the first child
01821                 QDomNode node = e.firstChild();
01822                 while( ! node.isElement() ) {
01823                     node = node.nextSibling();
01824                     if ( node.isNull() ) {
01825                         return -1;
01826                     }
01827                 }
01828                 e = node.toElement();
01829                 tag = e.tagName().lower();
01830             }
01831             child = creationStrategy->createElement(tag, e);
01832             if (child != 0) {
01833                 child->setParent(this);
01834                 if (style != 0) {
01835                     child->setStyle(style);
01836                 }
01837                 nodeNumber = child->buildFromMathMLDom( e );
01838                 if ( nodeNumber != -1 ) {
01839                     list.append(child);
01840                 }
01841                 else {
01842                     delete child;
01843                     return -1;
01844                 }
01845             }
01846             else {
01847                 kdWarning() << "Unsupported MathML element: " << tag << endl;
01848             }
01849         }
01850         for (int i = 0; i < nodeNumber; i++ ) {
01851             if ( n.isNull() ) {
01852                 return -1;
01853             }
01854             n = n.nextSibling();
01855         }
01856     }
01857     // Operator elements inside a sequence have to be parsed to get proper form
01858     // value. Form value is needed to access operator dictionary and has to be
01859     // obtained after sequence parsing since its value depends on position
01860     // inside the sequence.
01861 
01862     // If the sequence contains more than one element, if the first or last
01863     // element are operators, they have to be marked differently
01864     if ( list.count() > 1 ) {
01865         if ( list.getFirst()->getElementName() == "mo" ) {
01866             static_cast<OperatorElement*>( list.getFirst() )->setForm( PrefixForm );
01867         }
01868         if ( list.getLast()->getElementName() == "mo" ) {
01869             static_cast<OperatorElement*>( list.getLast() )->setForm( PostfixForm );
01870         }
01871         for ( uint i = 1; i < list.count() - 1; i++ ) {
01872             if ( list.at( i )->getElementName() == "mo" ) {
01873                 static_cast<OperatorElement*>( list.at( i ) )->setForm( InfixForm );
01874             }
01875         }
01876     }
01877     else if ( list.count() == 1 ) {
01878         if ( list.getFirst()->getElementName() == "mo" ) {
01879             static_cast<OperatorElement*>( list.getFirst() )->setForm( InfixForm );
01880         }
01881     }
01882     parse();
01883     return 1;
01884 }
01885 
01888 int SequenceElement::readContentFromMathMLDom(QDomNode& node)
01889 {
01890     if ( BasicElement::readContentFromMathMLDom(node) == -1 ) {
01891         return -1;
01892     }
01893 
01894     return buildChildrenFromMathMLDom(children, node);
01895 }
01896 
01897 int SequenceElement::buildMathMLChild( QDomNode node )
01898 {
01899     int nodeCounter = 1;
01900     while ( ! node.isElement() ) {
01901         node = node.nextSibling();
01902         nodeCounter++;
01903         if ( node.isNull() ) {
01904             return -1;
01905         }
01906     }
01907     QDomElement e = node.toElement();
01908     BasicElement* child = 0;
01909     QString tag = e.tagName().lower();
01910 
01911     child = creationStrategy->createElement(tag, e);
01912     if (child != 0) {
01913         child->setParent(this);
01914         if (style != 0) {
01915             child->setStyle(style);
01916         }
01917         if (child->buildFromMathMLDom(e) != -1) {
01918             children.append(child);
01919         }
01920         else {
01921             delete child;
01922             return -1;
01923         }
01924     }
01925     else {
01926         return -1;
01927     }
01928     parse();
01929     return nodeCounter;
01930 }
01931 
01932 
01933 
01934 KFORMULA_NAMESPACE_END
KDE Home | KDE Accessibility Home | Description of Access Keys