00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
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
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
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
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
00256
00257
00258
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
00268
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
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
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
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 {
00375 painter.setRasterOp( Qt::XorROP );
00376 if ( cursor->isSelection() ) {
00377 const LuPixelRect& r = cursor->cursorSize;
00378 painter.fillRect( context.layoutUnitToPixelX( r.x() ),
00379 context.layoutUnitToPixelY( r.y() ),
00380 context.layoutUnitToPixelX( r.width() ),
00381 context.layoutUnitToPixelY( r.height() ),
00382 Qt::white );
00383 }
00384 else {
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 ( smallCursor ) {
00390 painter.drawLine( context.layoutUnitToPixelX( point.x() ),
00391 context.layoutUnitToPixelY( size.top() ),
00392 context.layoutUnitToPixelX( point.x() ),
00393 context.layoutUnitToPixelY( size.bottom() )-1 );
00394 }
00395 else {
00396 painter.drawLine( context.layoutUnitToPixelX( point.x() ),
00397 context.layoutUnitToPixelY( size.top() ),
00398 context.layoutUnitToPixelX( point.x() ),
00399 context.layoutUnitToPixelY( size.bottom() )-1 );
00400 painter.drawLine( context.layoutUnitToPixelX( size.left() ),
00401 context.layoutUnitToPixelY( size.bottom() )-1,
00402 context.layoutUnitToPixelX( size.right() )-1,
00403 context.layoutUnitToPixelY( size.bottom() )-1 );
00404 }
00405 }
00406
00407 painter.setRasterOp( Qt::CopyROP );
00408 }
00409
00410
00411 luPixel SequenceElement::getChildPosition( const ContextStyle& context, uint child )
00412 {
00413 if (child < children.count()) {
00414 return children.at(child)->getX();
00415 }
00416 else {
00417 if (children.count() > 0) {
00418 return children.at(child-1)->getX() + children.at(child-1)->getWidth();
00419 }
00420 else {
00421 return context.ptToLayoutUnitPixX( 2 );
00422 }
00423 }
00424 }
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00440 void SequenceElement::moveLeft(FormulaCursor* cursor, BasicElement* from)
00441 {
00442
00443 if (from == getParent()) {
00444 cursor->setTo(this, children.count());
00445 from->entered( this );
00446 }
00447
00448
00449 else if (from == this) {
00450 if (cursor->getPos() > 0) {
00451 if (cursor->isSelectionMode()) {
00452 cursor->setTo(this, cursor->getPos()-1);
00453
00454
00455 if (children.at(cursor->getPos())->isInvisible()) {
00456 moveLeft(cursor, this);
00457 }
00458 }
00459 else {
00460 children.at(cursor->getPos()-1)->moveLeft(cursor, this);
00461 }
00462 }
00463 else {
00464
00465 if (getParent() != 0) {
00466 getParent()->moveLeft(cursor, this);
00467 }
00468 else {
00469 formula()->moveOutLeft( cursor );
00470 }
00471 }
00472 }
00473
00474
00475
00476 else {
00477 int fromPos = children.find(from);
00478 cursor->setTo(this, fromPos);
00479 if (cursor->isSelectionMode()) {
00480 cursor->setMark(fromPos+1);
00481 }
00482
00483
00484 if (from->isInvisible()) {
00485 moveLeft(cursor, this);
00486 }
00487 formula()->tell( "" );
00488 }
00489 }
00490
00496 void SequenceElement::moveRight(FormulaCursor* cursor, BasicElement* from)
00497 {
00498
00499 if (from == getParent()) {
00500 cursor->setTo(this, 0);
00501 from->entered( this );
00502 }
00503
00504
00505 else if (from == this) {
00506 uint pos = cursor->getPos();
00507 if (pos < children.count()) {
00508 if (cursor->isSelectionMode()) {
00509 cursor->setTo(this, pos+1);
00510
00511
00512 if (children.at(pos)->isInvisible()) {
00513 moveRight(cursor, this);
00514 }
00515 }
00516 else {
00517 children.at(pos)->moveRight(cursor, this);
00518 }
00519 }
00520 else {
00521
00522 if (getParent() != 0) {
00523 getParent()->moveRight(cursor, this);
00524 }
00525 else {
00526 formula()->moveOutRight( cursor );
00527 }
00528 }
00529 }
00530
00531
00532
00533 else {
00534 int fromPos = children.find(from);
00535 cursor->setTo(this, fromPos+1);
00536 if (cursor->isSelectionMode()) {
00537 cursor->setMark(fromPos);
00538 }
00539
00540
00541 if (from->isInvisible()) {
00542 moveRight(cursor, this);
00543 }
00544 formula()->tell( "" );
00545 }
00546 }
00547
00548
00549 void SequenceElement::moveWordLeft(FormulaCursor* cursor)
00550 {
00551 uint pos = cursor->getPos();
00552 if (pos > 0) {
00553 ElementType* type = children.at(pos-1)->getElementType();
00554 if (type != 0) {
00555 cursor->setTo(this, type->start());
00556 }
00557 }
00558 else {
00559 moveLeft(cursor, this);
00560 }
00561 }
00562
00563
00564 void SequenceElement::moveWordRight(FormulaCursor* cursor)
00565 {
00566 uint pos = cursor->getPos();
00567 if (pos < children.count()) {
00568 ElementType* type = children.at(pos)->getElementType();
00569 if (type != 0) {
00570 cursor->setTo(this, type->end());
00571 }
00572 }
00573 else {
00574 moveRight(cursor, this);
00575 }
00576 }
00577
00578
00584 void SequenceElement::moveUp(FormulaCursor* cursor, BasicElement* from)
00585 {
00586 if (from == getParent()) {
00587 moveRight(cursor, this);
00588 }
00589 else {
00590 if (getParent() != 0) {
00591 getParent()->moveUp(cursor, this);
00592 }
00593 else {
00594 formula()->moveOutAbove( cursor );
00595 }
00596 }
00597 }
00598
00604 void SequenceElement::moveDown(FormulaCursor* cursor, BasicElement* from)
00605 {
00606 if (from == getParent()) {
00607 moveRight(cursor, this);
00608 }
00609 else {
00610 if (getParent() != 0) {
00611 getParent()->moveDown(cursor, this);
00612 }
00613 else {
00614 formula()->moveOutBelow( cursor );
00615 }
00616 }
00617 }
00618
00623 void SequenceElement::moveHome(FormulaCursor* cursor)
00624 {
00625 if (cursor->isSelectionMode()) {
00626 BasicElement* element = cursor->getElement();
00627 if (element != this) {
00628 while (element->getParent() != this) {
00629 element = element->getParent();
00630 }
00631 cursor->setMark(children.find(element)+1);
00632 }
00633 }
00634 cursor->setTo(this, 0);
00635 }
00636
00641 void SequenceElement::moveEnd(FormulaCursor* cursor)
00642 {
00643 if (cursor->isSelectionMode()) {
00644 BasicElement* element = cursor->getElement();
00645 if (element != this) {
00646 while (element->getParent() != this) {
00647 element = element->getParent();
00648 if (element == 0) {
00649 cursor->setMark(children.count());
00650 break;
00651 }
00652 }
00653 if (element != 0) {
00654 cursor->setMark(children.find(element));
00655 }
00656 }
00657 }
00658 cursor->setTo(this, children.count());
00659 }
00660
00665 void SequenceElement::goInside(FormulaCursor* cursor)
00666 {
00667 cursor->setSelection(false);
00668 cursor->setTo(this, 0);
00669 }
00670
00671
00672
00673
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00704 void SequenceElement::insert(FormulaCursor* cursor,
00705 QPtrList<BasicElement>& newChildren,
00706 Direction direction)
00707 {
00708 int pos = cursor->getPos();
00709 uint count = newChildren.count();
00710 for (uint i = 0; i < count; i++) {
00711 BasicElement* child = newChildren.take(0);
00712 child->setParent(this);
00713 children.insert(pos+i, child);
00714 }
00715 if (direction == beforeCursor) {
00716 cursor->setTo(this, pos+count, pos);
00717 }
00718 else {
00719 cursor->setTo(this, pos, pos+count);
00720 }
00721
00722 formula()->changed();
00723 parse();
00724 }
00725
00726
00733 void SequenceElement::remove(FormulaCursor* cursor,
00734 QPtrList<BasicElement>& removedChildren,
00735 Direction direction)
00736 {
00737 if (cursor->isSelection()) {
00738 int from = cursor->getSelectionStart();
00739 int to = cursor->getSelectionEnd();
00740 for (int i = from; i < to; i++) {
00741 removeChild(removedChildren, from);
00742 }
00743 cursor->setTo(this, from);
00744 cursor->setSelection(false);
00745 }
00746 else {
00747 if (direction == beforeCursor) {
00748 int pos = cursor->getPos() - 1;
00749 if (pos >= 0) {
00750 while (pos >= 0) {
00751 BasicElement* child = children.at(pos);
00752 formula()->elementRemoval(child);
00753 children.take(pos);
00754 removedChildren.prepend(child);
00755 if (!child->isInvisible()) {
00756 break;
00757 }
00758 pos--;
00759 }
00760 cursor->setTo(this, pos);
00761 formula()->changed();
00762 }
00763 }
00764 else {
00765 uint pos = cursor->getPos();
00766 if (pos < children.count()) {
00767 while (pos < children.count()) {
00768 BasicElement* child = children.at(pos);
00769 formula()->elementRemoval(child);
00770 children.take(pos);
00771 removedChildren.append(child);
00772 if (!child->isInvisible()) {
00773 break;
00774 }
00775 }
00776
00777
00778
00779 cursor->setTo(this, pos);
00780 formula()->changed();
00781 }
00782 }
00783 }
00784 parse();
00785 }
00786
00787
00791 void SequenceElement::removeChild(QPtrList<BasicElement>& removedChildren, int pos)
00792 {
00793 BasicElement* child = children.at(pos);
00794 formula()->elementRemoval(child);
00795 children.take(pos);
00796 removedChildren.append(child);
00797
00798 formula()->changed();
00799 }
00800
00801
00806 void SequenceElement::normalize(FormulaCursor* cursor, Direction)
00807 {
00808 cursor->setSelection(false);
00809 }
00810
00811
00816 BasicElement* SequenceElement::getChild( FormulaCursor* cursor, Direction direction )
00817 {
00818 if ( direction == beforeCursor ) {
00819 if ( cursor->getPos() > 0 ) {
00820 return children.at( cursor->getPos() - 1 );
00821 }
00822 }
00823 else {
00824 if ( cursor->getPos() < qRound( children.count() ) ) {
00825 return children.at( cursor->getPos() );
00826 }
00827 }
00828 return 0;
00829 }
00830
00831
00836 void SequenceElement::selectChild(FormulaCursor* cursor, BasicElement* child)
00837 {
00838 int pos = children.find(child);
00839 if (pos > -1) {
00840 cursor->setTo(this, pos+1, pos);
00841 }
00842 }
00843
00844 void SequenceElement::childWillVanish(FormulaCursor* cursor, BasicElement* child)
00845 {
00846 int childPos = children.find(child);
00847 if (childPos > -1) {
00848 int pos = cursor->getPos();
00849 if (pos > childPos) {
00850 pos--;
00851 }
00852 int mark = cursor->getMark();
00853 if (mark > childPos) {
00854 mark--;
00855 }
00856 cursor->setTo(this, pos, mark);
00857 }
00858 }
00859
00860
00864 void SequenceElement::selectAllChildren(FormulaCursor* cursor)
00865 {
00866 cursor->setTo(this, children.count(), 0);
00867 }
00868
00869 bool SequenceElement::onlyTextSelected( FormulaCursor* cursor )
00870 {
00871 if ( cursor->isSelection() ) {
00872 uint from = QMIN( cursor->getPos(), cursor->getMark() );
00873 uint to = QMAX( cursor->getPos(), cursor->getMark() );
00874 for ( uint i = from; i < to; i++ ) {
00875 BasicElement* element = getChild( i );
00876 if ( element->getCharacter() == QChar::null ) {
00877 return false;
00878 }
00879 }
00880 }
00881 return true;
00882 }
00883
00884
00885 KCommand* SequenceElement::buildCommand( Container* container, Request* request )
00886 {
00887 FormulaCursor* cursor = container->activeCursor();
00888 if ( cursor->isReadOnly() ) {
00889 formula()->tell( i18n( "write protection" ) );
00890 return 0;
00891 }
00892
00893 switch ( *request ) {
00894 case req_addText: {
00895 KFCReplace* command = new KFCReplace( i18n("Add Text"), container );
00896 TextRequest* tr = static_cast<TextRequest*>( request );
00897 for ( uint i = 0; i < tr->text().length(); i++ ) {
00898 command->addElement( creationStrategy->createTextElement( tr->text()[i] ) );
00899 }
00900 return command;
00901 }
00902 case req_addTextChar: {
00903 KFCReplace* command = new KFCReplace( i18n("Add Text"), container );
00904 TextCharRequest* tr = static_cast<TextCharRequest*>( request );
00905 TextElement* element = creationStrategy->createTextElement( tr->ch(), tr->isSymbol() );
00906 command->addElement( element );
00907 return command;
00908 }
00909 case req_addEmptyBox: {
00910 EmptyElement* element = creationStrategy->createEmptyElement();
00911 if ( element != 0 ) {
00912 KFCReplace* command = new KFCReplace( i18n("Add Empty Box"), container );
00913 command->addElement( element );
00914 return command;
00915 }
00916 break;
00917 }
00918 case req_addNameSequence:
00919 if ( onlyTextSelected( container->activeCursor() ) ) {
00920 NameSequence* nameSequence = creationStrategy->createNameSequence();
00921 if ( nameSequence != 0 ) {
00922 KFCAddReplacing* command = new KFCAddReplacing( i18n( "Add Name" ), container );
00923 command->setElement( nameSequence );
00924 return command;
00925 }
00926 }
00927 break;
00928 case req_addBracket: {
00929 BracketRequest* br = static_cast<BracketRequest*>( request );
00930 BracketElement* bracketElement =
00931 creationStrategy->createBracketElement( br->left(), br->right() );
00932 if ( bracketElement != 0 ) {
00933 KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Bracket"), container);
00934 command->setElement( bracketElement );
00935 return command;
00936 }
00937 break;
00938 }
00939 case req_addOverline: {
00940 OverlineElement* overline = creationStrategy->createOverlineElement();
00941 if ( overline != 0 ) {
00942 KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Overline"), container);
00943 command->setElement( overline );
00944 return command;
00945 }
00946 break;
00947 }
00948 case req_addUnderline: {
00949 UnderlineElement* underline = creationStrategy->createUnderlineElement();
00950 if ( underline != 0 ) {
00951 KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Underline"), container);
00952 command->setElement( underline );
00953 return command;
00954 }
00955 break;
00956 }
00957 case req_addMultiline: {
00958 MultilineElement* multiline = creationStrategy->createMultilineElement();
00959 if ( multiline != 0 ) {
00960 KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Multiline"), container);
00961 command->setElement( multiline );
00962 return command;
00963 }
00964 break;
00965 }
00966 case req_addSpace: {
00967 SpaceRequest* sr = static_cast<SpaceRequest*>( request );
00968 SpaceElement* element = creationStrategy->createSpaceElement( sr->space() );
00969 if ( element != 0 ) {
00970 KFCReplace* command = new KFCReplace( i18n("Add Space"), container );
00971 command->addElement( element );
00972 return command;
00973 }
00974 break;
00975 }
00976 case req_addFraction: {
00977 FractionElement* fraction = creationStrategy->createFractionElement();
00978 if ( fraction != 0 ) {
00979 KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Fraction"), container);
00980 command->setElement( fraction );
00981 return command;
00982 }
00983 break;
00984 }
00985 case req_addRoot: {
00986 RootElement* root = creationStrategy->createRootElement();
00987 if ( root != 0 ) {
00988 KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Root"), container);
00989 command->setElement( root );
00990 return command;
00991 }
00992 break;
00993 }
00994 case req_addSymbol: {
00995 SymbolRequest* sr = static_cast<SymbolRequest*>( request );
00996 SymbolElement* symbol = creationStrategy->createSymbolElement( sr->type() );
00997 if ( symbol != 0 ) {
00998 KFCAddReplacing* command = new KFCAddReplacing( i18n( "Add Symbol" ), container );
00999 command->setElement( symbol );
01000 return command;
01001 }
01002 break;
01003 }
01004 case req_addOneByTwoMatrix: {
01005 FractionElement* element = creationStrategy->createFractionElement();
01006 if ( element != 0 ) {
01007 KFCAddReplacing* command = new KFCAddReplacing( i18n("Add 1x2 Matrix"), container );
01008 element->showLine(false);
01009 command->setElement(element);
01010 return command;
01011 }
01012 }
01013 case req_addMatrix: {
01014 MatrixRequest* mr = static_cast<MatrixRequest*>( request );
01015 uint rows = mr->rows(), cols = mr->columns();
01016 if ( ( rows == 0 ) || ( cols == 0 ) ) {
01017 MatrixDialog* dialog = new MatrixDialog( 0 );
01018 if ( dialog->exec() ) {
01019 rows = dialog->h;
01020 cols = dialog->w;
01021 }
01022 delete dialog;
01023 }
01024
01025 if ( ( rows != 0 ) && ( cols != 0 ) ) {
01026 KFCAddReplacing* command = new KFCAddReplacing( i18n( "Add Matrix" ), container );
01027 command->setElement( creationStrategy->createMatrixElement( rows, cols ) );
01028 return command;
01029 }
01030 else
01031 return 0L;
01032 }
01033 case req_addIndex: {
01034 if ( cursor->getPos() > 0 && !cursor->isSelection() ) {
01035 IndexElement* element =
01036 dynamic_cast<IndexElement*>( children.at( cursor->getPos()-1 ) );
01037 if ( element != 0 ) {
01038 element->getMainChild()->goInside( cursor );
01039 return element->getMainChild()->buildCommand( container, request );
01040 }
01041 }
01042 IndexElement* element = creationStrategy->createIndexElement();
01043 if ( element != 0 ) {
01044 if ( !cursor->isSelection() ) {
01045 cursor->moveLeft( SelectMovement | WordMovement );
01046 }
01047 IndexRequest* ir = static_cast<IndexRequest*>( request );
01048 KFCAddIndex* command = new KFCAddIndex( container, element,
01049 element->getIndex( ir->index() ) );
01050 return command;
01051 }
01052 break;
01053 }
01054 case req_removeEnclosing: {
01055 if ( !cursor->isSelection() ) {
01056 DirectedRemove* dr = static_cast<DirectedRemove*>( request );
01057 KFCRemoveEnclosing* command = new KFCRemoveEnclosing( container, dr->direction() );
01058 return command;
01059 }
01060 }
01061 case req_remove: {
01062 SequenceElement* sequence = cursor->normal();
01063 if ( sequence &&
01064 ( sequence == sequence->formula() ) &&
01065 ( sequence->countChildren() == 0 ) ) {
01066 sequence->formula()->removeFormula( cursor );
01067 return 0;
01068 }
01069 else {
01070 DirectedRemove* dr = static_cast<DirectedRemove*>( request );
01071
01072
01073 if ( !cursor->isSelection() ) {
01074 if ( countChildren() > 0 ) {
01075 if ( ( cursor->getPos() == 0 ) && ( dr->direction() == beforeCursor ) ) {
01076 return 0;
01077 }
01078 if ( ( cursor->getPos() == countChildren() ) && ( dr->direction() == afterCursor ) ) {
01079 return 0;
01080 }
01081 }
01082 else if ( getParent() == 0 ) {
01083 return 0;
01084 }
01085 }
01086
01087 KFCRemove* command = new KFCRemove( container, dr->direction() );
01088 return command;
01089 }
01090 }
01091 case req_compactExpression: {
01092 cursor->moveEnd();
01093 cursor->moveRight();
01094 formula()->cursorHasMoved( cursor );
01095 break;
01096 }
01097 case req_makeGreek: {
01098 TextElement* element = cursor->getActiveTextElement();
01099 if ((element != 0) && !element->isSymbol()) {
01100 cursor->selectActiveElement();
01101 const SymbolTable& table = container->document()->getSymbolTable();
01102 if (table.greekLetters().find(element->getCharacter()) != -1) {
01103 KFCReplace* command = new KFCReplace( i18n( "Change Char to Symbol" ), container );
01104 TextElement* symbol = creationStrategy->createTextElement( table.unicodeFromSymbolFont( element->getCharacter() ), true );
01105 command->addElement( symbol );
01106 return command;
01107 }
01108 cursor->setSelection( false );
01109 }
01110 break;
01111 }
01112 case req_paste:
01113 case req_copy:
01114 case req_cut:
01115 break;
01116 case req_formatBold:
01117 case req_formatItalic: {
01118 if ( cursor->isSelection() ) {
01119 CharStyleRequest* csr = static_cast<CharStyleRequest*>( request );
01120 CharStyle cs = normalChar;
01121 if ( csr->bold() ) cs = static_cast<CharStyle>( cs | boldChar );
01122 if ( csr->italic() ) cs = static_cast<CharStyle>( cs | italicChar );
01123 CharStyleCommand* cmd = new CharStyleCommand( cs, i18n( "Change Char Style" ), container );
01124 int end = cursor->getSelectionEnd();
01125 for ( int i = cursor->getSelectionStart(); i<end; ++i ) {
01126 cmd->addElement( children.at( i ) );
01127 }
01128 return cmd;
01129 }
01130 break;
01131 }
01132 case req_formatFamily: {
01133 if ( cursor->isSelection() ) {
01134 CharFamilyRequest* cfr = static_cast<CharFamilyRequest*>( request );
01135 CharFamily cf = cfr->charFamily();
01136 CharFamilyCommand* cmd = new CharFamilyCommand( cf, i18n( "Change Char Family" ), container );
01137 int end = cursor->getSelectionEnd();
01138 for ( int i = cursor->getSelectionStart(); i<end; ++i ) {
01139 cmd->addElement( children.at( i ) );
01140 }
01141 return cmd;
01142 }
01143 break;
01144 }
01145 default:
01146 break;
01147 }
01148 return 0;
01149 }
01150
01151
01152 KCommand* SequenceElement::input( Container* container, QKeyEvent* event )
01153 {
01154 QChar ch = event->text().at( 0 );
01155 if ( ch.isPrint() ) {
01156 return input( container, ch );
01157 }
01158 else {
01159 int action = event->key();
01160 int state = event->state();
01161 MoveFlag flag = movementFlag(state);
01162
01163 switch ( action ) {
01164 case Qt::Key_BackSpace: {
01165 DirectedRemove r( req_remove, beforeCursor );
01166 return buildCommand( container, &r );
01167 }
01168 case Qt::Key_Delete: {
01169 DirectedRemove r( req_remove, afterCursor );
01170 return buildCommand( container, &r );
01171 }
01172 case Qt::Key_Left: {
01173 FormulaCursor* cursor = container->activeCursor();
01174 cursor->moveLeft( flag );
01175 formula()->cursorHasMoved( cursor );
01176 break;
01177 }
01178 case Qt::Key_Right: {
01179 FormulaCursor* cursor = container->activeCursor();
01180 cursor->moveRight( flag );
01181 formula()->cursorHasMoved( cursor );
01182 break;
01183 }
01184 case Qt::Key_Up: {
01185 FormulaCursor* cursor = container->activeCursor();
01186 cursor->moveUp( flag );
01187 formula()->cursorHasMoved( cursor );
01188 break;
01189 }
01190 case Qt::Key_Down: {
01191 FormulaCursor* cursor = container->activeCursor();
01192 cursor->moveDown( flag );
01193 formula()->cursorHasMoved( cursor );
01194 break;
01195 }
01196 case Qt::Key_Home: {
01197 FormulaCursor* cursor = container->activeCursor();
01198 cursor->moveHome( flag );
01199 formula()->cursorHasMoved( cursor );
01200 break;
01201 }
01202 case Qt::Key_End: {
01203 FormulaCursor* cursor = container->activeCursor();
01204 cursor->moveEnd( flag );
01205 formula()->cursorHasMoved( cursor );
01206 break;
01207 }
01208 default:
01209 if ( state & Qt::ControlButton ) {
01210 switch ( event->key() ) {
01211 case Qt::Key_AsciiCircum: {
01212 IndexRequest r( upperLeftPos );
01213 return buildCommand( container, &r );
01214 }
01215 case Qt::Key_Underscore: {
01216 IndexRequest r( lowerLeftPos );
01217 return buildCommand( container, &r );
01218 }
01219 default:
01220 break;
01221 }
01222 }
01223 }
01224 }
01225 return 0;
01226 }
01227
01228
01229 KCommand* SequenceElement::input( Container* container, QChar ch )
01230 {
01231 int unicode = ch.unicode();
01232 switch (unicode) {
01233 case '(': {
01234 BracketRequest r( container->document()->leftBracketChar(),
01235 container->document()->rightBracketChar() );
01236 singlePipe = true;
01237 return buildCommand( container, &r );
01238 }
01239 case '[': {
01240 BracketRequest r( LeftSquareBracket, RightSquareBracket );
01241 singlePipe = true;
01242 return buildCommand( container, &r );
01243 }
01244 case '{': {
01245 BracketRequest r( LeftCurlyBracket, RightCurlyBracket );
01246 singlePipe = true;
01247 return buildCommand( container, &r );
01248 }
01249 case '|': {
01250 if (!singlePipe) {
01251
01252 DirectedRemove rDelete( req_remove, beforeCursor );
01253 KCommand* command = buildCommand( container, &rDelete );
01254 command->execute();
01255
01256 BracketRequest rBracket( LeftLineBracket , RightLineBracket);
01257 singlePipe = true;
01258 return buildCommand( container, &rBracket );
01259 }
01260 else {
01261 TextCharRequest r(ch);
01262
01263
01264 singlePipe = false;
01265
01266 return buildCommand( container, &r );
01267 }
01268 }
01269 case '^': {
01270 IndexRequest r( upperRightPos );
01271 singlePipe = true;
01272 return buildCommand( container, &r );
01273 }
01274 case '_': {
01275 IndexRequest r( lowerRightPos );
01276 singlePipe = true;
01277 return buildCommand( container, &r );
01278 }
01279 case ' ': {
01280 Request r( req_compactExpression );
01281 singlePipe = true;
01282 return buildCommand( container, &r );
01283 }
01284 case '}': {
01285 Request r( req_addEmptyBox );
01286 singlePipe = true;
01287 return buildCommand( container, &r );
01288 }
01289 case ']':
01290 case ')':
01291 singlePipe = true;
01292 break;
01293 case '\\': {
01294 Request r( req_addNameSequence );
01295 singlePipe = true;
01296 return buildCommand( container, &r );
01297 }
01298 default: {
01299 TextCharRequest r( ch );
01300 singlePipe = true;
01301 return buildCommand( container, &r );
01302 }
01303 }
01304 return 0;
01305 }
01306
01310 void SequenceElement::getChildrenDom( QDomDocument& doc, QDomElement elem,
01311 uint from, uint to)
01312 {
01313 for (uint i = from; i < to; i++) {
01314 QDomElement tmpEleDom=children.at(i)->getElementDom(doc);
01315 elem.appendChild(tmpEleDom);
01316 }
01317 }
01318
01319
01325 bool SequenceElement::buildChildrenFromDom(QPtrList<BasicElement>& list, QDomNode n)
01326 {
01327 while (!n.isNull()) {
01328 if (n.isElement()) {
01329 QDomElement e = n.toElement();
01330 BasicElement* child = 0;
01331 QString tag = e.tagName().upper();
01332
01333 child = createElement(tag);
01334 if (child != 0) {
01335 child->setParent(this);
01336 if (child->buildFromDom(e)) {
01337 list.append(child);
01338 }
01339 else {
01340 delete child;
01341 return false;
01342 }
01343 }
01344 else {
01345 return false;
01346 }
01347 }
01348 n = n.nextSibling();
01349 }
01350 parse();
01351 return true;
01352 }
01353
01354
01355 BasicElement* SequenceElement::createElement( QString type )
01356 {
01357 return creationStrategy->createElement( type );
01358 }
01359
01363 void SequenceElement::writeDom(QDomElement element)
01364 {
01365 BasicElement::writeDom(element);
01366
01367 uint count = children.count();
01368 QDomDocument doc = element.ownerDocument();
01369 getChildrenDom(doc, element, 0, count);
01370 }
01371
01376 bool SequenceElement::readAttributesFromDom(QDomElement element)
01377 {
01378 if (!BasicElement::readAttributesFromDom(element)) {
01379 return false;
01380 }
01381 return true;
01382 }
01383
01389 bool SequenceElement::readContentFromDom(QDomNode& node)
01390 {
01391 if (!BasicElement::readContentFromDom(node)) {
01392 return false;
01393 }
01394
01395 return buildChildrenFromDom(children, node);
01396 }
01397
01398
01399 void SequenceElement::parse()
01400 {
01401 delete parseTree;
01402
01403 textSequence = true;
01404 for (BasicElement* element = children.first();
01405 element != 0;
01406 element = children.next()) {
01407
01408
01409
01410 element->setElementType(0);
01411
01412 if (element->getCharacter().isNull()) {
01413 textSequence = false;
01414 }
01415 }
01416
01417 const SymbolTable& symbols = formula()->getSymbolTable();
01418 SequenceParser parser(symbols);
01419 parseTree = parser.parse(children);
01420
01421
01422
01423 BasicElement* p = getParent();
01424 if ( p != 0 ) {
01425 SequenceElement* seq = dynamic_cast<SequenceElement*>( p->getParent() );
01426 if ( seq != 0 ) {
01427 seq->parse();
01428 }
01429 }
01430
01431
01432 }
01433
01434
01435 bool SequenceElement::isFirstOfToken( BasicElement* child )
01436 {
01437 return ( child->getElementType() != 0 ) && isChildNumber( child->getElementType()->start(), child );
01438 }
01439
01440
01441 QString SequenceElement::toLatex()
01442 {
01443 QString content;
01444 uint count = children.count();
01445 for ( uint i = 0; i < count; i++ ) {
01446 BasicElement* child = children.at( i );
01447
01448
01449
01450 content += child->toLatex();
01451 }
01452 return content;
01453 }
01454
01455
01456 QString SequenceElement::formulaString()
01457 {
01458 QString content;
01459 uint count = children.count();
01460 for ( uint i = 0; i < count; i++ ) {
01461 BasicElement* child = children.at( i );
01462
01463
01464
01465 content += child->formulaString();
01466 }
01467 return content;
01468 }
01469
01470
01471 void SequenceElement::writeMathML( QDomDocument& doc, QDomNode parent, bool oasisFormat )
01472 {
01473 QDomElement de = doc.createElement( oasisFormat ? "math:mrow" : "mrow" );
01474
01475 BasicElement* last = children.last();
01476 if ( last != 0 ) {
01477
01478 QPtrList<ElementType> tokenList;
01479 ElementType* token = last->getElementType();
01480 while ( token != 0 ) {
01481
01482 tokenList.prepend( token );
01483 token = token->getPrev();
01484 }
01485
01486 if ( tokenList.count() == 1 ) {
01487 tokenList.first()->saveMathML( this, doc, parent.toElement(), oasisFormat );
01488 return;
01489 }
01490
01491 for ( uint i = 0; i < tokenList.count(); ++i ) {
01492 tokenList.at( i )->saveMathML( this, doc, de, oasisFormat );
01493 }
01494 }
01495 parent.appendChild( de );
01496 }
01497
01498
01499 int SequenceElement::childPos( const BasicElement* child ) const
01500 {
01501 QPtrListIterator<BasicElement> it( children );
01502 uint count = it.count();
01503 for ( uint i=0; i<count; ++i, ++it ) {
01504 if ( it.current() == child ) {
01505 return i;
01506 }
01507 }
01508 return -1;
01509 }
01510
01511
01512 NameSequence::NameSequence( BasicElement* parent )
01513 : SequenceElement( parent )
01514 {
01515 }
01516
01517
01518 bool NameSequence::accept( ElementVisitor* visitor )
01519 {
01520 return visitor->visit( this );
01521 }
01522
01523
01524 void NameSequence::calcCursorSize( const ContextStyle& context,
01525 FormulaCursor* cursor, bool smallCursor )
01526 {
01527 inherited::calcCursorSize( context, cursor, smallCursor );
01528 LuPixelPoint point = widgetPos();
01529 luPixel unitX = context.ptToLayoutUnitPixX( 1 );
01530 luPixel unitY = context.ptToLayoutUnitPixY( 1 );
01531 cursor->addCursorSize( LuPixelRect( point.x()-unitX, point.y()-unitY,
01532 getWidth()+2*unitX, getHeight()+2*unitY ) );
01533 }
01534
01535 void NameSequence::drawCursor( QPainter& painter, const ContextStyle& context,
01536 FormulaCursor* cursor, bool smallCursor )
01537 {
01538 LuPixelPoint point = widgetPos();
01539 painter.setPen( QPen( context.getEmptyColor(),
01540 context.layoutUnitToPixelX( context.getLineWidth()/2 ) ) );
01541 luPixel unitX = context.ptToLayoutUnitPixX( 1 );
01542 luPixel unitY = context.ptToLayoutUnitPixY( 1 );
01543 painter.drawRect( context.layoutUnitToPixelX( point.x()-unitX ),
01544 context.layoutUnitToPixelY( point.y()-unitY ),
01545 context.layoutUnitToPixelX( getWidth()+2*unitX ),
01546 context.layoutUnitToPixelY( getHeight()+2*unitY ) );
01547
01548 inherited::drawCursor( painter, context, cursor, smallCursor );
01549 }
01550
01551 void NameSequence::moveWordLeft( FormulaCursor* cursor )
01552 {
01553 uint pos = cursor->getPos();
01554 if ( pos > 0 ) {
01555 cursor->setTo( this, 0 );
01556 }
01557 else {
01558 moveLeft( cursor, this );
01559 }
01560 }
01561
01562 void NameSequence::moveWordRight( FormulaCursor* cursor )
01563 {
01564 int pos = cursor->getPos();
01565 if ( pos < countChildren() ) {
01566 cursor->setTo( this, countChildren() );
01567 }
01568 else {
01569 moveRight( cursor, this );
01570 }
01571 }
01572
01573
01574 KCommand* NameSequence::compactExpressionCmd( Container* container )
01575 {
01576 BasicElement* element = replaceElement( container->document()->getSymbolTable() );
01577 if ( element != 0 ) {
01578 getParent()->selectChild( container->activeCursor(), this );
01579
01580 KFCReplace* command = new KFCReplace( i18n( "Add Element" ), container );
01581 command->addElement( element );
01582 return command;
01583 }
01584 return 0;
01585 }
01586
01587 KCommand* NameSequence::buildCommand( Container* container, Request* request )
01588 {
01589 switch ( *request ) {
01590 case req_compactExpression:
01591 return compactExpressionCmd( container );
01592 case req_addSpace:
01593 case req_addIndex:
01594 case req_addMatrix:
01595 case req_addOneByTwoMatrix:
01596 case req_addSymbol:
01597 case req_addRoot:
01598 case req_addFraction:
01599 case req_addBracket:
01600 case req_addNameSequence:
01601 return 0;
01602 default:
01603 break;
01604 }
01605 return inherited::buildCommand( container, request );
01606 }
01607
01608
01609 KCommand* NameSequence::input( Container* container, QChar ch )
01610 {
01611 int unicode = ch.unicode();
01612 switch (unicode) {
01613 case '(':
01614 case '[':
01615 case '|':
01616 case '^':
01617 case '_':
01618 case '}':
01619 case ']':
01620 case ')':
01621 case '\\': {
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633 break;
01634 }
01635 case '{':
01636 case ' ': {
01637 Request r( req_compactExpression );
01638 return buildCommand( container, &r );
01639 }
01640 default: {
01641 TextCharRequest r( ch );
01642 return buildCommand( container, &r );
01643 }
01644 }
01645 return 0;
01646 }
01647
01648 void NameSequence::setElementType( ElementType* t )
01649 {
01650 inherited::setElementType( t );
01651 parse();
01652 }
01653
01654 BasicElement* NameSequence::replaceElement( const SymbolTable& table )
01655 {
01656 QString name = buildName();
01657 QChar ch = table.unicode( name );
01658 if ( !ch.isNull() ) {
01659 return new TextElement( ch, true );
01660 }
01661 else {
01662 ch = table.unicode( i18n( name.latin1() ) );
01663 if ( !ch.isNull() ) {
01664 return new TextElement( ch, true );
01665 }
01666 }
01667
01668 if ( name == "!" ) return new SpaceElement( NEGTHIN );
01669 if ( name == "," ) return new SpaceElement( THIN );
01670 if ( name == ">" ) return new SpaceElement( MEDIUM );
01671 if ( name == ";" ) return new SpaceElement( THICK );
01672 if ( name == "quad" ) return new SpaceElement( QUAD );
01673
01674 if ( name == "frac" ) return new FractionElement();
01675 if ( name == "atop" ) {
01676 FractionElement* frac = new FractionElement();
01677 frac->showLine( false );
01678 return frac;
01679 }
01680 if ( name == "sqrt" ) return new RootElement();
01681
01682 return 0;
01683 }
01684
01685 BasicElement* NameSequence::createElement( QString type )
01686 {
01687 if ( type == "TEXT" ) return new TextElement();
01688 return 0;
01689 }
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700 QString NameSequence::buildName()
01701 {
01702 QString name;
01703 for ( int i = 0; i < countChildren(); i++ ) {
01704 name += getChild( i )->getCharacter();
01705 }
01706 return name;
01707 }
01708
01709 bool NameSequence::isValidSelection( FormulaCursor* cursor )
01710 {
01711 SequenceElement* sequence = cursor->normal();
01712 if ( sequence == 0 ) {
01713 return false;
01714 }
01715 return sequence->onlyTextSelected( cursor );
01716 }
01717
01718 void NameSequence::writeMathML( QDomDocument& doc, QDomNode parent,bool oasisFormat )
01719 {
01720 QDomElement de = doc.createElement( oasisFormat ? "math:mi" : "mi" );
01721 QString value;
01722 for ( int i = 0; i < countChildren(); ++i ) {
01723
01724 value += getChild( i )->getCharacter();
01725 }
01726 de.appendChild( doc.createTextNode( value ) );
01727 parent.appendChild( de );
01728 }
01729
01730 KFORMULA_NAMESPACE_END