• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2004, 2005, 2006, 2009 Apple 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 "config.h"
27 #include "Position.h"
28 
29 #include "CSSComputedStyleDeclaration.h"
30 #include "CString.h"
31 #include "CharacterNames.h"
32 #include "Logging.h"
33 #include "PositionIterator.h"
34 #include "RenderBlock.h"
35 #include "Text.h"
36 #include "TextIterator.h"
37 #include "VisiblePosition.h"
38 #include "htmlediting.h"
39 #include "visible_units.h"
40 #include <stdio.h>
41 
42 namespace WebCore {
43 
44 using namespace HTMLNames;
45 
nextRenderedEditable(Node * node)46 static Node* nextRenderedEditable(Node* node)
47 {
48     while (1) {
49         node = node->nextEditable();
50         if (!node)
51             return 0;
52         RenderObject* renderer = node->renderer();
53         if (!renderer)
54             continue;
55         if ((renderer->isBox() && toRenderBox(renderer)->inlineBoxWrapper()) || (renderer->isText() && toRenderText(renderer)->firstTextBox()))
56             return node;
57     }
58     return 0;
59 }
60 
previousRenderedEditable(Node * node)61 static Node* previousRenderedEditable(Node* node)
62 {
63     while (1) {
64         node = node->previousEditable();
65         if (!node)
66             return 0;
67         RenderObject* renderer = node->renderer();
68         if (!renderer)
69             continue;
70         if ((renderer->isBox() && toRenderBox(renderer)->inlineBoxWrapper()) || (renderer->isText() && toRenderText(renderer)->firstTextBox()))
71             return node;
72     }
73     return 0;
74 }
75 
Position(PassRefPtr<Node> anchorNode,int offset)76 Position::Position(PassRefPtr<Node> anchorNode, int offset)
77     : m_anchorNode(anchorNode)
78     , m_offset(offset)
79     , m_anchorType(anchorTypeForLegacyEditingPosition(m_anchorNode.get(), m_offset))
80     , m_isLegacyEditingPosition(true)
81 {
82 }
83 
Position(PassRefPtr<Node> anchorNode,AnchorType anchorType)84 Position::Position(PassRefPtr<Node> anchorNode, AnchorType anchorType)
85     : m_anchorNode(anchorNode)
86     , m_offset(0)
87     , m_anchorType(anchorType)
88     , m_isLegacyEditingPosition(false)
89 {
90     ASSERT(anchorType != PositionIsOffsetInAnchor);
91 }
92 
Position(PassRefPtr<Node> anchorNode,int offset,AnchorType anchorType)93 Position::Position(PassRefPtr<Node> anchorNode, int offset, AnchorType anchorType)
94     : m_anchorNode(anchorNode)
95     , m_offset(offset)
96     , m_anchorType(anchorType)
97     , m_isLegacyEditingPosition(false)
98 {
99     ASSERT(anchorType == PositionIsOffsetInAnchor);
100 }
101 
moveToPosition(PassRefPtr<Node> node,int offset)102 void Position::moveToPosition(PassRefPtr<Node> node, int offset)
103 {
104     ASSERT(anchorType() == PositionIsOffsetInAnchor || m_isLegacyEditingPosition);
105     m_anchorNode = node;
106     m_offset = offset;
107     if (m_isLegacyEditingPosition)
108         m_anchorType = anchorTypeForLegacyEditingPosition(m_anchorNode.get(), m_offset);
109 }
moveToOffset(int offset)110 void Position::moveToOffset(int offset)
111 {
112     ASSERT(anchorType() == PositionIsOffsetInAnchor || m_isLegacyEditingPosition);
113     m_offset = offset;
114     if (m_isLegacyEditingPosition)
115         m_anchorType = anchorTypeForLegacyEditingPosition(m_anchorNode.get(), m_offset);
116 }
117 
containerNode() const118 Node* Position::containerNode() const
119 {
120     if (!m_anchorNode)
121         return 0;
122 
123     switch (anchorType()) {
124     case PositionIsOffsetInAnchor:
125         return m_anchorNode.get();
126     case PositionIsBeforeAnchor:
127     case PositionIsAfterAnchor:
128         return m_anchorNode->parentNode();
129     }
130     ASSERT_NOT_REACHED();
131     return 0;
132 }
133 
computeOffsetInContainerNode() const134 int Position::computeOffsetInContainerNode() const
135 {
136     if (!m_anchorNode)
137         return 0;
138 
139     switch (anchorType()) {
140     case PositionIsOffsetInAnchor:
141     {
142         int maximumValidOffset = m_anchorNode->offsetInCharacters() ? m_anchorNode->maxCharacterOffset() : m_anchorNode->childNodeCount();
143         return std::min(maximumValidOffset, m_offset);
144     }
145     case PositionIsBeforeAnchor:
146         return m_anchorNode->nodeIndex();
147     case PositionIsAfterAnchor:
148         return m_anchorNode->nodeIndex() + 1;
149     }
150     ASSERT_NOT_REACHED();
151     return 0;
152 }
153 
computeNodeBeforePosition() const154 Node* Position::computeNodeBeforePosition() const
155 {
156     if (!m_anchorNode)
157         return 0;
158 
159     switch (anchorType()) {
160     case PositionIsOffsetInAnchor:
161         return m_anchorNode->childNode(m_offset - 1); // -1 converts to childNode((unsigned)-1) and returns null.
162     case PositionIsBeforeAnchor:
163         return m_anchorNode->previousSibling();
164     case PositionIsAfterAnchor:
165         return m_anchorNode.get();
166     }
167     ASSERT_NOT_REACHED();
168     return 0;
169 }
170 
computeNodeAfterPosition() const171 Node* Position::computeNodeAfterPosition() const
172 {
173     if (!m_anchorNode)
174         return 0;
175 
176     switch (anchorType()) {
177     case PositionIsOffsetInAnchor:
178         return m_anchorNode->childNode(m_offset);
179     case PositionIsBeforeAnchor:
180         return m_anchorNode.get();
181     case PositionIsAfterAnchor:
182         return m_anchorNode->nextSibling();
183     }
184     ASSERT_NOT_REACHED();
185     return 0;
186 }
187 
anchorTypeForLegacyEditingPosition(Node * anchorNode,int offset)188 Position::AnchorType Position::anchorTypeForLegacyEditingPosition(Node* anchorNode, int offset)
189 {
190     if (anchorNode && editingIgnoresContent(anchorNode)) {
191         if (offset == 0)
192             return Position::PositionIsBeforeAnchor;
193         return Position::PositionIsAfterAnchor;
194     }
195     return Position::PositionIsOffsetInAnchor;
196 }
197 
198 // FIXME: This method is confusing (does it return anchorNode() or containerNode()?) and should be renamed or removed
element() const199 Element* Position::element() const
200 {
201     Node* n = anchorNode();
202     while (n && !n->isElementNode())
203         n = n->parentNode();
204     return static_cast<Element*>(n);
205 }
206 
computedStyle() const207 PassRefPtr<CSSComputedStyleDeclaration> Position::computedStyle() const
208 {
209     Element* elem = element();
210     if (!elem)
211         return 0;
212     return WebCore::computedStyle(elem);
213 }
214 
previous(PositionMoveType moveType) const215 Position Position::previous(PositionMoveType moveType) const
216 {
217     Node* n = node();
218     if (!n)
219         return *this;
220 
221     int o = m_offset;
222     // FIXME: Negative offsets shouldn't be allowed. We should catch this earlier.
223     ASSERT(o >= 0);
224 
225     if (o > 0) {
226         Node* child = n->childNode(o - 1);
227         if (child)
228             return lastDeepEditingPositionForNode(child);
229 
230         // There are two reasons child might be 0:
231         //   1) The node is node like a text node that is not an element, and therefore has no children.
232         //      Going backward one character at a time is correct.
233         //   2) The old offset was a bogus offset like (<br>, 1), and there is no child.
234         //      Going from 1 to 0 is correct.
235         switch (moveType) {
236         case CodePoint:
237             return Position(n, o - 1);
238         case Character:
239             return Position(n, uncheckedPreviousOffset(n, o));
240         case BackwardDeletion:
241             return Position(n, uncheckedPreviousOffsetForBackwardDeletion(n, o));
242         }
243     }
244 
245     Node* parent = n->parentNode();
246     if (!parent)
247         return *this;
248 
249     return Position(parent, n->nodeIndex());
250 }
251 
next(PositionMoveType moveType) const252 Position Position::next(PositionMoveType moveType) const
253 {
254     ASSERT(moveType != BackwardDeletion);
255 
256     Node* n = node();
257     if (!n)
258         return *this;
259 
260     int o = m_offset;
261     // FIXME: Negative offsets shouldn't be allowed. We should catch this earlier.
262     ASSERT(o >= 0);
263 
264     Node* child = n->childNode(o);
265     if (child || (!n->hasChildNodes() && o < lastOffsetForEditing(n))) {
266         if (child)
267             return firstDeepEditingPositionForNode(child);
268 
269         // There are two reasons child might be 0:
270         //   1) The node is node like a text node that is not an element, and therefore has no children.
271         //      Going forward one character at a time is correct.
272         //   2) The new offset is a bogus offset like (<br>, 1), and there is no child.
273         //      Going from 0 to 1 is correct.
274         return Position(n, (moveType == Character) ? uncheckedNextOffset(n, o) : o + 1);
275     }
276 
277     Node* parent = n->parentNode();
278     if (!parent)
279         return *this;
280 
281     return Position(parent, n->nodeIndex() + 1);
282 }
283 
uncheckedPreviousOffset(const Node * n,int current)284 int Position::uncheckedPreviousOffset(const Node* n, int current)
285 {
286     return n->renderer() ? n->renderer()->previousOffset(current) : current - 1;
287 }
288 
uncheckedPreviousOffsetForBackwardDeletion(const Node * n,int current)289 int Position::uncheckedPreviousOffsetForBackwardDeletion(const Node* n, int current)
290 {
291     return n->renderer() ? n->renderer()->previousOffsetForBackwardDeletion(current) : current - 1;
292 }
293 
uncheckedNextOffset(const Node * n,int current)294 int Position::uncheckedNextOffset(const Node* n, int current)
295 {
296     return n->renderer() ? n->renderer()->nextOffset(current) : current + 1;
297 }
298 
atFirstEditingPositionForNode() const299 bool Position::atFirstEditingPositionForNode() const
300 {
301     if (isNull())
302         return true;
303     return m_offset <= 0;
304 }
305 
atLastEditingPositionForNode() const306 bool Position::atLastEditingPositionForNode() const
307 {
308     if (isNull())
309         return true;
310     return m_offset >= lastOffsetForEditing(node());
311 }
312 
atStartOfTree() const313 bool Position::atStartOfTree() const
314 {
315     if (isNull())
316         return true;
317     return !node()->parentNode() && m_offset <= 0;
318 }
319 
atEndOfTree() const320 bool Position::atEndOfTree() const
321 {
322     if (isNull())
323         return true;
324     return !node()->parentNode() && m_offset >= lastOffsetForEditing(node());
325 }
326 
renderedOffset() const327 int Position::renderedOffset() const
328 {
329     if (!node()->isTextNode())
330         return m_offset;
331 
332     if (!node()->renderer())
333         return m_offset;
334 
335     int result = 0;
336     RenderText *textRenderer = toRenderText(node()->renderer());
337     for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
338         int start = box->start();
339         int end = box->start() + box->len();
340         if (m_offset < start)
341             return result;
342         if (m_offset <= end) {
343             result += m_offset - start;
344             return result;
345         }
346         result += box->len();
347     }
348     return result;
349 }
350 
351 // return first preceding DOM position rendered at a different location, or "this"
previousCharacterPosition(EAffinity affinity) const352 Position Position::previousCharacterPosition(EAffinity affinity) const
353 {
354     if (isNull())
355         return Position();
356 
357     Node *fromRootEditableElement = node()->rootEditableElement();
358 
359     bool atStartOfLine = isStartOfLine(VisiblePosition(*this, affinity));
360     bool rendered = isCandidate();
361 
362     Position currentPos = *this;
363     while (!currentPos.atStartOfTree()) {
364         currentPos = currentPos.previous();
365 
366         if (currentPos.node()->rootEditableElement() != fromRootEditableElement)
367             return *this;
368 
369         if (atStartOfLine || !rendered) {
370             if (currentPos.isCandidate())
371                 return currentPos;
372         } else if (rendersInDifferentPosition(currentPos))
373             return currentPos;
374     }
375 
376     return *this;
377 }
378 
379 // return first following position rendered at a different location, or "this"
nextCharacterPosition(EAffinity affinity) const380 Position Position::nextCharacterPosition(EAffinity affinity) const
381 {
382     if (isNull())
383         return Position();
384 
385     Node *fromRootEditableElement = node()->rootEditableElement();
386 
387     bool atEndOfLine = isEndOfLine(VisiblePosition(*this, affinity));
388     bool rendered = isCandidate();
389 
390     Position currentPos = *this;
391     while (!currentPos.atEndOfTree()) {
392         currentPos = currentPos.next();
393 
394         if (currentPos.node()->rootEditableElement() != fromRootEditableElement)
395             return *this;
396 
397         if (atEndOfLine || !rendered) {
398             if (currentPos.isCandidate())
399                 return currentPos;
400         } else if (rendersInDifferentPosition(currentPos))
401             return currentPos;
402     }
403 
404     return *this;
405 }
406 
407 // Whether or not [node, 0] and [node, lastOffsetForEditing(node)] are their own VisiblePositions.
408 // If true, adjacent candidates are visually distinct.
409 // FIXME: Disregard nodes with renderers that have no height, as we do in isCandidate.
410 // FIXME: Share code with isCandidate, if possible.
endsOfNodeAreVisuallyDistinctPositions(Node * node)411 static bool endsOfNodeAreVisuallyDistinctPositions(Node* node)
412 {
413     if (!node || !node->renderer())
414         return false;
415 
416     if (!node->renderer()->isInline())
417         return true;
418 
419     // Don't include inline tables.
420     if (node->hasTagName(tableTag))
421         return false;
422 
423     // There is a VisiblePosition inside an empty inline-block container.
424     return node->renderer()->isReplaced() && canHaveChildrenForEditing(node) && toRenderBox(node->renderer())->height() != 0 && !node->firstChild();
425 }
426 
enclosingVisualBoundary(Node * node)427 static Node* enclosingVisualBoundary(Node* node)
428 {
429     while (node && !endsOfNodeAreVisuallyDistinctPositions(node))
430         node = node->parentNode();
431 
432     return node;
433 }
434 
435 // upstream() and downstream() want to return positions that are either in a
436 // text node or at just before a non-text node.  This method checks for that.
isStreamer(const PositionIterator & pos)437 static bool isStreamer(const PositionIterator& pos)
438 {
439     if (!pos.node())
440         return true;
441 
442     if (isAtomicNode(pos.node()))
443         return true;
444 
445     return pos.atStartOfNode();
446 }
447 
448 // This function and downstream() are used for moving back and forth between visually equivalent candidates.
449 // For example, for the text node "foo     bar" where whitespace is collapsible, there are two candidates
450 // that map to the VisiblePosition between 'b' and the space.  This function will return the left candidate
451 // and downstream() will return the right one.
452 // Also, upstream() will return [boundary, 0] for any of the positions from [boundary, 0] to the first candidate
453 // in boundary, where endsOfNodeAreVisuallyDistinctPositions(boundary) is true.
upstream() const454 Position Position::upstream() const
455 {
456     Node* startNode = node();
457     if (!startNode)
458         return Position();
459 
460     // iterate backward from there, looking for a qualified position
461     Node* boundary = enclosingVisualBoundary(startNode);
462     PositionIterator lastVisible = *this;
463     PositionIterator currentPos = lastVisible;
464     bool startEditable = startNode->isContentEditable();
465     Node* lastNode = startNode;
466     for (; !currentPos.atStart(); currentPos.decrement()) {
467         Node* currentNode = currentPos.node();
468 
469         // Don't check for an editability change if we haven't moved to a different node,
470         // to avoid the expense of computing isContentEditable().
471         if (currentNode != lastNode) {
472             // Don't change editability.
473             bool currentEditable = currentNode->isContentEditable();
474             if (startEditable != currentEditable)
475                 break;
476             lastNode = currentNode;
477         }
478 
479         // If we've moved to a position that is visually disinct, return the last saved position. There
480         // is code below that terminates early if we're *about* to move to a visually distinct position.
481         if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentNode != boundary)
482             return lastVisible;
483 
484         // skip position in unrendered or invisible node
485         RenderObject* renderer = currentNode->renderer();
486         if (!renderer || renderer->style()->visibility() != VISIBLE)
487             continue;
488 
489         // track last visible streamer position
490         if (isStreamer(currentPos))
491             lastVisible = currentPos;
492 
493         // Don't move past a position that is visually distinct.  We could rely on code above to terminate and
494         // return lastVisible on the next iteration, but we terminate early to avoid doing a nodeIndex() call.
495         if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentPos.atStartOfNode())
496             return lastVisible;
497 
498         // Return position after tables and nodes which have content that can be ignored.
499         if (editingIgnoresContent(currentNode) || isTableElement(currentNode)) {
500             if (currentPos.atEndOfNode())
501                 return lastDeepEditingPositionForNode(currentNode);
502             continue;
503         }
504 
505         // return current position if it is in rendered text
506         if (renderer->isText() && toRenderText(renderer)->firstTextBox()) {
507             if (currentNode != startNode) {
508                 // This assertion fires in layout tests in the case-transform.html test because
509                 // of a mix-up between offsets in the text in the DOM tree with text in the
510                 // render tree which can have a different length due to case transformation.
511                 // Until we resolve that, disable this so we can run the layout tests!
512                 //ASSERT(currentOffset >= renderer->caretMaxOffset());
513                 return Position(currentNode, renderer->caretMaxOffset());
514             }
515 
516             unsigned textOffset = currentPos.offsetInLeafNode();
517             RenderText* textRenderer = toRenderText(renderer);
518             InlineTextBox* lastTextBox = textRenderer->lastTextBox();
519             for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
520                 if (textOffset <= box->start() + box->len()) {
521                     if (textOffset > box->start())
522                         return currentPos;
523                     continue;
524                 }
525 
526                 if (box == lastTextBox || textOffset != box->start() + box->len() + 1)
527                     continue;
528 
529                 // The text continues on the next line only if the last text box is not on this line and
530                 // none of the boxes on this line have a larger start offset.
531 
532                 bool continuesOnNextLine = true;
533                 InlineBox* otherBox = box;
534                 while (continuesOnNextLine) {
535                     otherBox = otherBox->nextLeafChild();
536                     if (!otherBox)
537                         break;
538                     if (otherBox == lastTextBox || (otherBox->renderer() == textRenderer && static_cast<InlineTextBox*>(otherBox)->start() > textOffset))
539                         continuesOnNextLine = false;
540                 }
541 
542                 otherBox = box;
543                 while (continuesOnNextLine) {
544                     otherBox = otherBox->prevLeafChild();
545                     if (!otherBox)
546                         break;
547                     if (otherBox == lastTextBox || (otherBox->renderer() == textRenderer && static_cast<InlineTextBox*>(otherBox)->start() > textOffset))
548                         continuesOnNextLine = false;
549                 }
550 
551                 if (continuesOnNextLine)
552                     return currentPos;
553             }
554         }
555     }
556 
557     return lastVisible;
558 }
559 
560 // This function and upstream() are used for moving back and forth between visually equivalent candidates.
561 // For example, for the text node "foo     bar" where whitespace is collapsible, there are two candidates
562 // that map to the VisiblePosition between 'b' and the space.  This function will return the right candidate
563 // and upstream() will return the left one.
564 // Also, downstream() will return the last position in the last atomic node in boundary for all of the positions
565 // in boundary after the last candidate, where endsOfNodeAreVisuallyDistinctPositions(boundary).
downstream() const566 Position Position::downstream() const
567 {
568     Node* startNode = node();
569     if (!startNode)
570         return Position();
571 
572     // iterate forward from there, looking for a qualified position
573     Node* boundary = enclosingVisualBoundary(startNode);
574     PositionIterator lastVisible = *this;
575     PositionIterator currentPos = lastVisible;
576     bool startEditable = startNode->isContentEditable();
577     Node* lastNode = startNode;
578     for (; !currentPos.atEnd(); currentPos.increment()) {
579         Node* currentNode = currentPos.node();
580 
581         // Don't check for an editability change if we haven't moved to a different node,
582         // to avoid the expense of computing isContentEditable().
583         if (currentNode != lastNode) {
584             // Don't change editability.
585             bool currentEditable = currentNode->isContentEditable();
586             if (startEditable != currentEditable)
587                 break;
588             lastNode = currentNode;
589         }
590 
591         // stop before going above the body, up into the head
592         // return the last visible streamer position
593         if (currentNode->hasTagName(bodyTag) && currentPos.atEndOfNode())
594             break;
595 
596         // Do not move to a visually distinct position.
597         if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentNode != boundary)
598             return lastVisible;
599         // Do not move past a visually disinct position.
600         // Note: The first position after the last in a node whose ends are visually distinct
601         // positions will be [boundary->parentNode(), originalBlock->nodeIndex() + 1].
602         if (boundary && boundary->parentNode() == currentNode)
603             return lastVisible;
604 
605         // skip position in unrendered or invisible node
606         RenderObject* renderer = currentNode->renderer();
607         if (!renderer || renderer->style()->visibility() != VISIBLE)
608             continue;
609 
610         // track last visible streamer position
611         if (isStreamer(currentPos))
612             lastVisible = currentPos;
613 
614         // Return position before tables and nodes which have content that can be ignored.
615         if (editingIgnoresContent(currentNode) || isTableElement(currentNode)) {
616             if (currentPos.offsetInLeafNode() <= renderer->caretMinOffset())
617                 return Position(currentNode, renderer->caretMinOffset());
618             continue;
619         }
620 
621         // return current position if it is in rendered text
622         if (renderer->isText() && toRenderText(renderer)->firstTextBox()) {
623             if (currentNode != startNode) {
624                 ASSERT(currentPos.atStartOfNode());
625                 return Position(currentNode, renderer->caretMinOffset());
626             }
627 
628             unsigned textOffset = currentPos.offsetInLeafNode();
629             RenderText* textRenderer = toRenderText(renderer);
630             InlineTextBox* lastTextBox = textRenderer->lastTextBox();
631             for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
632                 if (textOffset <= box->end()) {
633                     if (textOffset >= box->start())
634                         return currentPos;
635                     continue;
636                 }
637 
638                 if (box == lastTextBox || textOffset != box->start() + box->len())
639                     continue;
640 
641                 // The text continues on the next line only if the last text box is not on this line and
642                 // none of the boxes on this line have a larger start offset.
643 
644                 bool continuesOnNextLine = true;
645                 InlineBox* otherBox = box;
646                 while (continuesOnNextLine) {
647                     otherBox = otherBox->nextLeafChild();
648                     if (!otherBox)
649                         break;
650                     if (otherBox == lastTextBox || (otherBox->renderer() == textRenderer && static_cast<InlineTextBox*>(otherBox)->start() >= textOffset))
651                         continuesOnNextLine = false;
652                 }
653 
654                 otherBox = box;
655                 while (continuesOnNextLine) {
656                     otherBox = otherBox->prevLeafChild();
657                     if (!otherBox)
658                         break;
659                     if (otherBox == lastTextBox || (otherBox->renderer() == textRenderer && static_cast<InlineTextBox*>(otherBox)->start() >= textOffset))
660                         continuesOnNextLine = false;
661                 }
662 
663                 if (continuesOnNextLine)
664                     return currentPos;
665             }
666         }
667     }
668 
669     return lastVisible;
670 }
671 
hasRenderedNonAnonymousDescendantsWithHeight(RenderObject * renderer)672 bool Position::hasRenderedNonAnonymousDescendantsWithHeight(RenderObject* renderer)
673 {
674     RenderObject* stop = renderer->nextInPreOrderAfterChildren();
675     for (RenderObject *o = renderer->firstChild(); o && o != stop; o = o->nextInPreOrder())
676         if (o->node()) {
677             if ((o->isText() && toRenderText(o)->linesBoundingBox().height()) ||
678                 (o->isBox() && toRenderBox(o)->borderBoundingBox().height()))
679                 return true;
680         }
681     return false;
682 }
683 
nodeIsUserSelectNone(Node * node)684 bool Position::nodeIsUserSelectNone(Node* node)
685 {
686     return node && node->renderer() && node->renderer()->style()->userSelect() == SELECT_NONE;
687 }
688 
isCandidate() const689 bool Position::isCandidate() const
690 {
691     if (isNull())
692         return false;
693 
694     RenderObject *renderer = node()->renderer();
695     if (!renderer)
696         return false;
697 
698     if (renderer->style()->visibility() != VISIBLE)
699         return false;
700 
701     if (renderer->isBR())
702         return m_offset == 0 && !nodeIsUserSelectNone(node()->parent());
703 
704     if (renderer->isText())
705         return inRenderedText() && !nodeIsUserSelectNone(node());
706 
707     if (isTableElement(node()) || editingIgnoresContent(node()))
708         return (atFirstEditingPositionForNode() || atLastEditingPositionForNode()) && !nodeIsUserSelectNone(node()->parent());
709 
710     if (!node()->hasTagName(htmlTag) && renderer->isBlockFlow() && !hasRenderedNonAnonymousDescendantsWithHeight(renderer) &&
711        (toRenderBox(renderer)->height() || node()->hasTagName(bodyTag)))
712         return atFirstEditingPositionForNode() && !nodeIsUserSelectNone(node());
713 
714     return false;
715 }
716 
inRenderedText() const717 bool Position::inRenderedText() const
718 {
719     if (isNull() || !node()->isTextNode())
720         return false;
721 
722     RenderObject *renderer = node()->renderer();
723     if (!renderer)
724         return false;
725 
726     RenderText *textRenderer = toRenderText(renderer);
727     for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
728         if (m_offset < static_cast<int>(box->start()) && !textRenderer->containsReversedText()) {
729             // The offset we're looking for is before this node
730             // this means the offset must be in content that is
731             // not rendered. Return false.
732             return false;
733         }
734         if (box->containsCaretOffset(m_offset))
735             // Return false for offsets inside composed characters.
736             return m_offset == 0 || m_offset == textRenderer->nextOffset(textRenderer->previousOffset(m_offset));
737     }
738 
739     return false;
740 }
741 
caretMaxRenderedOffset(const Node * n)742 static unsigned caretMaxRenderedOffset(const Node* n)
743 {
744     RenderObject* r = n->renderer();
745     if (r)
746         return r->caretMaxRenderedOffset();
747 
748     if (n->isCharacterDataNode())
749         return static_cast<const CharacterData*>(n)->length();
750     return 1;
751 }
752 
isRenderedCharacter() const753 bool Position::isRenderedCharacter() const
754 {
755     if (isNull() || !node()->isTextNode())
756         return false;
757 
758     RenderObject* renderer = node()->renderer();
759     if (!renderer)
760         return false;
761 
762     RenderText* textRenderer = toRenderText(renderer);
763     for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
764         if (m_offset < static_cast<int>(box->start()) && !textRenderer->containsReversedText()) {
765             // The offset we're looking for is before this node
766             // this means the offset must be in content that is
767             // not rendered. Return false.
768             return false;
769         }
770         if (m_offset >= static_cast<int>(box->start()) && m_offset < static_cast<int>(box->start() + box->len()))
771             return true;
772     }
773 
774     return false;
775 }
776 
rendersInDifferentPosition(const Position & pos) const777 bool Position::rendersInDifferentPosition(const Position &pos) const
778 {
779     if (isNull() || pos.isNull())
780         return false;
781 
782     RenderObject *renderer = node()->renderer();
783     if (!renderer)
784         return false;
785 
786     RenderObject *posRenderer = pos.node()->renderer();
787     if (!posRenderer)
788         return false;
789 
790     if (renderer->style()->visibility() != VISIBLE ||
791         posRenderer->style()->visibility() != VISIBLE)
792         return false;
793 
794     if (node() == pos.node()) {
795         if (node()->hasTagName(brTag))
796             return false;
797 
798         if (m_offset == pos.deprecatedEditingOffset())
799             return false;
800 
801         if (!node()->isTextNode() && !pos.node()->isTextNode()) {
802             if (m_offset != pos.deprecatedEditingOffset())
803                 return true;
804         }
805     }
806 
807     if (node()->hasTagName(brTag) && pos.isCandidate())
808         return true;
809 
810     if (pos.node()->hasTagName(brTag) && isCandidate())
811         return true;
812 
813     if (node()->enclosingBlockFlowElement() != pos.node()->enclosingBlockFlowElement())
814         return true;
815 
816     if (node()->isTextNode() && !inRenderedText())
817         return false;
818 
819     if (pos.node()->isTextNode() && !pos.inRenderedText())
820         return false;
821 
822     int thisRenderedOffset = renderedOffset();
823     int posRenderedOffset = pos.renderedOffset();
824 
825     if (renderer == posRenderer && thisRenderedOffset == posRenderedOffset)
826         return false;
827 
828     int ignoredCaretOffset;
829     InlineBox* b1;
830     getInlineBoxAndOffset(DOWNSTREAM, b1, ignoredCaretOffset);
831     InlineBox* b2;
832     pos.getInlineBoxAndOffset(DOWNSTREAM, b2, ignoredCaretOffset);
833 
834     LOG(Editing, "renderer:               %p [%p]\n", renderer, b1);
835     LOG(Editing, "thisRenderedOffset:         %d\n", thisRenderedOffset);
836     LOG(Editing, "posRenderer:            %p [%p]\n", posRenderer, b2);
837     LOG(Editing, "posRenderedOffset:      %d\n", posRenderedOffset);
838     LOG(Editing, "node min/max:           %d:%d\n", caretMinOffset(node()), caretMaxRenderedOffset(node()));
839     LOG(Editing, "pos node min/max:       %d:%d\n", caretMinOffset(pos.node()), caretMaxRenderedOffset(pos.node()));
840     LOG(Editing, "----------------------------------------------------------------------\n");
841 
842     if (!b1 || !b2) {
843         return false;
844     }
845 
846     if (b1->root() != b2->root()) {
847         return true;
848     }
849 
850     if (nextRenderedEditable(node()) == pos.node() &&
851         thisRenderedOffset == (int)caretMaxRenderedOffset(node()) && posRenderedOffset == 0) {
852         return false;
853     }
854 
855     if (previousRenderedEditable(node()) == pos.node() &&
856         thisRenderedOffset == 0 && posRenderedOffset == (int)caretMaxRenderedOffset(pos.node())) {
857         return false;
858     }
859 
860     return true;
861 }
862 
863 // This assumes that it starts in editable content.
leadingWhitespacePosition(EAffinity affinity,bool considerNonCollapsibleWhitespace) const864 Position Position::leadingWhitespacePosition(EAffinity affinity, bool considerNonCollapsibleWhitespace) const
865 {
866     ASSERT(isEditablePosition(*this));
867     if (isNull())
868         return Position();
869 
870     if (upstream().node()->hasTagName(brTag))
871         return Position();
872 
873     Position prev = previousCharacterPosition(affinity);
874     if (prev != *this && prev.node()->inSameContainingBlockFlowElement(node()) && prev.node()->isTextNode()) {
875         String string = static_cast<Text *>(prev.node())->data();
876         UChar c = string[prev.deprecatedEditingOffset()];
877         if (considerNonCollapsibleWhitespace ? (isSpaceOrNewline(c) || c == noBreakSpace) : isCollapsibleWhitespace(c))
878             if (isEditablePosition(prev))
879                 return prev;
880     }
881 
882     return Position();
883 }
884 
885 // This assumes that it starts in editable content.
trailingWhitespacePosition(EAffinity,bool considerNonCollapsibleWhitespace) const886 Position Position::trailingWhitespacePosition(EAffinity, bool considerNonCollapsibleWhitespace) const
887 {
888     ASSERT(isEditablePosition(*this));
889     if (isNull())
890         return Position();
891 
892     VisiblePosition v(*this);
893     UChar c = v.characterAfter();
894     // The space must not be in another paragraph and it must be editable.
895     if (!isEndOfParagraph(v) && v.next(true).isNotNull())
896         if (considerNonCollapsibleWhitespace ? (isSpaceOrNewline(c) || c == noBreakSpace) : isCollapsibleWhitespace(c))
897             return *this;
898 
899     return Position();
900 }
901 
getInlineBoxAndOffset(EAffinity affinity,InlineBox * & inlineBox,int & caretOffset) const902 void Position::getInlineBoxAndOffset(EAffinity affinity, InlineBox*& inlineBox, int& caretOffset) const
903 {
904     TextDirection primaryDirection = LTR;
905     for (RenderObject* r = node()->renderer(); r; r = r->parent()) {
906         if (r->isBlockFlow()) {
907             primaryDirection = r->style()->direction();
908             break;
909         }
910     }
911     getInlineBoxAndOffset(affinity, primaryDirection, inlineBox, caretOffset);
912 }
913 
isNonTextLeafChild(RenderObject * object)914 static bool isNonTextLeafChild(RenderObject* object)
915 {
916     if (object->firstChild())
917         return false;
918     if (object->isText())
919         return false;
920     return true;
921 }
922 
searchAheadForBetterMatch(RenderObject * renderer)923 static InlineTextBox* searchAheadForBetterMatch(RenderObject* renderer)
924 {
925     RenderBlock* container = renderer->containingBlock();
926     RenderObject* next = renderer;
927     while ((next = next->nextInPreOrder(container))) {
928         if (next->isRenderBlock())
929             return 0;
930         if (next->isBR())
931             return 0;
932         if (isNonTextLeafChild(next))
933             return 0;
934         if (next->isText()) {
935             InlineTextBox* match = 0;
936             int minOffset = INT_MAX;
937             for (InlineTextBox* box = toRenderText(next)->firstTextBox(); box; box = box->nextTextBox()) {
938                 int caretMinOffset = box->caretMinOffset();
939                 if (caretMinOffset < minOffset) {
940                     match = box;
941                     minOffset = caretMinOffset;
942                 }
943             }
944             if (match)
945                 return match;
946         }
947     }
948     return 0;
949 }
950 
getInlineBoxAndOffset(EAffinity affinity,TextDirection primaryDirection,InlineBox * & inlineBox,int & caretOffset) const951 void Position::getInlineBoxAndOffset(EAffinity affinity, TextDirection primaryDirection, InlineBox*& inlineBox, int& caretOffset) const
952 {
953     caretOffset = m_offset;
954     RenderObject* renderer = node()->renderer();
955     if (!renderer->isText()) {
956         inlineBox = renderer->isBox() ? toRenderBox(renderer)->inlineBoxWrapper() : 0;
957         if (!inlineBox || (caretOffset > inlineBox->caretMinOffset() && caretOffset < inlineBox->caretMaxOffset()))
958             return;
959     } else {
960         RenderText* textRenderer = toRenderText(renderer);
961 
962         InlineTextBox* box;
963         InlineTextBox* candidate = 0;
964 
965         for (box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
966             int caretMinOffset = box->caretMinOffset();
967             int caretMaxOffset = box->caretMaxOffset();
968 
969             if (caretOffset < caretMinOffset || caretOffset > caretMaxOffset || (caretOffset == caretMaxOffset && box->isLineBreak()))
970                 continue;
971 
972             if (caretOffset > caretMinOffset && caretOffset < caretMaxOffset) {
973                 inlineBox = box;
974                 return;
975             }
976 
977             if ((caretOffset == caretMinOffset) ^ (affinity == UPSTREAM))
978                 break;
979 
980             candidate = box;
981         }
982         if (candidate && !box && affinity == DOWNSTREAM) {
983             box = searchAheadForBetterMatch(textRenderer);
984             if (box)
985                 caretOffset = box->caretMinOffset();
986         }
987         inlineBox = box ? box : candidate;
988     }
989 
990     if (!inlineBox)
991         return;
992 
993     unsigned char level = inlineBox->bidiLevel();
994 
995     if (inlineBox->direction() == primaryDirection) {
996         if (caretOffset == inlineBox->caretRightmostOffset()) {
997             InlineBox* nextBox = inlineBox->nextLeafChild();
998             if (!nextBox || nextBox->bidiLevel() >= level)
999                 return;
1000 
1001             level = nextBox->bidiLevel();
1002             InlineBox* prevBox = inlineBox;
1003             do {
1004                 prevBox = prevBox->prevLeafChild();
1005             } while (prevBox && prevBox->bidiLevel() > level);
1006 
1007             if (prevBox && prevBox->bidiLevel() == level)   // For example, abc FED 123 ^ CBA
1008                 return;
1009 
1010             // For example, abc 123 ^ CBA
1011             while (InlineBox* nextBox = inlineBox->nextLeafChild()) {
1012                 if (nextBox->bidiLevel() < level)
1013                     break;
1014                 inlineBox = nextBox;
1015             }
1016             caretOffset = inlineBox->caretRightmostOffset();
1017         } else {
1018             InlineBox* prevBox = inlineBox->prevLeafChild();
1019             if (!prevBox || prevBox->bidiLevel() >= level)
1020                 return;
1021 
1022             level = prevBox->bidiLevel();
1023             InlineBox* nextBox = inlineBox;
1024             do {
1025                 nextBox = nextBox->nextLeafChild();
1026             } while (nextBox && nextBox->bidiLevel() > level);
1027 
1028             if (nextBox && nextBox->bidiLevel() == level)
1029                 return;
1030 
1031             while (InlineBox* prevBox = inlineBox->prevLeafChild()) {
1032                 if (prevBox->bidiLevel() < level)
1033                     break;
1034                 inlineBox = prevBox;
1035             }
1036             caretOffset = inlineBox->caretLeftmostOffset();
1037         }
1038         return;
1039     }
1040 
1041     if (caretOffset == inlineBox->caretLeftmostOffset()) {
1042         InlineBox* prevBox = inlineBox->prevLeafChild();
1043         if (!prevBox || prevBox->bidiLevel() < level) {
1044             // Left edge of a secondary run. Set to the right edge of the entire run.
1045             while (InlineBox* nextBox = inlineBox->nextLeafChild()) {
1046                 if (nextBox->bidiLevel() < level)
1047                     break;
1048                 inlineBox = nextBox;
1049             }
1050             caretOffset = inlineBox->caretRightmostOffset();
1051         } else if (prevBox->bidiLevel() > level) {
1052             // Right edge of a "tertiary" run. Set to the left edge of that run.
1053             while (InlineBox* tertiaryBox = inlineBox->prevLeafChild()) {
1054                 if (tertiaryBox->bidiLevel() <= level)
1055                     break;
1056                 inlineBox = tertiaryBox;
1057             }
1058             caretOffset = inlineBox->caretLeftmostOffset();
1059         }
1060     } else {
1061         InlineBox* nextBox = inlineBox->nextLeafChild();
1062         if (!nextBox || nextBox->bidiLevel() < level) {
1063             // Right edge of a secondary run. Set to the left edge of the entire run.
1064             while (InlineBox* prevBox = inlineBox->prevLeafChild()) {
1065                 if (prevBox->bidiLevel() < level)
1066                     break;
1067                 inlineBox = prevBox;
1068             }
1069             caretOffset = inlineBox->caretLeftmostOffset();
1070         } else if (nextBox->bidiLevel() > level) {
1071             // Left edge of a "tertiary" run. Set to the right edge of that run.
1072             while (InlineBox* tertiaryBox = inlineBox->nextLeafChild()) {
1073                 if (tertiaryBox->bidiLevel() <= level)
1074                     break;
1075                 inlineBox = tertiaryBox;
1076             }
1077             caretOffset = inlineBox->caretRightmostOffset();
1078         }
1079     }
1080 }
1081 
debugPosition(const char * msg) const1082 void Position::debugPosition(const char* msg) const
1083 {
1084     if (isNull())
1085         fprintf(stderr, "Position [%s]: null\n", msg);
1086     else
1087         fprintf(stderr, "Position [%s]: %s [%p] at %d\n", msg, node()->nodeName().utf8().data(), node(), m_offset);
1088 }
1089 
1090 #ifndef NDEBUG
1091 
formatForDebugger(char * buffer,unsigned length) const1092 void Position::formatForDebugger(char* buffer, unsigned length) const
1093 {
1094     String result;
1095 
1096     if (isNull())
1097         result = "<null>";
1098     else {
1099         char s[1024];
1100         result += "offset ";
1101         result += String::number(m_offset);
1102         result += " of ";
1103         node()->formatForDebugger(s, sizeof(s));
1104         result += s;
1105     }
1106 
1107     strncpy(buffer, result.utf8().data(), length - 1);
1108 }
1109 
showTreeForThis() const1110 void Position::showTreeForThis() const
1111 {
1112     if (node())
1113         node()->showTreeForThis();
1114 }
1115 
1116 #endif
1117 
startPosition(const Range * r)1118 Position startPosition(const Range* r)
1119 {
1120     return r ? r->startPosition() : Position();
1121 }
1122 
endPosition(const Range * r)1123 Position endPosition(const Range* r)
1124 {
1125     return r ? r->endPosition() : Position();
1126 }
1127 
1128 // NOTE: first/lastDeepEditingPositionForNode can return "editing positions" (like [img, 0])
1129 // for elements which editing "ignores".  the rest of the editing code will treat [img, 0]
1130 // as "the last position before the img"
firstDeepEditingPositionForNode(Node * node)1131 Position firstDeepEditingPositionForNode(Node* node)
1132 {
1133     return Position(node, 0);
1134 }
1135 
lastDeepEditingPositionForNode(Node * node)1136 Position lastDeepEditingPositionForNode(Node* node)
1137 {
1138     return Position(node, lastOffsetForEditing(node));
1139 }
1140 
1141 } // namespace WebCore
1142 
1143 #ifndef NDEBUG
1144 
showTree(const WebCore::Position & pos)1145 void showTree(const WebCore::Position& pos)
1146 {
1147     pos.showTreeForThis();
1148 }
1149 
showTree(const WebCore::Position * pos)1150 void showTree(const WebCore::Position* pos)
1151 {
1152     if (pos)
1153         pos->showTreeForThis();
1154 }
1155 
1156 #endif
1157