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