24 #include "html/html_documentimpl.h"
35 enum ObjectAdvanceState {
36 LeftObject = 0x01, AdvancedToSibling = 0x02, EnteredObject = 0x04
47 enum ObjectTraversalState {
48 OutsideDescending, InsideDescending, InsideAscending, OutsideAscending
60 static RenderObject* traverseRenderObjects(RenderObject *obj,
61 ObjectTraversalState &trav,
bool toBegin, RenderObject *base,
66 case OutsideDescending:
67 trav = InsideDescending;
69 case InsideDescending:
70 r = toBegin ? obj->lastChild() : obj->firstChild();
72 trav = OutsideDescending;
74 state |= EnteredObject;
76 trav = InsideAscending;
80 trav = OutsideAscending;
82 case OutsideAscending:
83 r = toBegin ? obj->previousSibling() : obj->nextSibling();
85 trav = OutsideDescending;
86 state |= AdvancedToSibling;
90 trav = InsideAscending;
105 static inline RenderObject *renderObjectBelow(RenderObject *obj, ObjectTraversalState &trav, RenderObject *base)
107 trav = InsideDescending;
109 RenderObject *r = obj;
110 while (r && trav != OutsideDescending) {
111 r = traverseRenderObjects(r, trav,
false, base, state);
112 #if DEBUG_CARETMODE > 3
113 kDebug(6200) <<
"renderObjectBelow: r " << r <<
" trav " << trav;
116 trav = InsideDescending;
125 static inline RenderObject *renderObjectAbove(RenderObject *obj, ObjectTraversalState &trav, RenderObject *base)
127 trav = OutsideAscending;
129 RenderObject *r = obj;
130 while (r && trav != InsideAscending) {
131 r = traverseRenderObjects(r, trav,
true, base, state);
132 #if DEBUG_CARETMODE > 3
133 kDebug(6200) <<
"renderObjectAbove: r " << r <<
" trav " << trav;
136 trav = InsideAscending;
144 static inline bool isIndicatedInlineBox(InlineBox *box)
147 if (box->isInlineTextBox())
return false;
148 RenderStyle *s = box->object()->style();
149 return s->borderLeftWidth() || s->borderRightWidth()
150 || s->borderTopWidth() || s->borderBottomWidth()
151 || s->paddingLeft().value() || s->paddingRight().value()
152 || s->paddingTop().value() || s->paddingBottom().value()
155 || s->marginLeft().value() || s->marginRight().value();
162 static inline bool isIndicatedFlow(RenderObject *r)
164 RenderStyle *s = r->style();
165 return s->borderLeftStyle() != BNONE || s->borderRightStyle() != BNONE
166 || s->borderTopStyle() != BNONE || s->borderBottomStyle() != BNONE
170 || s->hasClip() || s->hidesOverflow()
171 || s->backgroundColor().isValid() || s->backgroundImage();
187 static RenderObject *advanceObject(RenderObject *r,
188 ObjectTraversalState &trav,
bool toBegin,
189 RenderObject *base,
int &state)
192 ObjectTraversalState origtrav = trav;
193 RenderObject *a = traverseRenderObjects(r, trav, toBegin, base, state);
195 bool ignoreOutsideDesc = toBegin && origtrav == OutsideAscending;
198 RenderObject *la = 0;
199 ObjectTraversalState latrav = trav;
200 ObjectTraversalState lasttrav = origtrav;
203 #if DEBUG_CARETMODE > 5
204 kDebug(6200) <<
"a " << a <<
" trav " << trav;
207 #if DEBUG_CARETMODE > 4
208 kDebug(6200) <<
"a " << a <<
" trav " << trav <<
" origtrav " << origtrav <<
" ignoreOD " << ignoreOutsideDesc;
213 case OutsideDescending:
214 if (trav == InsideAscending)
return a;
215 if (trav == OutsideDescending)
return a;
217 case InsideDescending:
218 if (trav == OutsideDescending)
return a;
220 case InsideAscending:
221 if (trav == OutsideAscending)
return a;
223 case OutsideAscending:
224 if (trav == OutsideAscending)
return a;
225 if (trav == InsideAscending && lasttrav == InsideDescending)
return a;
226 if (trav == OutsideDescending && !ignoreOutsideDesc)
return a;
230 la = a; latrav = trav;
231 ignoreOutsideDesc =
false;
238 case OutsideDescending:
239 if (trav == InsideAscending)
return a;
240 if (trav == OutsideDescending)
return a;
242 case InsideDescending:
245 case InsideAscending:
248 case OutsideAscending:
253 if (trav == OutsideDescending)
return a;
254 if (trav == OutsideAscending) {
258 la = a; latrav = trav;
267 a = traverseRenderObjects(a, trav, toBegin, base, state);
270 if (la) trav = latrav, a = la;
283 static inline bool isUnsuitable(RenderObject *r, ObjectTraversalState trav)
285 if (!r)
return false;
286 return r->isTableCol() || r->isTableSection() || r->isTableRow()
287 || (r->isText() && !
static_cast<RenderText *
>(r)->firstTextBox());
305 static inline RenderObject *advanceSuitableObject(RenderObject *r,
306 ObjectTraversalState &trav,
bool toBegin,
307 RenderObject *base,
int &state)
310 r = advanceObject(r, trav, toBegin, base, state);
311 #if DEBUG_CARETMODE > 2
312 kDebug(6200) <<
"after advanceSWP: r " << r <<
" trav " << trav <<
" toBegin " << toBegin;
314 }
while (isUnsuitable(r, trav));
327 static NodeImpl *nextLeafNode(NodeImpl *r, NodeImpl *baseElem)
329 NodeImpl *n = r->firstChild();
331 while (n) { r = n; n = n->firstChild(); }
332 return const_cast<NodeImpl *
>(r);
334 n = r->nextSibling();
337 while (n) { r = n; n = n->firstChild(); }
338 return const_cast<NodeImpl *
>(r);
342 if (n == baseElem) n = 0;
345 n = r->nextSibling();
349 while (n) { r = n; n = n->firstChild(); }
350 return const_cast<NodeImpl *
>(r);
353 if (n == baseElem) n = 0;
358 #if 0 // currently not used
368 static NodeImpl *prevLeafNode(NodeImpl *r, NodeImpl *baseElem)
370 NodeImpl *n = r->firstChild();
372 while (n) { r = n; n = n->firstChild(); }
373 return const_cast<NodeImpl *
>(r);
375 n = r->previousSibling();
378 while (n) { r = n; n = n->firstChild(); }
379 return const_cast<NodeImpl *
>(r);
383 if (n == baseElem) n = 0;
386 n = r->previousSibling();
390 while (n) { r = n; n = n->lastChild(); }
391 return const_cast<NodeImpl *
>(r);
394 if (n == baseElem) n = 0;
411 void mapDOMPosToRenderPos(NodeImpl *node,
long offset,
412 RenderObject *&r,
long &r_ofs,
bool &outside,
bool &outsideEnd)
414 if (node->nodeType() == Node::TEXT_NODE) {
417 r = node->renderer();
419 }
else if (node->nodeType() == Node::ELEMENT_NODE || node->nodeType() == Node::DOCUMENT_NODE) {
423 if (node->firstChild()) {
425 NodeImpl *child = offset <= 0 ? node->firstChild()
427 : node->childNode((
unsigned long)offset);
430 #if DEBUG_CARETMODE > 5
431 kDebug(6200) <<
"mapDTR: child " << child <<
"@" << (child ? child->nodeName().string() :
QString()) <<
" atEnd " << atEnd;
433 if (atEnd) child = node->lastChild();
435 r = child->renderer();
441 if (r && child->nodeType() == Node::TEXT_NODE) {
443 RenderObject *o = node->renderer();
444 while (o->continuation() && o->continuation() != r)
445 o = o->continuation();
446 if (!r || o->continuation() != r) {
447 r = child->renderer();
453 if (r && r->isBR()) {
454 r = r->objectAbove();
462 r = node->renderer();
468 kWarning() <<
"Mapping from nodes of type " << node->nodeType()
469 <<
" not supported!" << endl;
483 void mapRenderPosToDOMPos(RenderObject *r,
long r_ofs,
484 bool outside,
bool outsideEnd, NodeImpl *&node,
long &offset)
488 #if DEBUG_CARETMODE > 5
489 kDebug(6200) <<
"mapRTD: r " << r <<
'@' << (r ? r->renderName() :
QString()) << (r && r->element() ?
QString(
".node ") + QString::number((
unsigned)r->element(),16) +
'@' + r->element()->nodeName().string() :
QString()) <<
" outside " << outside <<
" outsideEnd " << outsideEnd;
491 if (node->nodeType() == Node::ELEMENT_NODE || node->nodeType() == Node::TEXT_NODE) {
494 NodeImpl *parent = node->parent();
498 if (r != node->renderer()) {
499 RenderObject *o = node->renderer();
500 while (o->continuation() && o->continuation() != r)
501 o = o->continuation();
502 if (o->continuation() == r) {
506 node = r->firstChild() ? r->firstChild()->element() : node;
510 if (!parent)
goto inside;
512 offset = (long)node->nodeIndex() + outsideEnd;
514 #if DEBUG_CARETMODE > 5
515 kDebug(6200) << node <<
"@" << (node ? node->nodeName().string() :
QString()) <<
" offset " << offset;
524 kWarning() <<
"Mapping to nodes of type " << node->nodeType()
525 <<
" not supported!" << endl;
530 static inline void ensureLeafNode(NodeImpl *&node, NodeImpl *base)
532 if (node && node->hasChildNodes()) node = nextLeafNode(node, base);
541 static inline void mapRenderPosToTraversalState(
bool outside,
bool atEnd,
542 bool toBegin, ObjectTraversalState &trav)
544 if (!outside) atEnd = !toBegin;
545 if (!atEnd ^ toBegin)
546 trav = outside ? OutsideDescending : InsideDescending;
548 trav = outside ? OutsideAscending : InsideAscending;
557 static inline void mapTraversalStateToRenderPos(ObjectTraversalState trav,
558 bool toBegin,
bool &outside,
bool &atEnd)
562 case OutsideDescending: outside =
true;
563 case InsideDescending: atEnd = toBegin;
break;
564 case OutsideAscending: outside =
true;
565 case InsideAscending: atEnd = !toBegin;
break;
584 static RenderObject* findRenderer(NodeImpl *&node,
long offset,
585 RenderObject *base,
long &r_ofs,
586 bool &outside,
bool &outsideEnd)
590 mapDOMPosToRenderPos(node, offset, r, r_ofs, outside, outsideEnd);
591 #if DEBUG_CARETMODE > 2
592 kDebug(6200) <<
"findRenderer: node " << node <<
" " << (node ? node->nodeName().string() :
QString()) <<
" offset " << offset <<
" r " << r <<
"[" << (r ? r->renderName() :
QString()) <<
"] r_ofs " << r_ofs <<
" outside " << outside <<
" outsideEnd " << outsideEnd;
595 NodeImpl *baseElem = base ? base->element() : 0;
597 node = nextLeafNode(node, baseElem);
599 r = node->renderer();
600 if (r) r_ofs = offset;
602 #if DEBUG_CARETMODE > 3
603 kDebug(6200) <<
"1r " << r;
605 ObjectTraversalState trav;
607 mapRenderPosToTraversalState(outside, outsideEnd,
false, trav);
608 if (r && isUnsuitable(r, trav)) {
609 r = advanceSuitableObject(r, trav,
false, base, state);
610 mapTraversalStateToRenderPos(trav,
false, outside, outsideEnd);
611 if (r) r_ofs = r->minOffset();
613 #if DEBUG_CARETMODE > 3
614 kDebug(6200) <<
"2r " << r;
622 static ElementImpl *determineBaseElement(NodeImpl *caretNode)
627 DocumentImpl *doc = caretNode->getDocument();
630 if (doc->isHTMLDocument())
631 return static_cast<HTMLDocumentImpl *>(doc)->body();
638 #if DEBUG_CARETMODE > 0
639 void CaretBox::dump(QTextStream &ts,
const QString &ind)
const
641 ts << ind <<
"b@" <<
_box;
644 ts <<
"<" << _box->object() <<
":" << _box->object()->renderName() <<
">";
647 ts <<
" " <<
_x <<
"+" <<
_y <<
"+" <<
_w <<
"*" <<
_h;
650 if (cb) ts <<
":" << cb->renderName();
659 #if DEBUG_CARETMODE > 0
660 # define DEBUG_ACIB 1
662 # define DEBUG_ACIB DEBUG_CARETMODE
668 bool coalesceOutsideBoxes =
false;
670 for (; box; box = box->nextOnLine()) {
672 kDebug(6200) <<
"box " << box;
673 kDebug(6200) <<
"box->object " << box->object();
674 kDebug(6200) <<
"x " << box->m_x <<
" y " << box->m_y <<
" w " << box->m_width <<
" h " << box->m_height <<
" baseline " << box->m_baseline <<
" ifb " << box->isInlineFlowBox() <<
" itb " << box->isInlineTextBox() <<
" rlb " << box->isRootInlineBox();
677 if (!box->object())
continue;
679 RenderStyle *s = box->object()->style(box->m_firstLine);
681 RenderStyle *ps = box->parent() && box->parent()->object()
682 ? box->parent()->object()->style(box->parent()->m_firstLine)
685 if (box->isInlineFlowBox()) {
687 kDebug(6200) <<
"isinlineflowbox " << box;
689 InlineFlowBox *flowBox =
static_cast<InlineFlowBox *
>(box);
690 bool rtl = ps->direction() == RTL;
691 const QFontMetrics &pfm = ps->fontMetrics();
693 if (flowBox->includeLeftEdge()) {
697 if (coalesceOutsideBoxes) {
698 if (sbp.
equalsBox(flowBox,
true,
false)) {
699 sbp.
it = lastCoalescedBox;
700 Q_ASSERT(!sbp.
found);
709 if (flowBox->firstChild()) {
711 kDebug(6200) <<
"this " <<
this <<
" flowBox " << flowBox <<
" firstChild " << flowBox->firstChild();
712 kDebug(6200) <<
"== recursive invocation";
716 kDebug(6200) <<
"== recursive invocation end";
724 if (flowBox->includeRightEdge()) {
726 lastCoalescedBox =
preEnd();
727 sbp.
check(lastCoalescedBox);
728 coalesceOutsideBoxes =
true;
731 }
else if (box->isInlineTextBox()) {
733 kDebug(6200) <<
"isinlinetextbox " << box << (box->object() ?
QString(
" contains \"%1\"").arg(QConstString(static_cast<RenderText *>(box->object())->str->s+box->minOffset(), qMin(box->maxOffset() - box->minOffset(), 15L)).string()) :
QString());
738 coalesceOutsideBoxes =
false;
742 kDebug(6200) <<
"some replaced or what " << box;
745 bool rtl = ps->direction() == RTL;
746 const QFontMetrics &pfm = ps->fontMetrics();
748 if (coalesceOutsideBoxes) {
750 sbp.
it = lastCoalescedBox;
751 Q_ASSERT(!sbp.
found);
763 lastCoalescedBox =
preEnd();
764 sbp.
check(lastCoalescedBox);
765 coalesceOutsideBoxes =
true;
781 caretBox->
_y += flowBox->baseline() - fm.ascent();
782 caretBox->
_h = fm.height();
790 if (left ^ rtl) caretBox->
_x -= flowBox->paddingLeft() + flowBox->borderLeft() + 1;
791 else caretBox->
_x += caretBox->
_w + flowBox->paddingRight() + flowBox->borderRight();
793 caretBox->
_y += flowBox->baseline() - fm.ascent();
794 caretBox->
_h = fm.height();
803 if (left ^ rtl) caretBox->
_x--;
804 else caretBox->
_x += caretBox->
_w;
806 caretBox->
_y += box->baseline() - fm.ascent();
807 caretBox->
_h = fm.height();
812 InlineFlowBox *basicFlowBox, InlineBox *seekBox,
bool seekOutside,
827 deleter->append(result);
829 SeekBoxParams sbp(seekBox, seekOutside, seekOutsideEnd, seekObject, iter);
834 if (!sbp.found) sbp.it = result->
end();
840 RenderBox *cb,
bool outside,
bool outsideEnd, CaretBoxIterator &iter)
849 RenderStyle *s = cb->element() && cb->element()->parent()
850 && cb->element()->parent()->renderer()
851 ? cb->element()->parent()->renderer()->style()
853 bool rtl = s->direction() == RTL;
855 const QFontMetrics &fm = s->fontMetrics();
856 height = fm.height();
864 int hl = fm.leading() / 2;
865 int baseline = cb->baselinePosition(
false);
866 if (!cb->isReplaced() || cb->style()->display() == BLOCK) {
867 if (!outsideEnd ^ rtl)
868 _y -= fm.leading() / 2;
870 _y += qMax(cb->height() - fm.ascent() - hl, 0);
872 _y += baseline - fm.ascent() - hl;
877 RenderStyle *s = cb->style();
878 const QFontMetrics &fm = s->fontMetrics();
879 height = fm.height();
881 _x += cb->borderLeft() + cb->paddingLeft();
882 _y += cb->borderTop() + cb->paddingTop();
885 switch (s->textAlign()) {
893 _x += cb->contentWidth() / 2;
897 _x += cb->contentWidth();
903 deleter->append(result);
904 result->caret_boxes.append(
new CaretBox(_x, _y, width, height, cb,
905 outside, outsideEnd));
906 iter = result->begin();
910 #if DEBUG_CARETMODE > 0
911 void CaretBoxLine::dump(QTextStream &ts,
const QString &ind)
const
913 ts << ind <<
"cbl: baseFlowBox@" <<
basefb << endl;
916 if (i > 0) ts << endl;
931 inline InlineFlowBox *seekBaseFlowBox(InlineBox *b, RenderObject *base = 0)
934 while (b->parent() && b->object() != base) {
937 Q_ASSERT(b->isInlineFlowBox());
938 return static_cast<InlineFlowBox *
>(b);
943 inline bool isBlockRenderReplaced(RenderObject *r)
945 return r->isRenderReplaced() && r->style()->display() == BLOCK;
964 static CaretBoxLine* findCaretBoxLine(DOM::NodeImpl *node,
long offset,
965 CaretBoxLineDeleter *cblDeleter, RenderObject *base,
966 long &r_ofs, CaretBoxIterator &caretBoxIt)
968 bool outside, outsideEnd;
969 RenderObject *r = findRenderer(node, offset, base, r_ofs, outside, outsideEnd);
970 if (!r) {
return 0; }
971 #if DEBUG_CARETMODE > 0
972 kDebug(6200) <<
"=================== findCaretBoxLine";
973 kDebug(6200) <<
"node " << node <<
" offset: " << offset <<
" r " << r->renderName() <<
"[" << r <<
"].node " << r->element()->nodeName().string() <<
"[" << r->element() <<
"]" <<
" r_ofs " << r_ofs <<
" outside " << outside <<
" outsideEnd " << outsideEnd;
986 if (r->isText())
do {
987 RenderText *t =
static_cast<RenderText *
>(r);
989 InlineBox *b = t->findInlineTextBox(offset, dummy,
true);
994 if (!t->lastTextBox())
996 b = t->lastTextBox();
1000 InlineFlowBox *baseFlowBox = seekBaseFlowBox(b, base);
1001 #if DEBUG_CARETMODE > 2
1002 kDebug(6200) <<
"text-box b: " << b <<
" baseFlowBox: " << baseFlowBox << (b && b->object() ?
QString(
" contains \"%1\"").arg(QConstString(static_cast<RenderText *>(b->object())->str->s+b->minOffset(), qMin(b->maxOffset() - b->minOffset(), 15L)).string()) :
QString());
1005 if (t->containingBlock()->isListItem()) dumpLineBoxes(static_cast<RenderFlow *>(t->containingBlock()));
1007 #if DEBUG_CARETMODE > 0
1008 kDebug(6200) <<
"=================== end findCaretBoxLine (renderText)";
1011 b, outside, outsideEnd, caretBoxIt);
1015 bool isrepl = isBlockRenderReplaced(r);
1016 if (r->isRenderBlock() || r->isRenderInline() || isrepl) {
1017 RenderFlow *flow =
static_cast<RenderFlow *
>(r);
1018 InlineFlowBox *firstLineBox = isrepl ? 0 : flow->firstLineBox();
1023 if (isrepl || r->isRenderBlock() && (outside || !firstLineBox)
1024 || r->isRenderInline() && !firstLineBox) {
1025 #if DEBUG_CARETMODE > 0
1026 kDebug(6200) <<
"=================== end findCaretBoxLine (box " << (outside ? (outsideEnd ?
"outside end" :
"outside begin") :
"inside") <<
")";
1028 Q_ASSERT(r->isBox());
1030 static_cast<RenderBox *>(r), outside, outsideEnd, caretBoxIt);
1033 kDebug(6200) <<
"firstlinebox " << firstLineBox;
1034 InlineFlowBox *baseFlowBox = seekBaseFlowBox(firstLineBox, base);
1036 firstLineBox, outside, outsideEnd, caretBoxIt);
1039 RenderBlock *cb = r->containingBlock();
1045 if (!cb->isRenderBlock()) {
1046 kWarning() <<
"containing block is no render block!!! crash imminent";
1049 InlineFlowBox *flowBox = cb->firstLineBox();
1059 #if DEBUG_CARETMODE > 0
1060 kDebug(6200) <<
"=================== end findCaretBoxLine (2)";
1063 outside, outsideEnd, caretBoxIt);
1069 for (; flowBox; flowBox =
static_cast<InlineFlowBox *
>(flowBox->nextLineBox())) {
1070 #if DEBUG_CARETMODE > 0
1071 kDebug(6200) <<
"[scan line]";
1075 InlineFlowBox *baseFlowBox = seekBaseFlowBox(flowBox, base);
1077 baseFlowBox, 0, outside, outsideEnd, caretBoxIt, r);
1078 #if DEBUG_CARETMODE > 5
1079 kDebug(6200) << cbl->information();
1081 if (caretBoxIt != cbl->end()) {
1082 #if DEBUG_CARETMODE > 0
1083 kDebug(6200) <<
"=================== end findCaretBoxLine (3)";
1093 CaretBoxLine *cbl = findCaretBoxLine(nextLeafNode(node, base ? base->element() : 0), 0, cblDeleter, base, r_ofs, caretBoxIt);
1094 #if DEBUG_CARETMODE > 0
1095 kDebug(6200) <<
"=================== end findCaretBoxLine";
1106 static inline RenderTable *findTableUpTo(RenderObject *r, RenderFlow *cb)
1108 while (r && r != cb && !r->isTable()) r = r->parent();
1109 return r && r->isTable() ?
static_cast<RenderTable *
>(r) : 0;
1114 static inline bool isDescendant(RenderObject *r, RenderObject *cb)
1116 while (r && r != cb) r = r->parent();
1130 static bool containsEditableElement(
KHTMLPart *part, RenderBlock *cb,
1131 RenderTable *&table,
bool fromEnd =
false)
1133 RenderObject *r = cb;
1135 while (r->lastChild()) r = r->lastChild();
1137 while (r->firstChild()) r = r->firstChild();
1139 RenderTable *tempTable = 0;
1143 ObjectTraversalState trav = InsideDescending;
1145 bool modWithinCb = withinCb = isDescendant(r, cb);
1152 tempTable = findTableUpTo(r, cb);
1154 #if DEBUG_CARETMODE > 1
1155 kDebug(6201) <<
"cee: r " << (r ? r->renderName() :
QString()) <<
"@" << r <<
" cb " << cb <<
" withinCb " << withinCb <<
" modWithinCb " << modWithinCb <<
" tempTable " << tempTable;
1157 if (r && modWithinCb && r->element() && !isUnsuitable(r, trav)
1159 || r->style()->userInput() == UI_ENABLED)) {
1161 #if DEBUG_CARETMODE > 1
1162 kDebug(6201) <<
"cee: editable";
1170 r = fromEnd ? r->objectAbove() : r->objectBelow();
1171 }
while (r && withinCb);
1187 static bool containsEditableChildElement(
KHTMLPart *part, RenderBlock *cb,
1188 RenderTable *&table,
bool fromEnd, RenderObject *start)
1191 ObjectTraversalState trav = OutsideAscending;
1193 RenderObject *r = start;
1195 r = traverseRenderObjects(r, trav, fromEnd, cb->parent(), state);
1196 }
while(r && !(state & AdvancedToSibling));
1201 if (!r)
return false;
1204 while (r->firstChild()) r = r->firstChild();
1206 while (r->lastChild()) r = r->lastChild();
1208 if (!r)
return false;
1210 RenderTable *tempTable = 0;
1212 bool withinCb =
false;
1215 bool modWithinCb = withinCb = isDescendant(r, cb);
1222 tempTable = findTableUpTo(r, cb);
1224 #if DEBUG_CARETMODE > 1
1225 kDebug(6201) <<
"cece: r " << (r ? r->renderName() :
QString()) <<
"@" << r <<
" cb " << cb <<
" withinCb " << withinCb <<
" modWithinCb " << modWithinCb <<
" tempTable " << tempTable;
1227 if (r && withinCb && r->element() && !isUnsuitable(r, trav)
1229 || r->style()->userInput() == UI_ENABLED)) {
1231 #if DEBUG_CARETMODE > 1
1232 kDebug(6201) <<
"cece: editable";
1237 r = fromEnd ? r->objectAbove() : r->objectBelow();
1245 CaretAdvancePolicy advancePolicy, ElementImpl *baseElem)
1246 : node(node), offset(offset), m_part(part),
1247 advPol(advancePolicy), base(0)
1249 if (node == 0)
return;
1252 RenderObject *b = baseElem->renderer();
1253 if (b && (b->isRenderBlock() || b->isRenderInline()))
1278 NodeImpl *n = base ? base->element() : 0;
1279 if (!base) n = node ? node->getDocument() : 0;
1280 if (!n)
return end();
1282 n = n->firstChild();
1284 while (n->firstChild()) n = n->firstChild();
1286 if (!n)
return end();
1292 NodeImpl *n = base ? base->element() : 0;
1293 if (!base) n = node ? node->getDocument() : 0;
1298 while (n->lastChild()) n = n->lastChild();
1323 if (!node) { cbl = 0;
return; }
1327 #if DEBUG_CARETMODE > 0
1328 if (!cbl)
kDebug(6200) <<
"no render object found!";
1331 #if DEBUG_CARETMODE > 1
1332 kDebug(6200) <<
"LineIterator: offset " << offset <<
" outside " << cbl->isOutside();
1334 #if DEBUG_CARETMODE > 3
1335 kDebug(6200) << cbl->information();
1338 #if DEBUG_CARETMODE > 0
1339 kDebug(6200) <<
"LineIterator: findCaretBoxLine failed";
1349 bool cb_outside = cbl->isOutside();
1350 bool cb_outside_end = cbl->isOutsideEnd();
1353 RenderObject *r = cbl->enclosingObject();
1355 ObjectTraversalState trav;
1357 mapRenderPosToTraversalState(cb_outside, cb_outside_end,
false, trav);
1358 #if DEBUG_CARETMODE > 1
1359 kDebug(6200) <<
"nextBlock: before adv r" << r <<
' ' << (r ? r->renderName() :
QString()) << (r && r->isText() ?
" contains \"" +
QString(((RenderText *)r)->str->s, qMin(((RenderText *)r)->str->l,15)) +
"\"" :
QString()) <<
" trav " << trav <<
" cb_outside " << cb_outside <<
" cb_outside_end " << cb_outside_end;
1361 r = advanceSuitableObject(r, trav,
false, base, state);
1367 mapTraversalStateToRenderPos(trav,
false, cb_outside, cb_outside_end);
1368 #if DEBUG_CARETMODE > 1
1369 kDebug(6200) <<
"nextBlock: after r" << r <<
" trav " << trav <<
" cb_outside " << cb_outside <<
" cb_outside_end " << cb_outside_end;
1371 #if DEBUG_CARETMODE > 0
1372 kDebug(6200) <<
"++: r " << r <<
"[" << (r?r->renderName():
QString()) <<
"]";
1378 bool isrepl = isBlockRenderReplaced(r);
1379 if (r->isRenderBlock() || isrepl) {
1380 RenderBox *cb =
static_cast<RenderBox *
>(r);
1385 #if DEBUG_CARETMODE > 0
1386 kDebug(6200) <<
"r->isFlow is cb. continuation @" << cb->continuation();
1390 cb = r->containingBlock();
1391 Q_ASSERT(cb->isRenderBlock());
1393 InlineFlowBox *flowBox = cb->firstLineBox();
1394 #if DEBUG_CARETMODE > 0
1395 kDebug(6200) <<
"++: flowBox " << flowBox <<
" cb " << cb <<
'[' << (cb?cb->renderName()+
QString(
".node ")+QString::number((
unsigned)cb->element(),16)+(cb->element()?
'@'+cb->element()->nodeName().string():
QString()):
QString()) <<
']';
1399 cb_outside = cb_outside_end =
true;
1405 bool seekOutside =
false, seekOutsideEnd =
false;
1408 flowBox, flowBox->firstChild(), seekOutside, seekOutsideEnd, it);
1416 bool cb_outside = cbl->isOutside();
1417 bool cb_outside_end = cbl->isOutsideEnd();
1420 RenderObject *r = cbl->enclosingObject();
1421 if (r->isAnonymous() && !cb_outside)
1422 cb_outside =
true, cb_outside_end =
false;
1424 ObjectTraversalState trav;
1426 mapRenderPosToTraversalState(cb_outside, cb_outside_end,
true, trav);
1427 #if DEBUG_CARETMODE > 1
1428 kDebug(6200) <<
"prevBlock: before adv r" << r <<
" " << (r ? r->renderName() :
QString()) << (r && r->isText() ?
" contains \"" +
QString(((RenderText *)r)->str->s, qMin(((RenderText *)r)->str->l,15)) +
"\"" :
QString()) <<
" trav " << trav <<
" cb_outside " << cb_outside <<
" cb_outside_end " << cb_outside_end;
1430 r = advanceSuitableObject(r, trav,
true, base, state);
1436 mapTraversalStateToRenderPos(trav,
true, cb_outside, cb_outside_end);
1437 #if DEBUG_CARETMODE > 1
1438 kDebug(6200) <<
"prevBlock: after r" << r <<
" trav " << trav <<
" cb_outside " << cb_outside <<
" cb_outside_end " << cb_outside_end;
1440 #if DEBUG_CARETMODE > 0
1441 kDebug(6200) <<
"--: r " << r <<
"[" << (r?r->renderName():
QString()) <<
"]";
1447 bool isrepl = isBlockRenderReplaced(r);
1449 if (r->isRenderBlock() || isrepl) {
1450 RenderBox *cb =
static_cast<RenderBox *
>(r);
1455 #if DEBUG_CARETMODE > 0
1456 kDebug(6200) <<
"r->isFlow is cb. continuation @" << cb->continuation();
1460 cb = r->containingBlock();
1461 Q_ASSERT(cb->isRenderBlock());
1463 InlineFlowBox *flowBox = cb->lastLineBox();
1464 #if DEBUG_CARETMODE > 0
1465 kDebug(6200) <<
"--: flowBox " << flowBox <<
" cb " << cb <<
"[" << (cb?cb->renderName()+
QString(
".node ")+QString::number((
unsigned)cb->element(),16)+(cb->element()?
"@"+cb->element()->nodeName().string():
QString()):
QString()) <<
"]";
1469 cb_outside =
true; cb_outside_end =
false;
1475 bool seekOutside =
false, seekOutsideEnd =
false;
1478 flowBox, flowBox->firstChild(), seekOutside, seekOutsideEnd, it);
1484 InlineFlowBox *flowBox = cbl->baseFlowBox();
1486 flowBox =
static_cast<InlineFlowBox *
>(toBegin ? flowBox->prevLineBox() : flowBox->nextLineBox());
1488 bool seekOutside =
false, seekOutsideEnd =
false;
1491 flowBox, flowBox->firstChild(), seekOutside, seekOutsideEnd, it);
1498 #if DEBUG_CARETMODE > 3
1499 if (cbl)
kDebug(6200) << cbl->information();
1507 #if DEBUG_CARETMODE > 3
1508 kDebug(6200) <<
"---------------" <<
"toBegin " << toBegin;
1514 bool islastuseable =
true;
1519 #if DEBUG_CARETMODE > 4
1524 bool curAtEnd = *
this == preBegin || *
this == end;
1530 atEnd = *
this == preBegin || *
this == end;
1533 bool haslast = lastbox != end && lastbox != preBegin;
1534 bool hascoming = !atEnd;
1535 bool iscominguseable =
true;
1537 if (!atEnd) iscominguseable =
isEditable(*
this, toBegin);
1539 #if DEBUG_CARETMODE > 3
1540 kDebug(6200) <<
"ebit::advance: " << (*curbox)->object() <<
"@" << (*curbox)->object()->renderName() <<
".node " << (*curbox)->object()->element() <<
"[" << ((*curbox)->object()->element() ? (*curbox)->object()->element()->nodeName().string() :
QString()) <<
"] inline " << (*curbox)->isInline() <<
" outside " << (*curbox)->isOutside() <<
" outsideEnd " << (*curbox)->isOutsideEnd();
1549 if (advpol == VisibleFlows)
break;
1555 InlineBox *prev = box->
isOutsideEnd() ? ibox : ibox->prevOnLine();
1559 const bool isprevindicated = !prev || isIndicatedInlineBox(prev);
1560 const bool isnextindicated = !next || isIndicatedInlineBox(next);
1561 const bool last = haslast && !islastuseable;
1562 const bool coming = hascoming && !iscominguseable;
1563 const bool left = !prev || prev->isInlineFlowBox() && isprevindicated
1564 || (toBegin && coming || !toBegin && last);
1565 const bool right = !next || next->isInlineFlowBox() && isnextindicated
1566 || (!toBegin && coming || toBegin && last);
1567 const bool text2indicated = toBegin && next && next->isInlineTextBox()
1569 || !toBegin && prev && prev->isInlineTextBox() && isnextindicated;
1570 const bool indicated2text = !toBegin && next && next->isInlineTextBox()
1571 && prev && isprevindicated
1574 #if DEBUG_CARETMODE > 5
1575 kDebug(6200) <<
"prev " << prev <<
" haslast " << haslast <<
" islastuseable " << islastuseable <<
" left " << left <<
" next " << next <<
" hascoming " << hascoming <<
" iscominguseable " << iscominguseable <<
" right " << right <<
" text2indicated " << text2indicated <<
" indicated2text " << indicated2text;
1578 if (left && right && !text2indicated || indicated2text) {
1580 #if DEBUG_CARETMODE > 4
1581 kDebug(6200) <<
"left && right && !text2indicated || indicated2text";
1588 #if DEBUG_CARETMODE > 4
1591 kDebug(6200) <<
"inside " << (!ibox->isInlineFlowBox() ||
static_cast<InlineFlowBox *
>(ibox)->firstChild() ?
"non-empty" :
"empty") << (isIndicatedInlineBox(ibox) ?
" indicated" :
"") <<
" adjacent=" << adjacent;
1594 RenderStyle *s = ibox->object()->style();
1595 kDebug(6200) <<
"bordls " << s->borderLeftStyle()
1596 <<
" bordl " << (s->borderLeftStyle() != BNONE)
1597 <<
" bordr " << (s->borderRightStyle() != BNONE)
1598 <<
" bordt " << (s->borderTopStyle() != BNONE)
1599 <<
" bordb " << (s->borderBottomStyle() != BNONE)
1600 <<
" padl " << s->paddingLeft().value()
1601 <<
" padr " << s->paddingRight().value()
1602 <<
" padt " << s->paddingTop().value()
1603 <<
" padb " << s->paddingBottom().value()
1606 <<
" marl " << s->marginLeft().value()
1607 <<
" marr " << s->marginRight().value()
1616 if (!(*curbox)->isOutside()) {
1623 islastuseable = iscuruseable;
1625 iscuruseable = iscominguseable;
1629 atEnd = *
this == preBegin || *
this == end;
1634 #if DEBUG_CARETMODE > 4
1637 #if DEBUG_CARETMODE > 3
1638 kDebug(6200) <<
"---------------" <<
"end ";
1644 Q_ASSERT(boxit != cbl->end() && boxit != cbl->preBegin());
1646 RenderObject *r = b->object();
1647 #if DEBUG_CARETMODE > 0
1649 kDebug(6200) <<
"isEditable r" << r <<
": " << (r ? r->renderName() :
QString()) << (r && r->isText() ?
" contains \"" +
QString(((RenderText *)r)->str->s, qMin(((RenderText *)r)->str->l,15)) +
"\"" :
QString());
1654 NodeImpl *node = r->element();
1655 ObjectTraversalState trav;
1656 mapRenderPosToTraversalState(b->isOutside(), b->isOutsideEnd(), fromEnd, trav);
1657 if (isUnsuitable(r, trav) || !node) {
1662 if (!b->isOutside() && r->isRenderReplaced() && !r->firstChild())
1665 RenderObject *eff_r = r;
1669 if (b->isOutside() && !globallyNavigable) {
1670 NodeImpl *par = node->parent();
1674 if (par) node = par;
1675 eff_r = node->renderer();
1679 bool result = globallyNavigable || eff_r->style()->userInput() == UI_ENABLED;
1680 #if DEBUG_CARETMODE > 0
1692 bool haslasteditable =
false;
1693 bool haslastindicated =
false;
1694 bool uselasteditable =
false;
1699 #if DEBUG_CARETMODE > 3
1700 kDebug(6200) <<
"advance: " << cbl->enclosingObject() <<
"@" << cbl->enclosingObject()->renderName() <<
".node " << cbl->enclosingObject()->element() <<
"[" << (cbl->enclosingObject()->element() ? cbl->enclosingObject()->element()->nodeName().string() :
QString()) <<
"]";
1703 bool hasindicated = isIndicatedFlow(cbl->enclosingObject());
1705 haslastindicated =
true;
1706 lastindicated = *
this;
1710 case IndicatedFlows:
1711 if (hasindicated)
goto wend;
1714 if (cbl->isOutside())
break;
1716 case VisibleFlows:
goto wend;
1720 lasteditable = *
this;
1721 haslasteditable =
true;
1722 #if DEBUG_CARETMODE > 4
1723 kDebug(6200) <<
"remembered lasteditable " << *lasteditable;
1731 if (haslasteditable) { uselasteditable =
true;
break; }
1738 if (uselasteditable) *
this = haslastindicated ? lastindicated : lasteditable;
1739 if (!cbl && haslastindicated) *
this = lastindicated;
1750 else if (b && !box->
isOutside() && b->isInlineTextBox())
1751 _char = static_cast<RenderText *>(b->object())->str->s[
_offset].unicode();
1759 static inline bool isCaretBoxEmpty(
CaretBox *box) {
1760 if (!box->
isInline())
return false;
1762 return ibox->isInlineFlowBox()
1763 && !
static_cast<InlineFlowBox *
>(ibox)->firstChild()
1764 && !isIndicatedInlineBox(ibox);
1774 #if DEBUG_CARETMODE > 0
1778 #if DEBUG_CARETMODE > 2
1779 kDebug(6200) <<
"_offset == maxofs: " <<
_offset <<
" == " << maxofs;
1782 }
else if (
_offset > maxofs) {
1783 #if DEBUG_CARETMODE > 2
1784 kDebug(6200) <<
"_offset > maxofs: " <<
_offset <<
" > " << maxofs ;
1788 if (
ebit == (*_it)->end()) {
1790 #if DEBUG_CARETMODE > 3
1797 #if DEBUG_CARETMODE > 3
1801 #if DEBUG_CARETMODE > 3
1802 RenderObject *_r = box->
object();
1803 kDebug(6200) <<
"_r " << _r <<
":" << _r->element()->nodeName().string();
1806 #if DEBUG_CARETMODE > 3
1820 if (adjacent && !(*ebit)->isInlineTextBox()) {
1823 if (
ebit != (*_it)->end() && (*ebit)->isInlineTextBox()
1831 if (adjacent && !(*ebit)->isInlineTextBox()) {
1832 bool noemptybox =
true;
1833 while (isCaretBoxEmpty(*
ebit)) {
1837 if (
ebit == (*_it)->end()) {
ebit = copy;
break; }
1839 if (noemptybox) adjacent =
false;
1842 _offset = (*ebit)->minOffset() + adjacent;
1850 if (b && !box->
isOutside() && b->isInlineTextBox() &&
_offset < b->maxOffset())
1851 _char = static_cast<RenderText *>(b->object())->str->s[
_offset].unicode();
1855 #if DEBUG_CARETMODE > 2
1859 #if DEBUG_CARETMODE > 0
1860 if (!
_end &&
ebit != (*_it)->end()) {
1862 RenderObject *_r = box->
object();
1879 #if DEBUG_CARETMODE > 0
1883 #if DEBUG_CARETMODE > 2
1884 kDebug(6200) <<
"_offset == minofs: " <<
_offset <<
" == " << minofs;
1888 if (b && !box->
isOutside() && b->isInlineTextBox())
1889 _char = static_cast<RenderText *>(b->object())->text()[
_offset].unicode();
1894 bool do_prev =
false;
1901 if (
ebit == (*_it)->preBegin()) {
ebit = copy;
break; }
1902 }
while (isCaretBoxEmpty(*
ebit));
1910 if (do_prev)
goto prev;
1911 }
else if (
_offset < minofs) {
1913 #if DEBUG_CARETMODE > 2
1914 kDebug(6200) <<
"_offset < minofs: " <<
_offset <<
" < " << minofs ;
1919 if (
ebit == (*_it)->preBegin()) {
1921 #if DEBUG_CARETMODE > 3
1929 #if DEBUG_CARETMODE > 3
1935 #if DEBUG_CARETMODE > 0
1944 #if DEBUG_CARETMODE > 0
1946 kDebug(6200) <<
"adjacent " << adjacent <<
" _peekNext " << _peekNext <<
" _peekNext->isInlineTextBox: " << (_peekNext ? _peekNext->
isInlineTextBox() :
false) <<
" !((*ebit)->isInlineTextBox): " << (*
ebit ? !(*ebit)->isInlineTextBox() :
true);
1951 && !(*ebit)->isInlineTextBox()) {
1954 if (
ebit == (*_it)->preBegin())
1961 && !(*ebit)->isInlineTextBox()) {
1962 bool noemptybox =
true;
1963 while (isCaretBoxEmpty(*
ebit)) {
1967 if (
ebit == (*_it)->preBegin()) {
ebit = copy;
break; }
1968 else _peekNext = *copy;
1970 if (noemptybox) adjacent =
false;
1973 #if DEBUG_CARETMODE > 0
1974 kDebug(6200) <<
"(*ebit)->obj " << (*ebit)->object()->renderName() <<
"[" << (*ebit)->object() <<
"]" <<
" minOffset: " << (*ebit)->minOffset() <<
" maxOffset: " << (*ebit)->maxOffset();
1976 #if DEBUG_CARETMODE > 3
1977 RenderObject *_r = (*ebit)->object();
1978 kDebug(6200) <<
"_r " << _r <<
":" << _r->element()->nodeName().string();
1980 _offset = (*ebit)->maxOffset();
1982 #if DEBUG_CARETMODE > 3
1987 #if DEBUG_CARETMODE > 0
1988 kDebug(6200) <<
"_offset: " <<
_offset <<
" _peekNext: " << _peekNext;
1991 if (_peekNext &&
_offset >= box->
maxOffset() && _peekNext->isInlineTextBox())
1992 _char = static_cast<RenderText *>(_peekNext->object())->text()[_peekNext->minOffset()].unicode();
1993 else if (b && _offset < b->maxOffset() && b->isInlineTextBox())
1994 _char = static_cast<RenderText *>(b->object())->text()[
_offset].unicode();
1999 #if DEBUG_CARETMODE > 0
2000 if (!
_end &&
ebit != (*_it)->preBegin()) {
2011 RenderTableSection::RowStruct *row)
2012 : sec(table, fromEnd)
2016 if (fromEnd)
index = (*sec)->grid.size() - 1;
2022 while (
operator *() != row)
2031 if (
index >= (
int)(*sec)->grid.size()) {
2046 if (*
sec)
index = (*sec)->grid.size() - 1;
2054 static RenderTableCell *findNearestTableCellInRow(
KHTMLPart *part,
int x,
2055 RenderTableSection::RowStruct *row,
bool fromEnd);
2070 static inline RenderTableCell *findNearestTableCell(
KHTMLPart *part,
int x,
2073 RenderTableCell *result = 0;
2076 result = findNearestTableCellInRow(part, x, *it, fromEnd);
2079 if (fromEnd) --it;
else ++it;
2098 static RenderTableCell *findNearestTableCellInRow(
KHTMLPart *part,
int x,
2099 RenderTableSection::RowStruct *row,
bool fromEnd)
2102 int n = (int)row->row->size();
2104 for (i = 0; i < n; i++) {
2105 RenderTableCell *cell = row->row->at(i);
2106 if (!cell || (
long)cell == -1)
continue;
2109 cell->absolutePosition(absx, absy,
false);
2110 #if DEBUG_CARETMODE > 1
2111 kDebug(6201) <<
"i/n " << i <<
"/" << n <<
" absx " << absx <<
" absy " << absy;
2116 #if DEBUG_CARETMODE > 1
2117 kDebug(6201) <<
"x " << x <<
" < " << (absx + cell->width()) <<
"?";
2119 if (x < absx + cell->width())
break;
2121 if (i >= n) i = n - 1;
2125 for (
int cnt = 0; cnt < 2*n; cnt++) {
2126 int index = i - ((cnt >> 1) + 1)*(cnt & 1) + (cnt >> 1)*!(cnt & 1);
2127 if (index < 0 || index >= n)
continue;
2129 RenderTableCell *cell = row->row->at(index);
2130 if (!cell || (
long)cell == -1)
continue;
2132 #if DEBUG_CARETMODE > 1
2133 kDebug(6201) <<
"index " << index <<
" cell " << cell;
2135 RenderTable *nestedTable;
2136 if (containsEditableElement(part, cell, nestedTable, fromEnd)) {
2139 TableRowIterator it(nestedTable, fromEnd);
2142 cell = findNearestTableCell(part, x, it, fromEnd);
2144 if (fromEnd) --it;
else ++it;
2160 static RenderObject *commonAncestorTableSectionOrCell(RenderObject *r1,
2163 if (!r1 || !r2)
return 0;
2164 RenderTableSection *sec = 0;
2165 int start_depth=0, end_depth=0;
2167 RenderObject *n = r1;
2168 while (n->parent()) {
2173 while( n->parent()) {
2178 while (end_depth > start_depth) {
2182 while (start_depth > end_depth) {
2190 if (r1->isTableSection()) sec = static_cast<RenderTableSection *>(r1);
2196 while (r1 && !r1->isTableCell() && !r1->isTableSection() && !r1->isTable())
2199 return r1 && r1->isTable() ? sec : r1;
2209 static int findRowInSection(RenderTableSection *section, RenderTableCell *cell,
2210 RenderTableSection::RowStruct *&row, RenderTableCell *&directCell)
2213 RenderObject *r = cell;
2214 while (r != section) {
2215 if (r->isTableCell()) directCell = static_cast<RenderTableCell *>(r);
2222 int n = section->numRows();
2223 for (
int i = 0; i < n; i++) {
2224 row = §ion->grid[i];
2227 int m = row->row->size();
2228 for (
int j = 0; j < m; j++) {
2229 RenderTableCell *c = row->row->at(j);
2230 if (c == directCell)
return i;
2243 static inline RenderTable *findFirstDescendantTable(RenderObject *leaf, RenderBlock *block)
2245 RenderTable *result = 0;
2246 while (leaf && leaf != block) {
2247 if (leaf->isTable()) result = static_cast<RenderTable *>(leaf);
2248 leaf = leaf->parent();
2256 static inline RenderTableCell *containingTableCell(RenderObject *r)
2258 while (r && !r->isTableCell()) r = r->parent();
2259 return static_cast<RenderTableCell *
>(r);
2263 RenderBlock *newBlock,
bool toBegin)
2269 newBlock,
true, toBegin, it);
2270 #if DEBUG_CARETMODE > 3
2271 kDebug(6201) << cbl->information();
2283 RenderTableCell *oldCell, RenderObject *newObject,
bool toBegin)
2292 RenderObject *commonAncestor = commonAncestorTableSectionOrCell(oldCell, newObject);
2293 #if DEBUG_CARETMODE > 1
2294 kDebug(6201) <<
" ancestor " << commonAncestor;
2298 if (!commonAncestor || commonAncestor->isTableCell()) {
2300 RenderTableCell *cell =
static_cast<RenderTableCell *
>(commonAncestor);
2301 RenderTable *table = findFirstDescendantTable(newObject, cell);
2303 #if DEBUG_CARETMODE > 0
2304 kDebug(6201) <<
"table cell: " << cell;
2313 }
else if (commonAncestor->isTableSection()) {
2315 RenderTableSection *section =
static_cast<RenderTableSection *
>(commonAncestor);
2316 RenderTableSection::RowStruct *row;
2317 int idx = findRowInSection(section, oldCell, row, oldCell);
2318 #if DEBUG_CARETMODE > 1
2319 kDebug(6201) <<
"table section: row idx " << idx;
2325 int rowspan = oldCell->rowSpan();
2326 while (*it && rowspan--) {
2327 if (toBegin) --it;
else ++it;
2331 kError(6201) <<
"Neither common cell nor section! " << commonAncestor->renderName() << endl;
2335 RenderTableCell *cell = findNearestTableCell(
lines->
m_part,
xCoor, it, toBegin);
2336 #if DEBUG_CARETMODE > 1
2337 kDebug(6201) <<
"findNearestTableCell result: " << cell;
2340 RenderBlock *newBlock = cell;
2342 Q_ASSERT(commonAncestor->isTableSection());
2343 RenderTableSection *section =
static_cast<RenderTableSection *
>(commonAncestor);
2344 cell = containingTableCell(section);
2345 #if DEBUG_CARETMODE > 1
2346 kDebug(6201) <<
"containing cell: " << cell;
2349 RenderTable *nestedTable;
2350 bool editableChild = cell && containsEditableChildElement(
lines->
m_part,
2351 cell, nestedTable, toBegin, section->table());
2353 if (cell && !editableChild) {
2354 #if DEBUG_CARETMODE > 1
2355 kDebug(6201) <<
"========= recursive invocation outer =========";
2358 #if DEBUG_CARETMODE > 1
2359 kDebug(6201) <<
"========= end recursive invocation outer =========";
2363 }
else if (cell && nestedTable) {
2364 #if DEBUG_CARETMODE > 1
2365 kDebug(6201) <<
"========= recursive invocation inner =========";
2368 #if DEBUG_CARETMODE > 1
2369 kDebug(6201) <<
"========= end recursive invocation inner =========";
2374 #if DEBUG_CARETMODE > 1
2375 kDebug(6201) <<
"newBlock is table: " << section->table();
2377 RenderObject *r = section->table();
2379 ObjectTraversalState trav = OutsideAscending;
2380 r = advanceSuitableObject(r, trav, toBegin,
lines->
baseObject(), state);
2381 if (!r) { cbl = 0;
return; }
2383 newBlock =
static_cast<RenderBlock *
>(!r || r->isRenderBlock() ? r : r->containingBlock());
2392 RenderObject *r = newBlock;
2394 ObjectTraversalState trav = OutsideAscending;
2396 newBlock =
static_cast<RenderBlock *
>(!r || r->isRenderBlock() ? r : r->containingBlock());
2406 RenderTableCell *oldCell = containingTableCell(cbl->enclosingObject());
2411 RenderTableCell *newCell = containingTableCell(cbl->enclosingObject());
2413 if (!newCell || newCell == oldCell)
return *
this;
2422 RenderTableCell *oldCell = containingTableCell(cbl->enclosingObject());
2427 RenderTableCell *newCell = containingTableCell(cbl->enclosingObject());
2429 if (!newCell || newCell == oldCell)
return *
this;
2448 int &x,
int &absx,
int &absy)
2452 #if DEBUG_CARETMODE > 4
2453 kDebug(6200) <<
"nearestCB: cb " << cb <<
"@" << (cb ? cb->renderName() :
"");
2456 if (cb) cb->absolutePosition(absx, absy);
2457 else absx = absy = 0;
2462 x = cv->
origX - absx;
2468 #if DEBUG_CARETMODE > 0
2474 for (
CaretBox *b; fbit != (*it)->end(); ++fbit) {
2477 #if DEBUG_CARETMODE > 0
2487 if (oldXPos < 0 || x - (oldXPos + caretBox->
width()) > xPos - x) {
2496 if (x >= xPos && x < xPos + caretBox->width())
2512 static void moveItToNextWord(EditableCharacterIterator &it)
2514 #if DEBUG_CARETMODE > 0
2515 kDebug(6200) <<
"%%%%%%%%%%%%%%%%%%%%% moveItToNextWord";
2517 EditableCharacterIterator
copy;
2518 while (!it.isEnd() && !(*it).isSpace() && !(*it).isPunct()) {
2519 #if DEBUG_CARETMODE > 2
2520 kDebug(6200) <<
"reading1 '" << (*it).toLatin1().constData() <<
"'";
2531 while (!it.isEnd() && ((*it).isSpace() || (*it).isPunct())) {
2532 #if DEBUG_CARETMODE > 2
2533 kDebug(6200) <<
"reading2 '" << (*it).toLatin1().constData() <<
"'";
2539 if (it.isEnd()) it = copy;
2547 static void moveItToPrevWord(EditableCharacterIterator &it)
2549 if (it.isEnd())
return;
2551 #if DEBUG_CARETMODE > 0
2552 kDebug(6200) <<
"%%%%%%%%%%%%%%%%%%%%% moveItToPrevWord";
2554 EditableCharacterIterator copy;
2560 #if DEBUG_CARETMODE > 2
2561 if (!it.isEnd())
kDebug(6200) <<
"reading1 '" << (*it).toLatin1().constData() <<
"'";
2563 }
while (!it.isEnd() && ((*it).isSpace() || (*it).isPunct()));
2573 #if DEBUG_CARETMODE > 0
2574 if (!it.isEnd())
kDebug(6200) <<
"reading2 '" << (*it).toLatin1().constData() <<
"' (" << (int)(*it).toLatin1().constData() <<
") box " << it.caretBox();
2576 }
while (!it.isEnd() && !(*it).isSpace() && !(*it).isPunct());
2579 #if DEBUG_CARETMODE > 1
2580 if (!it.isEnd())
kDebug(6200) <<
"effective '" << (*it).toLatin1().constData() <<
"' (" << (int)(*it).toLatin1().constData() <<
") box " << it.caretBox();
2591 static void moveIteratorByPage(LinearDocument &ld,
2592 ErgonomicEditableLineIterator &it,
int mindist,
bool next)
2596 if (it == ld.end() || it == ld.preBegin())
return;
2598 ErgonomicEditableLineIterator copy = it;
2599 #if DEBUG_CARETMODE > 0
2600 kDebug(6200) <<
" mindist: " << mindist;
2603 CaretBoxLine *cbl = *copy;
2604 int absx = 0, absy = 0;
2606 RenderBlock *lastcb = cbl->containingBlock();
2607 Q_ASSERT(lastcb->isRenderBlock());
2608 lastcb->absolutePosition(absx, absy,
false);
2610 int lastfby = cbl->begin().data()->yPos();
2614 if (next) ++copy;
else --copy;
2615 if (copy == ld.end() || copy == ld.preBegin())
break;
2618 RenderBlock *cb = cbl->containingBlock();
2623 int fby = cbl->begin().data()->yPos();
2626 diff = absy + lastfby + lastheight;
2627 cb->absolutePosition(absx, absy,
false);
2628 diff = absy - diff + fby;
2632 cb->absolutePosition(absx, absy,
false);
2633 diff -= absy + fby + lastheight;
2634 lastfby = fby - lastheight;
2636 #if DEBUG_CARETMODE > 2
2637 kDebug(6200) <<
"absdiff " << diff;
2640 diff = qAbs(fby - lastfby);
2642 #if DEBUG_CARETMODE > 2
2643 kDebug(6200) <<
"cbl->begin().data()->yPos(): " << fby <<
" diff " << diff;
2648 lastheight = qAbs(fby - lastfby);
2652 #if DEBUG_CARETMODE > 0
2653 kDebug(6200) <<
" mindist: " << mindist;
2659 }
while (mindist - lastheight > 0 && --rescue);