00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <qpainter.h>
00022
00023 #include <kdebug.h>
00024
00025 #include "elementvisitor.h"
00026 #include "formulacursor.h"
00027 #include "formulaelement.h"
00028 #include "kformulacommand.h"
00029 #include "sequenceelement.h"
00030 #include "symbolelement.h"
00031
00032 KFORMULA_NAMESPACE_BEGIN
00033
00034
00035 class SymbolSequenceElement : public SequenceElement {
00036 typedef SequenceElement inherited;
00037 public:
00038
00039 SymbolSequenceElement( BasicElement* parent = 0 ) : SequenceElement( parent ) {}
00040
00049 virtual KCommand* buildCommand( Container*, Request* );
00050 };
00051
00052
00053 KCommand* SymbolSequenceElement::buildCommand( Container* container, Request* request )
00054 {
00055 FormulaCursor* cursor = container->activeCursor();
00056 if ( cursor->isReadOnly() ) {
00057 return 0;
00058 }
00059
00060 switch ( *request ) {
00061 case req_addIndex: {
00062 FormulaCursor* cursor = container->activeCursor();
00063 if ( cursor->isSelection() ||
00064 ( cursor->getPos() > 0 && cursor->getPos() < countChildren() ) ) {
00065 break;
00066 }
00067 IndexRequest* ir = static_cast<IndexRequest*>( request );
00068 if ( ( ir->index() == upperMiddlePos ) || ( ir->index() == lowerMiddlePos ) ) {
00069 SymbolElement* element = static_cast<SymbolElement*>( getParent() );
00070 ElementIndexPtr index = element->getIndex( ir->index() );
00071 if ( !index->hasIndex() ) {
00072 KFCAddGenericIndex* command = new KFCAddGenericIndex( container, index );
00073 return command;
00074 }
00075 else {
00076 index->moveToIndex( cursor, afterCursor );
00077 cursor->setSelection( false );
00078 formula()->cursorHasMoved( cursor );
00079 return 0;
00080 }
00081 }
00082 }
00083 default:
00084 break;
00085 }
00086 return inherited::buildCommand( container, request );
00087 }
00088
00089
00090 SymbolElement::SymbolElement(SymbolType type, BasicElement* parent)
00091 : BasicElement(parent), symbol( 0 ), symbolType( type )
00092 {
00093 content = new SymbolSequenceElement( this );
00094 upper = 0;
00095 lower = 0;
00096 }
00097
00098 SymbolElement::~SymbolElement()
00099 {
00100 delete lower;
00101 delete upper;
00102 delete content;
00103 delete symbol;
00104 }
00105
00106
00107 SymbolElement::SymbolElement( const SymbolElement& other )
00108 : BasicElement( other ), symbol( 0 ), symbolType( other.symbolType )
00109 {
00110 content = new SymbolSequenceElement( *dynamic_cast<SymbolSequenceElement*>( other.content ) );
00111 content->setParent( this );
00112
00113 if ( other.upper ) {
00114 upper = new SequenceElement( *( other.upper ) );
00115 upper->setParent( this );
00116 }
00117 else {
00118 upper = 0;
00119 }
00120 if ( other.lower ) {
00121 lower = new SequenceElement( *( other.lower ) );
00122 lower->setParent( this );
00123 }
00124 else {
00125 lower = 0;
00126 }
00127 }
00128
00129
00130 bool SymbolElement::accept( ElementVisitor* visitor )
00131 {
00132 return visitor->visit( this );
00133 }
00134
00135
00136 BasicElement* SymbolElement::goToPos( FormulaCursor* cursor, bool& handled,
00137 const LuPixelPoint& point, const LuPixelPoint& parentOrigin )
00138 {
00139 BasicElement* e = BasicElement::goToPos(cursor, handled, point, parentOrigin);
00140 if (e != 0) {
00141 LuPixelPoint myPos(parentOrigin.x() + getX(),
00142 parentOrigin.y() + getY());
00143
00144 e = content->goToPos(cursor, handled, point, myPos);
00145 if (e != 0) {
00146 return e;
00147 }
00148 if (hasLower()) {
00149 e = lower->goToPos(cursor, handled, point, myPos);
00150 if (e != 0) {
00151 return e;
00152 }
00153 }
00154 if (hasUpper()) {
00155 e = upper->goToPos(cursor, handled, point, myPos);
00156 if (e != 0) {
00157 return e;
00158 }
00159 }
00160
00161
00162 luPixel dx = point.x() - myPos.x();
00163 luPixel dy = point.y() - myPos.y();
00164 if (dy < symbol->getY()) {
00165 if (hasUpper() && (dx > upper->getX())) {
00166 upper->moveLeft(cursor, this);
00167 handled = true;
00168 return upper;
00169 }
00170 }
00171 else if (dy > symbol->getY()+symbol->getHeight()) {
00172 if (hasLower() && (dx > lower->getX())) {
00173 lower->moveLeft(cursor, this);
00174 handled = true;
00175 return lower;
00176 }
00177 }
00178
00179
00180 if ( ( dx < symbol->getX()+symbol->getWidth() ) &&
00181 ( dx > symbol->getX()+symbol->getWidth()/2 ) ) {
00182 content->moveRight( cursor, this );
00183 handled = true;
00184 return content;
00185 }
00186
00187 return this;
00188 }
00189 return 0;
00190 }
00191
00192
00197 void SymbolElement::calcSizes(const ContextStyle& style, ContextStyle::TextStyle tstyle, ContextStyle::IndexStyle istyle )
00198 {
00199 luPt mySize = style.getAdjustedSize( tstyle );
00200 luPixel distX = style.ptToPixelX( style.getThinSpace( tstyle ) );
00201 luPixel distY = style.ptToPixelY( style.getThinSpace( tstyle ) );
00202
00203
00204 delete symbol;
00205 symbol = style.fontStyle().createArtwork( symbolType );
00206
00207
00208 symbol->calcSizes(style, tstyle, mySize);
00209 content->calcSizes(style, tstyle, istyle);
00210
00211
00212
00213 luPixel upperWidth = 0;
00214 luPixel upperHeight = 0;
00215 if (hasUpper()) {
00216 upper->calcSizes(style, style.convertTextStyleIndex( tstyle ),
00217 style.convertIndexStyleUpper( istyle ) );
00218 upperWidth = upper->getWidth();
00219 upperHeight = upper->getHeight() + distY;
00220 }
00221
00222 luPixel lowerWidth = 0;
00223 luPixel lowerHeight = 0;
00224 if (hasLower()) {
00225 lower->calcSizes(style, style.convertTextStyleIndex( tstyle ),
00226 style.convertIndexStyleLower( istyle ) );
00227 lowerWidth = lower->getWidth();
00228 lowerHeight = lower->getHeight() + distY;
00229 }
00230
00231
00232 luPixel xOffset = QMAX(symbol->getWidth(), QMAX(upperWidth, lowerWidth));
00233 if (style.getCenterSymbol()) {
00234 symbol->setX((xOffset - symbol->getWidth()) / 2);
00235 }
00236 else {
00237 symbol->setX(xOffset - symbol->getWidth());
00238 }
00239
00240 content->setX(xOffset +
00241 static_cast<luPixel>( symbol->slant()*symbol->getHeight()/2 ) +
00242 distX/2);
00243
00244 setWidth(QMAX(content->getX() + content->getWidth(),
00245 QMAX(upperWidth, lowerWidth)));
00246
00247
00248
00249 luPixel toMidline = QMAX(content->axis( style, tstyle ),
00250 upperHeight + symbol->getHeight()/2);
00251
00252 luPixel fromMidline = QMAX(content->getHeight() - content->axis( style, tstyle ),
00253 lowerHeight + symbol->getHeight()/2);
00254 setHeight(toMidline + fromMidline);
00255
00256
00257 symbol->setY(toMidline - symbol->getHeight()/2);
00258
00259 content->setY(toMidline - content->axis( style, tstyle ));
00260
00261 if (hasUpper()) {
00262 luPixel slant =
00263 static_cast<luPixel>( symbol->slant()*( symbol->getHeight()+distY ) );
00264 if (style.getCenterSymbol()) {
00265 upper->setX((xOffset - upperWidth) / 2 + slant );
00266 }
00267 else {
00268 if (upperWidth < symbol->getWidth()) {
00269 upper->setX(symbol->getX() +
00270 (symbol->getWidth() - upperWidth) / 2 + slant );
00271 }
00272 else {
00273 upper->setX(xOffset - upperWidth);
00274 }
00275 }
00276 upper->setY(toMidline - upperHeight - symbol->getHeight()/2);
00277 }
00278 if (hasLower()) {
00279 luPixel slant = static_cast<luPixel>( -symbol->slant()*distY );
00280 if (style.getCenterSymbol()) {
00281 lower->setX((xOffset - lowerWidth) / 2 + slant);
00282 }
00283 else {
00284 if (lowerWidth < symbol->getWidth()) {
00285 lower->setX(symbol->getX() +
00286 (symbol->getWidth() - lowerWidth) / 2 + slant );
00287 }
00288 else {
00289 lower->setX(xOffset - lowerWidth);
00290 }
00291 }
00292 lower->setY(toMidline + symbol->getHeight()/2 + distY);
00293 }
00294 setBaseline(content->getBaseline() + content->getY());
00295 }
00296
00302 void SymbolElement::draw( QPainter& painter, const LuPixelRect& r,
00303 const ContextStyle& style,
00304 ContextStyle::TextStyle tstyle,
00305 ContextStyle::IndexStyle istyle,
00306 const LuPixelPoint& parentOrigin )
00307 {
00308 LuPixelPoint myPos( parentOrigin.x()+getX(), parentOrigin.y()+getY() );
00309
00310
00311
00312 luPt mySize = style.getAdjustedSize( tstyle );
00313 symbol->draw( painter, r, style, tstyle, mySize, myPos );
00314 content->draw( painter, r, style, tstyle, istyle, myPos );
00315 if ( hasUpper() ) {
00316 upper->draw( painter, r, style, style.convertTextStyleIndex( tstyle ),
00317 style.convertIndexStyleUpper( istyle ), myPos );
00318 }
00319 if ( hasLower() ) {
00320 lower->draw( painter, r, style, style.convertTextStyleIndex( tstyle ),
00321 style.convertIndexStyleLower( istyle ), myPos );
00322 }
00323
00324
00325 #if 0
00326 painter.setBrush(Qt::NoBrush);
00327 painter.setPen(Qt::red);
00328
00329
00330
00331
00332 painter.drawRect( style.layoutUnitToPixelX( myPos.x()+symbol->getX() ),
00333 style.layoutUnitToPixelY( myPos.y()+symbol->getY() ),
00334 style.layoutUnitToPixelX( symbol->getWidth() ),
00335 style.layoutUnitToPixelY( symbol->getHeight() ) );
00336 painter.setPen(Qt::green);
00337 painter.drawLine( style.layoutUnitToPixelX( myPos.x() ),
00338 style.layoutUnitToPixelY( myPos.y()+axis(style, tstyle) ),
00339 style.layoutUnitToPixelX( myPos.x()+getWidth() ),
00340 style.layoutUnitToPixelY( myPos.y()+axis(style, tstyle) ) );
00341 #endif
00342 }
00343
00344
00345 void SymbolElement::dispatchFontCommand( FontCommand* cmd )
00346 {
00347 content->dispatchFontCommand( cmd );
00348 if ( hasUpper() ) {
00349 upper->dispatchFontCommand( cmd );
00350 }
00351 if ( hasLower() ) {
00352 lower->dispatchFontCommand( cmd );
00353 }
00354 }
00355
00356
00357
00358
00359
00360
00361
00362
00363
00369 void SymbolElement::moveLeft(FormulaCursor* cursor, BasicElement* from)
00370 {
00371 if (cursor->isSelectionMode()) {
00372 getParent()->moveLeft(cursor, this);
00373 }
00374 else {
00375 bool linear = cursor->getLinearMovement();
00376 if (from == getParent()) {
00377 content->moveLeft(cursor, this);
00378 }
00379 else if (from == content) {
00380 if (linear && hasLower()) {
00381 lower->moveLeft(cursor, this);
00382 }
00383 else if (linear && hasUpper()) {
00384 upper->moveLeft(cursor, this);
00385 }
00386 else {
00387 getParent()->moveLeft(cursor, this);
00388 }
00389 }
00390 else if (from == lower) {
00391 if (linear && hasUpper()) {
00392 upper->moveLeft(cursor, this);
00393 }
00394 else {
00395 getParent()->moveLeft(cursor, this);
00396 }
00397 }
00398 else if (from == upper) {
00399 getParent()->moveLeft(cursor, this);
00400 }
00401 }
00402 }
00403
00409 void SymbolElement::moveRight(FormulaCursor* cursor, BasicElement* from)
00410 {
00411 if (cursor->isSelectionMode()) {
00412 getParent()->moveRight(cursor, this);
00413 }
00414 else {
00415 bool linear = cursor->getLinearMovement();
00416 if (from == getParent()) {
00417 if (linear && hasUpper()) {
00418 upper->moveRight(cursor, this);
00419 }
00420 else if (linear && hasLower()) {
00421 lower->moveRight(cursor, this);
00422 }
00423 else {
00424 content->moveRight(cursor, this);
00425 }
00426 }
00427 else if (from == upper) {
00428 if (linear && hasLower()) {
00429 lower->moveRight(cursor, this);
00430 }
00431 else {
00432 content->moveRight(cursor, this);
00433 }
00434 }
00435 else if (from == lower) {
00436 content->moveRight(cursor, this);
00437 }
00438 else if (from == content) {
00439 getParent()->moveRight(cursor, this);
00440 }
00441 }
00442 }
00443
00449 void SymbolElement::moveUp(FormulaCursor* cursor, BasicElement* from)
00450 {
00451 if (cursor->isSelectionMode()) {
00452 getParent()->moveUp(cursor, this);
00453 }
00454 else {
00455 if (from == content) {
00456 if (hasUpper()) {
00457 upper->moveLeft(cursor, this);
00458 }
00459 else {
00460 getParent()->moveUp(cursor, this);
00461 }
00462 }
00463 else if (from == upper) {
00464 getParent()->moveUp(cursor, this);
00465 }
00466 else if ((from == getParent()) || (from == lower)) {
00467 content->moveRight(cursor, this);
00468 }
00469 }
00470 }
00471
00477 void SymbolElement::moveDown(FormulaCursor* cursor, BasicElement* from)
00478 {
00479 if (cursor->isSelectionMode()) {
00480 getParent()->moveDown(cursor, this);
00481 }
00482 else {
00483 if (from == content) {
00484 if (hasLower()) {
00485 lower->moveLeft(cursor, this);
00486 }
00487 else {
00488 getParent()->moveDown(cursor, this);
00489 }
00490 }
00491 else if (from == lower) {
00492 getParent()->moveDown(cursor, this);
00493 }
00494 else if ((from == getParent()) || (from == upper)) {
00495 content->moveRight(cursor, this);
00496 }
00497 }
00498 }
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00525 void SymbolElement::insert(FormulaCursor* cursor,
00526 QPtrList<BasicElement>& newChildren,
00527 Direction direction)
00528 {
00529 SequenceElement* index = static_cast<SequenceElement*>(newChildren.take(0));
00530 index->setParent(this);
00531
00532 switch (cursor->getPos()) {
00533 case upperMiddlePos:
00534 upper = index;
00535 break;
00536 case lowerMiddlePos:
00537 lower = index;
00538 break;
00539 default:
00540
00541 return;
00542 }
00543
00544 if (direction == beforeCursor) {
00545 index->moveLeft(cursor, this);
00546 }
00547 else {
00548 index->moveRight(cursor, this);
00549 }
00550 cursor->setSelection(false);
00551 formula()->changed();
00552 }
00553
00565 void SymbolElement::remove(FormulaCursor* cursor,
00566 QPtrList<BasicElement>& removedChildren,
00567 Direction direction)
00568 {
00569 int pos = cursor->getPos();
00570 switch (pos) {
00571 case upperMiddlePos:
00572 removedChildren.append(upper);
00573 formula()->elementRemoval(upper);
00574 upper = 0;
00575 setToUpper(cursor);
00576 break;
00577 case lowerMiddlePos:
00578 removedChildren.append(lower);
00579 formula()->elementRemoval(lower);
00580 lower = 0;
00581 setToLower(cursor);
00582 break;
00583 case contentPos: {
00584 BasicElement* parent = getParent();
00585 parent->selectChild(cursor, this);
00586 parent->remove(cursor, removedChildren, direction);
00587 break;
00588 }
00589 }
00590 formula()->changed();
00591 }
00592
00597 void SymbolElement::normalize(FormulaCursor* cursor, Direction direction)
00598 {
00599 if (direction == beforeCursor) {
00600 content->moveLeft(cursor, this);
00601 }
00602 else {
00603 content->moveRight(cursor, this);
00604 }
00605 }
00606
00610 BasicElement* SymbolElement::getChild(FormulaCursor* cursor, Direction)
00611 {
00612 int pos = cursor->getPos();
00613 switch (pos) {
00614 case contentPos:
00615 return content;
00616 case upperMiddlePos:
00617 return upper;
00618 case lowerMiddlePos:
00619 return lower;
00620 }
00621 return 0;
00622 }
00623
00628 void SymbolElement::selectChild(FormulaCursor* cursor, BasicElement* child)
00629 {
00630 if (child == content) {
00631 setToContent(cursor);
00632 }
00633 else if (child == upper) {
00634 setToUpper(cursor);
00635 }
00636 else if (child == lower) {
00637 setToLower(cursor);
00638 }
00639 }
00640
00641 void SymbolElement::setToUpper(FormulaCursor* cursor)
00642 {
00643 cursor->setTo(this, upperMiddlePos);
00644 }
00645
00646 void SymbolElement::setToLower(FormulaCursor* cursor)
00647 {
00648 cursor->setTo(this, lowerMiddlePos);
00649 }
00650
00657 void SymbolElement::setToContent(FormulaCursor* cursor)
00658 {
00659 cursor->setTo(this, contentPos);
00660 }
00661
00662
00663 void SymbolElement::moveToUpper(FormulaCursor* cursor, Direction direction)
00664 {
00665 if (hasUpper()) {
00666 if (direction == beforeCursor) {
00667 upper->moveLeft(cursor, this);
00668 }
00669 else {
00670 upper->moveRight(cursor, this);
00671 }
00672 }
00673 }
00674
00675 void SymbolElement::moveToLower(FormulaCursor* cursor, Direction direction)
00676 {
00677 if (hasLower()) {
00678 if (direction == beforeCursor) {
00679 lower->moveLeft(cursor, this);
00680 }
00681 else {
00682 lower->moveRight(cursor, this);
00683 }
00684 }
00685 }
00686
00687
00688 ElementIndexPtr SymbolElement::getIndex( int position )
00689 {
00690 switch ( position ) {
00691 case lowerMiddlePos:
00692 return getLowerIndex();
00693 case upperMiddlePos:
00694 return getUpperIndex();
00695 }
00696 return getUpperIndex();
00697 }
00698
00699
00703 void SymbolElement::writeDom(QDomElement element)
00704 {
00705 BasicElement::writeDom(element);
00706
00707 element.setAttribute("TYPE", symbolType);
00708
00709 QDomDocument doc = element.ownerDocument();
00710
00711 QDomElement con = doc.createElement("CONTENT");
00712 con.appendChild(content->getElementDom(doc));
00713 element.appendChild(con);
00714
00715 if(hasLower()) {
00716 QDomElement ind = doc.createElement("LOWER");
00717 ind.appendChild(lower->getElementDom(doc));
00718 element.appendChild(ind);
00719 }
00720 if(hasUpper()) {
00721 QDomElement ind = doc.createElement("UPPER");
00722 ind.appendChild(upper->getElementDom(doc));
00723 element.appendChild(ind);
00724 }
00725 }
00726
00731 bool SymbolElement::readAttributesFromDom(QDomElement element)
00732 {
00733 if (!BasicElement::readAttributesFromDom(element)) {
00734 return false;
00735 }
00736
00737 QString typeStr = element.attribute("TYPE");
00738 if(!typeStr.isNull()) {
00739 symbolType = static_cast<SymbolType>(typeStr.toInt());
00740 }
00741
00742 return true;
00743 }
00744
00750 bool SymbolElement::readContentFromDom(QDomNode& node)
00751 {
00752 if (!BasicElement::readContentFromDom(node)) {
00753 return false;
00754 }
00755
00756 if ( !buildChild( content, node, "CONTENT" ) ) {
00757 kdWarning( DEBUGID ) << "Empty content in SymbolElement." << endl;
00758 return false;
00759 }
00760 node = node.nextSibling();
00761
00762 bool lowerRead = false;
00763 bool upperRead = false;
00764
00765 while (!node.isNull() && !(upperRead && lowerRead)) {
00766
00767 if (!lowerRead && (node.nodeName().upper() == "LOWER")) {
00768 lowerRead = buildChild( lower=new SequenceElement( this ), node, "LOWER" );
00769 if ( !lowerRead ) return false;
00770 }
00771
00772 if (!upperRead && (node.nodeName().upper() == "UPPER")) {
00773 upperRead = buildChild( upper=new SequenceElement( this ), node, "UPPER" );
00774 if ( !upperRead ) return false;
00775 }
00776
00777 node = node.nextSibling();
00778 }
00779 return true;
00780 }
00781
00782 QString SymbolElement::toLatex()
00783 {
00784 QString sym;
00785
00786 switch(symbolType) {
00787
00788 case 1001:
00789 sym="\\int";
00790 break;
00791 case 1002:
00792 sym="\\sum";
00793 break;
00794 case 1003:
00795 sym="\\prod";
00796 break;
00797
00798 default:
00799 sym=" ";
00800
00801 }
00802
00803
00804 if(hasLower()) {
00805 sym+="_{";
00806 sym+=lower->toLatex();
00807 sym+="}";
00808 }
00809
00810 if(hasUpper()) {
00811 sym+="^{";
00812 sym+=upper->toLatex();
00813 sym+="} ";
00814 }
00815
00816 sym += " ";
00817
00818 sym+=content->toLatex();
00819
00820
00821 return sym;
00822 }
00823
00824 QString SymbolElement::formulaString()
00825 {
00826 QString sym;
00827 switch ( symbolType ) {
00828 case 1001:
00829 sym="int(";
00830 break;
00831 case 1002:
00832 sym="sum(";
00833 break;
00834 case 1003:
00835 sym="prod(";
00836 break;
00837 default:
00838 sym="(";
00839 }
00840 sym += content->formulaString();
00841 if ( hasLower() ) {
00842 sym += ", " + lower->formulaString();
00843 }
00844 if ( hasUpper() ) {
00845 sym += ", " + upper->formulaString();
00846 }
00847 return sym + ")";
00848 }
00849
00850 void SymbolElement::writeMathML( QDomDocument& doc, QDomNode parent, bool oasisFormat )
00851 {
00852 QDomElement de = doc.createElement( oasisFormat ? "math:mrow" : "mrow" );
00853 QDomElement mo = doc.createElement( oasisFormat ? "math:mo" : "mo" );
00854
00855 QString value;
00856
00857 switch( symbolType )
00858 {
00859 case EmptyBracket: break;
00860 case LeftLineBracket: case RightLineBracket:
00861 mo.appendChild( doc.createTextNode( "|" ) ); break;
00862 case Integral:
00863 mo.appendChild( doc.createEntityReference( "int" ) ); break;
00864 case Sum:
00865 mo.appendChild( doc.createEntityReference( "sum" ) ); break;
00866 case Product:
00867 mo.appendChild( doc.createEntityReference( "prod" ) ); break;
00868 default:
00869 mo.appendChild( doc.createTextNode( QChar( symbolType ) ) );
00870 }
00871
00872 QDomElement between;
00873 if ( hasUpper() && hasLower() )
00874 {
00875 between = doc.createElement( oasisFormat ? "math:msubsup" : "msubsup" );
00876 between.appendChild( mo );
00877 lower->writeMathML( doc, between, oasisFormat );
00878 upper->writeMathML( doc, between, oasisFormat );
00879 }
00880 else if ( hasUpper() )
00881 {
00882 between = doc.createElement( oasisFormat ? "math:msup" : "msup" );
00883 between.appendChild( mo );
00884 upper->writeMathML( doc, between, oasisFormat );
00885 }
00886 else if ( hasLower() )
00887 {
00888 between = doc.createElement( oasisFormat ? "math:msub" : "msub" );
00889 between.appendChild( mo );
00890 lower->writeMathML( doc, between, oasisFormat );
00891 }
00892 else
00893 between = mo;
00894
00895 de.appendChild( between );
00896 content->writeMathML( doc, de, oasisFormat );
00897
00898 parent.appendChild( de );
00899 }
00900
00901 KFORMULA_NAMESPACE_END