1 /*
2  * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "dom_position.h"
27 
28 #include "misc/helper.h"
29 #include "rendering/render_block.h"
30 #include "rendering/render_line.h"
31 #include "rendering/render_object.h"
32 #include "rendering/render_style.h"
33 #include "rendering/render_text.h"
34 #include "xml/dom_positioniterator.h"
35 #include "xml/dom_elementimpl.h"
36 #include "xml/dom_docimpl.h"
37 #include "xml/dom_nodeimpl.h"
38 #include "html/html_documentimpl.h"
39 #include "rendering/render_position.h"
40 
41 #include "khtml_part.h"
42 
43 #include <qstring.h>
44 
45 #define DEBUG_CARET
46 
47 // FIXME shouldn't use any rendereing related here except for RenderPosition
48 using khtml::InlineBox;
49 using khtml::InlineFlowBox;
50 using khtml::InlineTextBox;
51 using khtml::RenderBlock;
52 using khtml::RenderObject;
53 using khtml::RenderText;
54 using khtml::RootInlineBox;
55 using khtml::RenderPosition;
56 
57 namespace DOM
58 {
59 
nextRenderedEditable(NodeImpl * node)60 static NodeImpl *nextRenderedEditable(NodeImpl *node)
61 {
62     while (1) {
63         node = node->nextEditable();
64         if (!node) {
65             return nullptr;
66         }
67         if (!node->renderer()) {
68             continue;
69         }
70         if (node->renderer()->inlineBox(0)) {
71             return node;
72         }
73     }
74     return nullptr;
75 }
76 
previousRenderedEditable(NodeImpl * node)77 static NodeImpl *previousRenderedEditable(NodeImpl *node)
78 {
79     while (1) {
80         node = node->previousEditable();
81         if (!node) {
82             return nullptr;
83         }
84         if (!node->renderer()) {
85             continue;
86         }
87         if (node->renderer()->inlineBox(0)) {
88             return node;
89         }
90     }
91     return nullptr;
92 }
93 
rootNavigableElement(NodeImpl * node)94 /*static*/ NodeImpl *rootNavigableElement(NodeImpl *node)
95 {
96     DocumentImpl *doc = node->document();
97     if (doc && doc->part()->isCaretMode()) {
98         if (doc->isHTMLDocument()) {
99             return static_cast<HTMLDocumentImpl *>(doc)->body();
100         } else {
101             return doc->documentElement();
102         }
103     }
104 
105     return node->rootEditableElement();
106 }
107 
inSameRootNavigableElement(NodeImpl * n1,NodeImpl * n2)108 /*inline*/ /*static*/ bool inSameRootNavigableElement(NodeImpl *n1, NodeImpl *n2)
109 {
110     return n1 && n2 && rootNavigableElement(n1) == rootNavigableElement(n2);
111 }
112 
printSubTree(NodeImpl * node,int indent=0)113 static void printSubTree(NodeImpl *node, int indent = 0)
114 {
115     QString temp;
116     temp.fill(' ', indent);
117     // qCDebug(KHTML_LOG) << temp << node << node->nodeName() << node->renderer()
118     //    << (node->renderer() ? node->renderer()->renderName() : "")
119     //    << (node->isTextNode() ? static_cast<TextImpl*>(node)->toString() : "");
120     for (NodeImpl *subNode = node->firstChild(); subNode; subNode = subNode->nextSibling()) {
121         printSubTree(subNode, indent + 1);
122     }
123 }
124 
printEnclosingBlockTree(NodeImpl * node)125 void printEnclosingBlockTree(NodeImpl *node)
126 {
127     if (!node || !node->enclosingBlockFlowElement()) {
128         // qCDebug(KHTML_LOG) << "[null node]" << node;
129         return;
130     }
131     printSubTree(node->enclosingBlockFlowElement());
132 }
133 
printRootEditableTree(NodeImpl * node)134 void printRootEditableTree(NodeImpl *node)
135 {
136     if (!node || !node->rootEditableElement()) {
137         // qCDebug(KHTML_LOG) << "[null node]" << node;
138         return;
139     }
140     printSubTree(node->rootEditableElement());
141 }
142 
Position(NodeImpl * node,long offset)143 Position::Position(NodeImpl *node, long offset)
144     : m_node(nullptr), m_offset(offset)
145 {
146     if (node) {
147         m_node = node;
148         m_node->ref();
149     }
150 }
151 
Position(const Position & o)152 Position::Position(const Position &o)
153     : m_node(nullptr), m_offset(o.offset())
154 {
155     if (o.node()) {
156         m_node = o.node();
157         m_node->ref();
158     }
159 }
160 
~Position()161 Position::~Position()
162 {
163     if (m_node) {
164         m_node->deref();
165     }
166 }
167 
operator =(const Position & o)168 Position &Position::operator=(const Position &o)
169 {
170     if (m_node) {
171         m_node->deref();
172     }
173     m_node = o.node();
174     if (m_node) {
175         m_node->ref();
176     }
177 
178     m_offset = o.offset();
179 
180     return *this;
181 }
182 
element() const183 ElementImpl *Position::element() const
184 {
185     if (isEmpty()) {
186         return nullptr;
187     }
188 
189     NodeImpl *n = node();
190     for (; n && !n->isElementNode(); n = n->parentNode()) {}; //loop
191 
192     return static_cast<ElementImpl *>(n);
193 }
194 
renderedOffset() const195 long Position::renderedOffset() const
196 {
197     return RenderPosition::fromDOMPosition(*this).renderedOffset();
198 }
199 
equivalentLeafPosition() const200 Position Position::equivalentLeafPosition() const
201 {
202 #ifdef DEBUG_CARET
203     // qCDebug(KHTML_LOG) << *this;
204 #endif
205     if (isEmpty()) {
206         return Position();
207     }
208 
209     if (!node()->renderer() || !node()->renderer()->firstChild()) {
210         return *this;
211     }
212 
213 #ifdef DEBUG_CARET
214     // qCDebug(KHTML_LOG) << "[Position]" << this;
215 #endif
216     NodeImpl *n = node();
217     int count = 0;
218     while (1) {
219         n = n->nextLeafNode();
220         if (!n || !n->inSameContainingBlockFlowElement(node())) {
221             return *this;
222         }
223 #ifdef DEBUG_CARET
224         // qCDebug(KHTML_LOG) << "[iterate]" << n << count << n->maxOffset();
225 #endif
226         if (count + n->maxOffset() >= offset()) {
227             count = offset() - count;
228             break;
229         }
230         count += n->maxOffset();
231     }
232     return Position(n, count);
233 }
234 
previousRenderedEditablePosition() const235 Position Position::previousRenderedEditablePosition() const
236 {
237 #ifdef DEBUG_CARET
238     // qCDebug(KHTML_LOG) << *this;
239 #endif
240     if (isEmpty()) {
241         return Position();
242     }
243 
244     if ((node()->document()->part()->isCaretMode() || node()->isContentEditable()) && node()->hasChildNodes() == false && inRenderedContent()) {
245         return *this;
246     }
247 
248     NodeImpl *n = node();
249     while (1) {
250         n = n->previousEditable();
251         if (!n) {
252             return Position();
253         }
254         if (n->renderer() && n->renderer()->style()->visibility() == khtml::VISIBLE) {
255             break;
256         }
257     }
258 
259     return Position(n, 0);
260 }
261 
nextRenderedEditablePosition() const262 Position Position::nextRenderedEditablePosition() const
263 {
264 #ifdef DEBUG_CARET
265     // qCDebug(KHTML_LOG) << *this;
266 #endif
267     if (isEmpty()) {
268         return Position();
269     }
270 
271     if ((node()->document()->part()->isCaretMode() || node()->isContentEditable()) && node()->hasChildNodes() == false && inRenderedContent()) {
272         return *this;
273     }
274 
275     NodeImpl *n = node();
276     while (1) {
277         n = n->nextEditable();
278         if (!n) {
279             return Position();
280         }
281         if (n->renderer() && n->renderer()->style()->visibility() == khtml::VISIBLE) {
282             break;
283         }
284     }
285 
286     return Position(n, 0);
287 }
288 
previousCharacterPosition() const289 Position Position::previousCharacterPosition() const
290 {
291 #ifdef DEBUG_CARET
292     // qCDebug(KHTML_LOG) << *this;
293 #endif
294     if (isEmpty()) {
295         return Position();
296     }
297 
298     NodeImpl *fromRootNavigableElement = rootNavigableElement(node());
299 #ifdef DEBUG_CARET
300     // qCDebug(KHTML_LOG) << "RootElement" << fromRootNavigableElement;
301 #endif
302     PositionIterator it(*this);
303 
304     RenderPosition originalRPosition = RenderPosition::fromDOMPosition(*this);
305 
306     while (!it.atStart()) {
307         Position pos = it.previous();
308 #ifdef DEBUG_CARET
309         // qCDebug(KHTML_LOG) << "iterate" << pos;
310 #endif
311 
312         if (rootNavigableElement(pos.node()) != fromRootNavigableElement) {
313 #ifdef DEBUG_CARET
314             // qCDebug(KHTML_LOG) << "different root" << rootNavigableElement(pos.node());
315 #endif
316             return *this;
317         }
318         RenderPosition currentRPosition = RenderPosition::fromDOMPosition(pos);
319         if (RenderPosition::rendersInDifferentPosition(originalRPosition, currentRPosition)) {
320             return currentRPosition.position();
321         }
322     }
323 #ifdef DEBUG_CARET
324     // qCDebug(KHTML_LOG) << "no previous position";
325 #endif
326     return *this;
327 }
328 
nextCharacterPosition() const329 Position Position::nextCharacterPosition() const
330 {
331 #ifdef DEBUG_CARET
332     // qCDebug(KHTML_LOG) << *this;
333 #endif
334     if (isEmpty()) {
335         return Position();
336     }
337 
338     NodeImpl *fromRootNavigableElement = rootNavigableElement(node());
339     PositionIterator it(*this);
340 
341     RenderPosition originalRPosition = RenderPosition::fromDOMPosition(*this);
342 
343     while (!it.atEnd()) {
344         Position pos = it.next();
345 
346         if (rootNavigableElement(pos.node()) != fromRootNavigableElement) {
347             return *this;
348         }
349         RenderPosition currentRPosition = RenderPosition::fromDOMPosition(pos);
350         if (RenderPosition::rendersInDifferentPosition(originalRPosition, currentRPosition)) {
351             return currentRPosition.position();
352         }
353     }
354 
355     return *this;
356 }
357 
previousWordPosition() const358 Position Position::previousWordPosition() const
359 {
360     if (isEmpty()) {
361         return Position();
362     }
363 
364     Position pos = *this;
365     for (PositionIterator it(*this); !it.atStart(); it.previous()) {
366         if (it.current().node()->nodeType() == Node::TEXT_NODE || it.current().node()->nodeType() == Node::CDATA_SECTION_NODE) {
367             // use RenderPosition here
368             DOMString t = it.current().node()->nodeValue();
369             QChar *chars = t.unicode();
370             uint len = t.length();
371             int start, end;
372             khtml::findWordBoundary(chars, len, it.current().offset(), &start, &end);
373             pos = Position(it.current().node(), start);
374         } else {
375             pos = Position(it.current().node(), it.current().node()->caretMinOffset());
376         }
377         if (pos != *this) {
378             return pos;
379         }
380         it.setPosition(pos);
381     }
382 
383     return *this;
384 }
385 
nextWordPosition() const386 Position Position::nextWordPosition() const
387 {
388     if (isEmpty()) {
389         return Position();
390     }
391 
392     Position pos = *this;
393     for (PositionIterator it(*this); !it.atEnd(); it.next()) {
394         if (it.current().node()->nodeType() == Node::TEXT_NODE || it.current().node()->nodeType() == Node::CDATA_SECTION_NODE) {
395             // use RenderPosition here
396             DOMString t = it.current().node()->nodeValue();
397             QChar *chars = t.unicode();
398             uint len = t.length();
399             int start, end;
400             khtml::findWordBoundary(chars, len, it.current().offset(), &start, &end);
401             pos = Position(it.current().node(), end);
402         } else {
403             pos = Position(it.current().node(), it.current().node()->caretMaxOffset());
404         }
405         if (pos != *this) {
406             return pos;
407         }
408         it.setPosition(pos);
409     }
410 
411     return *this;
412 }
413 
previousLinePosition(int x) const414 Position Position::previousLinePosition(int x) const
415 {
416     return RenderPosition::fromDOMPosition(*this).previousLinePosition(x).position();
417 }
418 
nextLinePosition(int x) const419 Position Position::nextLinePosition(int x) const
420 {
421     return RenderPosition::fromDOMPosition(*this).nextLinePosition(x).position();
422 }
423 
equivalentUpstreamPosition() const424 Position Position::equivalentUpstreamPosition() const
425 {
426 #ifdef DEBUG_CARET
427     // qCDebug(KHTML_LOG) << *this;
428 #endif
429     if (!node()) {
430         return Position();
431     }
432 
433     NodeImpl *block = node()->enclosingBlockFlowElement();
434 
435     PositionIterator it(*this);
436     for (; !it.atStart(); it.previous()) {
437 #ifdef DEBUG_CARET
438         // qCDebug(KHTML_LOG) << "[iterate]" << it.current();
439 #endif
440         NodeImpl *currentBlock = it.current().node()->enclosingBlockFlowElement();
441         if (block != currentBlock) {
442             return it.next();
443         }
444 
445         RenderObject *renderer = it.current().node()->renderer();
446         if (!renderer) {
447             continue;
448         }
449 
450         if (renderer->style()->visibility() != khtml::VISIBLE) {
451             continue;
452         }
453 
454         if (renderer->isBlockFlow() || renderer->isReplaced() || renderer->isBR()) {
455             if (it.current().offset() >= renderer->caretMaxOffset()) {
456                 return Position(it.current().node(), renderer->caretMaxOffset());
457             } else {
458                 continue;
459             }
460         }
461 
462         if (renderer->isText() && static_cast<RenderText *>(renderer)->firstTextBox()) {
463             if (it.current().node() != node()) {
464                 Position result(it.current().node(), renderer->caretMaxOffset());
465                 if (rendersInDifferentPosition(result)) {
466                     return it.next();
467                 }
468                 return result;
469             }
470 
471             if (it.current().offset() < 0) {
472                 continue;
473             }
474             uint textOffset = it.current().offset();
475 
476             RenderText *textRenderer = static_cast<RenderText *>(renderer);
477             textOffset = textRenderer->convertToRenderedPosition(textOffset);
478             // textRenderer->firstTextBox()->parent()->printTree();
479             for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
480                 if (textOffset > box->start() && textOffset <= box->start() + box->len()) {
481                     return it.current();
482                 }
483             }
484         }
485     }
486 
487     if (it.current().node()->enclosingBlockFlowElement() != block) {
488         return it.next();
489     }
490 
491     return it.current();
492 }
493 
equivalentDownstreamPosition() const494 Position Position::equivalentDownstreamPosition() const
495 {
496     // qCDebug(KHTML_LOG) << *this;
497     if (!node()) {
498         return Position();
499     }
500 
501     NodeImpl *block = node()->enclosingBlockFlowElement();
502 
503     PositionIterator it(*this);
504     for (; !it.atEnd(); it.next()) {
505         // qCDebug(KHTML_LOG) << "[iterate]" << it.current();
506         NodeImpl *currentBlock = it.current().node()->enclosingBlockFlowElement();
507         if (block != currentBlock) {
508             return it.previous();
509         }
510 
511         RenderObject *renderer = it.current().node()->renderer();
512         if (!renderer) {
513             continue;
514         }
515 
516         if (renderer->style()->visibility() != khtml::VISIBLE) {
517             continue;
518         }
519 
520         if (renderer->isBlockFlow() || renderer->isReplaced() || renderer->isBR()) {
521             if (it.current().offset() <= renderer->caretMinOffset()) {
522                 return Position(it.current().node(), renderer->caretMinOffset());
523             } else {
524                 continue;
525             }
526         }
527 
528         if (renderer->isText() && static_cast<RenderText *>(renderer)->firstTextBox()) {
529             if (it.current().node() != node()) {
530                 Position result(it.current().node(), renderer->caretMinOffset());
531                 if (rendersInDifferentPosition(result)) {
532                     return it.previous();
533                 }
534                 return result;
535             }
536 
537             if (it.current().offset() < 0) {
538                 continue;
539             }
540             uint textOffset = it.current().offset();
541 
542             RenderText *textRenderer = static_cast<RenderText *>(renderer);
543             textOffset = textRenderer->convertToRenderedPosition(textOffset);
544             // textRenderer->firstTextBox()->parent()->printTree();
545             for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
546                 if (textOffset >= box->start() && textOffset <= box->end()) {
547                     return it.current();
548                 }
549             }
550         }
551     }
552 
553     if (it.current().node()->enclosingBlockFlowElement() != block) {
554         return it.previous();
555     }
556 
557     return it.current();
558 }
559 
equivalentRangeCompliantPosition() const560 Position Position::equivalentRangeCompliantPosition() const
561 {
562     if (isEmpty()) {
563         return *this;
564     }
565 
566     if (!node()->parentNode()) {
567         return *this;
568     }
569 
570     RenderObject *renderer = node()->renderer();
571     if (!renderer) {
572         return *this;
573     }
574 
575     if (!renderer->isReplaced() && !renderer->isBR()) {
576         return *this;
577     }
578 
579     int o = 0;
580     const NodeImpl *n = node();
581     while ((n = n->previousSibling())) {
582         o++;
583     }
584 
585     return Position(node()->parentNode(), o + offset());
586 }
587 
equivalentShallowPosition() const588 Position Position::equivalentShallowPosition() const
589 {
590     if (isEmpty()) {
591         return *this;
592     }
593 
594     Position pos(*this);
595     while (pos.offset() == pos.node()->caretMinOffset() && pos.node()->parentNode() && pos.node() == pos.node()->parentNode()->firstChild()) {
596         pos = Position(pos.node()->parentNode(), 0);
597     }
598     return pos;
599 }
600 
atStartOfContainingEditableBlock() const601 bool Position::atStartOfContainingEditableBlock() const
602 {
603     return renderedOffset() == 0 && inFirstEditableInContainingEditableBlock();
604 }
605 
atStartOfRootEditableElement() const606 bool Position::atStartOfRootEditableElement() const
607 {
608     return renderedOffset() == 0 && inFirstEditableInRootEditableElement();
609 }
610 
inRenderedContent() const611 bool Position::inRenderedContent() const
612 {
613     return RenderPosition::fromDOMPosition(*this).inRenderedContent();
614 }
615 
inRenderedText() const616 bool Position::inRenderedText() const
617 {
618     return RenderPosition::fromDOMPosition(*this).inRenderedContent() && node() && node()->renderer() && node()->renderer()->isText();
619 }
620 
rendersOnSameLine(const Position & pos) const621 bool Position::rendersOnSameLine(const Position &pos) const
622 {
623     if (isEmpty() || pos.isEmpty()) {
624         return false;
625     }
626 
627     if (*this == pos) {
628         return true;
629     }
630 
631     if (node()->enclosingBlockFlowElement() != pos.node()->enclosingBlockFlowElement()) {
632         return false;
633     }
634 
635     RenderPosition self = RenderPosition::fromDOMPosition(*this);
636     RenderPosition other = RenderPosition::fromDOMPosition(pos);
637     return RenderPosition::rendersOnSameLine(self, other);
638 }
639 
rendersInDifferentPosition(const Position & pos) const640 bool Position::rendersInDifferentPosition(const Position &pos) const
641 {
642     return RenderPosition::rendersInDifferentPosition(RenderPosition::fromDOMPosition(*this), RenderPosition::fromDOMPosition(pos));
643     /*// qCDebug(KHTML_LOG) << *this << pos;
644     if (isEmpty() || pos.isEmpty())
645         return false;
646 
647     RenderObject *renderer = node()->renderer();
648     if (!renderer)
649         return false;
650 
651     RenderObject *posRenderer = pos.node()->renderer();
652     if (!posRenderer)
653         return false;
654 
655     if (renderer->style()->visibility() != khtml::VISIBLE ||
656         posRenderer->style()->visibility() != khtml::VISIBLE)
657         return false;
658 
659     if (node() == pos.node()) {
660         if (node()->id() == ID_BR)
661             return false;
662 
663         if (offset() == pos.offset())
664             return false;
665 
666         if (!node()->isTextNode() && !pos.node()->isTextNode()) {
667             if (offset() != pos.offset())
668                 return true;
669         }
670     }
671 
672     if (node()->id() == ID_BR && pos.inRenderedContent())
673         return true;
674 
675     if (pos.node()->id() == ID_BR && inRenderedContent())
676         return true;
677 
678     if (node()->enclosingBlockFlowElement() != pos.node()->enclosingBlockFlowElement())
679         return true;
680 
681     if (node()->isTextNode() && !inRenderedText())
682         return false;
683 
684     if (pos.node()->isTextNode() && !pos.inRenderedText())
685         return false;
686 
687     long thisRenderedOffset = renderedOffset();
688     long posRenderedOffset = pos.renderedOffset();
689 
690     if (renderer == posRenderer && thisRenderedOffset == posRenderedOffset)
691         return false;
692 
693     // qCDebug(KHTML_LOG) << "onDifferentLine:" << (renderersOnDifferentLine(renderer, offset(), posRenderer, pos.offset()) ? "YES" : "NO");
694     // qCDebug(KHTML_LOG) << "renderer:" << renderer << "[" << (renderer ? renderer->inlineBox(offset()) : 0) << "]";
695     // qCDebug(KHTML_LOG) << "thisRenderedOffset:" << thisRenderedOffset;
696     // qCDebug(KHTML_LOG) << "posRenderer:" << posRenderer <<  "[" << (posRenderer ? posRenderer->inlineBox(offset()) : 0) << "]";
697     // qCDebug(KHTML_LOG) << "posRenderedOffset:"<< posRenderedOffset;
698     // qCDebug(KHTML_LOG) << "node min/max:"<< node()->caretMinOffset() << "/" << node()->caretMaxRenderedOffset();
699     // qCDebug(KHTML_LOG) << "pos node min/max:"<< pos.node()->caretMinOffset() << "/" << pos.node()->caretMaxRenderedOffset();
700     // qCDebug(KHTML_LOG) << "----------------------------------------------------------------------";
701 
702     InlineBox *b1 = renderer ? renderer->inlineBox(offset()) : 0;
703     InlineBox *b2 = posRenderer ? posRenderer->inlineBox(pos.offset()) : 0;
704 
705     if (!b1 || !b2) {
706         return false;
707     }
708 
709     if (b1->root() != b2->root()) {
710         return true;
711     }
712 
713     if (nextRenderedEditable(node()) == pos.node() &&
714         thisRenderedOffset == (long)node()->caretMaxRenderedOffset() && posRenderedOffset == 0) {
715         return false;
716     }
717 
718     if (previousRenderedEditable(node()) == pos.node() &&
719         thisRenderedOffset == 0 && posRenderedOffset == (long)pos.node()->caretMaxRenderedOffset()) {
720         return false;
721     }
722 
723     return true;*/
724 }
725 
isFirstRenderedPositionOnLine() const726 bool Position::isFirstRenderedPositionOnLine() const
727 {
728     // return RenderPosition::fromDOMPosition(*this).isFirst*/
729     // qCDebug(KHTML_LOG) << *this;
730     if (isEmpty()) {
731         return false;
732     }
733 
734     RenderObject *renderer = node()->renderer();
735     if (!renderer) {
736         return false;
737     }
738     // qCDebug(KHTML_LOG) << "Renderer" << renderer << renderer->renderName();
739 
740     if (renderer->style()->visibility() != khtml::VISIBLE) {
741         return false;
742     }
743 
744     Position pos(node(), offset());
745     PositionIterator it(pos);
746     while (!it.atStart()) {
747         it.previous();
748         // qCDebug(KHTML_LOG) << "To previous" << it.current();
749         if (it.current().inRenderedContent()) {
750             return !rendersOnSameLine(it.current());
751         }
752         // return renderersOnDifferentLine(renderer, offset(), it.current().node()->renderer(), it.current().offset());
753     }
754 
755     return true;
756 }
757 
isLastRenderedPositionOnLine() const758 bool Position::isLastRenderedPositionOnLine() const
759 {
760     if (isEmpty()) {
761         return false;
762     }
763 
764     RenderObject *renderer = node()->renderer();
765     if (!renderer) {
766         return false;
767     }
768 
769     if (renderer->style()->visibility() != khtml::VISIBLE) {
770         return false;
771     }
772 
773     if (node()->id() == ID_BR) {
774         return true;
775     }
776 
777     Position pos(node(), offset());
778     PositionIterator it(pos);
779     while (!it.atEnd()) {
780         it.next();
781         if (it.current().inRenderedContent()) {
782             return !rendersOnSameLine(it.current());
783         }
784         // return renderersOnDifferentLine(renderer, offset(), it.current().node()->renderer(), it.current().offset());
785     }
786 
787     return true;
788 }
789 
isLastRenderedPositionInEditableBlock() const790 bool Position::isLastRenderedPositionInEditableBlock() const
791 {
792     if (isEmpty()) {
793         return false;
794     }
795 
796     RenderObject *renderer = node()->renderer();
797     if (!renderer) {
798         return false;
799     }
800 
801     if (renderer->style()->visibility() != khtml::VISIBLE) {
802         return false;
803     }
804 
805     if (renderedOffset() != (long)node()->caretMaxRenderedOffset()) {
806         return false;
807     }
808 
809     Position pos(node(), offset());
810     PositionIterator it(pos);
811     while (!it.atEnd()) {
812         it.next();
813         if (!it.current().node()->inSameContainingBlockFlowElement(node())) {
814             return true;
815         }
816         if (it.current().inRenderedContent()) {
817             return false;
818         }
819     }
820     return true;
821 }
822 
inFirstEditableInRootEditableElement() const823 bool Position::inFirstEditableInRootEditableElement() const
824 {
825     if (isEmpty() || !inRenderedContent()) {
826         return false;
827     }
828 
829     PositionIterator it(*this);
830     while (!it.atStart()) {
831         if (it.previous().inRenderedContent()) {
832             return false;
833         }
834     }
835 
836     return true;
837 }
838 
inLastEditableInRootEditableElement() const839 bool Position::inLastEditableInRootEditableElement() const
840 {
841     if (isEmpty() || !inRenderedContent()) {
842         return false;
843     }
844 
845     PositionIterator it(*this);
846     while (!it.atEnd()) {
847         if (it.next().inRenderedContent()) {
848             return false;
849         }
850     }
851 
852     return true;
853 }
854 
inFirstEditableInContainingEditableBlock() const855 bool Position::inFirstEditableInContainingEditableBlock() const
856 {
857     if (isEmpty() || !RenderPosition::inRenderedContent(*this)) {
858         return false;
859     }
860 
861     NodeImpl *block = node()->enclosingBlockFlowElement();
862 
863     PositionIterator it(*this);
864     while (!it.atStart()) {
865         it.previous();
866         if (!RenderPosition::inRenderedContent(it.current())) {
867             continue;
868         }
869         return block != it.current().node()->enclosingBlockFlowElement();
870     }
871 
872     return true;
873 }
874 
inLastEditableInContainingEditableBlock() const875 bool Position::inLastEditableInContainingEditableBlock() const
876 {
877     if (isEmpty() || !RenderPosition::inRenderedContent(*this)) {
878         return false;
879     }
880 
881     NodeImpl *block = node()->enclosingBlockFlowElement();
882 
883     PositionIterator it(*this);
884     while (!it.atEnd()) {
885         it.next();
886         if (!RenderPosition::inRenderedContent(it.current())) {
887             continue;
888         }
889         return block != it.current().node()->enclosingBlockFlowElement();
890     }
891 
892     return true;
893 }
894 
operator <<(QDebug stream,const Position & position)895 QDebug operator<<(QDebug stream, const Position &position)
896 {
897     const NodeImpl *node = position.node();
898     stream << "Position(" << node << (node ? node->nodeName() : QString()) << ":" << position.offset() << ")";
899     return stream;
900 }
901 
902 } // namespace DOM
903