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;
00484
#endif
00485
if (r && withinCb && r->element() && !r->isTableCol()
00486 && (part->
isCaretMode() || part->
isEditable()
00487 || r->style()->userInput() == UI_ENABLED)) {
00488 table = tempTable;
00489
return true;
00490 }
00491
00492 r = fromEnd ? prevSuitableLeafRenderObject(r) : nextSuitableLeafRenderObject(r);
00493 }
while (r && withinCb);
00494
return false;
00495 }
00496
00509
static bool containsEditableChildElement(
KHTMLPart *part, RenderFlow *cb,
00510 RenderTable *&table,
bool fromEnd, RenderObject *start)
00511 {
00512 RenderObject *r = start;
00513
if (fromEnd)
00514
while (r->firstChild()) r = r->firstChild();
00515
else
00516
while (r->lastChild()) r = r->lastChild();
00517
00518
if (!r)
return false;
00519
00520 RenderTable *tempTable = 0;
00521 table = 0;
00522
bool withinCb =
false;
00523
do {
00524 r = fromEnd ? prevSuitableLeafRenderObject(r) : nextSuitableLeafRenderObject(r);
00525
if (!r)
break;
00526
00527 withinCb = isDescendant(r, cb) && r != cb;
00528 tempTable = findTableUpTo(r, cb);
00529
00530
#if DEBUG_CARETMODE > 1
00531
kdDebug(6201) <<
"r " << (r ? r->renderName() :
QString::null) <<
"@" << r <<
endl;
00532
#endif
00533
if (r && withinCb && r->element() && !r->isTableCol()
00534 && (part->
isCaretMode() || part->
isEditable()
00535 || r->style()->userInput() == UI_ENABLED)) {
00536 table = tempTable;
00537
return true;
00538 }
00539
00540 }
while (withinCb);
00541
return false;
00542 }
00543
00544
00545
00546 LinearDocument::LinearDocument(
KHTMLPart *part, NodeImpl *node,
long offset)
00547 : arena(0), node(node), offset(offset), m_part(part)
00548 {
00549
if (node == 0)
return;
00550 sanitizeCaretState(this->node, this->offset);
00551
00552 arena =
new RenderArena(512);
00553
00554 initPreBeginIterator();
00555 initEndIterator();
00556
00557 }
00558
00559 LinearDocument::~LinearDocument()
00560 {
00561
delete arena;
00562 }
00563
00564 int LinearDocument::count()
const
00565
{
00566
00567
return 1;
00568 }
00569
00570 LinearDocument::Iterator LinearDocument::current()
00571 {
00572
return LineIterator(
this, node, offset);
00573 }
00574
00575 LinearDocument::Iterator LinearDocument::begin()
00576 {
00577 DocumentImpl *doc = node ? node->getDocument() : 0;
00578
if (!doc)
return end();
00579
00580 NodeImpl *firstLeaf = doc->nextLeafNode();
00581
if (!firstLeaf)
return end();
00582
return LineIterator(
this, firstLeaf, firstLeaf->minOffset());
00583 }
00584
00585 LinearDocument::Iterator LinearDocument::preEnd()
00586 {
00587 DocumentImpl *doc = node ? node->getDocument() : 0;
00588
if (!doc)
return preBegin();
00589
00590 NodeImpl *lastLeaf = doc;
00591
while (lastLeaf->lastChild()) lastLeaf = lastLeaf->lastChild();
00592
00593
if (!lastLeaf)
return preBegin();
00594
return LineIterator(
this, lastLeaf, lastLeaf->maxOffset());
00595 }
00596
00597
void LinearDocument::initPreBeginIterator()
00598 {
00599 _preBegin =
LineIterator(
this, 0, 0);
00600 }
00601
00602
void LinearDocument::initEndIterator()
00603 {
00604 _end = LineIterator(
this, 0, 1);
00605 }
00606
00607
00608
00609 LineIterator::LineIterator(
LinearDocument *l, DOM::NodeImpl *node,
long offset)
00610 : lines(l)
00611 {
00612
00613 flowBox = findFlowBox(node, offset, lines->
arena, cb, ¤tBox);
00614
if (!flowBox) {
00615
#if DEBUG_CARETMODE > 0
00616
kdDebug(6200) <<
"LineIterator: findFlowBox failed" <<
endl;
00617
#endif
00618
cb = 0;
00619 }
00620 }
00621
00622 void LineIterator::nextBlock()
00623 {
00624 RenderObject *r = cb;
00625 RenderObject *n = r->lastChild();
00626
while (n) r = n, n = r->lastChild();
00627 r = nextSuitableLeafRenderObject(r);
00628
#if DEBUG_CARETMODE > 0
00629
kdDebug(6200) <<
"++: r " << r <<
"[" << (r?r->renderName():QString::null) <<
"]" <<
endl;
00630
#endif
00631
if (!r) {
00632 cb = 0;
00633
return;
00634 }
00635
00636
00637
00638
if (r->isRenderBlock()) {
00639 cb = static_cast<RenderBlock *>(r);
00640
#if DEBUG_CARETMODE > 0
00641
kdDebug(6200) <<
"r->isFlow is cb. continuation @" << cb->continuation() <<
endl;
00642
#endif
00643
00644
00645
00646
00647 RenderFlow *flow = static_cast<RenderFlow *>(cb->element()
00648 ? cb->element()->renderer() : 0);
00649
if (cb->continuation() || flow && flow->isRenderBlock() && flow != cb
00650 && flow->continuation()) {
00651
nextBlock();
00652
return;
00653 }
00654 }
else {
00655 cb = static_cast<RenderFlow *>(r->containingBlock());
00656
if (!cb->isRenderBlock()) {
00657
#if DEBUG_CARETMODE > 0
00658
kdDebug(6200) <<
"dummy cb created " << cb <<
endl;
00659
#endif
00660
cb = generateDummyBlock(lines->
arena, r);
00661 }
00662 }
00663 flowBox = cb->firstLineBox();
00664
#if DEBUG_CARETMODE > 0
00665
kdDebug(6200) <<
"++: flowBox " << flowBox <<
endl;
00666
#endif
00667
00668
if (!flowBox) flowBox = generateDummyFlowBox(lines->
arena, cb, r);
00669
#if DEBUG_CARETMODE > 0
00670
if (!cb->firstLineBox())
kdDebug(6200) <<
"++: dummy flowBox " << flowBox <<
endl;
00671
#endif
00672
}
00673
00674 inline LineIterator &LineIterator::operator ++()
00675 {
00676 flowBox = static_cast<InlineFlowBox *>(flowBox->nextLineBox());
00677
00678
00679
00680
if (!flowBox)
nextBlock();
00681
00682
return *
this;
00683 }
00684
00685 inline LineIterator LineIterator::operator ++(
int)
00686 {
00687
LineIterator it(*
this);
00688
operator ++();
00689
return it;
00690 }
00691
00692 void LineIterator::prevBlock()
00693 {
00694 RenderObject *r = cb;
00695 RenderObject *n = r->firstChild();
00696
while (n) r = n, n = r->firstChild();
00697 r = prevSuitableLeafRenderObject(r);
00698
if (!r) {
00699 cb = 0;
00700
return;
00701 }
00702
00703
00704
00705
if (r->isRenderBlock()) {
00706 cb = static_cast<RenderFlow *>(r);
00707
#if DEBUG_CARETMODE > 0
00708
kdDebug(6200) <<
"r->isFlow is cb. continuation @" << cb->continuation() <<
endl;
00709
#endif
00710
00711
00712
00713
00714 RenderFlow *flow = static_cast<RenderFlow *>(cb->element()
00715 ? cb->element()->renderer() : 0);
00716
if (cb->continuation() || flow && flow->isRenderBlock() && flow != cb
00717 && flow->continuation()) {
00718
prevBlock();
00719
return;
00720 }
00721 }
else {
00722 cb = static_cast<RenderFlow *>(r->containingBlock());
00723
if (!cb->isRenderBlock()) {
00724
#if DEBUG_CARETMODE > 0
00725
kdDebug(6200) <<
"dummy cb created " << cb <<
endl;
00726
#endif
00727
cb = generateDummyBlock(lines->
arena, r);
00728 }
00729 }
00730 flowBox = cb->lastLineBox();
00731
00732
if (!flowBox) flowBox = generateDummyFlowBox(lines->
arena, cb, r);
00733 }
00734
00735 inline LineIterator &LineIterator::operator --()
00736 {
00737 flowBox = static_cast<InlineFlowBox *>(flowBox->prevLineBox());
00738
00739
00740
00741
if (!flowBox)
prevBlock();
00742
00743
return *
this;
00744 }
00745
00746 inline LineIterator LineIterator::operator --(
int)
00747 {
00748
LineIterator it(*
this);
00749
operator --();
00750
return it;
00751 }
00752
00753
#if 0 // not implemented because it's not needed
00754
LineIterator LineIterator::operator +(
int )
const
00755
{
00756
00757
return LineIterator();
00758 }
00759
00760 LineIterator LineIterator::operator -(
int )
const
00761
{
00762
00763
return LineIterator();
00764 }
00765
#endif
00766
00767 LineIterator &LineIterator::operator +=(
int summand)
00768 {
00769
if (summand > 0)
00770
while (summand-- && *
this != lines->
end()) ++*
this;
00771
else if (summand < 0)
00772
operator -=(-summand);
00773
return *
this;
00774 }
00775
00776 LineIterator &LineIterator::operator -=(
int summand)
00777 {
00778
if (summand > 0)
00779
while (summand-- && *
this != lines->
preBegin()) --*
this;
00780
else if (summand < 0)
00781
operator +=(-summand);
00782
return *
this;
00783 }
00784
00785
00786
00787 void EditableCharacterIterator::initFirstChar()
00788 {
00789 InlineBox *b = *ebit;
00790
if (b) {
00791
if (_offset == b->maxOffset())
00792
peekNext();
00793
else if (b->isInlineTextBox())
00794 _char = static_cast<RenderText *>(b->object())->str->s[_offset].unicode();
00795
else
00796 _char = -1;
00797 }
00798 }
00799
00800 EditableCharacterIterator &EditableCharacterIterator::operator ++()
00801 {
00802 _offset++;
00803
00804 InlineBox *b = *ebit;
00805 RenderObject *r = b->object();
00806
00807
00808
00809
long maxofs = r->isBR() || r->isRenderBlock() ? b->minOffset() : b->maxOffset();
00810
#if DEBUG_CARETMODE > 0
00811
kdDebug(6200) <<
"b->maxOffset() " << b->maxOffset() <<
" b->minOffset() " << b->minOffset() <<
endl;
00812
#endif
00813
if (_offset == maxofs) {
00814
#if DEBUG_CARETMODE > 2
00815
kdDebug(6200) <<
"_offset == maxofs: " << _offset <<
" == " << maxofs <<
endl;
00816
#endif
00817
00818
peekNext();
00819 }
else if (_offset > maxofs) {
00820
#if DEBUG_CARETMODE > 2
00821
kdDebug(6200) <<
"_offset > maxofs: " << _offset <<
" > " << maxofs <<
endl;
00822
#endif
00823
if (
true) {
00824
if (*ebit)
00825 ++ebit;
00826
if (!*ebit) {
00827 ++_it;
00828
#if DEBUG_CARETMODE > 3
00829
kdDebug(6200) <<
"++_it" <<
endl;
00830
#endif
00831
if (_it != ld->
end()) {
00832 ebit = _it;
00833 b = *ebit;
00834
#if DEBUG_CARETMODE > 3
00835
kdDebug(6200) <<
"b " << b <<
" isText " << b->isInlineTextBox() <<
endl;
00836
#endif
00837
_node = b->object()->element();
00838
#if DEBUG_CARETMODE > 3
00839
kdDebug(6200) <<
"_node " << _node <<
":" << _node->nodeName().string() <<
endl;
00840
#endif
00841
_offset = b->minOffset();
00842
#if DEBUG_CARETMODE > 3
00843
kdDebug(6200) <<
"_offset " << _offset <<
endl;
00844
#endif
00845
}
else {
00846 _node = 0;
00847 b = 0;
00848 }
00849
goto readchar;
00850 }
00851 }
00852
bool adjacent = ebit.isAdjacent();
00853
00854
if (adjacent && !(*ebit)->isInlineTextBox()) {
00855
EditableInlineBoxIterator copy = ebit;
00856 ++ebit;
00857
if (*ebit && (*ebit)->isInlineTextBox()) adjacent =
false;
00858
else ebit = copy;
00859 }
00860 _node = (*ebit)->object()->element();
00861 _offset = (*ebit)->minOffset() + adjacent;
00862
00863 b = *ebit;
00864
goto readchar;
00865 }
else {
00866 readchar:
00867
00868
if (b && b->isInlineTextBox() && _offset < b->maxOffset())
00869 _char = static_cast<RenderText *>(b->object())->str->s[_offset].unicode();
00870
else
00871 _char = -1;
00872 }
00873
#if DEBUG_CARETMODE > 2
00874
kdDebug(6200) <<
"_offset: " << _offset <<
" char '" << (
char)_char <<
"'" <<
endl;
00875
#endif
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) <<
" node " << (_node ? _node->nodeName().string() :
QString(
"<nil>")) <<
endl;
00881 }
00882
#endif
00883
return *
this;
00884 }
00885
00886 EditableCharacterIterator &EditableCharacterIterator::operator --()
00887 {
00888 _offset--;
00889
00890
00891 InlineBox *b = *ebit;
00892 InlineBox *_peekPrev = 0;
00893 InlineBox *_peekNext = 0;
00894
long minofs = b ? b->minOffset() : _offset + 1;
00895
#if DEBUG_CARETMODE > 0
00896
kdDebug(6200) <<
"b->maxOffset() " << b->maxOffset() <<
" b->minOffset() " << b->minOffset() <<
endl;
00897
#endif
00898
if (_offset == minofs) {
00899
#if DEBUG_CARETMODE > 2
00900
kdDebug(6200) <<
"_offset == minofs: " << _offset <<
" == " << minofs <<
endl;
00901
#endif
00902
_peekNext = b;
00903
00904
if (b && b->isInlineTextBox())
00905 _char = static_cast<RenderText *>(b->object())->text()[_offset].unicode();
00906
else
00907 _char = -1;
00908
00909
00910
bool do_prev =
false;
00911 {
00912
EditableInlineBoxIterator copy = ebit;
00913 --ebit;
00914 _peekPrev = *ebit;
00915
00916
if (ebit.isAdjacent() && *ebit && (*ebit)->isInlineTextBox())
00917
00918 do_prev =
true;
00919
else
00920 ebit = copy;
00921 }
00922
if (do_prev)
goto prev;
00923 }
else if (_offset < minofs) {
00924 prev:
00925
#if DEBUG_CARETMODE > 2
00926
kdDebug(6200) <<
"_offset < minofs: " << _offset <<
" < " << minofs <<
endl;
00927
#endif
00928
if (!_peekPrev) {
00929 _peekNext = *ebit;
00930
if (*ebit)
00931 --ebit;
00932
if (!*ebit) {
00933 --_it;
00934
#if DEBUG_CARETMODE > 3
00935
kdDebug(6200) <<
"--_it" <<
endl;
00936
#endif
00937
if (_it != ld->
preBegin()) {
00938
00939 ebit =
EditableInlineBoxIterator(_it,
true);
00940 RenderObject *r = (*ebit)->object();
00941
#if DEBUG_CARETMODE > 3
00942
kdDebug(6200) <<
"b " << *ebit <<
" isText " << (*ebit)->isInlineTextBox() <<
endl;
00943
#endif
00944
_node = r->element();
00945 _offset = r->isBR() ? (*ebit)->minOffset() : (*ebit)->maxOffset();
00946 _char = -1;
00947
#if DEBUG_CARETMODE > 0
00948
{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;}
00949
#endif
00950
}
else
00951 _node = 0;
00952
return *
this;
00953 }
00954 }
00955
00956
bool adjacent = ebit.isAdjacent();
00957
00958
#if DEBUG_CARETMODE > 0
00959
kdDebug(6200) <<
"adjacent " << adjacent <<
" _peekNext " << _peekNext <<
" _peekNext->isInlineTextBox: " << (_peekNext ? _peekNext->isInlineTextBox() :
false) <<
" !((*ebit)->isInlineTextBox): " << (*ebit ? !(*ebit)->isInlineTextBox() :
true) <<
endl;
00960
#endif
00961
if (adjacent && _peekNext && _peekNext->isInlineTextBox()
00962 && !(*ebit)->isInlineTextBox()) {
00963
EditableInlineBoxIterator copy = ebit;
00964 --ebit;
00965
if (!*ebit)
00966 ebit = copy;
00967 }
00968
#if DEBUG_CARETMODE > 0
00969
kdDebug(6200) <<
"(*ebit)->obj " << (*ebit)->object()->renderName() <<
"[" << (*ebit)->object() <<
"]" <<
" minOffset: " << (*ebit)->minOffset() <<
" maxOffset: " << (*ebit)->maxOffset() <<
endl;
00970
#endif
00971
_node = (*ebit)->object()->element();
00972
#if DEBUG_CARETMODE > 3
00973
kdDebug(6200) <<
"_node " << _node <<
":" << _node->nodeName().string() <<
endl;
00974
#endif
00975
_offset = (*ebit)->maxOffset();
00976
#if DEBUG_CARETMODE > 3
00977
kdDebug(6200) <<
"_offset " << _offset <<
endl;
00978
#endif
00979
_peekPrev = 0;
00980 }
else {
00981
#if DEBUG_CARETMODE > 0
00982
kdDebug(6200) <<
"_offset: " << _offset <<
" _peekNext: " << _peekNext <<
endl;
00983
#endif
00984
00985
if (_peekNext && _offset >= b->maxOffset() && _peekNext->isInlineTextBox())
00986 _char = static_cast<RenderText *>(_peekNext->object())->text()[_peekNext->minOffset()].unicode();
00987
else if (b && _offset < b->maxOffset() && b->isInlineTextBox())
00988 _char = static_cast<RenderText *>(b->object())->text()[_offset].unicode();
00989
else
00990 _char = -1;
00991 }
00992
00993
#if DEBUG_CARETMODE > 0
00994
if (*ebit) {
00995 InlineBox *box = *ebit;
00996
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;
00997 }
00998
#endif
00999
return *
this;
01000 }
01001
01002
01003
01004 TableRowIterator::TableRowIterator(RenderTable *table,
bool fromEnd,
01005 RenderTableSection::RowStruct *row)
01006 : sec(table, fromEnd)
01007 {
01008
01009
if (*sec) {
01010
if (fromEnd) index = (*sec)->grid.size() - 1;
01011
else index = 0;
01012 }
01013
01014
01015
if (row && *sec) {
01016
while (
operator *() != row)
01017
if (fromEnd)
operator --();
else operator ++();
01018 }
01019 }
01020
01021 TableRowIterator &TableRowIterator::operator ++()
01022 {
01023 index++;
01024
01025
if (index >= (
int)(*sec)->grid.size()) {
01026 ++sec;
01027
01028
if (*sec) index = 0;
01029 }
01030
return *
this;
01031 }
01032
01033 TableRowIterator &TableRowIterator::operator --()
01034 {
01035 index--;
01036
01037
if (index < 0) {
01038 --sec;
01039
01040
if (*sec) index = (*sec)->grid.size() - 1;
01041 }
01042
return *
this;
01043 }
01044
01045
01046
01047
01048
static RenderTableCell *findNearestTableCellInRow(
KHTMLPart *part,
int x,
01049 RenderTableSection::RowStruct *row,
bool fromEnd);
01050
01064
static inline RenderTableCell *findNearestTableCell(
KHTMLPart *part,
int x,
01065
TableRowIterator &it,
bool fromEnd)
01066 {
01067 RenderTableCell *result = 0;
01068
01069
while (*it) {
01070 result = findNearestTableCellInRow(part, x, *it, fromEnd);
01071
if (result)
break;
01072
01073
if (fromEnd) --it;
else ++it;
01074 }
01075
01076
return result;
01077 }
01078
01092
static RenderTableCell *findNearestTableCellInRow(
KHTMLPart *part,
int x,
01093 RenderTableSection::RowStruct *row,
bool fromEnd)
01094 {
01095
01096
int n = (
int)row->row->size();
01097
int i;
01098
for (i = 0; i < n; i++) {
01099 RenderTableCell *cell = row->row->at(i);
01100
if (!cell || (
int)cell == -1)
continue;
01101
01102
int absx, absy;
01103 cell->absolutePosition(absx, absy,
false);
01104
#if DEBUG_CARETMODE > 1
01105
kdDebug(6201) <<
"i/n " << i <<
"/" << n <<
" absx " << absx <<
" absy " << absy <<
endl;
01106
#endif
01107
01108
01109
01110
#if DEBUG_CARETMODE > 1
01111
kdDebug(6201) <<
"x " << x <<
" < " << (absx + cell->width()) <<
"?" <<
endl;
01112
#endif
01113
if (x < absx + cell->width())
break;
01114 }
01115
if (i >= n) i = n - 1;
01116
01117
01118
01119
for (
int cnt = 0; cnt < 2*n; cnt++) {
01120
int index = i - ((cnt >> 1) + 1)*(cnt & 1) + (cnt >> 1)*!(cnt & 1);
01121
if (index < 0 || index >= n)
continue;
01122
01123 RenderTableCell *cell = row->row->at(index);
01124
if (!cell || (
int)cell == -1)
continue;
01125
01126
#if DEBUG_CARETMODE > 1
01127
kdDebug(6201) <<
"index " << index <<
" cell " << cell <<
endl;
01128
#endif
01129
RenderTable *nestedTable;
01130
if (containsEditableElement(part, cell, nestedTable, fromEnd)) {
01131
01132
if (nestedTable) {
01133 TableRowIterator it(nestedTable, fromEnd);
01134
while (*it) {
01135 cell = findNearestTableCell(part, x, it, fromEnd);
01136
if (cell)
break;
01137
if (fromEnd) --it;
else ++it;
01138 }
01139 }
01140
01141
return cell;
01142 }
01143 }
01144
return 0;
01145 }
01146
01153
static RenderObject *commonAncestorTableSectionOrCell(RenderObject *r1,
01154 RenderObject *r2)
01155 {
01156
if (!r1 || !r2)
return 0;
01157 RenderTableSection *sec = 0;
01158
int start_depth=0, end_depth=0;
01159
01160 RenderObject *n = r1;
01161
while (n->parent()) {
01162 n = n->parent();
01163 start_depth++;
01164 }
01165 n = r2;
01166
while( n->parent()) {
01167 n = n->parent();
01168 end_depth++;
01169 }
01170
01171
while (end_depth > start_depth) {
01172 r2 = r2->parent();
01173 end_depth--;
01174 }
01175
while (start_depth > end_depth) {
01176 r1 = r1->parent();
01177
01178 start_depth--;
01179 }
01180
01181
while (r1 != r2){
01182 r1 = r1->parent();
01183
if (r1->isTableSection()) sec = static_cast<RenderTableSection *>(r1);
01184 r2 = r2->parent();
01185 }
01186
01187
01188
01189
while (r1 && !r1->isTableCell() && !r1->isTableSection() && !r1->isTable())
01190 r1 = r1->parent();
01191
01192
return r1 && r1->isTable() ? sec : r1;
01193 }
01194
01202
static int findRowInSection(RenderTableSection *section, RenderTableCell *cell,
01203 RenderTableSection::RowStruct *&row, RenderTableCell *&directCell)
01204 {
01205
01206 RenderObject *r = cell;
01207
while (r != section) {
01208
if (r->isTableCell()) directCell = static_cast<RenderTableCell *>(r);
01209 r = r->parent();
01210 }
01211
01212
01213
01214
01215
int n = section->numRows();
01216
for (
int i = 0; i < n; i++) {
01217 row = §ion->grid[i];
01218
01219
01220
int m = row->row->size();
01221
for (
int j = 0; j < m; j++) {
01222 RenderTableCell *c = row->row->at(j);
01223
if (c == directCell)
return i;
01224 }
01225
01226 }
01227 Q_ASSERT(
false);
01228
return -1;
01229 }
01230
01236
static inline RenderTable *findFirstDescendantTable(RenderObject *leaf, RenderFlow *block)
01237 {
01238 RenderTable *result = 0;
01239
while (leaf && leaf != block) {
01240
if (leaf->isTable()) result = static_cast<RenderTable *>(leaf);
01241 leaf = leaf->parent();
01242 }
01243
return result;
01244 }
01245
01249
static inline RenderTableCell *containingTableCell(RenderObject *r)
01250 {
01251
while (r && !r->isTableCell()) r = r->parent();
01252
return static_cast<RenderTableCell *>(r);
01253 }
01254
01255 inline void ErgonomicEditableLineIterator::calcAndStoreNewLine(
01256 RenderFlow *newBlock,
bool toBegin)
01257 {
01258
01259
01260 cb = newBlock;
01261
if (toBegin)
prevBlock();
else nextBlock();
01262
01263
if (!cb) {
01264 flowBox = 0;
01265
return;
01266 }
01267
01268
if (!
isEditable(*
this)) {
01269
if (toBegin) EditableLineIterator::operator --();
01270
else EditableLineIterator::operator ++();
01271 }
01272 }
01273
01274 void ErgonomicEditableLineIterator::determineTopologicalElement(
01275 RenderTableCell *oldCell, RenderObject *newObject,
bool toBegin)
01276 {
01277
01278
01279
01280
01281
01282
TableRowIterator it;
01283
01284 RenderObject *commonAncestor = commonAncestorTableSectionOrCell(oldCell, newObject);
01285
#if DEBUG_CARETMODE > 1
01286
kdDebug(6201) <<
" ancestor " << commonAncestor <<
endl;
01287
#endif
01288
01289
01290
if (!commonAncestor || commonAncestor->isTableCell()) {
01291
01292 RenderTableCell *cell = static_cast<RenderTableCell *>(commonAncestor);
01293 RenderTable *table = findFirstDescendantTable(newObject, cell);
01294
01295
#if DEBUG_CARETMODE > 0
01296
kdDebug(6201) <<
"table cell: " << cell <<
endl;
01297
#endif
01298
01299
01300
01301
if (!table)
return;
01302
01303 it =
TableRowIterator(table, toBegin);
01304
01305 }
else if (commonAncestor->isTableSection()) {
01306
01307 RenderTableSection *section = static_cast<RenderTableSection *>(commonAncestor);
01308 RenderTableSection::RowStruct *row;
01309
int idx = findRowInSection(section, oldCell, row, oldCell);
01310
#if DEBUG_CARETMODE > 1
01311
kdDebug(6201) <<
"table section: row idx " << idx <<
endl;
01312
#endif
01313
01314 it =
TableRowIterator(section, idx);
01315
01316
01317
int rowspan = oldCell->rowSpan();
01318
while (*it && rowspan--) {
01319
if (toBegin) --it;
else ++it;
01320 }
01321
01322 }
else {
01323
kdError(6201) <<
"Neither common cell nor section! " << commonAncestor->renderName() <<
endl;
01324
01325 }
01326
01327 RenderTableCell *cell = findNearestTableCell(lines->
m_part, xCoor, it, toBegin);
01328
#if DEBUG_CARETMODE > 1
01329
kdDebug(6201) <<
"findNearestTableCell result: " << cell <<
endl;
01330
#endif
01331
01332 RenderFlow *newBlock = cell;
01333
if (!cell) {
01334 Q_ASSERT(commonAncestor->isTableSection());
01335 RenderTableSection *section = static_cast<RenderTableSection *>(commonAncestor);
01336 cell = containingTableCell(section);
01337
#if DEBUG_CARETMODE > 1
01338
kdDebug(6201) <<
"containing cell: " << cell <<
endl;
01339
#endif
01340
01341 RenderTable *nestedTable;
01342
bool editableChild = cell && containsEditableChildElement(lines->
m_part,
01343 cell, nestedTable, toBegin, section->table());
01344
01345
if (cell && !editableChild) {
01346
#if DEBUG_CARETMODE > 1
01347
kdDebug(6201) <<
"========= recursive invocation outer =========" <<
endl;
01348
#endif
01349
determineTopologicalElement(cell, cell->section(), toBegin);
01350
#if DEBUG_CARETMODE > 1
01351
kdDebug(6201) <<
"========= end recursive invocation outer =========" <<
endl;
01352
#endif
01353
return;
01354
01355 }
else if (cell && nestedTable) {
01356
#if DEBUG_CARETMODE > 1
01357
kdDebug(6201) <<
"========= recursive invocation inner =========" <<
endl;
01358
#endif
01359
determineTopologicalElement(cell, nestedTable, toBegin);
01360
#if DEBUG_CARETMODE > 1
01361
kdDebug(6201) <<
"========= end recursive invocation inner =========" <<
endl;
01362
#endif
01363
return;
01364
01365 }
else {
01366
#if DEBUG_CARETMODE > 1
01367
kdDebug(6201) <<
"newBlock is table: " << section->table() <<
endl;
01368
#endif
01369
newBlock = section->table();
01370
01371 }
01372 }
else {
01373
01374 RenderObject *r = cell;
01375
if (toBegin) {
01376
while (r->lastChild()) r = r->lastChild();
01377 r = nextSuitableLeafRenderObject(r);
01378 }
else
01379 r = prevSuitableLeafRenderObject(r);
01380 newBlock = static_cast<RenderFlow *>(!r || r->isRenderBlock() ? r : r->containingBlock());
01381 }
01382
01383
calcAndStoreNewLine(newBlock, toBegin);
01384 }
01385
01386 ErgonomicEditableLineIterator &ErgonomicEditableLineIterator::operator ++()
01387 {
01388 RenderTableCell *oldCell = containingTableCell(cb);
01389
01390 EditableLineIterator::operator ++();
01391
if (*
this == lines->
end() || *
this == lines->
preBegin())
return *
this;
01392
01393 RenderTableCell *newCell = containingTableCell(cb);
01394
01395
if (!newCell || newCell == oldCell)
return *
this;
01396
01397
determineTopologicalElement(oldCell, newCell,
false);
01398
01399
return *
this;
01400 }
01401
01402 ErgonomicEditableLineIterator &ErgonomicEditableLineIterator::operator --()
01403 {
01404 RenderTableCell *oldCell = containingTableCell(cb);
01405
01406 EditableLineIterator::operator --();
01407
if (*
this == lines->
end() || *
this == lines->
preBegin())
return *
this;
01408
01409 RenderTableCell *newCell = containingTableCell(cb);
01410
01411
if (!newCell || newCell == oldCell)
return *
this;
01412
01413
determineTopologicalElement(oldCell, newCell,
true);
01414
01415
return *
this;
01416 }
01417
01418
01419
01429
static InlineBox *nearestInlineBox(
LineIterator &it,
CaretViewContext *cv,
01430
int &x,
int &absx,
int &absy)
01431 {
01432 InlineFlowBox *fbox = *it;
01433
01434
01435 RenderObject *cb = fbox->object();
01436
01437
if (cb) cb->absolutePosition(absx, absy);
01438
else absx = absy = 0;
01439
01440
01441
01442
01443 x = cv->
origX - absx;
01444 InlineBox *caretBox = 0;
01445
01446
int xPos;
01447
int oldXPos = -1;
01448
EditableInlineBoxIterator fbit = it;
01449
#if DEBUG_CARETMODE > 0
01450
kdDebug(6200) <<
"*fbit = " << *fbit <<
endl;
01451
#endif
01452
01453
01454
for (InlineBox *b; *fbit != 0; ++fbit) {
01455 b = *fbit;
01456
01457
01458
#if DEBUG_CARETMODE > 0
01459
if (b->isInlineFlowBox())
kdDebug(6200) <<
"b is inline flow box" <<
endl;
01460
01461
#endif
01462
01463 xPos = b->xPos();
01464
01465
01466
if (x < xPos) {
01467
01468
if (oldXPos < 0 || x - (oldXPos + caretBox->width()) > xPos - x) {
01469 caretBox = b;
01470
01471 }
01472
break;
01473 }
01474
01475 caretBox = b;
01476
01477
01478
01479
if (x >= xPos && x < xPos + caretBox->width())
01480
break;
01481 oldXPos = xPos;
01482
01483
01484
01485
01486
if (b == fbox)
break;
01487 }
01488
01489
return caretBox;
01490 }
01491
01497
static void moveItToNextWord(EditableCharacterIterator &it)
01498 {
01499
#if DEBUG_CARETMODE > 0
01500
kdDebug(6200) <<
"%%%%%%%%%%%%%%%%%%%%% moveItToNextWord" <<
endl;
01501
#endif
01502
EditableCharacterIterator
copy;
01503
while (it.node() && !(*it).isSpace() && !(*it).isPunct()) {
01504
#if DEBUG_CARETMODE > 2
01505
kdDebug(6200) <<
"reading1 '" << (*it).latin1() <<
"'" <<
endl;
01506
#endif
01507
copy = it;
01508 ++it;
01509 }
01510
01511
if (!it.node()) {
01512 it =
copy;
01513
return;
01514 }
01515
01516
while (it.node() && ((*it).isSpace() || (*it).isPunct())) {
01517
#if DEBUG_CARETMODE > 2
01518
kdDebug(6200) <<
"reading2 '" << (*it).latin1() <<
"'" <<
endl;
01519
#endif
01520
copy = it;
01521 ++it;
01522 }
01523
01524
if (!it.node()) it =
copy;
01525 }
01526
01532
static void moveItToPrevWord(EditableCharacterIterator &it)
01533 {
01534
if (!it.node())
return;
01535
01536
#if DEBUG_CARETMODE > 0
01537
kdDebug(6200) <<
"%%%%%%%%%%%%%%%%%%%%% moveItToPrevWord" <<
endl;
01538
#endif
01539
EditableCharacterIterator
copy;
01540
01541
01542
do {
01543
copy = it;
01544 --it;
01545
#if DEBUG_CARETMODE > 2
01546
if (it.node())
kdDebug(6200) <<
"reading1 '" << (*it).latin1() <<
"'" <<
endl;
01547
#endif
01548
}
while (it.node() && ((*it).isSpace() || (*it).isPunct()));
01549
01550
if (!it.node()) {
01551 it =
copy;
01552
return;
01553 }
01554
01555
do {
01556
copy = it;
01557 --it;
01558
#if DEBUG_CARETMODE > 0
01559
if (it.node())
kdDebug(6200) <<
"reading2 '" << (*it).latin1() <<
"'" <<
endl;
01560
#endif
01561
}
while (it.node() && !(*it).isSpace() && !(*it).isPunct());
01562
01563 it =
copy;
01564 }
01565
01566
01574
static void moveIteratorByPage(LinearDocument &ld,
01575 ErgonomicEditableLineIterator &it,
int mindist,
bool next)
01576 {
01577
if (it == ld.end() || it == ld.preBegin())
return;
01578
01579 ErgonomicEditableLineIterator
copy = it;
01580
#if DEBUG_CARETMODE > 0
01581
kdDebug(6200) <<
" mindist: " << mindist <<
endl;
01582
#endif
01583
01584 InlineFlowBox *flowBox = *
copy;
01585
int absx = 0, absy = 0;
01586
01587 RenderFlow *lastcb = static_cast<RenderFlow *>(flowBox->object());
01588 Q_ASSERT(lastcb->isRenderBlock());
01589 lastcb->absolutePosition(absx, absy,
false);
01590
01591
01592
01593
int lastfby = flowBox->firstChild()->yPos();
01594
int lastheight = 0;
01595
do {
01596
if (
next) ++
copy;
else --
copy;
01597
if (
copy == ld.end() ||
copy == ld.preBegin())
break;
01598
01599
01600 flowBox = static_cast<InlineFlowBox *>(*copy);
01601 Q_ASSERT(flowBox->isInlineFlowBox());
01602
01603 RenderFlow *cb = static_cast<RenderFlow *>(flowBox->object());
01604 Q_ASSERT(cb->isRenderBlock());
01605
01606
int diff = 0;
01607
01608
01609
int fby = flowBox->firstChild()->yPos();
01610
if (cb != lastcb) {
01611
if (
next) {
01612 diff = absy + lastfby + lastheight;
01613 cb->absolutePosition(absx, absy,
false);
01614 diff = absy - diff + fby;
01615 lastfby = 0;
01616 }
else {
01617 diff = absy;
01618 cb->absolutePosition(absx, absy,
false);
01619 diff -= absy + fby + lastheight;
01620 lastfby = fby - lastheight;
01621 }
01622
#if DEBUG_CARETMODE > 2
01623
kdDebug(6200) <<
"absdiff " << diff <<
endl;
01624
#endif
01625
}
else {
01626 diff = QABS(fby - lastfby);
01627 }
01628
#if DEBUG_CARETMODE > 2
01629
kdDebug(6200) <<
"flowBox->firstChild->yPos: " << fby <<
" diff " << diff <<
endl;
01630
#endif
01631
01632 mindist -= diff;
01633
01634 lastheight = QABS(fby - lastfby);
01635 lastfby = fby;
01636 lastcb = cb;
01637 it =
copy;
01638
#if DEBUG_CARETMODE > 0
01639
kdDebug(6200) <<
" mindist: " << mindist <<
endl;
01640
#endif
01641
01642
01643
01644
01645 }
while (mindist - lastheight > 0);
01646 }
01647
01648
01649 }