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