File indexing completed on 2024-04-28 11:39:36

0001 /*
0002  * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
0003  *
0004  * Redistribution and use in source and binary forms, with or without
0005  * modification, are permitted provided that the following conditions
0006  * are met:
0007  * 1. Redistributions of source code must retain the above copyright
0008  *    notice, this list of conditions and the following disclaimer.
0009  * 2. Redistributions in binary form must reproduce the above copyright
0010  *    notice, this list of conditions and the following disclaimer in the
0011  *    documentation and/or other materials provided with the distribution.
0012  *
0013  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
0014  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0015  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
0016  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
0017  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0018  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
0019  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
0020  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
0021  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0022  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0023  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0024  */
0025 
0026 #include "dom_position.h"
0027 
0028 #include "misc/helper.h"
0029 #include "rendering/render_block.h"
0030 #include "rendering/render_line.h"
0031 #include "rendering/render_object.h"
0032 #include "rendering/render_style.h"
0033 #include "rendering/render_text.h"
0034 #include "xml/dom_positioniterator.h"
0035 #include "xml/dom_elementimpl.h"
0036 #include "xml/dom_docimpl.h"
0037 #include "xml/dom_nodeimpl.h"
0038 #include "html/html_documentimpl.h"
0039 #include "rendering/render_position.h"
0040 
0041 #include "khtml_part.h"
0042 
0043 #include <qstring.h>
0044 
0045 #define DEBUG_CARET
0046 
0047 // FIXME shouldn't use any rendereing related here except for RenderPosition
0048 using khtml::InlineBox;
0049 using khtml::InlineFlowBox;
0050 using khtml::InlineTextBox;
0051 using khtml::RenderBlock;
0052 using khtml::RenderObject;
0053 using khtml::RenderText;
0054 using khtml::RootInlineBox;
0055 using khtml::RenderPosition;
0056 
0057 namespace DOM
0058 {
0059 
0060 static NodeImpl *nextRenderedEditable(NodeImpl *node)
0061 {
0062     while (1) {
0063         node = node->nextEditable();
0064         if (!node) {
0065             return nullptr;
0066         }
0067         if (!node->renderer()) {
0068             continue;
0069         }
0070         if (node->renderer()->inlineBox(0)) {
0071             return node;
0072         }
0073     }
0074     return nullptr;
0075 }
0076 
0077 static NodeImpl *previousRenderedEditable(NodeImpl *node)
0078 {
0079     while (1) {
0080         node = node->previousEditable();
0081         if (!node) {
0082             return nullptr;
0083         }
0084         if (!node->renderer()) {
0085             continue;
0086         }
0087         if (node->renderer()->inlineBox(0)) {
0088             return node;
0089         }
0090     }
0091     return nullptr;
0092 }
0093 
0094 /*static*/ NodeImpl *rootNavigableElement(NodeImpl *node)
0095 {
0096     DocumentImpl *doc = node->document();
0097     if (doc && doc->part()->isCaretMode()) {
0098         if (doc->isHTMLDocument()) {
0099             return static_cast<HTMLDocumentImpl *>(doc)->body();
0100         } else {
0101             return doc->documentElement();
0102         }
0103     }
0104 
0105     return node->rootEditableElement();
0106 }
0107 
0108 /*inline*/ /*static*/ bool inSameRootNavigableElement(NodeImpl *n1, NodeImpl *n2)
0109 {
0110     return n1 && n2 && rootNavigableElement(n1) == rootNavigableElement(n2);
0111 }
0112 
0113 static void printSubTree(NodeImpl *node, int indent = 0)
0114 {
0115     QString temp;
0116     temp.fill(' ', indent);
0117     // qCDebug(KHTML_LOG) << temp << node << node->nodeName() << node->renderer()
0118     //    << (node->renderer() ? node->renderer()->renderName() : "")
0119     //    << (node->isTextNode() ? static_cast<TextImpl*>(node)->toString() : "");
0120     for (NodeImpl *subNode = node->firstChild(); subNode; subNode = subNode->nextSibling()) {
0121         printSubTree(subNode, indent + 1);
0122     }
0123 }
0124 
0125 void printEnclosingBlockTree(NodeImpl *node)
0126 {
0127     if (!node || !node->enclosingBlockFlowElement()) {
0128         // qCDebug(KHTML_LOG) << "[null node]" << node;
0129         return;
0130     }
0131     printSubTree(node->enclosingBlockFlowElement());
0132 }
0133 
0134 void printRootEditableTree(NodeImpl *node)
0135 {
0136     if (!node || !node->rootEditableElement()) {
0137         // qCDebug(KHTML_LOG) << "[null node]" << node;
0138         return;
0139     }
0140     printSubTree(node->rootEditableElement());
0141 }
0142 
0143 Position::Position(NodeImpl *node, long offset)
0144     : m_node(nullptr), m_offset(offset)
0145 {
0146     if (node) {
0147         m_node = node;
0148         m_node->ref();
0149     }
0150 }
0151 
0152 Position::Position(const Position &o)
0153     : m_node(nullptr), m_offset(o.offset())
0154 {
0155     if (o.node()) {
0156         m_node = o.node();
0157         m_node->ref();
0158     }
0159 }
0160 
0161 Position::~Position()
0162 {
0163     if (m_node) {
0164         m_node->deref();
0165     }
0166 }
0167 
0168 Position &Position::operator=(const Position &o)
0169 {
0170     if (m_node) {
0171         m_node->deref();
0172     }
0173     m_node = o.node();
0174     if (m_node) {
0175         m_node->ref();
0176     }
0177 
0178     m_offset = o.offset();
0179 
0180     return *this;
0181 }
0182 
0183 ElementImpl *Position::element() const
0184 {
0185     if (isEmpty()) {
0186         return nullptr;
0187     }
0188 
0189     NodeImpl *n = node();
0190     for (; n && !n->isElementNode(); n = n->parentNode()) {}; //loop
0191 
0192     return static_cast<ElementImpl *>(n);
0193 }
0194 
0195 long Position::renderedOffset() const
0196 {
0197     return RenderPosition::fromDOMPosition(*this).renderedOffset();
0198 }
0199 
0200 Position Position::equivalentLeafPosition() const
0201 {
0202 #ifdef DEBUG_CARET
0203     // qCDebug(KHTML_LOG) << *this;
0204 #endif
0205     if (isEmpty()) {
0206         return Position();
0207     }
0208 
0209     if (!node()->renderer() || !node()->renderer()->firstChild()) {
0210         return *this;
0211     }
0212 
0213 #ifdef DEBUG_CARET
0214     // qCDebug(KHTML_LOG) << "[Position]" << this;
0215 #endif
0216     NodeImpl *n = node();
0217     int count = 0;
0218     while (1) {
0219         n = n->nextLeafNode();
0220         if (!n || !n->inSameContainingBlockFlowElement(node())) {
0221             return *this;
0222         }
0223 #ifdef DEBUG_CARET
0224         // qCDebug(KHTML_LOG) << "[iterate]" << n << count << n->maxOffset();
0225 #endif
0226         if (count + n->maxOffset() >= offset()) {
0227             count = offset() - count;
0228             break;
0229         }
0230         count += n->maxOffset();
0231     }
0232     return Position(n, count);
0233 }
0234 
0235 Position Position::previousRenderedEditablePosition() const
0236 {
0237 #ifdef DEBUG_CARET
0238     // qCDebug(KHTML_LOG) << *this;
0239 #endif
0240     if (isEmpty()) {
0241         return Position();
0242     }
0243 
0244     if ((node()->document()->part()->isCaretMode() || node()->isContentEditable()) && node()->hasChildNodes() == false && inRenderedContent()) {
0245         return *this;
0246     }
0247 
0248     NodeImpl *n = node();
0249     while (1) {
0250         n = n->previousEditable();
0251         if (!n) {
0252             return Position();
0253         }
0254         if (n->renderer() && n->renderer()->style()->visibility() == khtml::VISIBLE) {
0255             break;
0256         }
0257     }
0258 
0259     return Position(n, 0);
0260 }
0261 
0262 Position Position::nextRenderedEditablePosition() const
0263 {
0264 #ifdef DEBUG_CARET
0265     // qCDebug(KHTML_LOG) << *this;
0266 #endif
0267     if (isEmpty()) {
0268         return Position();
0269     }
0270 
0271     if ((node()->document()->part()->isCaretMode() || node()->isContentEditable()) && node()->hasChildNodes() == false && inRenderedContent()) {
0272         return *this;
0273     }
0274 
0275     NodeImpl *n = node();
0276     while (1) {
0277         n = n->nextEditable();
0278         if (!n) {
0279             return Position();
0280         }
0281         if (n->renderer() && n->renderer()->style()->visibility() == khtml::VISIBLE) {
0282             break;
0283         }
0284     }
0285 
0286     return Position(n, 0);
0287 }
0288 
0289 Position Position::previousCharacterPosition() const
0290 {
0291 #ifdef DEBUG_CARET
0292     // qCDebug(KHTML_LOG) << *this;
0293 #endif
0294     if (isEmpty()) {
0295         return Position();
0296     }
0297 
0298     NodeImpl *fromRootNavigableElement = rootNavigableElement(node());
0299 #ifdef DEBUG_CARET
0300     // qCDebug(KHTML_LOG) << "RootElement" << fromRootNavigableElement;
0301 #endif
0302     PositionIterator it(*this);
0303 
0304     RenderPosition originalRPosition = RenderPosition::fromDOMPosition(*this);
0305 
0306     while (!it.atStart()) {
0307         Position pos = it.previous();
0308 #ifdef DEBUG_CARET
0309         // qCDebug(KHTML_LOG) << "iterate" << pos;
0310 #endif
0311 
0312         if (rootNavigableElement(pos.node()) != fromRootNavigableElement) {
0313 #ifdef DEBUG_CARET
0314             // qCDebug(KHTML_LOG) << "different root" << rootNavigableElement(pos.node());
0315 #endif
0316             return *this;
0317         }
0318         RenderPosition currentRPosition = RenderPosition::fromDOMPosition(pos);
0319         if (RenderPosition::rendersInDifferentPosition(originalRPosition, currentRPosition)) {
0320             return currentRPosition.position();
0321         }
0322     }
0323 #ifdef DEBUG_CARET
0324     // qCDebug(KHTML_LOG) << "no previous position";
0325 #endif
0326     return *this;
0327 }
0328 
0329 Position Position::nextCharacterPosition() const
0330 {
0331 #ifdef DEBUG_CARET
0332     // qCDebug(KHTML_LOG) << *this;
0333 #endif
0334     if (isEmpty()) {
0335         return Position();
0336     }
0337 
0338     NodeImpl *fromRootNavigableElement = rootNavigableElement(node());
0339     PositionIterator it(*this);
0340 
0341     RenderPosition originalRPosition = RenderPosition::fromDOMPosition(*this);
0342 
0343     while (!it.atEnd()) {
0344         Position pos = it.next();
0345 
0346         if (rootNavigableElement(pos.node()) != fromRootNavigableElement) {
0347             return *this;
0348         }
0349         RenderPosition currentRPosition = RenderPosition::fromDOMPosition(pos);
0350         if (RenderPosition::rendersInDifferentPosition(originalRPosition, currentRPosition)) {
0351             return currentRPosition.position();
0352         }
0353     }
0354 
0355     return *this;
0356 }
0357 
0358 Position Position::previousWordPosition() const
0359 {
0360     if (isEmpty()) {
0361         return Position();
0362     }
0363 
0364     Position pos = *this;
0365     for (PositionIterator it(*this); !it.atStart(); it.previous()) {
0366         if (it.current().node()->nodeType() == Node::TEXT_NODE || it.current().node()->nodeType() == Node::CDATA_SECTION_NODE) {
0367             // use RenderPosition here
0368             DOMString t = it.current().node()->nodeValue();
0369             QChar *chars = t.unicode();
0370             uint len = t.length();
0371             int start, end;
0372             khtml::findWordBoundary(chars, len, it.current().offset(), &start, &end);
0373             pos = Position(it.current().node(), start);
0374         } else {
0375             pos = Position(it.current().node(), it.current().node()->caretMinOffset());
0376         }
0377         if (pos != *this) {
0378             return pos;
0379         }
0380         it.setPosition(pos);
0381     }
0382 
0383     return *this;
0384 }
0385 
0386 Position Position::nextWordPosition() const
0387 {
0388     if (isEmpty()) {
0389         return Position();
0390     }
0391 
0392     Position pos = *this;
0393     for (PositionIterator it(*this); !it.atEnd(); it.next()) {
0394         if (it.current().node()->nodeType() == Node::TEXT_NODE || it.current().node()->nodeType() == Node::CDATA_SECTION_NODE) {
0395             // use RenderPosition here
0396             DOMString t = it.current().node()->nodeValue();
0397             QChar *chars = t.unicode();
0398             uint len = t.length();
0399             int start, end;
0400             khtml::findWordBoundary(chars, len, it.current().offset(), &start, &end);
0401             pos = Position(it.current().node(), end);
0402         } else {
0403             pos = Position(it.current().node(), it.current().node()->caretMaxOffset());
0404         }
0405         if (pos != *this) {
0406             return pos;
0407         }
0408         it.setPosition(pos);
0409     }
0410 
0411     return *this;
0412 }
0413 
0414 Position Position::previousLinePosition(int x) const
0415 {
0416     return RenderPosition::fromDOMPosition(*this).previousLinePosition(x).position();
0417 }
0418 
0419 Position Position::nextLinePosition(int x) const
0420 {
0421     return RenderPosition::fromDOMPosition(*this).nextLinePosition(x).position();
0422 }
0423 
0424 Position Position::equivalentUpstreamPosition() const
0425 {
0426 #ifdef DEBUG_CARET
0427     // qCDebug(KHTML_LOG) << *this;
0428 #endif
0429     if (!node()) {
0430         return Position();
0431     }
0432 
0433     NodeImpl *block = node()->enclosingBlockFlowElement();
0434 
0435     PositionIterator it(*this);
0436     for (; !it.atStart(); it.previous()) {
0437 #ifdef DEBUG_CARET
0438         // qCDebug(KHTML_LOG) << "[iterate]" << it.current();
0439 #endif
0440         NodeImpl *currentBlock = it.current().node()->enclosingBlockFlowElement();
0441         if (block != currentBlock) {
0442             return it.next();
0443         }
0444 
0445         RenderObject *renderer = it.current().node()->renderer();
0446         if (!renderer) {
0447             continue;
0448         }
0449 
0450         if (renderer->style()->visibility() != khtml::VISIBLE) {
0451             continue;
0452         }
0453 
0454         if (renderer->isBlockFlow() || renderer->isReplaced() || renderer->isBR()) {
0455             if (it.current().offset() >= renderer->caretMaxOffset()) {
0456                 return Position(it.current().node(), renderer->caretMaxOffset());
0457             } else {
0458                 continue;
0459             }
0460         }
0461 
0462         if (renderer->isText() && static_cast<RenderText *>(renderer)->firstTextBox()) {
0463             if (it.current().node() != node()) {
0464                 Position result(it.current().node(), renderer->caretMaxOffset());
0465                 if (rendersInDifferentPosition(result)) {
0466                     return it.next();
0467                 }
0468                 return result;
0469             }
0470 
0471             if (it.current().offset() < 0) {
0472                 continue;
0473             }
0474             uint textOffset = it.current().offset();
0475 
0476             RenderText *textRenderer = static_cast<RenderText *>(renderer);
0477             textOffset = textRenderer->convertToRenderedPosition(textOffset);
0478             // textRenderer->firstTextBox()->parent()->printTree();
0479             for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
0480                 if (textOffset > box->start() && textOffset <= box->start() + box->len()) {
0481                     return it.current();
0482                 }
0483             }
0484         }
0485     }
0486 
0487     if (it.current().node()->enclosingBlockFlowElement() != block) {
0488         return it.next();
0489     }
0490 
0491     return it.current();
0492 }
0493 
0494 Position Position::equivalentDownstreamPosition() const
0495 {
0496     // qCDebug(KHTML_LOG) << *this;
0497     if (!node()) {
0498         return Position();
0499     }
0500 
0501     NodeImpl *block = node()->enclosingBlockFlowElement();
0502 
0503     PositionIterator it(*this);
0504     for (; !it.atEnd(); it.next()) {
0505         // qCDebug(KHTML_LOG) << "[iterate]" << it.current();
0506         NodeImpl *currentBlock = it.current().node()->enclosingBlockFlowElement();
0507         if (block != currentBlock) {
0508             return it.previous();
0509         }
0510 
0511         RenderObject *renderer = it.current().node()->renderer();
0512         if (!renderer) {
0513             continue;
0514         }
0515 
0516         if (renderer->style()->visibility() != khtml::VISIBLE) {
0517             continue;
0518         }
0519 
0520         if (renderer->isBlockFlow() || renderer->isReplaced() || renderer->isBR()) {
0521             if (it.current().offset() <= renderer->caretMinOffset()) {
0522                 return Position(it.current().node(), renderer->caretMinOffset());
0523             } else {
0524                 continue;
0525             }
0526         }
0527 
0528         if (renderer->isText() && static_cast<RenderText *>(renderer)->firstTextBox()) {
0529             if (it.current().node() != node()) {
0530                 Position result(it.current().node(), renderer->caretMinOffset());
0531                 if (rendersInDifferentPosition(result)) {
0532                     return it.previous();
0533                 }
0534                 return result;
0535             }
0536 
0537             if (it.current().offset() < 0) {
0538                 continue;
0539             }
0540             uint textOffset = it.current().offset();
0541 
0542             RenderText *textRenderer = static_cast<RenderText *>(renderer);
0543             textOffset = textRenderer->convertToRenderedPosition(textOffset);
0544             // textRenderer->firstTextBox()->parent()->printTree();
0545             for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
0546                 if (textOffset >= box->start() && textOffset <= box->end()) {
0547                     return it.current();
0548                 }
0549             }
0550         }
0551     }
0552 
0553     if (it.current().node()->enclosingBlockFlowElement() != block) {
0554         return it.previous();
0555     }
0556 
0557     return it.current();
0558 }
0559 
0560 Position Position::equivalentRangeCompliantPosition() const
0561 {
0562     if (isEmpty()) {
0563         return *this;
0564     }
0565 
0566     if (!node()->parentNode()) {
0567         return *this;
0568     }
0569 
0570     RenderObject *renderer = node()->renderer();
0571     if (!renderer) {
0572         return *this;
0573     }
0574 
0575     if (!renderer->isReplaced() && !renderer->isBR()) {
0576         return *this;
0577     }
0578 
0579     int o = 0;
0580     const NodeImpl *n = node();
0581     while ((n = n->previousSibling())) {
0582         o++;
0583     }
0584 
0585     return Position(node()->parentNode(), o + offset());
0586 }
0587 
0588 Position Position::equivalentShallowPosition() const
0589 {
0590     if (isEmpty()) {
0591         return *this;
0592     }
0593 
0594     Position pos(*this);
0595     while (pos.offset() == pos.node()->caretMinOffset() && pos.node()->parentNode() && pos.node() == pos.node()->parentNode()->firstChild()) {
0596         pos = Position(pos.node()->parentNode(), 0);
0597     }
0598     return pos;
0599 }
0600 
0601 bool Position::atStartOfContainingEditableBlock() const
0602 {
0603     return renderedOffset() == 0 && inFirstEditableInContainingEditableBlock();
0604 }
0605 
0606 bool Position::atStartOfRootEditableElement() const
0607 {
0608     return renderedOffset() == 0 && inFirstEditableInRootEditableElement();
0609 }
0610 
0611 bool Position::inRenderedContent() const
0612 {
0613     return RenderPosition::fromDOMPosition(*this).inRenderedContent();
0614 }
0615 
0616 bool Position::inRenderedText() const
0617 {
0618     return RenderPosition::fromDOMPosition(*this).inRenderedContent() && node() && node()->renderer() && node()->renderer()->isText();
0619 }
0620 
0621 bool Position::rendersOnSameLine(const Position &pos) const
0622 {
0623     if (isEmpty() || pos.isEmpty()) {
0624         return false;
0625     }
0626 
0627     if (*this == pos) {
0628         return true;
0629     }
0630 
0631     if (node()->enclosingBlockFlowElement() != pos.node()->enclosingBlockFlowElement()) {
0632         return false;
0633     }
0634 
0635     RenderPosition self = RenderPosition::fromDOMPosition(*this);
0636     RenderPosition other = RenderPosition::fromDOMPosition(pos);
0637     return RenderPosition::rendersOnSameLine(self, other);
0638 }
0639 
0640 bool Position::rendersInDifferentPosition(const Position &pos) const
0641 {
0642     return RenderPosition::rendersInDifferentPosition(RenderPosition::fromDOMPosition(*this), RenderPosition::fromDOMPosition(pos));
0643     /*// qCDebug(KHTML_LOG) << *this << pos;
0644     if (isEmpty() || pos.isEmpty())
0645         return false;
0646 
0647     RenderObject *renderer = node()->renderer();
0648     if (!renderer)
0649         return false;
0650 
0651     RenderObject *posRenderer = pos.node()->renderer();
0652     if (!posRenderer)
0653         return false;
0654 
0655     if (renderer->style()->visibility() != khtml::VISIBLE ||
0656         posRenderer->style()->visibility() != khtml::VISIBLE)
0657         return false;
0658 
0659     if (node() == pos.node()) {
0660         if (node()->id() == ID_BR)
0661             return false;
0662 
0663         if (offset() == pos.offset())
0664             return false;
0665 
0666         if (!node()->isTextNode() && !pos.node()->isTextNode()) {
0667             if (offset() != pos.offset())
0668                 return true;
0669         }
0670     }
0671 
0672     if (node()->id() == ID_BR && pos.inRenderedContent())
0673         return true;
0674 
0675     if (pos.node()->id() == ID_BR && inRenderedContent())
0676         return true;
0677 
0678     if (node()->enclosingBlockFlowElement() != pos.node()->enclosingBlockFlowElement())
0679         return true;
0680 
0681     if (node()->isTextNode() && !inRenderedText())
0682         return false;
0683 
0684     if (pos.node()->isTextNode() && !pos.inRenderedText())
0685         return false;
0686 
0687     long thisRenderedOffset = renderedOffset();
0688     long posRenderedOffset = pos.renderedOffset();
0689 
0690     if (renderer == posRenderer && thisRenderedOffset == posRenderedOffset)
0691         return false;
0692 
0693     // qCDebug(KHTML_LOG) << "onDifferentLine:" << (renderersOnDifferentLine(renderer, offset(), posRenderer, pos.offset()) ? "YES" : "NO");
0694     // qCDebug(KHTML_LOG) << "renderer:" << renderer << "[" << (renderer ? renderer->inlineBox(offset()) : 0) << "]";
0695     // qCDebug(KHTML_LOG) << "thisRenderedOffset:" << thisRenderedOffset;
0696     // qCDebug(KHTML_LOG) << "posRenderer:" << posRenderer <<  "[" << (posRenderer ? posRenderer->inlineBox(offset()) : 0) << "]";
0697     // qCDebug(KHTML_LOG) << "posRenderedOffset:"<< posRenderedOffset;
0698     // qCDebug(KHTML_LOG) << "node min/max:"<< node()->caretMinOffset() << "/" << node()->caretMaxRenderedOffset();
0699     // qCDebug(KHTML_LOG) << "pos node min/max:"<< pos.node()->caretMinOffset() << "/" << pos.node()->caretMaxRenderedOffset();
0700     // qCDebug(KHTML_LOG) << "----------------------------------------------------------------------";
0701 
0702     InlineBox *b1 = renderer ? renderer->inlineBox(offset()) : 0;
0703     InlineBox *b2 = posRenderer ? posRenderer->inlineBox(pos.offset()) : 0;
0704 
0705     if (!b1 || !b2) {
0706         return false;
0707     }
0708 
0709     if (b1->root() != b2->root()) {
0710         return true;
0711     }
0712 
0713     if (nextRenderedEditable(node()) == pos.node() &&
0714         thisRenderedOffset == (long)node()->caretMaxRenderedOffset() && posRenderedOffset == 0) {
0715         return false;
0716     }
0717 
0718     if (previousRenderedEditable(node()) == pos.node() &&
0719         thisRenderedOffset == 0 && posRenderedOffset == (long)pos.node()->caretMaxRenderedOffset()) {
0720         return false;
0721     }
0722 
0723     return true;*/
0724 }
0725 
0726 bool Position::isFirstRenderedPositionOnLine() const
0727 {
0728     // return RenderPosition::fromDOMPosition(*this).isFirst*/
0729     // qCDebug(KHTML_LOG) << *this;
0730     if (isEmpty()) {
0731         return false;
0732     }
0733 
0734     RenderObject *renderer = node()->renderer();
0735     if (!renderer) {
0736         return false;
0737     }
0738     // qCDebug(KHTML_LOG) << "Renderer" << renderer << renderer->renderName();
0739 
0740     if (renderer->style()->visibility() != khtml::VISIBLE) {
0741         return false;
0742     }
0743 
0744     Position pos(node(), offset());
0745     PositionIterator it(pos);
0746     while (!it.atStart()) {
0747         it.previous();
0748         // qCDebug(KHTML_LOG) << "To previous" << it.current();
0749         if (it.current().inRenderedContent()) {
0750             return !rendersOnSameLine(it.current());
0751         }
0752         // return renderersOnDifferentLine(renderer, offset(), it.current().node()->renderer(), it.current().offset());
0753     }
0754 
0755     return true;
0756 }
0757 
0758 bool Position::isLastRenderedPositionOnLine() const
0759 {
0760     if (isEmpty()) {
0761         return false;
0762     }
0763 
0764     RenderObject *renderer = node()->renderer();
0765     if (!renderer) {
0766         return false;
0767     }
0768 
0769     if (renderer->style()->visibility() != khtml::VISIBLE) {
0770         return false;
0771     }
0772 
0773     if (node()->id() == ID_BR) {
0774         return true;
0775     }
0776 
0777     Position pos(node(), offset());
0778     PositionIterator it(pos);
0779     while (!it.atEnd()) {
0780         it.next();
0781         if (it.current().inRenderedContent()) {
0782             return !rendersOnSameLine(it.current());
0783         }
0784         // return renderersOnDifferentLine(renderer, offset(), it.current().node()->renderer(), it.current().offset());
0785     }
0786 
0787     return true;
0788 }
0789 
0790 bool Position::isLastRenderedPositionInEditableBlock() const
0791 {
0792     if (isEmpty()) {
0793         return false;
0794     }
0795 
0796     RenderObject *renderer = node()->renderer();
0797     if (!renderer) {
0798         return false;
0799     }
0800 
0801     if (renderer->style()->visibility() != khtml::VISIBLE) {
0802         return false;
0803     }
0804 
0805     if (renderedOffset() != (long)node()->caretMaxRenderedOffset()) {
0806         return false;
0807     }
0808 
0809     Position pos(node(), offset());
0810     PositionIterator it(pos);
0811     while (!it.atEnd()) {
0812         it.next();
0813         if (!it.current().node()->inSameContainingBlockFlowElement(node())) {
0814             return true;
0815         }
0816         if (it.current().inRenderedContent()) {
0817             return false;
0818         }
0819     }
0820     return true;
0821 }
0822 
0823 bool Position::inFirstEditableInRootEditableElement() const
0824 {
0825     if (isEmpty() || !inRenderedContent()) {
0826         return false;
0827     }
0828 
0829     PositionIterator it(*this);
0830     while (!it.atStart()) {
0831         if (it.previous().inRenderedContent()) {
0832             return false;
0833         }
0834     }
0835 
0836     return true;
0837 }
0838 
0839 bool Position::inLastEditableInRootEditableElement() const
0840 {
0841     if (isEmpty() || !inRenderedContent()) {
0842         return false;
0843     }
0844 
0845     PositionIterator it(*this);
0846     while (!it.atEnd()) {
0847         if (it.next().inRenderedContent()) {
0848             return false;
0849         }
0850     }
0851 
0852     return true;
0853 }
0854 
0855 bool Position::inFirstEditableInContainingEditableBlock() const
0856 {
0857     if (isEmpty() || !RenderPosition::inRenderedContent(*this)) {
0858         return false;
0859     }
0860 
0861     NodeImpl *block = node()->enclosingBlockFlowElement();
0862 
0863     PositionIterator it(*this);
0864     while (!it.atStart()) {
0865         it.previous();
0866         if (!RenderPosition::inRenderedContent(it.current())) {
0867             continue;
0868         }
0869         return block != it.current().node()->enclosingBlockFlowElement();
0870     }
0871 
0872     return true;
0873 }
0874 
0875 bool Position::inLastEditableInContainingEditableBlock() const
0876 {
0877     if (isEmpty() || !RenderPosition::inRenderedContent(*this)) {
0878         return false;
0879     }
0880 
0881     NodeImpl *block = node()->enclosingBlockFlowElement();
0882 
0883     PositionIterator it(*this);
0884     while (!it.atEnd()) {
0885         it.next();
0886         if (!RenderPosition::inRenderedContent(it.current())) {
0887             continue;
0888         }
0889         return block != it.current().node()->enclosingBlockFlowElement();
0890     }
0891 
0892     return true;
0893 }
0894 
0895 QDebug operator<<(QDebug stream, const Position &position)
0896 {
0897     const NodeImpl *node = position.node();
0898     stream << "Position(" << node << (node ? node->nodeName() : QString()) << ":" << position.offset() << ")";
0899     return stream;
0900 }
0901 
0902 } // namespace DOM