File indexing completed on 2024-04-28 15:24:52
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