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);
int origX
For natural traversal of lines, the original x position is saved, and the actual x is set to the firs...
CaretAdvancePolicy advPol
static CaretBoxIterator currentBox
virtual ~LinearDocument()
Iterator begin()
Returns a line iterator pointing to the very first line of the document.
KAction * copy(const QObject *recvr, const char *slot, QObject *parent)
RenderBlock * containingBlock() const
returns the containing block of this caret box.
Iterator preEnd()
Returns a line iterator pointing to the very last line of the document.
bool check(const CaretBoxIterator &chit)
checks whether this box matches the given iterator.
This class is khtml's main class.
static QDebug kError(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
CaretBoxIterator preEnd()
TableRowIterator()
empty constructor.
Represents a render table as a linear list of rows.
EditableLineIterator & operator++()
seek next line
bool isAdjacent() const
returns true when the current caret box is adjacent to the previously iterated caret box...
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
void peekNext()
reads ahead the next node and updates the data structures accordingly
Iterates through the editable lines of a document, in a topological order.
void addCreatedInlineBoxEdge(InlineBox *box, const QFontMetrics &fm, bool left, bool rtl)
creates and adds the edge of a generic inline box
TableRowIterator & operator++()
advances to the next row
void calcAndStoreNewLine(RenderBlock *newBlock, bool toBegin)
initializes the iterator to point to the first previous/following editable line.
void prevBlock()
seeks previous block.
void advance(bool toBegin)
advances to the editable caret box to come
CaretBoxLineDeleter cblDeleter
Iterator current()
Returns a line iterator containing the current position as its starting value.
const Iterator & preBegin() const
Returns a line iterator pointing just before the very first line of the document (this is somewhat an...
void addConvertedInlineBox(InlineBox *, SeekBoxParams &)
recursively converts the given inline box into caret boxes and adds them to this caret box line...
TableRowIterator & operator--()
advances to the previous row
int count() const
Returns the count of lines.
const Iterator & end() const
Returns a line iterator pointing right after the end of the document.
CaretBoxDeleter caret_boxes
bool equalsBox(const InlineBox *box, bool outside, bool outsideEnd) const
compares whether this seek box matches the given specification
long minOffset() const
returns the minimum offset for this caret box.
void addCreatedFlowBoxEdge(InlineFlowBox *flowBox, const QFontMetrics &fm, bool left, bool rtl)
creates and adds the edge of an inline flow box
static long currentOffset
Resembles a line consisting of caret boxes.
ErgonomicEditableLineIterator & operator--()
seek previous line.
static CaretBoxLine * constructCaretBoxLine(MassDeleter< CaretBoxLine > *deleter, InlineFlowBox *baseFlowBox, InlineBox *seekBox, bool seekOutside, bool seekOutsideEnd, CaretBoxIterator &iter, RenderObject *seekObject=0)
constructs a new caret box line out of the given inline flow box
KAction * next(const QObject *recvr, const char *slot, QObject *parent)
Iterates over the elements of a caret box line.
LinearDocument(KHTMLPart *part, DOM::NodeImpl *node, long offset, CaretAdvancePolicy advancePolicy, DOM::ElementImpl *baseElem)
Creates a new instance, and initializes it to the line specified by the parameters below...
CaretBoxIterator & operator++()
increments the iterator to point to the next caret box.
contextual information about the caret which is related to the view.
RenderObject * object() const
returns the associated render object.
bool isInline() const
returns the replaced render object if this caret box represents one, 0 otherwise. ...
bool isOutside() const
returns true when this caret box represents an ouside position of an element.
InlineBox * inlineBox() const
friend class LineIterator
void determineTopologicalElement(RenderTableCell *oldCell, RenderObject *newObject, bool toBegin)
determines the topologically next render object.
void nextBlock()
seeks next block.
bool isInlineTextBox() const
returns true if this caret box represents an inline text box.
bool isEditable() const
Returns true if the document is editable, false otherwise.
void initFirstChar()
initializes the _char member by reading the character at the current offset, peeking ahead as necessa...
ErgonomicEditableLineIterator & operator++()
seek next line.
long maxOffset() const
returns the maximum offset for this caret box.
void advance(bool toBegin)
advances to the line to come.
EditableCaretBoxIterator ebit
CaretAdvancePolicy advancePolicy() const
Returns the current caret advance policy.
Iterates through the lines of a document.
bool isCaretMode() const
Returns whether caret mode is on/off.
Represents the whole document in terms of lines.
Represents a rectangular box within which the caret is located.
static QDebug kWarning(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
bool isOutsideEnd() const
returns the position at which the outside is targeted at.
EditableCharacterIterator & operator--()
moves to the previous editable character.
CaretBoxIterator & operator--()
decrements the iterator to point to the previous caret box.
RenderObject * baseObject() const
Returns the base render object which the caret must not advance beyond.
void initPreBeginIterator()
Provides iterating through the document in terms of characters.
void advance(bool toBegin)
advances to the line to come.
EditableCharacterIterator & operator++()
returns whether the current line box represents the outside of its render object. ...
EditableLineIterator & operator--()
seek previous line.
bool isEditable(const CaretBoxIterator &boxit, bool fromEnd)
finds out if the given box is editable.
Iterates over the editable inner elements of a caret line box.
contains the seek parameters
void addCreatedFlowBoxInside(InlineFlowBox *flowBox, const QFontMetrics &fm)
creates and adds the inside of an inline flow box
bool isEditable(LineIterator &it)
finds out if the current line is editable.
LineIterator()
Default constructor, only for internal use.