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 
00055 #include <assert.h>
00056 
00057 KFORMULA_NAMESPACE_BEGIN
00058 //using namespace std;
00059 
00060 ElementCreationStrategy* SequenceElement::creationStrategy = 0;
00061 
00062 void SequenceElement::setCreationStrategy( ElementCreationStrategy* strategy )
00063 {
00064     creationStrategy = strategy;
00065 }
00066 
00067 
00068 SequenceElement::SequenceElement(BasicElement* parent)
00069         : BasicElement(parent), parseTree(0), textSequence(true),singlePipe(true)
00070 {
00071     assert( creationStrategy != 0 );
00072     children.setAutoDelete(true);
00073 }
00074 
00075 
00076 SequenceElement::~SequenceElement()
00077 {
00078     delete parseTree;
00079 }
00080 
00081 SequenceElement::SequenceElement( const SequenceElement& other )
00082     : BasicElement( other )
00083 {
00084     children.setAutoDelete(true);
00085     uint count = other.children.count();
00086     for (uint i = 0; i < count; i++) {
00087         BasicElement* child = children.at(i)->clone();
00088         child->setParent( this );
00089         children.append( child );
00090     }
00091 }
00092 
00093 
00094 bool SequenceElement::accept( ElementVisitor* visitor )
00095 {
00096     return visitor->visit( this );
00097 }
00098 
00099 
00100 bool SequenceElement::readOnly( const FormulaCursor* ) const
00101 {
00102     return getParent()->readOnly( this );
00103 }
00104 
00105 
00109 BasicElement* SequenceElement::goToPos( FormulaCursor* cursor, bool& handled,
00110                                         const LuPixelPoint& point, const LuPixelPoint& parentOrigin )
00111 {
00112     BasicElement* e = BasicElement::goToPos(cursor, handled, point, parentOrigin);
00113     if (e != 0) {
00114         LuPixelPoint myPos(parentOrigin.x() + getX(),
00115                            parentOrigin.y() + getY());
00116 
00117         uint count = children.count();
00118         for (uint i = 0; i < count; i++) {
00119             BasicElement* child = children.at(i);
00120             e = child->goToPos(cursor, handled, point, myPos);
00121             if (e != 0) {
00122                 if (!handled) {
00123                     handled = true;
00124                     if ((point.x() - myPos.x()) < (e->getX() + e->getWidth()*2/3)) {
00125                         cursor->setTo(this, children.find(e));
00126                     }
00127                     else {
00128                         cursor->setTo(this, children.find(e)+1);
00129                     }
00130                 }
00131                 return e;
00132             }
00133         }
00134 
00135         luPixel dx = point.x() - myPos.x();
00136         //int dy = point.y() - myPos.y();
00137 
00138         for (uint i = 0; i < count; i++) {
00139             BasicElement* child = children.at(i);
00140             if (dx < child->getX()) {
00141                 cursor->setTo( this, i );
00142                 handled = true;
00143                 return children.at( i );
00144             }
00145         }
00146 
00147         cursor->setTo(this, countChildren());
00148         handled = true;
00149         return this;
00150     }
00151     return 0;
00152 }
00153 
00154 
00155 bool SequenceElement::isEmpty()
00156 {
00157     uint count = children.count();
00158     for (uint i = 0; i < count; i++) {
00159         BasicElement* child = children.at(i);
00160         if (!child->isInvisible()) {
00161             return false;
00162         }
00163     }
00164     return true;
00165 }
00166 
00167 
00172 void SequenceElement::calcSizes(const ContextStyle& style,
00173                                 ContextStyle::TextStyle tstyle,
00174                                 ContextStyle::IndexStyle istyle)
00175 {
00176     if (!isEmpty()) {
00177         luPixel width = 0;
00178         luPixel toBaseline = 0;
00179         luPixel fromBaseline = 0;
00180 
00181         // Let's do all normal elements that have a base line.
00182         QPtrListIterator<BasicElement> it( children );
00183         for ( ; it.current(); ++it ) {
00184             BasicElement* child = it.current();
00185 
00186             luPixel spaceBefore = 0;
00187             if ( isFirstOfToken( child ) ) {
00188                 spaceBefore =
00189                     style.ptToPixelX( child->getElementType()->getSpaceBefore( style,
00190                                                                                tstyle ) );
00191             }
00192 
00193             if ( !child->isInvisible() ) {
00194                 child->calcSizes( style, tstyle, istyle );
00195                 child->setX( width + spaceBefore );
00196                 width += child->getWidth() + spaceBefore;
00197 
00198                 luPixel childBaseline = child->getBaseline();
00199                 if ( childBaseline > -1 ) {
00200                     toBaseline = QMAX( toBaseline, childBaseline );
00201                     fromBaseline = QMAX( fromBaseline,
00202                                          child->getHeight() - childBaseline );
00203                 }
00204                 else {
00205                     luPixel bl = child->getHeight()/2 + style.axisHeight( tstyle );
00206                     toBaseline = QMAX( toBaseline, bl );
00207                     fromBaseline = QMAX( fromBaseline, child->getHeight() - bl );
00208                 }
00209             }
00210             else {
00211                 width += spaceBefore;
00212                 child->setX( width );
00213             }
00214         }
00215 
00216         setWidth(width);
00217         setHeight(toBaseline+fromBaseline);
00218         setBaseline(toBaseline);
00219 
00220         setChildrenPositions();
00221     }
00222     else {
00223         luPixel w = style.getEmptyRectWidth();
00224         luPixel h = style.getEmptyRectHeight();
00225         setWidth( w );
00226         setHeight( h );
00227         setBaseline( h );
00228         //setMidline( h*.5 );
00229     }
00230 }
00231 
00232 
00233 void SequenceElement::setChildrenPositions()
00234 {
00235     QPtrListIterator<BasicElement> it( children );
00236     for ( ; it.current(); ++it ) {
00237         BasicElement* child = it.current();
00238         child->setY(getBaseline() - child->getBaseline());
00239     }
00240 }
00241 
00242 
00248 void SequenceElement::draw( QPainter& painter, const LuPixelRect& r,
00249                             const ContextStyle& context,
00250                             ContextStyle::TextStyle tstyle,
00251                             ContextStyle::IndexStyle istyle,
00252                             const LuPixelPoint& parentOrigin )
00253 {
00254     LuPixelPoint myPos( parentOrigin.x() + getX(), parentOrigin.y() + getY() );
00255     // There might be zero sized elements that still want to be drawn at least
00256     // in edit mode. (EmptyElement)
00257     //if ( !LuPixelRect( myPos.x(), myPos.y(), getWidth(), getHeight() ).intersects( r ) )
00258     //    return;
00259 
00260     if (!isEmpty()) {
00261         QPtrListIterator<BasicElement> it( children );
00262         for ( ; it.current(); ) {
00263             BasicElement* child = it.current();
00264             if (!child->isInvisible()) {
00265                 child->draw(painter, r, context, tstyle, istyle, myPos);
00266 
00267                 // Each starting element draws the whole token
00268                 // This only concerns TextElements.
00269                 ElementType* token = child->getElementType();
00270                 if ( token != 0 ) {
00271                     it += token->end() - token->start();
00272                 }
00273                 else {
00274                     ++it;
00275                 }
00276             }
00277             else {
00278                 ++it;
00279             }
00280         }
00281     }
00282     else {
00283         drawEmptyRect( painter, context, myPos );
00284     }
00285     // Debug
00286     //painter.setPen(Qt::green);
00287     //painter.drawRect(parentOrigin.x() + getX(), parentOrigin.y() + getY(),
00288     //                 getWidth(), getHeight());
00289 //     painter.drawLine( context.layoutUnitToPixelX( parentOrigin.x() + getX() ),
00290 //                       context.layoutUnitToPixelY( parentOrigin.y() + getY() + axis( context, tstyle ) ),
00291 //                       context.layoutUnitToPixelX( parentOrigin.x() + getX() + getWidth() ),
00292 //                       context.layoutUnitToPixelY( parentOrigin.y() + getY() + axis( context, tstyle ) ) );
00293 //     painter.setPen(Qt::red);
00294 //     painter.drawLine( context.layoutUnitToPixelX( parentOrigin.x() + getX() ),
00295 //                       context.layoutUnitToPixelY( parentOrigin.y() + getY() + getBaseline() ),
00296 //                       context.layoutUnitToPixelX( parentOrigin.x() + getX() + getWidth() ),
00297 //                       context.layoutUnitToPixelY( parentOrigin.y() + getY() + getBaseline() ) );
00298 }
00299 
00300 
00301 void SequenceElement::dispatchFontCommand( FontCommand* cmd )
00302 {
00303     QPtrListIterator<BasicElement> it( children );
00304     for ( ; it.current(); ++it ) {
00305         BasicElement* child = it.current();
00306         child->dispatchFontCommand( cmd );
00307     }
00308 }
00309 
00310 
00311 void SequenceElement::drawEmptyRect( QPainter& painter, const ContextStyle& context,
00312                                      const LuPixelPoint& upperLeft )
00313 {
00314     if ( context.edit() ) {
00315         painter.setBrush(Qt::NoBrush);
00316         painter.setPen( QPen( context.getEmptyColor(),
00317                               context.layoutUnitToPixelX( context.getLineWidth() ) ) );
00318         painter.drawRect( context.layoutUnitToPixelX( upperLeft.x() ),
00319                           context.layoutUnitToPixelY( upperLeft.y() ),
00320                           context.layoutUnitToPixelX( getWidth() ),
00321                           context.layoutUnitToPixelY( getHeight() ) );
00322     }
00323 }
00324 
00325 void SequenceElement::calcCursorSize( const ContextStyle& context,
00326                                       FormulaCursor* cursor, bool smallCursor )
00327 {
00328     LuPixelPoint point = widgetPos();
00329     uint pos = cursor->getPos();
00330 
00331     luPixel posX = getChildPosition( context, pos );
00332     luPixel height = getHeight();
00333 
00334     luPixel unitX = context.ptToLayoutUnitPixX( 1 );
00335     luPixel unitY = context.ptToLayoutUnitPixY( 1 );
00336 
00337     // Here are those evil constants that describe the cursor size.
00338 
00339     if ( cursor->isSelection() ) {
00340         uint mark = cursor->getMark();
00341         luPixel markX = getChildPosition( context, mark );
00342         luPixel x = QMIN(posX, markX);
00343         luPixel width = abs(posX - markX);
00344 
00345         if ( smallCursor ) {
00346             cursor->cursorSize.setRect( point.x()+x, point.y(), width, height );
00347         }
00348         else {
00349             cursor->cursorSize.setRect( point.x()+x, point.y() - 2*unitY,
00350                                         width + unitX, height + 4*unitY );
00351         }
00352     }
00353     else {
00354         if ( smallCursor ) {
00355             cursor->cursorSize.setRect( point.x()+posX, point.y(),
00356                                         unitX, height );
00357         }
00358         else {
00359             cursor->cursorSize.setRect( point.x(), point.y() - 2*unitY,
00360                                         getWidth() + unitX, height + 4*unitY );
00361         }
00362     }
00363 
00364     cursor->cursorPoint.setX( point.x()+posX );
00365     cursor->cursorPoint.setY( point.y()+getHeight()/2 );
00366 }
00367 
00368 
00372 void SequenceElement::drawCursor( QPainter& painter, const ContextStyle& context,
00373                                   FormulaCursor* cursor, bool smallCursor,
00374                                   bool activeCursor )
00375 {
00376     painter.setRasterOp( Qt::XorROP );
00377     if ( cursor->isSelection() ) {
00378         const LuPixelRect& r = cursor->cursorSize;
00379         painter.fillRect( context.layoutUnitToPixelX( r.x() ),
00380                           context.layoutUnitToPixelY( r.y() ),
00381                           context.layoutUnitToPixelX( r.width() ),
00382                           context.layoutUnitToPixelY( r.height() ),
00383                           Qt::white );
00384     }
00385     painter.setPen( QPen( Qt::white,
00386                     context.layoutUnitToPixelX( context.getLineWidth()/2 ) ) );
00387     const LuPixelPoint& point = cursor->getCursorPoint();
00388     const LuPixelRect& size = cursor->getCursorSize();
00389     if ( activeCursor )
00390     {
00391         int offset = 0;
00392         if ( cursor->isSelection() && cursor->getPos() > cursor->getMark() )
00393             offset = -1;
00394         painter.drawLine( context.layoutUnitToPixelX( point.x() ) + offset,
00395                           context.layoutUnitToPixelY( size.top() ),
00396                           context.layoutUnitToPixelX( point.x() ) + offset,
00397                           context.layoutUnitToPixelY( size.bottom() )-1 );
00398         painter.drawLine( context.layoutUnitToPixelX( point.x() ) + offset + 1,
00399                           context.layoutUnitToPixelY( size.top() ),
00400                           context.layoutUnitToPixelX( point.x() ) + offset + 1,
00401                           context.layoutUnitToPixelY( size.bottom() )-1 );
00402     }
00403     if ( !smallCursor && !cursor->isSelection() )
00404         painter.drawLine( context.layoutUnitToPixelX( size.left() ),
00405                           context.layoutUnitToPixelY( size.bottom() )-1,
00406                           context.layoutUnitToPixelX( size.right() )-1,
00407                           context.layoutUnitToPixelY( size.bottom() )-1 );
00408     // This might be wrong but probably isn't.
00409     painter.setRasterOp( Qt::CopyROP );
00410 }
00411 
00412 
00413 luPixel SequenceElement::getChildPosition( const ContextStyle& context, uint child )
00414 {
00415     if (child < children.count()) {
00416         return children.at(child)->getX();
00417     }
00418     else {
00419         if (children.count() > 0) {
00420             return children.at(child-1)->getX() + children.at(child-1)->getWidth();
00421         }
00422         else {
00423             return context.ptToLayoutUnitPixX( 2 );
00424         }
00425     }
00426 }
00427 
00428 
00429 // navigation
00430 //
00431 // The elements are responsible to handle cursor movement themselves.
00432 // To do this they need to know the direction the cursor moves and
00433 // the element it comes from.
00434 //
00435 // The cursor might be in normal or in selection mode.
00436 
00442 void SequenceElement::moveLeft(FormulaCursor* cursor, BasicElement* from)
00443 {
00444     // Our parent asks us for a cursor position. Found.
00445     if (from == getParent()) {
00446         cursor->setTo(this, children.count());
00447         from->entered( this );
00448     }
00449 
00450     // We already owned the cursor. Ask next child then.
00451     else if (from == this) {
00452         if (cursor->getPos() > 0) {
00453             if (cursor->isSelectionMode()) {
00454                 cursor->setTo(this, cursor->getPos()-1);
00455 
00456                 // invisible elements are not visible so we move on.
00457                 if (children.at(cursor->getPos())->isInvisible()) {
00458                     moveLeft(cursor, this);
00459                 }
00460             }
00461             else {
00462                 children.at(cursor->getPos()-1)->moveLeft(cursor, this);
00463             }
00464         }
00465         else {
00466             // Needed because FormulaElement derives this.
00467             if (getParent() != 0) {
00468                 getParent()->moveLeft(cursor, this);
00469             }
00470             else {
00471                 formula()->moveOutLeft( cursor );
00472             }
00473         }
00474     }
00475 
00476     // The cursor came from one of our children or
00477     // something is wrong.
00478     else {
00479         int fromPos = children.find(from);
00480         cursor->setTo(this, fromPos);
00481         if (cursor->isSelectionMode()) {
00482             cursor->setMark(fromPos+1);
00483         }
00484 
00485         // invisible elements are not visible so we move on.
00486         if (from->isInvisible()) {
00487             moveLeft(cursor, this);
00488         }
00489         formula()->tell( "" );
00490     }
00491 }
00492 
00498 void SequenceElement::moveRight(FormulaCursor* cursor, BasicElement* from)
00499 {
00500     // Our parent asks us for a cursor position. Found.
00501     if (from == getParent()) {
00502         cursor->setTo(this, 0);
00503         from->entered( this );
00504     }
00505 
00506     // We already owned the cursor. Ask next child then.
00507     else if (from == this) {
00508         uint pos = cursor->getPos();
00509         if (pos < children.count()) {
00510             if (cursor->isSelectionMode()) {
00511                 cursor->setTo(this, pos+1);
00512 
00513                 // invisible elements are not visible so we move on.
00514                 if (children.at(pos)->isInvisible()) {
00515                     moveRight(cursor, this);
00516                 }
00517             }
00518             else {
00519                 children.at(pos)->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         cursor->setTo(this, fromPos+1);
00538         if (cursor->isSelectionMode()) {
00539             cursor->setMark(fromPos);
00540         }
00541 
00542         // invisible elements are not visible so we move on.
00543         if (from->isInvisible()) {
00544             moveRight(cursor, this);
00545         }
00546         formula()->tell( "" );
00547     }
00548 }
00549 
00550 
00551 void SequenceElement::moveWordLeft(FormulaCursor* cursor)
00552 {
00553     uint pos = cursor->getPos();
00554     if (pos > 0) {
00555         ElementType* type = children.at(pos-1)->getElementType();
00556         if (type != 0) {
00557             cursor->setTo(this, type->start());
00558         }
00559     }
00560     else {
00561         moveLeft(cursor, this);
00562     }
00563 }
00564 
00565 
00566 void SequenceElement::moveWordRight(FormulaCursor* cursor)
00567 {
00568     uint pos = cursor->getPos();
00569     if (pos < children.count()) {
00570         ElementType* type = children.at(pos)->getElementType();
00571         if (type != 0) {
00572             cursor->setTo(this, type->end());
00573         }
00574     }
00575     else {
00576         moveRight(cursor, this);
00577     }
00578 }
00579 
00580 
00586 void SequenceElement::moveUp(FormulaCursor* cursor, BasicElement* from)
00587 {
00588     if (from == getParent()) {
00589         moveRight(cursor, this);
00590     }
00591     else {
00592         if (getParent() != 0) {
00593             getParent()->moveUp(cursor, this);
00594         }
00595         else {
00596             formula()->moveOutAbove( cursor );
00597         }
00598     }
00599 }
00600 
00606 void SequenceElement::moveDown(FormulaCursor* cursor, BasicElement* from)
00607 {
00608     if (from == getParent()) {
00609         moveRight(cursor, this);
00610     }
00611     else {
00612         if (getParent() != 0) {
00613             getParent()->moveDown(cursor, this);
00614         }
00615         else {
00616             formula()->moveOutBelow( cursor );
00617         }
00618     }
00619 }
00620 
00625 void SequenceElement::moveHome(FormulaCursor* cursor)
00626 {
00627     if (cursor->isSelectionMode()) {
00628         BasicElement* element = cursor->getElement();
00629         if (element != this) {
00630             while (element->getParent() != this) {
00631                 element = element->getParent();
00632             }
00633             cursor->setMark(children.find(element)+1);
00634         }
00635     }
00636     cursor->setTo(this, 0);
00637 }
00638 
00643 void SequenceElement::moveEnd(FormulaCursor* cursor)
00644 {
00645     if (cursor->isSelectionMode()) {
00646         BasicElement* element = cursor->getElement();
00647         if (element != this) {
00648             while (element->getParent() != this) {
00649                 element = element->getParent();
00650                 if (element == 0) {
00651                     cursor->setMark(children.count());
00652                     break;
00653                 }
00654             }
00655             if (element != 0) {
00656                 cursor->setMark(children.find(element));
00657             }
00658         }
00659     }
00660     cursor->setTo(this, children.count());
00661 }
00662 
00667 void SequenceElement::goInside(FormulaCursor* cursor)
00668 {
00669     cursor->setSelection(false);
00670     cursor->setTo(this, 0);
00671 }
00672 
00673 
00674 // children
00675 
00683 // void SequenceElement::removeChild(FormulaCursor* cursor, BasicElement* child)
00684 // {
00685 //     int pos = children.find(child);
00686 //     formula()->elementRemoval(child, pos);
00687 //     cursor->setTo(this, pos);
00688 //     children.remove(pos);
00689 //     /*
00690 //         if len(self.children) == 0:
00691 //             if self.parent != None:
00692 //                 self.parent.removeChild(cursor, self)
00693 //                 return
00694 //     */
00695 //     formula()->changed();
00696 // }
00697 
00698 
00706 void SequenceElement::insert(FormulaCursor* cursor,
00707                              QPtrList<BasicElement>& newChildren,
00708                              Direction direction)
00709 {
00710     int pos = cursor->getPos();
00711     uint count = newChildren.count();
00712     for (uint i = 0; i < count; i++) {
00713         BasicElement* child = newChildren.take(0);
00714         child->setParent(this);
00715         children.insert(pos+i, child);
00716     }
00717     if (direction == beforeCursor) {
00718         cursor->setTo(this, pos+count, pos);
00719     }
00720     else {
00721         cursor->setTo(this, pos, pos+count);
00722     }
00723 
00724     formula()->changed();
00725     parse();
00726 }
00727 
00728 
00735 void SequenceElement::remove(FormulaCursor* cursor,
00736                              QPtrList<BasicElement>& removedChildren,
00737                              Direction direction)
00738 {
00739     if (cursor->isSelection()) {
00740         int from = cursor->getSelectionStart();
00741         int to = cursor->getSelectionEnd();
00742         for (int i = from; i < to; i++) {
00743             removeChild(removedChildren, from);
00744         }
00745         cursor->setTo(this, from);
00746         cursor->setSelection(false);
00747     }
00748     else {
00749         if (direction == beforeCursor) {
00750             int pos = cursor->getPos() - 1;
00751             if (pos >= 0) {
00752                 while (pos >= 0) {
00753                     BasicElement* child = children.at(pos);
00754                     formula()->elementRemoval(child);
00755                     children.take(pos);
00756                     removedChildren.prepend(child);
00757                     if (!child->isInvisible()) {
00758                         break;
00759                     }
00760                     pos--;
00761                 }
00762                 cursor->setTo(this, pos);
00763                 formula()->changed();
00764             }
00765         }
00766         else {
00767             uint pos = cursor->getPos();
00768             if (pos < children.count()) {
00769                 while (pos < children.count()) {
00770                     BasicElement* child = children.at(pos);
00771                     formula()->elementRemoval(child);
00772                     children.take(pos);
00773                     removedChildren.append(child);
00774                     if (!child->isInvisible()) {
00775                         break;
00776                     }
00777                 }
00778                 // It is necessary to set the cursor to its old
00779                 // position because it got a notification and
00780                 // moved to the beginning of this sequence.
00781                 cursor->setTo(this, pos);
00782                 formula()->changed();
00783             }
00784         }
00785     }
00786     parse();
00787 }
00788 
00789 
00793 void SequenceElement::removeChild(QPtrList<BasicElement>& removedChildren, int pos)
00794 {
00795     BasicElement* child = children.at(pos);
00796     formula()->elementRemoval(child);
00797     children.take(pos);
00798     removedChildren.append(child);
00799     //cerr << *removedChildren.at(0) << endl;
00800     formula()->changed();
00801 }
00802 
00803 
00808 void SequenceElement::normalize(FormulaCursor* cursor, Direction)
00809 {
00810     cursor->setSelection(false);
00811 }
00812 
00813 
00818 BasicElement* SequenceElement::getChild( FormulaCursor* cursor, Direction direction )
00819 {
00820     if ( direction == beforeCursor ) {
00821         if ( cursor->getPos() > 0 ) {
00822             return children.at( cursor->getPos() - 1 );
00823         }
00824     }
00825     else {
00826         if ( cursor->getPos() < qRound( children.count() ) ) {
00827             return children.at( cursor->getPos() );
00828         }
00829     }
00830     return 0;
00831 }
00832 
00833 
00838 void SequenceElement::selectChild(FormulaCursor* cursor, BasicElement* child)
00839 {
00840     int pos = children.find(child);
00841     if (pos > -1) {
00842         cursor->setTo(this, pos+1, pos);
00843     }
00844 }
00845 
00846 void SequenceElement::childWillVanish(FormulaCursor* cursor, BasicElement* child)
00847 {
00848     int childPos = children.find(child);
00849     if (childPos > -1) {
00850         int pos = cursor->getPos();
00851         if (pos > childPos) {
00852             pos--;
00853         }
00854         int mark = cursor->getMark();
00855         if (mark > childPos) {
00856             mark--;
00857         }
00858         cursor->setTo(this, pos, mark);
00859     }
00860 }
00861 
00862 
00866 void SequenceElement::selectAllChildren(FormulaCursor* cursor)
00867 {
00868     cursor->setTo(this, children.count(), 0);
00869 }
00870 
00871 bool SequenceElement::onlyTextSelected( FormulaCursor* cursor )
00872 {
00873     if ( cursor->isSelection() ) {
00874         uint from = QMIN( cursor->getPos(), cursor->getMark() );
00875         uint to = QMAX( cursor->getPos(), cursor->getMark() );
00876         for ( uint i = from; i < to; i++ ) {
00877             BasicElement* element = getChild( i );
00878             if ( element->getCharacter() == QChar::null ) {
00879                 return false;
00880             }
00881         }
00882     }
00883     return true;
00884 }
00885 
00886 
00887 KCommand* SequenceElement::buildCommand( Container* container, Request* request )
00888 {
00889     FormulaCursor* cursor = container->activeCursor();
00890     if ( cursor->isReadOnly() ) {
00891         formula()->tell( i18n( "write protection" ) );
00892         return 0;
00893     }
00894 
00895     switch ( *request ) {
00896     case req_addText: {
00897         KFCReplace* command = new KFCReplace( i18n("Add Text"), container );
00898         TextRequest* tr = static_cast<TextRequest*>( request );
00899         for ( uint i = 0; i < tr->text().length(); i++ ) {
00900             command->addElement( creationStrategy->createTextElement( tr->text()[i] ) );
00901         }
00902         return command;
00903     }
00904     case req_addTextChar: {
00905         KFCReplace* command = new KFCReplace( i18n("Add Text"), container );
00906         TextCharRequest* tr = static_cast<TextCharRequest*>( request );
00907         TextElement* element = creationStrategy->createTextElement( tr->ch(), tr->isSymbol() );
00908         command->addElement( element );
00909         return command;
00910     }
00911     case req_addEmptyBox: {
00912         EmptyElement* element = creationStrategy->createEmptyElement();
00913         if ( element != 0 ) {
00914             KFCReplace* command = new KFCReplace( i18n("Add Empty Box"), container );
00915             command->addElement( element );
00916             return command;
00917         }
00918         break;
00919     }
00920     case req_addNameSequence:
00921         if ( onlyTextSelected( container->activeCursor() ) ) {
00922             NameSequence* nameSequence = creationStrategy->createNameSequence();
00923             if ( nameSequence != 0 ) {
00924                 KFCAddReplacing* command = new KFCAddReplacing( i18n( "Add Name" ), container );
00925                 command->setElement( nameSequence );
00926                 return command;
00927             }
00928         }
00929         break;
00930     case req_addBracket: {
00931         BracketRequest* br = static_cast<BracketRequest*>( request );
00932         BracketElement* bracketElement =
00933             creationStrategy->createBracketElement( br->left(), br->right() );
00934         if ( bracketElement != 0 ) {
00935             KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Bracket"), container);
00936             command->setElement( bracketElement );
00937             return command;
00938         }
00939         break;
00940     }
00941     case req_addOverline: {
00942         OverlineElement* overline = creationStrategy->createOverlineElement();
00943         if ( overline != 0 ) {
00944             KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Overline"), container);
00945             command->setElement( overline );
00946             return command;
00947         }
00948         break;
00949     }
00950     case req_addUnderline: {
00951         UnderlineElement* underline = creationStrategy->createUnderlineElement();
00952         if ( underline != 0 ) {
00953             KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Underline"), container);
00954             command->setElement( underline );
00955             return command;
00956         }
00957         break;
00958     }
00959     case req_addMultiline: {
00960         MultilineElement* multiline = creationStrategy->createMultilineElement();
00961         if ( multiline != 0 ) {
00962             KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Multiline"), container);
00963             command->setElement( multiline );
00964             return command;
00965         }
00966         break;
00967     }
00968     case req_addSpace: {
00969         SpaceRequest* sr = static_cast<SpaceRequest*>( request );
00970         SpaceElement* element = creationStrategy->createSpaceElement( sr->space() );
00971         if ( element != 0 ) {
00972             KFCReplace* command = new KFCReplace( i18n("Add Space"), container );
00973             command->addElement( element );
00974             return command;
00975         }
00976         break;
00977     }
00978     case req_addFraction: {
00979         FractionElement* fraction = creationStrategy->createFractionElement();
00980         if ( fraction != 0 ) {
00981             KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Fraction"), container);
00982             command->setElement( fraction );
00983             return command;
00984         }
00985         break;
00986     }
00987     case req_addRoot: {
00988         RootElement* root = creationStrategy->createRootElement();
00989         if ( root != 0 ) {
00990             KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Root"), container);
00991             command->setElement( root );
00992             return command;
00993         }
00994         break;
00995     }
00996     case req_addSymbol: {
00997         SymbolRequest* sr = static_cast<SymbolRequest*>( request );
00998         SymbolElement* symbol = creationStrategy->createSymbolElement( sr->type() );
00999         if ( symbol != 0 ) {
01000             KFCAddReplacing* command = new KFCAddReplacing( i18n( "Add Symbol" ), container );
01001             command->setElement( symbol );
01002             return command;
01003         }
01004         break;
01005     }
01006     case req_addOneByTwoMatrix: {
01007         FractionElement* element = creationStrategy->createFractionElement();
01008         if ( element != 0 ) {
01009             KFCAddReplacing* command = new KFCAddReplacing( i18n("Add 1x2 Matrix"), container );
01010             element->showLine(false);
01011             command->setElement(element);
01012             return command;
01013         }
01014     }
01015     case req_addMatrix: {
01016         MatrixRequest* mr = static_cast<MatrixRequest*>( request );
01017         uint rows = mr->rows(), cols = mr->columns();
01018         if ( ( rows == 0 ) || ( cols == 0 ) ) {
01019             MatrixDialog* dialog = new MatrixDialog( 0 );
01020             if ( dialog->exec() ) {
01021                 rows = dialog->h;
01022                 cols = dialog->w;
01023             }
01024             delete dialog;
01025         }
01026 
01027         if ( ( rows != 0 ) && ( cols != 0 ) ) {
01028             KFCAddReplacing* command = new KFCAddReplacing( i18n( "Add Matrix" ), container );
01029             command->setElement( creationStrategy->createMatrixElement( rows, cols ) );
01030             return command;
01031         }
01032         else
01033             return 0L;
01034     }
01035     case req_addIndex: {
01036         if ( cursor->getPos() > 0 && !cursor->isSelection() ) {
01037             IndexElement* element =
01038                 dynamic_cast<IndexElement*>( children.at( cursor->getPos()-1 ) );
01039             if ( element != 0 ) {
01040                 element->getMainChild()->goInside( cursor );
01041                 return element->getMainChild()->buildCommand( container, request );
01042             }
01043         }
01044         IndexElement* element = creationStrategy->createIndexElement();
01045         if ( element != 0 ) {
01046             if ( !cursor->isSelection() ) {
01047                 cursor->moveLeft( SelectMovement | WordMovement );
01048             }
01049             IndexRequest* ir = static_cast<IndexRequest*>( request );
01050             KFCAddIndex* command = new KFCAddIndex( container, element,
01051                                                     element->getIndex( ir->index() ) );
01052             return command;
01053         }
01054         break;
01055     }
01056     case req_removeEnclosing: {
01057         if ( !cursor->isSelection() ) {
01058             DirectedRemove* dr = static_cast<DirectedRemove*>( request );
01059             KFCRemoveEnclosing* command = new KFCRemoveEnclosing( container, dr->direction() );
01060             return command;
01061         }
01062     }
01063     case req_remove: {
01064         SequenceElement* sequence = cursor->normal();
01065         if ( sequence &&
01066              ( sequence == sequence->formula() ) &&
01067              ( sequence->countChildren() == 0 ) ) {
01068             sequence->formula()->removeFormula( cursor );
01069             return 0;
01070         }
01071         else {
01072             DirectedRemove* dr = static_cast<DirectedRemove*>( request );
01073 
01074             // empty removes are not legal!
01075             if ( !cursor->isSelection() ) {
01076                 if ( countChildren() > 0 ) {
01077                     if ( ( cursor->getPos() == 0 ) && ( dr->direction() == beforeCursor ) ) {
01078                         return 0;
01079                     }
01080                     if ( ( cursor->getPos() == countChildren() ) && ( dr->direction() == afterCursor ) ) {
01081                         return 0;
01082                     }
01083                 }
01084                 else if ( getParent() == 0 ) {
01085                     return 0;
01086                 }
01087             }
01088 
01089             KFCRemove* command = new KFCRemove( container, dr->direction() );
01090             return command;
01091         }
01092     }
01093     case req_compactExpression: {
01094         cursor->moveEnd();
01095         cursor->moveRight();
01096         formula()->cursorHasMoved( cursor );
01097         break;
01098     }
01099     case req_makeGreek: {
01100         TextElement* element = cursor->getActiveTextElement();
01101         if ((element != 0) && !element->isSymbol()) {
01102             cursor->selectActiveElement();
01103             const SymbolTable& table = container->document()->getSymbolTable();
01104             if (table.greekLetters().find(element->getCharacter()) != -1) {
01105                 KFCReplace* command = new KFCReplace( i18n( "Change Char to Symbol" ), container );
01106                 TextElement* symbol = creationStrategy->createTextElement( table.unicodeFromSymbolFont( element->getCharacter() ), true );
01107                 command->addElement( symbol );
01108                 return command;
01109             }
01110             cursor->setSelection( false );
01111         }
01112         break;
01113     }
01114     case req_paste:
01115     case req_copy:
01116     case req_cut:
01117         break;
01118     case req_formatBold:
01119     case req_formatItalic: {
01120         if ( cursor->isSelection() ) {
01121             CharStyleRequest* csr = static_cast<CharStyleRequest*>( request );
01122             CharStyle cs = normalChar;
01123             if ( csr->bold() ) cs = static_cast<CharStyle>( cs | boldChar );
01124             if ( csr->italic() ) cs = static_cast<CharStyle>( cs | italicChar );
01125             CharStyleCommand* cmd = new CharStyleCommand( cs, i18n( "Change Char Style" ), container );
01126             int end = cursor->getSelectionEnd();
01127             for ( int i = cursor->getSelectionStart(); i<end; ++i ) {
01128                 cmd->addElement( children.at( i ) );
01129             }
01130             return cmd;
01131         }
01132         break;
01133     }
01134     case req_formatFamily: {
01135         if ( cursor->isSelection() ) {
01136             CharFamilyRequest* cfr = static_cast<CharFamilyRequest*>( request );
01137             CharFamily cf = cfr->charFamily();
01138             CharFamilyCommand* cmd = new CharFamilyCommand( cf, i18n( "Change Char Family" ), container );
01139             int end = cursor->getSelectionEnd();
01140             for ( int i = cursor->getSelectionStart(); i<end; ++i ) {
01141                 cmd->addElement( children.at( i ) );
01142             }
01143             return cmd;
01144         }
01145         break;
01146     }
01147     default:
01148         break;
01149     }
01150     return 0;
01151 }
01152 
01153 
01154 KCommand* SequenceElement::input( Container* container, QKeyEvent* event )
01155 {
01156     QChar ch = event->text().at( 0 );
01157     if ( ch.isPrint() ) {
01158         return input( container, ch );
01159     }
01160     else {
01161         int action = event->key();
01162         int state = event->state();
01163         MoveFlag flag = movementFlag(state);
01164 
01165     switch ( action ) {
01166         case Qt::Key_BackSpace: {
01167             DirectedRemove r( req_remove, beforeCursor );
01168             return buildCommand( container, &r );
01169         }
01170         case Qt::Key_Delete: {
01171             DirectedRemove r( req_remove, afterCursor );
01172             return buildCommand( container, &r );
01173         }
01174     case Qt::Key_Left: {
01175             FormulaCursor* cursor = container->activeCursor();
01176             cursor->moveLeft( flag );
01177             formula()->cursorHasMoved( cursor );
01178             break;
01179         }
01180         case Qt::Key_Right: {
01181             FormulaCursor* cursor = container->activeCursor();
01182             cursor->moveRight( flag );
01183             formula()->cursorHasMoved( cursor );
01184             break;
01185         }
01186         case Qt::Key_Up: {
01187             FormulaCursor* cursor = container->activeCursor();
01188             cursor->moveUp( flag );
01189             formula()->cursorHasMoved( cursor );
01190             break;
01191         }
01192         case Qt::Key_Down: {
01193             FormulaCursor* cursor = container->activeCursor();
01194             cursor->moveDown( flag );
01195             formula()->cursorHasMoved( cursor );
01196             break;
01197         }
01198         case Qt::Key_Home: {
01199             FormulaCursor* cursor = container->activeCursor();
01200             cursor->moveHome( flag );
01201             formula()->cursorHasMoved( cursor );
01202             break;
01203         }
01204         case Qt::Key_End: {
01205             FormulaCursor* cursor = container->activeCursor();
01206             cursor->moveEnd( flag );
01207             formula()->cursorHasMoved( cursor );
01208             break;
01209         }
01210         default:
01211             if ( state & Qt::ControlButton ) {
01212                 switch ( event->key() ) {
01213                 case Qt::Key_AsciiCircum: {
01214                     IndexRequest r( upperLeftPos );
01215                     return buildCommand( container, &r );
01216                 }
01217                 case Qt::Key_Underscore: {
01218                     IndexRequest r( lowerLeftPos );
01219                     return buildCommand( container, &r );
01220                 }
01221                 default:
01222                     break;
01223                 }
01224             }
01225         }
01226     }
01227     return 0;
01228 }
01229 
01230 
01231 KCommand* SequenceElement::input( Container* container, QChar ch )
01232 {
01233     int unicode = ch.unicode();
01234     switch (unicode) {
01235     case '(': {
01236         BracketRequest r( container->document()->leftBracketChar(),
01237                           container->document()->rightBracketChar() );
01238         singlePipe = true;
01239         return buildCommand( container, &r );
01240     }
01241     case '[': {
01242         BracketRequest r( LeftSquareBracket, RightSquareBracket );
01243         singlePipe = true;
01244         return buildCommand( container, &r );
01245     }
01246     case '{': {
01247         BracketRequest r( LeftCurlyBracket, RightCurlyBracket );
01248         singlePipe = true;
01249         return buildCommand( container, &r );
01250     }
01251     case '|': { 
01252         if (!singlePipe) { // We have had 2 '|' in a row so we want brackets
01253 
01254           DirectedRemove rDelete( req_remove, beforeCursor ); //Delete the previous '|' we dont need it any more
01255           KCommand* command = buildCommand( container, &rDelete );
01256           command->execute();
01257           
01258           BracketRequest rBracket( LeftLineBracket , RightLineBracket);
01259           singlePipe = true;  //the next '|' will be a single pipe again
01260           return buildCommand( container, &rBracket );    
01261         }
01262         else { // We really do only want 1 '|'
01263           TextCharRequest r(ch);
01264 
01265           //in case another '|' character is entered right after this one, '| |' brackets are made; see above
01266           singlePipe = false;
01267 
01268           return buildCommand( container, &r );   
01269         }
01270     }
01271     case '^': {
01272         IndexRequest r( upperRightPos );
01273         singlePipe = true;
01274         return buildCommand( container, &r );
01275     }
01276     case '_': {
01277         IndexRequest r( lowerRightPos );
01278         singlePipe = true;
01279         return buildCommand( container, &r );
01280     }
01281     case ' ': {
01282         Request r( req_compactExpression );
01283         singlePipe = true;
01284         return buildCommand( container, &r );
01285     }
01286     case '}': {
01287         Request r( req_addEmptyBox );
01288         singlePipe = true;
01289         return buildCommand( container, &r );
01290     }
01291     case ']':
01292     case ')':
01293         singlePipe = true; 
01294         break;
01295     case '\\': {
01296         Request r( req_addNameSequence );
01297         singlePipe = true;
01298         return buildCommand( container, &r );
01299     }
01300     default: {
01301         TextCharRequest r( ch );
01302         singlePipe = true;
01303         return buildCommand( container, &r );
01304     }
01305     }
01306     return 0;
01307 }
01308 
01312 void SequenceElement::getChildrenDom( QDomDocument& doc, QDomElement elem,
01313                                      uint from, uint to)
01314 {
01315     for (uint i = from; i < to; i++) {
01316         QDomElement tmpEleDom=children.at(i)->getElementDom(doc);
01317     elem.appendChild(tmpEleDom);
01318     }
01319 }
01320 
01321 
01327 bool SequenceElement::buildChildrenFromDom(QPtrList<BasicElement>& list, QDomNode n)
01328 {
01329     while (!n.isNull()) {
01330         if (n.isElement()) {
01331             QDomElement e = n.toElement();
01332             BasicElement* child = 0;
01333             QString tag = e.tagName().upper();
01334 
01335             child = createElement(tag);
01336             if (child != 0) {
01337                 child->setParent(this);
01338                 if (child->buildFromDom(e)) {
01339                     list.append(child);
01340                 }
01341                 else {
01342                     delete child;
01343                     return false;
01344                 }
01345             }
01346             else {
01347                 return false;
01348             }
01349         }
01350         n = n.nextSibling();
01351     }
01352     parse();
01353     return true;
01354 }
01355 
01356 
01357 BasicElement* SequenceElement::createElement( QString type )
01358 {
01359     return creationStrategy->createElement( type );
01360 }
01361 
01365 void SequenceElement::writeDom(QDomElement element)
01366 {
01367     BasicElement::writeDom(element);
01368 
01369     uint count = children.count();
01370     QDomDocument doc = element.ownerDocument();
01371     getChildrenDom(doc, element, 0, count);
01372 }
01373 
01378 bool SequenceElement::readAttributesFromDom(QDomElement element)
01379 {
01380     if (!BasicElement::readAttributesFromDom(element)) {
01381         return false;
01382     }
01383     return true;
01384 }
01385 
01391 bool SequenceElement::readContentFromDom(QDomNode& node)
01392 {
01393     if (!BasicElement::readContentFromDom(node)) {
01394         return false;
01395     }
01396 
01397     return buildChildrenFromDom(children, node);
01398 }
01399 
01400 
01401 void SequenceElement::parse()
01402 {
01403     delete parseTree;
01404 
01405     textSequence = true;
01406     for (BasicElement* element = children.first();
01407          element != 0;
01408          element = children.next()) {
01409 
01410         // Those types are gone. Make sure they won't
01411         // be used.
01412         element->setElementType(0);
01413 
01414         if (element->getCharacter().isNull()) {
01415             textSequence = false;
01416         }
01417     }
01418 
01419     const SymbolTable& symbols = formula()->getSymbolTable();
01420     SequenceParser parser(symbols);
01421     parseTree = parser.parse(children);
01422 
01423     // With the IndexElement dynamically changing its text/non-text
01424     // behaviour we need to reparse your parent, too. Hacky!
01425     BasicElement* p = getParent();
01426     if ( p != 0 ) {
01427         SequenceElement* seq = dynamic_cast<SequenceElement*>( p->getParent() );
01428         if ( seq != 0 ) {
01429             seq->parse();
01430         }
01431     }
01432     // debug
01433     //parseTree->output();
01434 }
01435 
01436 
01437 bool SequenceElement::isFirstOfToken( BasicElement* child )
01438 {
01439     return ( child->getElementType() != 0 ) && isChildNumber( child->getElementType()->start(), child );
01440 }
01441 
01442 
01443 QString SequenceElement::toLatex()
01444 {
01445     QString content;
01446     uint count = children.count();
01447     for ( uint i = 0; i < count; i++ ) {
01448         BasicElement* child = children.at( i );
01449 //         if ( isFirstOfToken( child ) ) {
01450 //             content += "";
01451 //         }
01452         content += child->toLatex();
01453     }
01454     return content;
01455 }
01456 
01457 
01458 QString SequenceElement::formulaString()
01459 {
01460     QString content;
01461     uint count = children.count();
01462     for ( uint i = 0; i < count; i++ ) {
01463         BasicElement* child = children.at( i );
01464         //if ( isFirstOfToken( child ) ) {
01465         //    content += " ";
01466         //}
01467         content += child->formulaString();
01468     }
01469     return content;
01470 }
01471 
01472 
01473 void SequenceElement::writeMathML( QDomDocument& doc, QDomNode parent, bool oasisFormat )
01474 {
01475     QDomElement de = doc.createElement( oasisFormat ? "math:mrow" : "mrow" );
01476 
01477     BasicElement* last = children.last();
01478     if ( last != 0 ) {
01479         // Create a list (right order!)
01480         QPtrList<ElementType> tokenList;
01481         ElementType* token = last->getElementType();
01482         while ( token != 0 ) {
01483             // Add to the list.
01484             tokenList.prepend( token );
01485             token = token->getPrev();
01486         }
01487 
01488         if ( tokenList.count() == 1 ) {
01489             tokenList.first()->saveMathML( this, doc, parent.toElement(), oasisFormat );
01490             return;
01491         }
01492 
01493         for ( uint i = 0; i < tokenList.count(); ++i ) {
01494             tokenList.at( i )->saveMathML( this, doc, de, oasisFormat );
01495         }
01496     }
01497     parent.appendChild( de );
01498 }
01499 
01500 
01501 int SequenceElement::childPos( const BasicElement* child ) const
01502 {
01503     QPtrListIterator<BasicElement> it( children );
01504     uint count = it.count();
01505     for ( uint i=0; i<count; ++i, ++it ) {
01506         if ( it.current() == child ) {
01507             return i;
01508         }
01509     }
01510     return -1;
01511 }
01512 
01513 
01514 NameSequence::NameSequence( BasicElement* parent )
01515     : SequenceElement( parent )
01516 {
01517 }
01518 
01519 
01520 bool NameSequence::accept( ElementVisitor* visitor )
01521 {
01522     return visitor->visit( this );
01523 }
01524 
01525 
01526 void NameSequence::calcCursorSize( const ContextStyle& context,
01527                                    FormulaCursor* cursor, bool smallCursor )
01528 {
01529     inherited::calcCursorSize( context, cursor, smallCursor );
01530     LuPixelPoint point = widgetPos();
01531     luPixel unitX = context.ptToLayoutUnitPixX( 1 );
01532     luPixel unitY = context.ptToLayoutUnitPixY( 1 );
01533     cursor->addCursorSize( LuPixelRect( point.x()-unitX, point.y()-unitY,
01534                                         getWidth()+2*unitX, getHeight()+2*unitY ) );
01535 }
01536 
01537 void NameSequence::drawCursor( QPainter& painter, const ContextStyle& context,
01538                                FormulaCursor* cursor, bool smallCursor,
01539                                bool activeCursor )
01540 {
01541     LuPixelPoint point = widgetPos();
01542     painter.setPen( QPen( context.getEmptyColor(),
01543                           context.layoutUnitToPixelX( context.getLineWidth()/2 ) ) );
01544     luPixel unitX = context.ptToLayoutUnitPixX( 1 );
01545     luPixel unitY = context.ptToLayoutUnitPixY( 1 );
01546     painter.drawRect( context.layoutUnitToPixelX( point.x()-unitX ),
01547                       context.layoutUnitToPixelY( point.y()-unitY ),
01548                       context.layoutUnitToPixelX( getWidth()+2*unitX ),
01549                       context.layoutUnitToPixelY( getHeight()+2*unitY ) );
01550 
01551     inherited::drawCursor( painter, context, cursor, smallCursor, activeCursor );
01552 }
01553 
01554 void NameSequence::moveWordLeft( FormulaCursor* cursor )
01555 {
01556     uint pos = cursor->getPos();
01557     if ( pos > 0 ) {
01558         cursor->setTo( this, 0 );
01559     }
01560     else {
01561         moveLeft( cursor, this );
01562     }
01563 }
01564 
01565 void NameSequence::moveWordRight( FormulaCursor* cursor )
01566 {
01567     int pos = cursor->getPos();
01568     if ( pos < countChildren() ) {
01569         cursor->setTo( this, countChildren() );
01570     }
01571     else {
01572         moveRight( cursor, this );
01573     }
01574 }
01575 
01576 
01577 KCommand* NameSequence::compactExpressionCmd( Container* container )
01578 {
01579     BasicElement* element = replaceElement( container->document()->getSymbolTable() );
01580     if ( element != 0 ) {
01581         getParent()->selectChild( container->activeCursor(), this );
01582 
01583         KFCReplace* command = new KFCReplace( i18n( "Add Element" ), container );
01584         command->addElement( element );
01585         return command;
01586     }
01587     return 0;
01588 }
01589 
01590 KCommand* NameSequence::buildCommand( Container* container, Request* request )
01591 {
01592     switch ( *request ) {
01593     case req_compactExpression:
01594         return compactExpressionCmd( container );
01595     case req_addSpace:
01596     case req_addIndex:
01597     case req_addMatrix:
01598     case req_addOneByTwoMatrix:
01599     case req_addSymbol:
01600     case req_addRoot:
01601     case req_addFraction:
01602     case req_addBracket:
01603     case req_addNameSequence:
01604         return 0;
01605     default:
01606         break;
01607     }
01608     return inherited::buildCommand( container, request );
01609 }
01610 
01611 
01612 KCommand* NameSequence::input( Container* container, QChar ch )
01613 {
01614     int unicode = ch.unicode();
01615     switch (unicode) {
01616     case '(':
01617     case '[':
01618     case '|':
01619     case '^':
01620     case '_':
01621     case '}':
01622     case ']':
01623     case ')':
01624     case '\\': {
01625 //         KCommand* compact = compactExpressionCmd( container );
01626 //         KCommand* cmd = static_cast<SequenceElement*>( getParent() )->input( container, ch );
01627 //         if ( compact != 0 ) {
01628 //             KMacroCommand* macro = new KMacroCommand( cmd->name() );
01629 //             macro->addCommand( compact );
01630 //             macro->addCommand( cmd );
01631 //             return macro;
01632 //         }
01633 //         else {
01634 //             return cmd;
01635 //         }
01636         break;
01637     }
01638     case '{':
01639     case ' ': {
01640         Request r( req_compactExpression );
01641         return buildCommand( container, &r );
01642     }
01643     default: {
01644         TextCharRequest r( ch );
01645         return buildCommand( container, &r );
01646     }
01647     }
01648     return 0;
01649 }
01650 
01651 void NameSequence::setElementType( ElementType* t )
01652 {
01653     inherited::setElementType( t );
01654     parse();
01655 }
01656 
01657 BasicElement* NameSequence::replaceElement( const SymbolTable& table )
01658 {
01659     QString name = buildName();
01660     QChar ch = table.unicode( name );
01661     if ( !ch.isNull() ) {
01662         return new TextElement( ch, true );
01663     }
01664     else {
01665         ch = table.unicode( i18n( name.latin1() ) );
01666         if ( !ch.isNull() ) {
01667             return new TextElement( ch, true );
01668         }
01669     }
01670 
01671     if ( name == "!" )    return new SpaceElement( NEGTHIN );
01672     if ( name == "," )    return new SpaceElement( THIN );
01673     if ( name == ">" )    return new SpaceElement( MEDIUM );
01674     if ( name == ";" )    return new SpaceElement( THICK );
01675     if ( name == "quad" ) return new SpaceElement( QUAD );
01676 
01677     if ( name == "frac" ) return new FractionElement();
01678     if ( name == "atop" ) {
01679         FractionElement* frac = new FractionElement();
01680         frac->showLine( false );
01681         return frac;
01682     }
01683     if ( name == "sqrt" ) return new RootElement();
01684 
01685     return 0;
01686 }
01687 
01688 BasicElement* NameSequence::createElement( QString type )
01689 {
01690     if      ( type == "TEXT" )         return new TextElement();
01691     return 0;
01692 }
01693 
01694 // void NameSequence::parse()
01695 // {
01696 //     // A name sequence is known as name and so are its children.
01697 //     // Caution: this is fake!
01698 //     for ( int i = 0; i < countChildren(); i++ ) {
01699 //         getChild( i )->setElementType( getElementType() );
01700 //     }
01701 // }
01702 
01703 QString NameSequence::buildName()
01704 {
01705     QString name;
01706     for ( int i = 0; i < countChildren(); i++ ) {
01707         name += getChild( i )->getCharacter();
01708     }
01709     return name;
01710 }
01711 
01712 bool NameSequence::isValidSelection( FormulaCursor* cursor )
01713 {
01714     SequenceElement* sequence = cursor->normal();
01715     if ( sequence == 0 ) {
01716         return false;
01717     }
01718     return sequence->onlyTextSelected( cursor );
01719 }
01720 
01721 void NameSequence::writeMathML( QDomDocument& doc, QDomNode parent,bool oasisFormat )
01722 {
01723     QDomElement de = doc.createElement( oasisFormat ? "math:mi" : "mi" );
01724     QString value;
01725     for ( int i = 0; i < countChildren(); ++i ) {
01726         // these are supposed to by TextElements
01727         value += getChild( i )->getCharacter();
01728     }
01729     de.appendChild( doc.createTextNode( value ) );
01730     parent.appendChild( de );
01731 }
01732 
01733 KFORMULA_NAMESPACE_END
KDE Home | KDE Accessibility Home | Description of Access Keys