00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 #include "khtml_caret_p.h"
00023 
00024 namespace khtml {
00025 
00026 static InlineFlowBox *findFlowBox(DOM::NodeImpl *node, long offset,
00027         RenderArena *arena, RenderFlow *&cb, InlineBox **ibox = 0);
00028 static RenderObject *nextLeafRenderObject(RenderObject *r);
00029 
00034 static inline RenderObject *nextSuitableLeafRenderObject(RenderObject *r)
00035 {
00036   do {
00037     r = nextLeafRenderObject(r);
00038   } while (r && r->isTableCol());
00039   return r;
00040 }
00041 
00043 static void ensureLeafNode(NodeImpl *&node)
00044 {
00045   if (node && node->hasChildNodes()) node = node->nextLeafNode();
00046 }
00047 
00056 static RenderObject* findRenderer(NodeImpl *&node)
00057 {
00058   if (!node) return 0;
00059   RenderObject *r = node->renderer();
00060   while (!r) {
00061     node = node->nextLeafNode();
00062     if (!node) break;
00063     r = node->renderer();
00064   }
00065   if (r && r->isTableCol()) r = nextSuitableLeafRenderObject(r);
00066   return r;
00067 }
00068 
00070 static void sanitizeCaretState(NodeImpl *&caretNode, long &offset)
00071 {
00072   ensureLeafNode(caretNode);
00073 
00074   
00075   
00076   
00077   
00078   NodeImpl *tmpNode = caretNode;
00079   if (findRenderer(tmpNode)) caretNode = tmpNode;
00080   if (!caretNode) return;
00081 
00082   long max = caretNode->maxOffset();
00083   long min = caretNode->minOffset();
00084   if (offset < min) offset = min;
00085   else if (offset > max) offset = max;
00086 }
00087 
00089 static RenderObject *prevLeafRenderObject(RenderObject *r)
00090 {
00091   RenderObject *n = r->objectAbove();
00092   while (n && n == r->parent()) {
00093     if (n->previousSibling()) return n->objectAbove();
00094     r = n;
00095     n = r->parent();
00096   }
00097   return n;
00098 }
00099 
00101 static RenderObject *nextLeafRenderObject(RenderObject *r)
00102 {
00103   RenderObject *n = r->objectBelow();
00104   r = n;
00105   while (n) r = n, n = n->firstChild();
00106   return r;
00107 }
00108 
00113 static RenderObject *prevSuitableLeafRenderObject(RenderObject *r)
00114 {
00115   do {
00116     r = prevLeafRenderObject(r);
00117   } while (r && r->isTableCol());
00118   return r;
00119 }
00120 
00123 static inline InlineBox *seekLeafInlineBox(InlineBox *box)
00124 {
00125   while (box && box->isInlineFlowBox()) {
00126 
00127       box = static_cast<InlineFlowBox *>(box)->firstChild();
00128 
00129 
00130 
00131 
00132   }
00133   return box;
00134 }
00135 
00138 static inline InlineBox *seekLeafInlineBoxFromEnd(InlineBox *box)
00139 {
00140   while (box && box->isInlineFlowBox()) {
00141       box = static_cast<InlineFlowBox *>(box)->lastChild();
00142   }
00143 #if DEBUG_CARETMODE > 0
00144   kdDebug(6200) << "seekLeafFromEnd: box " << box << (box && box->isInlineTextBox() ? QString(" contains \"%1\"").arg(QConstString(static_cast<RenderText *>(box->object())->str->s+box->minOffset(), box->maxOffset() - box->minOffset()).string()) : QString::null) << endl;
00145 #endif
00146   return box;
00147 }
00148 
00149 
00150 
00151 InlineBox *LineIterator::currentBox;
00152 
00153 InlineBoxIterator::InlineBoxIterator(RenderArena *arena, InlineFlowBox *flowBox, bool fromEnd)
00154     : arena(arena)
00155 {
00156     box = fromEnd ? seekLeafInlineBoxFromEnd(flowBox) : seekLeafInlineBox(flowBox);
00157 }
00158 
00159 InlineBoxIterator::InlineBoxIterator(LineIterator &lit, bool fromEnd,
00160                       InlineBox *initBox)
00161     : arena(lit.lines->arena)
00162 {
00163     if (initBox) box = initBox;
00164     else box = fromEnd ? seekLeafInlineBoxFromEnd(*lit) : seekLeafInlineBox(*lit);
00165 }
00166 
00167 
00168 InlineBoxIterator& InlineBoxIterator::operator ++()
00169 {
00170     InlineBox *newBox = box->nextOnLine();
00171 
00172     if (newBox)
00173       box = seekLeafInlineBox(newBox);
00174     else {
00175       InlineFlowBox *flowBox = box->parent();
00176       box = 0;
00177       while (flowBox) {
00178         InlineBox *newBox2 = flowBox->nextOnLine();
00179     if (newBox2) {
00180       box = seekLeafInlineBox(newBox2);
00181       break;
00182     }
00183 
00184     flowBox = flowBox->parent();
00185       }
00186     }
00187 
00188     return *this;
00189 }
00190 
00194 InlineBoxIterator& InlineBoxIterator::operator --()
00195 {
00196     InlineBox *newBox = box->prevOnLine();
00197 
00198     if (newBox)
00199         box = seekLeafInlineBoxFromEnd(newBox);
00200     else {
00201         InlineFlowBox *flowBox = box->parent();
00202         box = 0;
00203         while (flowBox) {
00204         InlineBox *newBox2 = flowBox->prevOnLine();
00205     if (newBox2) {
00206       box = seekLeafInlineBoxFromEnd(newBox2);
00207       break;
00208     }
00209 
00210     flowBox = flowBox->parent();
00211       }
00212     }
00213 
00214     return *this;
00215 }
00216 
00233 static InlineFlowBox* generateDummyFlowBox(RenderArena *arena, RenderFlow *cb,
00234             RenderObject *childNodeHint = 0)
00235 {
00236   InlineFlowBox *flowBox = new(arena) InlineFlowBox(cb);
00237   int width = cb->width();
00238   
00239   
00240   
00241   
00242   
00243   int height = cb->style()->fontMetrics().height();
00244   flowBox->setWidth(0);
00245   flowBox->setHeight(height);
00246 
00247   
00248   InlineBox *child = new(arena) InlineBox(childNodeHint ? childNodeHint : cb);
00249   
00250   switch (cb->style()->textAlign()) {
00251     case LEFT:
00252     case TAAUTO:    
00253     case JUSTIFY:
00254       child->setXPos(0);
00255       break;
00256     case CENTER:
00257     case KONQ_CENTER:
00258       child->setXPos(width / 2);
00259       break;
00260     case RIGHT:
00261       child->setXPos(width);
00262       break;
00263   }
00264   child->setYPos(0);
00265   child->setWidth(1);
00266   child->setHeight(height);
00267 
00268   flowBox->setXPos(child->xPos());
00269   flowBox->setYPos(child->yPos());
00270   flowBox->addToLine(child);
00271   
00272   return flowBox;
00273 }
00274 
00280 static RenderFlow* generateDummyBlock(RenderArena *, RenderObject *cb)
00281 {
00282     
00283   RenderFlow *result = RenderFlow::createFlow(cb->element(), cb->style(), cb->renderArena());
00284   result->setParent(cb->parent());
00285   result->setPreviousSibling(cb->previousSibling());
00286   result->setNextSibling(cb->nextSibling());
00287 
00288   result->setOverhangingContents(cb->overhangingContents());
00289   result->setPositioned(cb->isPositioned());
00290   result->setRelPositioned(cb->isRelPositioned());
00291   result->setFloating(cb->isFloating());
00292   result->setInline(cb->isInline());
00293   result->setMouseInside(cb->mouseInside());
00294 
00295   result->setPos(cb->xPos(), cb->yPos());
00296   result->setWidth(cb->width());
00297   result->setHeight(cb->height());
00298 
00299   return result;
00300 }
00301 
00317 static InlineFlowBox* findFlowBox(DOM::NodeImpl *node, long offset,
00318         RenderArena *arena, RenderFlow *&cb, InlineBox **ibox)
00319 {
00320   RenderObject *r = findRenderer(node);
00321   if (!r) { cb = 0; return 0; }
00322 #if DEBUG_CARETMODE > 0
00323   kdDebug(6200) << "=================== findFlowBox" << endl;
00324   kdDebug(6200) << "node " << node << " r " << r->renderName() << "[" << r << "].node " << r->element()->nodeName().string() << "[" << r->element() << "]" << " offset: " << offset << endl;
00325 #endif
00326 
00327   
00328   
00329   
00330   if (r->isRenderBlock() && !static_cast<RenderBlock *>(r)->firstLineBox()) {
00331     cb = static_cast<RenderBlock *>(r);
00332 #if DEBUG_CARETMODE > 0
00333   kdDebug(6200) << "=================== end findFlowBox (dummy)" << endl;
00334 #endif
00335     InlineFlowBox *fb = generateDummyFlowBox(arena, cb);
00336     if (ibox) *ibox = fb;
00337     return fb;
00338   }
00339 
00340   
00341   
00342   
00343   
00344   
00345   
00346   if (r->isText()) do {
00347     RenderText *t = static_cast<RenderText *>(r);
00348     int dummy;
00349     InlineBox *b = t->findInlineTextBox(offset, dummy, true);
00350     
00351     
00352     
00353     if (!b) {
00354       if (t->m_lines.count() > 0)
00355         b = t->m_lines[t->m_lines.count() - 1];
00356       else
00357         break;
00358     }
00359     Q_ASSERT(b);
00360     if (ibox) *ibox = b;
00361     while (b->parent()) {   
00362       b = b->parent();
00363     }
00364     
00365     Q_ASSERT(b->isRootInlineBox());
00366     cb = static_cast<RenderFlow *>(b->object());
00367     Q_ASSERT(cb->isRenderBlock());
00368 #if DEBUG_CARETMODE > 0
00369   kdDebug(6200) << "=================== end findFlowBox (renderText)" << endl;
00370 #endif
00371     return static_cast<InlineFlowBox *>(b);
00372   } while(false);
00373 
00374   cb = r->containingBlock();
00375   if ( !cb ) return 0L;
00376 
00377   if (!cb->isRenderBlock()) {
00378     cb = generateDummyBlock(arena, cb);
00379 #if DEBUG_CARETMODE > 0
00380     kdDebug(6200) << "dummy block created: " << cb << endl;
00381 #endif
00382   }
00383 
00384   InlineFlowBox *flowBox = cb->firstLineBox();
00385   
00386   
00387   
00388   if (!flowBox) {
00389     flowBox = generateDummyFlowBox(arena, cb, r);
00390     if (ibox) *ibox = flowBox->firstChild();
00391 #if DEBUG_CARETMODE > 0
00392   kdDebug(6200) << "=================== end findFlowBox (2)" << endl;
00393 #endif
00394     return flowBox;
00395   }
00396 
00397   
00398   
00399   
00400   for (; flowBox; flowBox = static_cast<InlineFlowBox *>(flowBox->nextLineBox())) {
00401 #if DEBUG_CARETMODE > 0
00402     kdDebug(6200) << "[scan line]" << endl;
00403 #endif
00404 
00405     
00406     InlineBox *box;
00407     InlineBoxIterator it(arena, flowBox);
00408     for (; (box = *it) != 0; ++it) {
00409       RenderObject *br = box->object();
00410       if (!br) continue;
00411 
00412 #if DEBUG_CARETMODE > 0
00413       kdDebug(6200) << "box->obj " << br->renderName() << "[" << br << "]" << " minOffset: " << box->minOffset() << " maxOffset: " << box->maxOffset() << endl;
00414 #endif
00415       if (br == r && offset >= box->minOffset() && offset <= box->maxOffset())
00416         break;  
00417     }
00418     if (box) {
00419       if (ibox) *ibox = box;
00420       break;
00421     }
00422 
00423   }
00424 
00425   
00426   
00427   
00428   if (!flowBox) flowBox = findFlowBox(node->nextLeafNode(), 0, arena, cb, ibox);
00429 
00430 #if DEBUG_CARETMODE > 0
00431   kdDebug(6200) << "=================== end findFlowBox" << endl;
00432 #endif
00433   return flowBox;
00434 }
00435 
00442 static inline RenderTable *findTableUpTo(RenderObject *r, RenderFlow *cb)
00443 {
00444   while (r && r != cb && !r->isTable()) r = r->parent();
00445   return r && r->isTable() ? static_cast<RenderTable *>(r) : 0;
00446 }
00447 
00450 static inline bool isDescendant(RenderObject *r, RenderObject *cb)
00451 {
00452   while (r && r != cb) r = r->parent();
00453   return r;
00454 }
00455 
00466 static bool containsEditableElement(KHTMLPart *part, RenderFlow *cb,
00467     RenderTable *&table, bool fromEnd = false)
00468 {
00469   RenderObject *r = cb;
00470   if (fromEnd)
00471     while (r->lastChild()) r = r->lastChild();
00472   else
00473     while (r->firstChild()) r = r->firstChild();
00474 
00475   RenderTable *tempTable = 0;
00476   table = 0;
00477   bool withinCb;
00478   do {
00479     tempTable = findTableUpTo(r, cb);
00480     withinCb = isDescendant(r, cb);
00481 
00482 #if DEBUG_CARETMODE > 1
00483     kdDebug(6201) << "r " << (r ? r->renderName() : QString::null) << "@" << r << endl;
#endif
    if (r && withinCb && r->element() && !r->isTableCol()
        && (part->isCaretMode() || part->isEditable()
        || r->style()->userInput() == UI_ENABLED)) {
      table = tempTable;
      return true;
    }/*end if*/
    r = fromEnd ? prevSuitableLeafRenderObject(r) : nextSuitableLeafRenderObject(r);
  } while (r && withinCb);
  return false;
}
00496 static bool containsEditableChildElement(KHTMLPart *part, RenderFlow *cb,
    RenderTable *&table, bool fromEnd, RenderObject *start)
{
  RenderObject *r = start;
  if (fromEnd)
    while (r->firstChild()) r = r->firstChild();
  else
    while (r->lastChild()) r = r->lastChild();
  if (!r) return false;
  RenderTable *tempTable = 0;
  table = 0;
  bool withinCb = false;
  do {
    r = fromEnd ? prevSuitableLeafRenderObject(r) : nextSuitableLeafRenderObject(r);
    if (!r) break;
    withinCb = isDescendant(r, cb) && r != cb;
    tempTable = findTableUpTo(r, cb);
#if DEBUG_CARETMODE > 1
    kdDebug(6201) << "r " << (r ? r->renderName() : QString::null) << "@" << r << endl;
#endif
    if (r && withinCb && r->element() && !r->isTableCol()
        && (part->isCaretMode() || part->isEditable()
        || r->style()->userInput() == UI_ENABLED)) {
      table = tempTable;
      return true;
    }/*end if*/
  } while (withinCb);
  return false;
}
// == class LinearDocument implementation
LinearDocument::LinearDocument(KHTMLPart *part, NodeImpl *node, long offset)
    : arena(0), node(node), offset(offset), m_part(part)
{
  if (node == 0) return;
  sanitizeCaretState(this->node, this->offset);
  arena = new RenderArena(512);
  initPreBeginIterator();
  initEndIterator();
  //m_part = node->getDocument()->view()->part();
}
LinearDocument::~LinearDocument()
{
  delete arena;
}
int LinearDocument::count() const
{
  // FIXME: not implemented
  return 1;
}
LinearDocument::Iterator LinearDocument::current()
{
  return LineIterator(this, node, offset);
}
LinearDocument::Iterator LinearDocument::begin()
{
  DocumentImpl *doc = node ? node->getDocument() : 0;
  if (!doc) return end();
  NodeImpl *firstLeaf = doc->nextLeafNode();
  if (!firstLeaf) return end();     // must be empty document (is this possible?)
  return LineIterator(this, firstLeaf, firstLeaf->minOffset());
}
LinearDocument::Iterator LinearDocument::preEnd()
{
  DocumentImpl *doc = node ? node->getDocument() : 0;
  if (!doc) return preBegin();
  NodeImpl *lastLeaf = doc;
  while (lastLeaf->lastChild()) lastLeaf = lastLeaf->lastChild();
  if (!lastLeaf) return preBegin(); // must be empty document (is this possible?)
  return LineIterator(this, lastLeaf, lastLeaf->maxOffset());
}
void LinearDocument::initPreBeginIterator()
{
  _preBegin = LineIterator(this, 0, 0);
}
void LinearDocument::initEndIterator()
{
  _end = LineIterator(this, 0, 1);
}
// == class LineIterator implementation
LineIterator::LineIterator(LinearDocument *l, DOM::NodeImpl *node, long offset)
        : lines(l)
{
//  kdDebug(6200) << "LineIterator: node " << node << " offset " << offset << endl;
00497   flowBox = findFlowBox(node, offset, lines->arena, cb, ¤tBox);
00498   if (!flowBox) {
00499 #if DEBUG_CARETMODE > 0
00500     kdDebug(6200) << "LineIterator: findFlowBox failed" << endl;
00501 #endif
00502     cb = 0;
00503   }
00504 }
00505 
00506 void LineIterator::nextBlock()
00507 {
00508   RenderObject *r = cb;
00509   RenderObject *n = r->lastChild();
00510   while (n) r = n, n = r->lastChild();
00511   r = nextSuitableLeafRenderObject(r);
00512 #if DEBUG_CARETMODE > 0
00513   kdDebug(6200) << "++: r " << r << "[" << (r?r->renderName():QString::null) << "]" << endl;
00514 #endif
00515   if (!r) {
00516     cb = 0;
00517     return;
00518   }
00519 
00520   
00521   
00522   if (r->isRenderBlock()) {
00523     cb = static_cast<RenderBlock *>(r);
00524 #if DEBUG_CARETMODE > 0
00525     kdDebug(6200) << "r->isFlow is cb. continuation @" << cb->continuation() << endl;
00526 #endif
00527     
00528     
00529     
00530     
00531     RenderFlow *flow = static_cast<RenderFlow *>(cb->element()
00532                 ? cb->element()->renderer() : 0);
00533     if (cb->continuation() || flow && flow->isRenderBlock() && flow != cb
00534             && flow->continuation()) {
00535       nextBlock();
00536       return;
00537     }
00538   } else {
00539     cb = static_cast<RenderFlow *>(r->containingBlock());
00540     if (!cb->isRenderBlock()) {
00541 #if DEBUG_CARETMODE > 0
00542       kdDebug(6200) << "dummy cb created " << cb << endl;
00543 #endif
00544       cb = generateDummyBlock(lines->arena, r);
00545     }
00546   }
00547   flowBox = cb->firstLineBox();
00548 #if DEBUG_CARETMODE > 0
00549   kdDebug(6200) << "++: flowBox " << flowBox << endl;
00550 #endif
00551 
00552   if (!flowBox) flowBox = generateDummyFlowBox(lines->arena, cb, r);
00553 #if DEBUG_CARETMODE > 0
00554   if (!cb->firstLineBox()) kdDebug(6200) << "++: dummy flowBox " << flowBox << endl;
00555 #endif
00556 }
00557 
00558 inline LineIterator &LineIterator::operator ++()
00559 {
00560   flowBox = static_cast<InlineFlowBox *>(flowBox->nextLineBox());
00561 
00562   
00563   
00564   if (!flowBox) nextBlock();
00565 
00566   return *this;
00567 }
00568 
00569 inline LineIterator LineIterator::operator ++(int)
00570 {
00571   LineIterator it(*this);
00572   operator ++();
00573   return it;
00574 }
00575 
00576 void LineIterator::prevBlock()
00577 {
00578   RenderObject *r = cb;
00579   RenderObject *n = r->firstChild();
00580   while (n) r = n, n = r->firstChild();
00581   r = prevSuitableLeafRenderObject(r);
00582   if (!r) {
00583     cb = 0;
00584     return;
00585   }
00586 
00587   
00588   
00589   if (r->isRenderBlock()) {
00590     cb = static_cast<RenderFlow *>(r);
00591 #if DEBUG_CARETMODE > 0
00592     kdDebug(6200) << "r->isFlow is cb. continuation @" << cb->continuation() << endl;
00593 #endif
00594     
00595     
00596     
00597     
00598     RenderFlow *flow = static_cast<RenderFlow *>(cb->element()
00599                 ? cb->element()->renderer() : 0);
00600     if (cb->continuation() || flow && flow->isRenderBlock() && flow != cb
00601             && flow->continuation()) {
00602       prevBlock();
00603       return;
00604     }
00605   } else {
00606     cb = static_cast<RenderFlow *>(r->containingBlock());
00607     if (!cb->isRenderBlock()) {
00608 #if DEBUG_CARETMODE > 0
00609       kdDebug(6200) << "dummy cb created " << cb << endl;
00610 #endif
00611       cb = generateDummyBlock(lines->arena, r);
00612     }
00613   }
00614   flowBox = cb->lastLineBox();
00615 
00616   if (!flowBox) flowBox = generateDummyFlowBox(lines->arena, cb, r);
00617 }
00618 
00619 inline LineIterator &LineIterator::operator --()
00620 {
00621   flowBox = static_cast<InlineFlowBox *>(flowBox->prevLineBox());
00622 
00623   
00624   
00625   if (!flowBox) prevBlock();
00626 
00627   return *this;
00628 }
00629 
00630 inline LineIterator LineIterator::operator --(int)
00631 {
00632   LineIterator it(*this);
00633   operator --();
00634   return it;
00635 }
00636 
00637 #if 0 // not implemented because it's not needed
00638 LineIterator LineIterator::operator +(int ) const
00639 {
00640   
00641   return LineIterator();
00642 }
00643 
00644 LineIterator LineIterator::operator -(int ) const
00645 {
00646   
00647   return LineIterator();
00648 }
00649 #endif
00650 
00651 LineIterator &LineIterator::operator +=(int summand)
00652 {
00653   if (summand > 0)
00654     while (summand-- && *this != lines->end()) ++*this;
00655   else if (summand < 0)
00656     operator -=(-summand);
00657   return *this;
00658 }
00659 
00660 LineIterator &LineIterator::operator -=(int summand)
00661 {
00662   if (summand > 0)
00663     while (summand-- && *this != lines->preBegin()) --*this;
00664   else if (summand < 0)
00665     operator +=(-summand);
00666   return *this;
00667 }
00668 
00669 
00670 
00671 void EditableCharacterIterator::initFirstChar()
00672 {
00673   InlineBox *b = *ebit;
00674   if (b) {
00675     if (_offset == b->maxOffset())
00676       peekNext();
00677     else if (b->isInlineTextBox())
00678       _char = static_cast<RenderText *>(b->object())->str->s[_offset].unicode();
00679     else
00680       _char = -1;
00681   }
00682 }
00683 
00684 EditableCharacterIterator &EditableCharacterIterator::operator ++()
00685 {
00686   _offset++;
00687 
00688   InlineBox *b = *ebit;
00689   RenderObject *r = b->object();
00690   
00691   
00692   
00693   long maxofs = r->isBR() || r->isRenderBlock() ? b->minOffset() : b->maxOffset();
00694 #if DEBUG_CARETMODE > 0
00695   kdDebug(6200) << "b->maxOffset() " << b->maxOffset() << " b->minOffset() " << b->minOffset() << endl;
00696 #endif
00697   if (_offset == maxofs) {
00698 #if DEBUG_CARETMODE > 2
00699 kdDebug(6200) << "_offset == maxofs: " << _offset << " == " << maxofs << endl;
00700 #endif
00701 
00702     peekNext();
00703   } else if (_offset > maxofs) {
00704 #if DEBUG_CARETMODE > 2
00705 kdDebug(6200) << "_offset > maxofs: " << _offset << " > " << maxofs  << endl;
00706 #endif
00707     if (true) {
00708       if (*ebit)
00709         ++ebit;
00710       if (!*ebit) {     
00711         ++_it;
00712 #if DEBUG_CARETMODE > 3
00713 kdDebug(6200) << "++_it" << endl;
00714 #endif
00715         if (_it != ld->end()) {
00716       ebit = _it;
00717           b = *ebit;
00718 #if DEBUG_CARETMODE > 3
00719 kdDebug(6200) << "b " << b << " isText " << b->isInlineTextBox() << endl;
00720 #endif
00721       _node = b->object()->element();
00722 #if DEBUG_CARETMODE > 3
00723 kdDebug(6200) << "_node " << _node << ":" << _node->nodeName().string() << endl;
00724 #endif
00725       _offset = b->minOffset();
00726 #if DEBUG_CARETMODE > 3
00727 kdDebug(6200) << "_offset " << _offset << endl;
00728 #endif
00729     } else {
00730       _node = 0;
00731       b = 0;
00732     }
00733         goto readchar;
00734       }
00735     }
00736     bool adjacent = ebit.isAdjacent();
00737     
00738     if (adjacent && !(*ebit)->isInlineTextBox()) {
00739       EditableInlineBoxIterator copy = ebit;
00740       ++ebit;
00741       if (*ebit && (*ebit)->isInlineTextBox()) adjacent = false;
00742       else ebit = copy;
00743     }
00744     _node = (*ebit)->object()->element();
00745     _offset = (*ebit)->minOffset() + adjacent;
00746     
00747     b = *ebit;
00748     goto readchar;
00749   } else {
00750 readchar:
00751     
00752     if (b && b->isInlineTextBox() && _offset < b->maxOffset())
00753       _char = static_cast<RenderText *>(b->object())->str->s[_offset].unicode();
00754     else
00755       _char = -1;
00756   }
00757 #if DEBUG_CARETMODE > 2
00758 kdDebug(6200) << "_offset: " << _offset  << " char '" << (char)_char << "'" << endl;
00759 #endif
00760 
00761 #if DEBUG_CARETMODE > 0
00762   if (*ebit) {
00763     InlineBox *box = *ebit;
00764     kdDebug(6200) << "echit++(1): box " << box << (box && box->isInlineTextBox() ? QString(" contains \"%1\"").arg(QConstString(static_cast<RenderText *>(box->object())->str->s+box->minOffset(), box->maxOffset() - box->minOffset()).string()) : QString::null) << " node " << (_node ? _node->nodeName().string() : QString("<nil>")) << endl;
00765   }
00766 #endif
00767   return *this;
00768 }
00769 
00770 EditableCharacterIterator &EditableCharacterIterator::operator --()
00771 {
00772   _offset--;
00773   
00774 
00775   InlineBox *b = *ebit;
00776   InlineBox *_peekPrev = 0;
00777   InlineBox *_peekNext = 0;
00778   long minofs = b ? b->minOffset() : _offset + 1;
00779 #if DEBUG_CARETMODE > 0
00780   kdDebug(6200) << "b->maxOffset() " << b->maxOffset() << " b->minOffset() " << b->minOffset() << endl;
00781 #endif
00782   if (_offset == minofs) {
00783 #if DEBUG_CARETMODE > 2
00784 kdDebug(6200) << "_offset == minofs: " << _offset << " == " << minofs << endl;
00785 #endif
00786     _peekNext = b;
00787     
00788     if (b && b->isInlineTextBox())
00789       _char = static_cast<RenderText *>(b->object())->text()[_offset].unicode();
00790     else
00791       _char = -1;
00792 
00793     
00794     bool do_prev = false;
00795     {
00796       EditableInlineBoxIterator copy = ebit;
00797       --ebit;
00798       _peekPrev = *ebit;
00799       
00800       if (ebit.isAdjacent() && *ebit && (*ebit)->isInlineTextBox())
00801         
00802     do_prev = true;
00803       else
00804         ebit = copy;
00805     }
00806     if (do_prev) goto prev;
00807   } else if (_offset < minofs) {
00808 prev:
00809 #if DEBUG_CARETMODE > 2
00810 kdDebug(6200) << "_offset < minofs: " << _offset << " < " << minofs  << endl;
00811 #endif
00812     if (!_peekPrev) {
00813       _peekNext = *ebit;
00814       if (*ebit)
00815         --ebit;
00816       if (!*ebit) {     
00817         --_it;
00818 #if DEBUG_CARETMODE > 3
00819 kdDebug(6200) << "--_it" << endl;
00820 #endif
00821         if (_it != ld->preBegin()) {
00822 
00823       ebit = EditableInlineBoxIterator(_it, true);
00824       RenderObject *r = (*ebit)->object();
00825 #if DEBUG_CARETMODE > 3
00826 kdDebug(6200) << "b " << *ebit << " isText " << (*ebit)->isInlineTextBox() << endl;
00827 #endif
00828       _node = r->element();
00829       _offset = r->isBR() ? (*ebit)->minOffset() : (*ebit)->maxOffset();
00830       _char = -1;
00831 #if DEBUG_CARETMODE > 0
00832           {InlineBox *box = *ebit; kdDebug(6200) << "echit--(2): box " << box << (box && box->isInlineTextBox() ? QString(" contains \"%1\"").arg(QConstString(static_cast<RenderText *>(box->object())->str->s+box->minOffset(), box->maxOffset() - box->minOffset()).string()) : QString::null) << endl;}
00833 #endif
00834     } else
00835       _node = 0;
00836     return *this;
00837       }
00838     }
00839 
00840     bool adjacent = ebit.isAdjacent();
00841     
00842 #if DEBUG_CARETMODE > 0
00843     kdDebug(6200) << "adjacent " << adjacent << " _peekNext " << _peekNext << " _peekNext->isInlineTextBox: " << (_peekNext ? _peekNext->isInlineTextBox() : false) << " !((*ebit)->isInlineTextBox): " << (*ebit ? !(*ebit)->isInlineTextBox() : true) << endl;
00844 #endif
00845     if (adjacent && _peekNext && _peekNext->isInlineTextBox()
00846         && !(*ebit)->isInlineTextBox()) {
00847       EditableInlineBoxIterator copy = ebit;
00848       --ebit;
00849       if (!*ebit) 
00850 ebit = copy;
00851     }
00852 #if DEBUG_CARETMODE > 0
00853     kdDebug(6200) << "(*ebit)->obj " << (*ebit)->object()->renderName() << "[" << (*ebit)->object() << "]" << " minOffset: " << (*ebit)->minOffset() << " maxOffset: " << (*ebit)->maxOffset() << endl;
00854 #endif
00855     _node = (*ebit)->object()->element();
00856 #if DEBUG_CARETMODE > 3
00857 kdDebug(6200) << "_node " << _node << ":" << _node->nodeName().string() << endl;
00858 #endif
00859     _offset = (*ebit)->maxOffset();
00860 #if DEBUG_CARETMODE > 3
00861 kdDebug(6200) << "_offset " << _offset << endl;
00862 #endif
00863     _peekPrev = 0;
00864   } else {
00865 #if DEBUG_CARETMODE > 0
00866 kdDebug(6200) << "_offset: " << _offset << " _peekNext: " << _peekNext << endl;
00867 #endif
00868     
00869     if (_peekNext && _offset >= b->maxOffset() && _peekNext->isInlineTextBox())
00870       _char = static_cast<RenderText *>(_peekNext->object())->text()[_peekNext->minOffset()].unicode();
00871     else if (b && _offset < b->maxOffset() && b->isInlineTextBox())
00872       _char = static_cast<RenderText *>(b->object())->text()[_offset].unicode();
00873     else
00874       _char = -1;
00875   }
00876 
00877 #if DEBUG_CARETMODE > 0
00878   if (*ebit) {
00879     InlineBox *box = *ebit;
00880     kdDebug(6200) << "echit--(1): box " << box << (box && box->isInlineTextBox() ? QString(" contains \"%1\"").arg(QConstString(static_cast<RenderText *>(box->object())->str->s+box->minOffset(), box->maxOffset() - box->minOffset()).string()) : QString::null) << endl;
00881   }
00882 #endif
00883   return *this;
00884 }
00885 
00886 
00887 
00888 TableRowIterator::TableRowIterator(RenderTable *table, bool fromEnd,
00889         RenderTableSection::RowStruct *row)
00890         : sec(table, fromEnd)
00891 {
00892   
00893   if (*sec) {
00894     if (fromEnd) index = (*sec)->grid.size() - 1;
00895     else index = 0;
00896   }
00897 
00898   
00899   if (row && *sec) {
00900     while (operator *() != row)
00901       if (fromEnd) operator --(); else operator ++();
00902   }
00903 }
00904 
00905 TableRowIterator &TableRowIterator::operator ++()
00906 {
00907   index++;
00908 
00909   if (index >= (int)(*sec)->grid.size()) {
00910     ++sec;
00911 
00912     if (*sec) index = 0;
00913   }
00914   return *this;
00915 }
00916 
00917 TableRowIterator &TableRowIterator::operator --()
00918 {
00919   index--;
00920 
00921   if (index < 0) {
00922     --sec;
00923 
00924     if (*sec) index = (*sec)->grid.size() - 1;
00925   }
00926   return *this;
00927 }
00928 
00929 
00930 
00931 
00932 static RenderTableCell *findNearestTableCellInRow(KHTMLPart *part, int x,
00933         RenderTableSection::RowStruct *row, bool fromEnd);
00934 
00948 static inline RenderTableCell *findNearestTableCell(KHTMLPart *part, int x,
00949         TableRowIterator &it, bool fromEnd)
00950 {
00951   RenderTableCell *result = 0;
00952 
00953   while (*it) {
00954     result = findNearestTableCellInRow(part, x, *it, fromEnd);
00955     if (result) break;
00956 
00957     if (fromEnd) --it; else ++it;
00958   }
00959 
00960   return result;
00961 }
00962 
00976 static RenderTableCell *findNearestTableCellInRow(KHTMLPart *part, int x,
00977         RenderTableSection::RowStruct *row, bool fromEnd)
00978 {
00979   
00980   int n = (int)row->row->size();
00981   int i;
00982   for (i = 0; i < n; i++) {
00983     RenderTableCell *cell = row->row->at(i);
00984     if (!cell || (int)cell == -1) continue;
00985 
00986     int absx, absy;
00987     cell->absolutePosition(absx, absy, false); 
00988 #if DEBUG_CARETMODE > 1
00989     kdDebug(6201) << "i/n " << i << "/" << n << " absx " << absx << " absy " << absy << endl;
00990 #endif
00991 
00992     
00993     
00994 #if DEBUG_CARETMODE > 1
00995     kdDebug(6201) << "x " << x << " < " << (absx + cell->width()) << "?" << endl;
00996 #endif
00997     if (x < absx + cell->width()) break;
00998   }
00999   if (i >= n) i = n - 1;
01000 
01001   
01002   
01003   for (int cnt = 0; cnt < 2*n; cnt++) {
01004     int index = i - ((cnt >> 1) + 1)*(cnt & 1) + (cnt >> 1)*!(cnt & 1);
01005     if (index < 0 || index >= n) continue;
01006 
01007     RenderTableCell *cell = row->row->at(index);
01008     if (!cell || (int)cell == -1) continue;
01009 
01010 #if DEBUG_CARETMODE > 1
01011     kdDebug(6201) << "index " << index << " cell " << cell << endl;
01012 #endif
01013     RenderTable *nestedTable;
01014     if (containsEditableElement(part, cell, nestedTable, fromEnd)) {
01015 
01016       if (nestedTable) {
01017         TableRowIterator it(nestedTable, fromEnd);
01018     while (*it) {
01019       cell = findNearestTableCell(part, x, it, fromEnd);
01020       if (cell) break;
01021       if (fromEnd) --it; else ++it;
01022     }
01023       }
01024 
01025       return cell;
01026     }
01027   }
01028   return 0;
01029 }
01030 
01037 static RenderObject *commonAncestorTableSectionOrCell(RenderObject *r1,
01038         RenderObject *r2)
01039 {
01040   if (!r1 || !r2) return 0;
01041   RenderTableSection *sec = 0;
01042   int start_depth=0, end_depth=0;
01043   
01044   RenderObject *n = r1;
01045   while (n->parent()) {
01046     n = n->parent();
01047     start_depth++;
01048   }
01049   n = r2;
01050   while( n->parent()) {
01051     n = n->parent();
01052     end_depth++;
01053   }
01054   
01055   while (end_depth > start_depth) {
01056     r2 = r2->parent();
01057     end_depth--;
01058   }
01059   while (start_depth > end_depth) {
01060     r1 = r1->parent();
01061 
01062     start_depth--;
01063   }
01064   
01065   while (r1 != r2){
01066     r1 = r1->parent();
01067     if (r1->isTableSection()) sec = static_cast<RenderTableSection *>(r1);
01068     r2 = r2->parent();
01069   }
01070 
01071   
01072   
01073   while (r1 && !r1->isTableCell() && !r1->isTableSection() && !r1->isTable())
01074     r1 = r1->parent();
01075 
01076   return r1 && r1->isTable() ? sec : r1;
01077 }
01078 
01086 static int findRowInSection(RenderTableSection *section, RenderTableCell *cell,
01087         RenderTableSection::RowStruct *&row, RenderTableCell *&directCell)
01088 {
01089   
01090   RenderObject *r = cell;
01091   while (r != section) {
01092     if (r->isTableCell()) directCell = static_cast<RenderTableCell *>(r);
01093     r = r->parent();
01094   }
01095 
01096   
01097   
01098   
01099   int n = section->numRows();
01100   for (int i = 0; i < n; i++) {
01101     row = §ion->grid[i];
01102 
01103     
01104     int m = row->row->size();
01105     for (int j = 0; j < m; j++) {
01106       RenderTableCell *c = row->row->at(j);
01107       if (c == directCell) return i;
01108     }
01109 
01110   }
01111   Q_ASSERT(false);
01112   return -1;
01113 }
01114 
01120 static inline RenderTable *findFirstDescendantTable(RenderObject *leaf, RenderFlow *block)
01121 {
01122   RenderTable *result = 0;
01123   while (leaf && leaf != block) {
01124     if (leaf->isTable()) result = static_cast<RenderTable *>(leaf);
01125     leaf = leaf->parent();
01126   }
01127   return result;
01128 }
01129 
01133 static inline RenderTableCell *containingTableCell(RenderObject *r)
01134 {
01135   while (r && !r->isTableCell()) r = r->parent();
01136   return static_cast<RenderTableCell *>(r);
01137 }
01138 
01139 inline void ErgonomicEditableLineIterator::calcAndStoreNewLine(
01140             RenderFlow *newBlock, bool toBegin)
01141 {
01142   
01143   
01144   cb = newBlock;
01145   if (toBegin) prevBlock(); else nextBlock();
01146 
01147   if (!cb) {
01148     flowBox = 0;
01149     return;
01150   }
01151 
01152   if (!isEditable(*this)) {
01153     if (toBegin) EditableLineIterator::operator --();
01154     else EditableLineIterator::operator ++();
01155   }
01156 }
01157 
01158 void ErgonomicEditableLineIterator::determineTopologicalElement(
01159         RenderTableCell *oldCell, RenderObject *newObject, bool toBegin)
01160 {
01161   
01162   
01163   
01164   
01165 
01166   TableRowIterator it;
01167 
01168   RenderObject *commonAncestor = commonAncestorTableSectionOrCell(oldCell, newObject);
01169 #if DEBUG_CARETMODE > 1
01170   kdDebug(6201) << " ancestor " << commonAncestor << endl;
01171 #endif
01172 
01173   
01174   if (!commonAncestor || commonAncestor->isTableCell()) {   
01175 
01176     RenderTableCell *cell = static_cast<RenderTableCell *>(commonAncestor);
01177     RenderTable *table = findFirstDescendantTable(newObject, cell);
01178 
01179 #if DEBUG_CARETMODE > 0
01180     kdDebug(6201) << "table cell: " << cell << endl;
01181 #endif
01182 
01183     
01184     
01185     if (!table) return;
01186 
01187     it = TableRowIterator(table, toBegin);
01188 
01189   } else if (commonAncestor->isTableSection()) {        
01190 
01191     RenderTableSection *section = static_cast<RenderTableSection *>(commonAncestor);
01192     RenderTableSection::RowStruct *row;
01193     int idx = findRowInSection(section, oldCell, row, oldCell);
01194 #if DEBUG_CARETMODE > 1
01195     kdDebug(6201) << "table section: row idx " << idx << endl;
01196 #endif
01197 
01198     it = TableRowIterator(section, idx);
01199 
01200     
01201     int rowspan = oldCell->rowSpan();
01202     while (*it && rowspan--) {
01203       if (toBegin) --it; else ++it;
01204     }
01205 
01206   } else {
01207     kdError(6201) << "Neither common cell nor section! " << commonAncestor->renderName() << endl;
01208     
01209   }
01210 
01211   RenderTableCell *cell = findNearestTableCell(lines->m_part, xCoor, it, toBegin);
01212 #if DEBUG_CARETMODE > 1
01213   kdDebug(6201) << "findNearestTableCell result: " << cell << endl;
01214 #endif
01215 
01216   RenderFlow *newBlock = cell;
01217   if (!cell) {
01218     Q_ASSERT(commonAncestor->isTableSection());
01219     RenderTableSection *section = static_cast<RenderTableSection *>(commonAncestor);
01220     cell = containingTableCell(section);
01221 #if DEBUG_CARETMODE > 1
01222     kdDebug(6201) << "containing cell: " << cell << endl;
01223 #endif
01224 
01225     RenderTable *nestedTable;
01226     bool editableChild = cell && containsEditableChildElement(lines->m_part,
01227             cell, nestedTable, toBegin, section->table());
01228 
01229     if (cell && !editableChild) {
01230 #if DEBUG_CARETMODE > 1
01231       kdDebug(6201) << "========= recursive invocation outer =========" << endl;
01232 #endif
01233       determineTopologicalElement(cell, cell->section(), toBegin);
01234 #if DEBUG_CARETMODE > 1
01235       kdDebug(6201) << "========= end recursive invocation outer =========" << endl;
01236 #endif
01237       return;
01238 
01239     } else if (cell && nestedTable) {
01240 #if DEBUG_CARETMODE > 1
01241       kdDebug(6201) << "========= recursive invocation inner =========" << endl;
01242 #endif
01243       determineTopologicalElement(cell, nestedTable, toBegin);
01244 #if DEBUG_CARETMODE > 1
01245       kdDebug(6201) << "========= end recursive invocation inner =========" << endl;
01246 #endif
01247       return;
01248 
01249     } else {
01250 #if DEBUG_CARETMODE > 1
01251       kdDebug(6201) << "newBlock is table: " << section->table() << endl;
01252 #endif
01253       newBlock = section->table();
01254 
01255     }
01256   } else {
01257     
01258     RenderObject *r = cell;
01259     if (toBegin) {
01260       while (r->lastChild()) r = r->lastChild();
01261       r = nextSuitableLeafRenderObject(r);
01262     } else
01263       r = prevSuitableLeafRenderObject(r);
01264     newBlock = static_cast<RenderFlow *>(!r || r->isRenderBlock() ? r : r->containingBlock());
01265   }
01266 
01267   calcAndStoreNewLine(newBlock, toBegin);
01268 }
01269 
01270 ErgonomicEditableLineIterator &ErgonomicEditableLineIterator::operator ++()
01271 {
01272   RenderTableCell *oldCell = containingTableCell(cb);
01273 
01274   EditableLineIterator::operator ++();
01275   if (*this == lines->end() || *this == lines->preBegin()) return *this;
01276 
01277   RenderTableCell *newCell = containingTableCell(cb);
01278 
01279   if (!newCell || newCell == oldCell) return *this;
01280 
01281   determineTopologicalElement(oldCell, newCell, false);
01282 
01283   return *this;
01284 }
01285 
01286 ErgonomicEditableLineIterator &ErgonomicEditableLineIterator::operator --()
01287 {
01288   RenderTableCell *oldCell = containingTableCell(cb);
01289 
01290   EditableLineIterator::operator --();
01291   if (*this == lines->end() || *this == lines->preBegin()) return *this;
01292 
01293   RenderTableCell *newCell = containingTableCell(cb);
01294 
01295   if (!newCell || newCell == oldCell) return *this;
01296 
01297   determineTopologicalElement(oldCell, newCell, true);
01298 
01299   return *this;
01300 }
01301 
01302 
01303 
01313 static InlineBox *nearestInlineBox(LineIterator &it, CaretViewContext *cv,
01314     int &x, int &absx, int &absy)
01315 {
01316   InlineFlowBox *fbox = *it;
01317 
01318   
01319   RenderObject *cb = fbox->object();
01320 
01321   if (cb) cb->absolutePosition(absx, absy);
01322   else absx = absy = 0;
01323 
01324   
01325 
01326   
01327   x = cv->origX - absx;
01328   InlineBox *caretBox = 0; 
01329 
01330   int xPos;        
01331   int oldXPos = -1;    
01332   EditableInlineBoxIterator fbit = it;
01333 #if DEBUG_CARETMODE > 0
01334   kdDebug(6200) << "*fbit = " << *fbit << endl;
01335 #endif
01336   
01337   
01338   for (InlineBox *b; *fbit != 0; ++fbit) {
01339     b = *fbit;
01340 
01341 
01342 #if DEBUG_CARETMODE > 0
01343     if (b->isInlineFlowBox()) kdDebug(6200) << "b is inline flow box" << endl;
01344 
01345 #endif
01346 
01347     xPos = b->xPos();
01348 
01349     
01350     if (x < xPos) {
01351       
01352       if (oldXPos < 0 || x - (oldXPos + caretBox->width()) > xPos - x) {
01353     caretBox = b;   
01354 
01355       }
01356       break;        
01357     }
01358 
01359     caretBox = b;
01360 
01361 
01362     
01363     if (x >= xPos && x < xPos + caretBox->width())
01364       break;
01365     oldXPos = xPos;
01366 
01367     
01368     
01369 
01370     if (b == fbox) break;
01371   }
01372 
01373   return caretBox;
01374 }
01375 
01381 static void moveItToNextWord(EditableCharacterIterator &it)
01382 {
01383 #if DEBUG_CARETMODE > 0
01384   kdDebug(6200) << "%%%%%%%%%%%%%%%%%%%%% moveItToNextWord" << endl;
01385 #endif
01386   EditableCharacterIterator copy;
01387   while (it.node() && !(*it).isSpace() && !(*it).isPunct()) {
01388 #if DEBUG_CARETMODE > 2
01389     kdDebug(6200) << "reading1 '" << (*it).latin1() << "'" << endl;
01390 #endif
01391     copy = it;
01392     ++it;
01393   }
01394 
01395   if (!it.node()) {
01396     it = copy;
01397     return;
01398   }
01399 
01400   while (it.node() && ((*it).isSpace() || (*it).isPunct())) {
01401 #if DEBUG_CARETMODE > 2
01402     kdDebug(6200) << "reading2 '" << (*it).latin1() << "'" << endl;
01403 #endif
01404     copy = it;
01405     ++it;
01406   }
01407 
01408   if (!it.node()) it = copy;
01409 }
01410 
01416 static void moveItToPrevWord(EditableCharacterIterator &it)
01417 {
01418   if (!it.node()) return;
01419 
01420 #if DEBUG_CARETMODE > 0
01421   kdDebug(6200) << "%%%%%%%%%%%%%%%%%%%%% moveItToPrevWord" << endl;
01422 #endif
01423   EditableCharacterIterator copy;
01424 
01425   
01426   do {
01427     copy = it;
01428     --it;
01429 #if DEBUG_CARETMODE > 2
01430     if (it.node()) kdDebug(6200) << "reading1 '" << (*it).latin1() << "'" << endl;
01431 #endif
01432   } while (it.node() && ((*it).isSpace() || (*it).isPunct()));
01433 
01434   if (!it.node()) {
01435     it = copy;
01436     return;
01437   }
01438 
01439   do {
01440     copy = it;
01441     --it;
01442 #if DEBUG_CARETMODE > 0
01443     if (it.node()) kdDebug(6200) << "reading2 '" << (*it).latin1() << "'" << endl;
01444 #endif
01445   } while (it.node() && !(*it).isSpace() && !(*it).isPunct());
01446 
01447   it = copy;
01448 }
01449 
01450 
01458 static void moveIteratorByPage(LinearDocument &ld,
01459         ErgonomicEditableLineIterator &it, int mindist, bool next)
01460 {
01461   if (it == ld.end() || it == ld.preBegin()) return;
01462 
01463   ErgonomicEditableLineIterator copy = it;
01464 #if DEBUG_CARETMODE > 0
01465   kdDebug(6200) << " mindist: " << mindist << endl;
01466 #endif
01467 
01468   InlineFlowBox *flowBox = *copy;
01469   int absx = 0, absy = 0;
01470 
01471   RenderFlow *lastcb = static_cast<RenderFlow *>(flowBox->object());
01472   Q_ASSERT(lastcb->isRenderBlock());
01473   lastcb->absolutePosition(absx, absy, false);  
01474 
01475   
01476   
01477   int lastfby = flowBox->firstChild()->yPos();
01478   int lastheight = 0;
01479   do {
01480     if (next) ++copy; else --copy;
01481     if (copy == ld.end() || copy == ld.preBegin()) break;
01482 
01483     
01484     flowBox = static_cast<InlineFlowBox *>(*copy);
01485     Q_ASSERT(flowBox->isInlineFlowBox());
01486 
01487     RenderFlow *cb = static_cast<RenderFlow *>(flowBox->object());
01488     Q_ASSERT(cb->isRenderBlock());
01489 
01490     int diff = 0;
01491     
01492     
01493     int fby = flowBox->firstChild()->yPos();
01494     if (cb != lastcb) {
01495       if (next) {
01496         diff = absy + lastfby + lastheight;
01497         cb->absolutePosition(absx, absy, false);    
01498         diff = absy - diff + fby;
01499         lastfby = 0;
01500       } else {
01501         diff = absy;
01502         cb->absolutePosition(absx, absy, false);    
01503         diff -= absy + fby + lastheight;
01504     lastfby = fby - lastheight;
01505       }
01506 #if DEBUG_CARETMODE > 2
01507       kdDebug(6200) << "absdiff " << diff << endl;
01508 #endif
01509     } else {
01510       diff = QABS(fby - lastfby);
01511     }
01512 #if DEBUG_CARETMODE > 2
01513     kdDebug(6200) << "flowBox->firstChild->yPos: " << fby << " diff " << diff << endl;
01514 #endif
01515 
01516     mindist -= diff;
01517 
01518     lastheight = QABS(fby - lastfby);
01519     lastfby = fby;
01520     lastcb = cb;
01521     it = copy;
01522 #if DEBUG_CARETMODE > 0
01523     kdDebug(6200) << " mindist: " << mindist << endl;
01524 #endif
01525     
01526     
01527     
01528     
01529   } while (mindist - lastheight > 0);
01530 }
01531 
01532 
01533 }
01534