dc82190c5be0ffa316e04b7ce722346f8a86f583
[WebKit-https.git] / Source / WebCore / dom / Position.cpp
1 /*
2  * Copyright (C) 2004, 2005, 2006, 2009, 2013 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 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 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 "HTMLNames.h"
31 #include "HTMLTableElement.h"
32 #include "InlineElementBox.h"
33 #include "InlineIterator.h"
34 #include "InlineTextBox.h"
35 #include "Logging.h"
36 #include "PositionIterator.h"
37 #include "RenderBlock.h"
38 #include "RenderInline.h"
39 #include "RenderIterator.h"
40 #include "RenderLineBreak.h"
41 #include "RenderText.h"
42 #include "RuntimeEnabledFeatures.h"
43 #include "Text.h"
44 #include "TextIterator.h"
45 #include "VisiblePosition.h"
46 #include "VisibleUnits.h"
47 #include "htmlediting.h"
48 #include <stdio.h>
49 #include <wtf/text/CString.h>
50 #include <wtf/unicode/CharacterNames.h>
51   
52 namespace WebCore {
53
54 using namespace HTMLNames;
55
56 static bool hasInlineBoxWrapper(RenderObject& renderer)
57 {
58     if (renderer.isBox() && toRenderBox(renderer).inlineBoxWrapper())
59         return true;
60     if (renderer.isText() && toRenderText(renderer).firstTextBox())
61         return true;
62     if (renderer.isLineBreak() && toRenderLineBreak(renderer).inlineBoxWrapper())
63         return true;
64     return false;
65 }
66
67 static Node* nextRenderedEditable(Node* node)
68 {
69     while ((node = nextLeafNode(node))) {
70         RenderObject* renderer = node->renderer();
71         if (!renderer || !node->hasEditableStyle())
72             continue;
73         if (hasInlineBoxWrapper(*renderer))
74             return node;
75     }
76     return 0;
77 }
78
79 static Node* previousRenderedEditable(Node* node)
80 {
81     while ((node = previousLeafNode(node))) {
82         RenderObject* renderer = node->renderer();
83         if (!renderer || !node->hasEditableStyle())
84             continue;
85         if (hasInlineBoxWrapper(*renderer))
86             return node;
87     }
88     return 0;
89 }
90
91 Position::Position(PassRefPtr<Node> anchorNode, LegacyEditingOffset offset)
92     : m_anchorNode(anchorNode)
93     , m_offset(offset.value())
94     , m_anchorType(anchorTypeForLegacyEditingPosition(m_anchorNode.get(), m_offset))
95     , m_isLegacyEditingPosition(true)
96 {
97     ASSERT(!m_anchorNode || !m_anchorNode->isShadowRoot() || m_anchorNode == containerNode());
98     ASSERT(!m_anchorNode || !m_anchorNode->isPseudoElement());
99 }
100
101 Position::Position(PassRefPtr<Node> anchorNode, AnchorType anchorType)
102     : m_anchorNode(anchorNode)
103     , m_offset(0)
104     , m_anchorType(anchorType)
105     , m_isLegacyEditingPosition(false)
106 {
107     ASSERT(!m_anchorNode || !m_anchorNode->isShadowRoot() || m_anchorNode == containerNode());
108     ASSERT(!m_anchorNode || !m_anchorNode->isPseudoElement());
109     ASSERT(anchorType != PositionIsOffsetInAnchor);
110     ASSERT(!((anchorType == PositionIsBeforeChildren || anchorType == PositionIsAfterChildren)
111         && (m_anchorNode->isTextNode() || editingIgnoresContent(m_anchorNode.get()))));
112 }
113
114 Position::Position(PassRefPtr<Node> anchorNode, int offset, AnchorType anchorType)
115     : m_anchorNode(anchorNode)
116     , m_offset(offset)
117     , m_anchorType(anchorType)
118     , m_isLegacyEditingPosition(false)
119 {
120     ASSERT(!m_anchorNode || !editingIgnoresContent(m_anchorNode.get()) || !m_anchorNode->isShadowRoot());
121     ASSERT(!m_anchorNode || !m_anchorNode->isPseudoElement());
122     ASSERT(anchorType == PositionIsOffsetInAnchor);
123 }
124
125 Position::Position(PassRefPtr<Text> textNode, unsigned offset)
126     : m_anchorNode(textNode)
127     , m_offset(static_cast<int>(offset))
128     , m_anchorType(PositionIsOffsetInAnchor)
129     , m_isLegacyEditingPosition(false)
130 {
131     ASSERT(m_anchorNode);
132 }
133
134 void Position::moveToPosition(PassRefPtr<Node> node, int offset)
135 {
136     ASSERT(!editingIgnoresContent(node.get()));
137     ASSERT(anchorType() == PositionIsOffsetInAnchor || m_isLegacyEditingPosition);
138     m_anchorNode = node;
139     m_offset = offset;
140     if (m_isLegacyEditingPosition)
141         m_anchorType = anchorTypeForLegacyEditingPosition(m_anchorNode.get(), m_offset);
142 }
143 void Position::moveToOffset(int offset)
144 {
145     ASSERT(anchorType() == PositionIsOffsetInAnchor || m_isLegacyEditingPosition);
146     m_offset = offset;
147     if (m_isLegacyEditingPosition)
148         m_anchorType = anchorTypeForLegacyEditingPosition(m_anchorNode.get(), m_offset);
149 }
150
151 Node* Position::containerNode() const
152 {
153     if (!m_anchorNode)
154         return nullptr;
155
156     switch (anchorType()) {
157     case PositionIsBeforeChildren:
158     case PositionIsAfterChildren:
159     case PositionIsOffsetInAnchor:
160         return m_anchorNode.get();
161     case PositionIsBeforeAnchor:
162     case PositionIsAfterAnchor:
163         return findParent(m_anchorNode.get());
164     }
165     ASSERT_NOT_REACHED();
166     return nullptr;
167 }
168
169 Text* Position::containerText() const
170 {
171     switch (anchorType()) {
172     case PositionIsOffsetInAnchor:
173         return m_anchorNode && is<Text>(*m_anchorNode) ? downcast<Text>(m_anchorNode.get()) : nullptr;
174     case PositionIsBeforeAnchor:
175     case PositionIsAfterAnchor:
176         return nullptr;
177     case PositionIsBeforeChildren:
178     case PositionIsAfterChildren:
179         ASSERT(!m_anchorNode || !is<Text>(*m_anchorNode));
180         return nullptr;
181     }
182     ASSERT_NOT_REACHED();
183     return nullptr;
184 }
185
186 int Position::computeOffsetInContainerNode() const
187 {
188     if (!m_anchorNode)
189         return 0;
190
191     switch (anchorType()) {
192     case PositionIsBeforeChildren:
193         return 0;
194     case PositionIsAfterChildren:
195         return lastOffsetInNode(m_anchorNode.get());
196     case PositionIsOffsetInAnchor:
197         return minOffsetForNode(m_anchorNode.get(), m_offset);
198     case PositionIsBeforeAnchor:
199         return m_anchorNode->computeNodeIndex();
200     case PositionIsAfterAnchor:
201         return m_anchorNode->computeNodeIndex() + 1;
202     }
203     ASSERT_NOT_REACHED();
204     return 0;
205 }
206
207 int Position::offsetForPositionAfterAnchor() const
208 {
209     ASSERT(m_anchorType == PositionIsAfterAnchor || m_anchorType == PositionIsAfterChildren);
210     ASSERT(!m_isLegacyEditingPosition);
211     return lastOffsetForEditing(m_anchorNode.get());
212 }
213
214 // Neighbor-anchored positions are invalid DOM positions, so they need to be
215 // fixed up before handing them off to the Range object.
216 Position Position::parentAnchoredEquivalent() const
217 {
218     if (!m_anchorNode)
219         return Position();
220     
221     // FIXME: This should only be necessary for legacy positions, but is also needed for positions before and after Tables
222     if (m_offset <= 0 && (m_anchorType != PositionIsAfterAnchor && m_anchorType != PositionIsAfterChildren)) {
223         if (findParent(m_anchorNode.get()) && (editingIgnoresContent(m_anchorNode.get()) || isRenderedTable(m_anchorNode.get())))
224             return positionInParentBeforeNode(m_anchorNode.get());
225         return Position(m_anchorNode.get(), 0, PositionIsOffsetInAnchor);
226     }
227
228     if (!m_anchorNode->offsetInCharacters()
229         && (m_anchorType == PositionIsAfterAnchor || m_anchorType == PositionIsAfterChildren || static_cast<unsigned>(m_offset) == m_anchorNode->countChildNodes())
230         && (editingIgnoresContent(m_anchorNode.get()) || isRenderedTable(m_anchorNode.get()))
231         && containerNode()) {
232         return positionInParentAfterNode(m_anchorNode.get());
233     }
234
235     return Position(containerNode(), computeOffsetInContainerNode(), PositionIsOffsetInAnchor);
236 }
237
238 Node* Position::computeNodeBeforePosition() const
239 {
240     if (!m_anchorNode)
241         return 0;
242
243     switch (anchorType()) {
244     case PositionIsBeforeChildren:
245         return 0;
246     case PositionIsAfterChildren:
247         return m_anchorNode->lastChild();
248     case PositionIsOffsetInAnchor:
249         return m_offset ? m_anchorNode->traverseToChildAt(m_offset - 1) : nullptr;
250     case PositionIsBeforeAnchor:
251         return m_anchorNode->previousSibling();
252     case PositionIsAfterAnchor:
253         return m_anchorNode.get();
254     }
255     ASSERT_NOT_REACHED();
256     return 0;
257 }
258
259 Node* Position::computeNodeAfterPosition() const
260 {
261     if (!m_anchorNode)
262         return 0;
263
264     switch (anchorType()) {
265     case PositionIsBeforeChildren:
266         return m_anchorNode->firstChild();
267     case PositionIsAfterChildren:
268         return 0;
269     case PositionIsOffsetInAnchor:
270         return m_anchorNode->traverseToChildAt(m_offset);
271     case PositionIsBeforeAnchor:
272         return m_anchorNode.get();
273     case PositionIsAfterAnchor:
274         return m_anchorNode->nextSibling();
275     }
276     ASSERT_NOT_REACHED();
277     return 0;
278 }
279
280 Position::AnchorType Position::anchorTypeForLegacyEditingPosition(Node* anchorNode, int offset)
281 {
282     if (anchorNode && editingIgnoresContent(anchorNode)) {
283         if (offset == 0)
284             return Position::PositionIsBeforeAnchor;
285         return Position::PositionIsAfterAnchor;
286     }
287     return Position::PositionIsOffsetInAnchor;
288 }
289
290 // FIXME: This method is confusing (does it return anchorNode() or containerNode()?) and should be renamed or removed
291 Element* Position::element() const
292 {
293     Node* node = anchorNode();
294     while (node && !is<Element>(node))
295         node = node->parentNode();
296     return downcast<Element>(node);
297 }
298
299 Position Position::previous(PositionMoveType moveType) const
300 {
301     Node* node = deprecatedNode();
302     if (!node)
303         return *this;
304
305     int offset = deprecatedEditingOffset();
306     // FIXME: Negative offsets shouldn't be allowed. We should catch this earlier.
307     ASSERT(offset >= 0);
308
309     if (offset > 0) {
310         if (Node* child = node->traverseToChildAt(offset - 1))
311             return lastPositionInOrAfterNode(child);
312
313         // There are two reasons child might be 0:
314         //   1) The node is node like a text node that is not an element, and therefore has no children.
315         //      Going backward one character at a time is correct.
316         //   2) The old offset was a bogus offset like (<br>, 1), and there is no child.
317         //      Going from 1 to 0 is correct.
318         switch (moveType) {
319         case CodePoint:
320             return createLegacyEditingPosition(node, offset - 1);
321         case Character:
322             return createLegacyEditingPosition(node, uncheckedPreviousOffset(node, offset));
323         case BackwardDeletion:
324             return createLegacyEditingPosition(node, uncheckedPreviousOffsetForBackwardDeletion(node, offset));
325         }
326     }
327
328     ContainerNode* parent = findParent(node);
329     if (!parent)
330         return *this;
331
332     return createLegacyEditingPosition(parent, node->computeNodeIndex());
333 }
334
335 Position Position::next(PositionMoveType moveType) const
336 {
337     ASSERT(moveType != BackwardDeletion);
338
339     Node* node = deprecatedNode();
340     if (!node)
341         return *this;
342
343     int offset = deprecatedEditingOffset();
344     // FIXME: Negative offsets shouldn't be allowed. We should catch this earlier.
345     ASSERT(offset >= 0);
346
347     Node* child = node->traverseToChildAt(offset);
348     if (child || (!node->hasChildNodes() && offset < lastOffsetForEditing(node))) {
349         if (child)
350             return firstPositionInOrBeforeNode(child);
351
352         // There are two reasons child might be 0:
353         //   1) The node is node like a text node that is not an element, and therefore has no children.
354         //      Going forward one character at a time is correct.
355         //   2) The new offset is a bogus offset like (<br>, 1), and there is no child.
356         //      Going from 0 to 1 is correct.
357         return createLegacyEditingPosition(node, (moveType == Character) ? uncheckedNextOffset(node, offset) : offset + 1);
358     }
359
360     ContainerNode* parent = findParent(node);
361     if (!parent)
362         return *this;
363
364     return createLegacyEditingPosition(parent, node->computeNodeIndex() + 1);
365 }
366
367 int Position::uncheckedPreviousOffset(const Node* n, int current)
368 {
369     return n->renderer() ? n->renderer()->previousOffset(current) : current - 1;
370 }
371
372 int Position::uncheckedPreviousOffsetForBackwardDeletion(const Node* n, int current)
373 {
374     return n->renderer() ? n->renderer()->previousOffsetForBackwardDeletion(current) : current - 1;
375 }
376
377 int Position::uncheckedNextOffset(const Node* n, int current)
378 {
379     return n->renderer() ? n->renderer()->nextOffset(current) : current + 1;
380 }
381
382 bool Position::atFirstEditingPositionForNode() const
383 {
384     if (isNull())
385         return true;
386     // FIXME: Position before anchor shouldn't be considered as at the first editing position for node
387     // since that position resides outside of the node.
388     switch (m_anchorType) {
389     case PositionIsOffsetInAnchor:
390         return m_offset <= 0;
391     case PositionIsBeforeChildren:
392     case PositionIsBeforeAnchor:
393         return true;
394     case PositionIsAfterChildren:
395     case PositionIsAfterAnchor:
396         return !lastOffsetForEditing(deprecatedNode());
397     }
398     ASSERT_NOT_REACHED();
399     return false;
400 }
401
402 bool Position::atLastEditingPositionForNode() const
403 {
404     if (isNull())
405         return true;
406     // FIXME: Position after anchor shouldn't be considered as at the first editing position for node
407     // since that position resides outside of the node.
408     return m_anchorType == PositionIsAfterAnchor || m_anchorType == PositionIsAfterChildren || m_offset >= lastOffsetForEditing(deprecatedNode());
409 }
410
411 // A position is considered at editing boundary if one of the following is true:
412 // 1. It is the first position in the node and the next visually equivalent position
413 //    is non editable.
414 // 2. It is the last position in the node and the previous visually equivalent position
415 //    is non editable.
416 // 3. It is an editable position and both the next and previous visually equivalent
417 //    positions are both non editable.
418 bool Position::atEditingBoundary() const
419 {
420     Position nextPosition = downstream(CanCrossEditingBoundary);
421     if (atFirstEditingPositionForNode() && nextPosition.isNotNull() && !nextPosition.deprecatedNode()->hasEditableStyle())
422         return true;
423         
424     Position prevPosition = upstream(CanCrossEditingBoundary);
425     if (atLastEditingPositionForNode() && prevPosition.isNotNull() && !prevPosition.deprecatedNode()->hasEditableStyle())
426         return true;
427         
428     return nextPosition.isNotNull() && !nextPosition.deprecatedNode()->hasEditableStyle()
429         && prevPosition.isNotNull() && !prevPosition.deprecatedNode()->hasEditableStyle();
430 }
431
432 Node* Position::parentEditingBoundary() const
433 {
434     if (!m_anchorNode)
435         return 0;
436
437     Node* documentElement = m_anchorNode->document().documentElement();
438     if (!documentElement)
439         return 0;
440
441     Node* boundary = m_anchorNode.get();
442     while (boundary != documentElement && boundary->nonShadowBoundaryParentNode() && m_anchorNode->hasEditableStyle() == boundary->parentNode()->hasEditableStyle())
443         boundary = boundary->nonShadowBoundaryParentNode();
444     
445     return boundary;
446 }
447
448
449 bool Position::atStartOfTree() const
450 {
451     if (isNull())
452         return true;
453     return !findParent(deprecatedNode()) && m_offset <= 0;
454 }
455
456 bool Position::atEndOfTree() const
457 {
458     if (isNull())
459         return true;
460     return !findParent(deprecatedNode()) && m_offset >= lastOffsetForEditing(deprecatedNode());
461 }
462
463 // return first preceding DOM position rendered at a different location, or "this"
464 Position Position::previousCharacterPosition(EAffinity affinity) const
465 {
466     if (isNull())
467         return Position();
468
469     Node* fromRootEditableElement = deprecatedNode()->rootEditableElement();
470
471     bool atStartOfLine = isStartOfLine(VisiblePosition(*this, affinity));
472     bool rendered = isCandidate();
473     
474     Position currentPos = *this;
475     while (!currentPos.atStartOfTree()) {
476         currentPos = currentPos.previous();
477
478         if (currentPos.deprecatedNode()->rootEditableElement() != fromRootEditableElement)
479             return *this;
480
481         if (atStartOfLine || !rendered) {
482             if (currentPos.isCandidate())
483                 return currentPos;
484         } else if (rendersInDifferentPosition(currentPos))
485             return currentPos;
486     }
487     
488     return *this;
489 }
490
491 // return first following position rendered at a different location, or "this"
492 Position Position::nextCharacterPosition(EAffinity affinity) const
493 {
494     if (isNull())
495         return Position();
496
497     Node* fromRootEditableElement = deprecatedNode()->rootEditableElement();
498
499     bool atEndOfLine = isEndOfLine(VisiblePosition(*this, affinity));
500     bool rendered = isCandidate();
501     
502     Position currentPos = *this;
503     while (!currentPos.atEndOfTree()) {
504         currentPos = currentPos.next();
505
506         if (currentPos.deprecatedNode()->rootEditableElement() != fromRootEditableElement)
507             return *this;
508
509         if (atEndOfLine || !rendered) {
510             if (currentPos.isCandidate())
511                 return currentPos;
512         } else if (rendersInDifferentPosition(currentPos))
513             return currentPos;
514     }
515     
516     return *this;
517 }
518
519 // Whether or not [node, 0] and [node, lastOffsetForEditing(node)] are their own VisiblePositions.
520 // If true, adjacent candidates are visually distinct.
521 // FIXME: Disregard nodes with renderers that have no height, as we do in isCandidate.
522 // FIXME: Share code with isCandidate, if possible.
523 static bool endsOfNodeAreVisuallyDistinctPositions(Node* node)
524 {
525     if (!node || !node->renderer())
526         return false;
527         
528     if (!node->renderer()->isInline())
529         return true;
530         
531     // Don't include inline tables.
532     if (is<HTMLTableElement>(node))
533         return false;
534     
535     // There is a VisiblePosition inside an empty inline-block container.
536     return node->renderer()->isReplaced() && canHaveChildrenForEditing(node) && toRenderBox(node->renderer())->height() != 0 && !node->firstChild();
537 }
538
539 static Node* enclosingVisualBoundary(Node* node)
540 {
541     while (node && !endsOfNodeAreVisuallyDistinctPositions(node))
542         node = node->parentNode();
543         
544     return node;
545 }
546
547 // upstream() and downstream() want to return positions that are either in a
548 // text node or at just before a non-text node.  This method checks for that.
549 static bool isStreamer(const PositionIterator& pos)
550 {
551     if (!pos.node())
552         return true;
553         
554     if (isAtomicNode(pos.node()))
555         return true;
556         
557     return pos.atStartOfNode();
558 }
559
560 // This function and downstream() 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 left candidate 
563 // and downstream() will return the right one.
564 // Also, upstream() will return [boundary, 0] for any of the positions from [boundary, 0] to the first candidate
565 // in boundary, where endsOfNodeAreVisuallyDistinctPositions(boundary) is true.
566 Position Position::upstream(EditingBoundaryCrossingRule rule) const
567 {
568     Node* startNode = deprecatedNode();
569     if (!startNode)
570         return Position();
571     
572     // iterate backward from there, looking for a qualified position
573     Node* boundary = enclosingVisualBoundary(startNode);
574     // FIXME: PositionIterator should respect Before and After positions.
575     PositionIterator lastVisible = m_anchorType == PositionIsAfterAnchor ? createLegacyEditingPosition(m_anchorNode.get(), caretMaxOffset(m_anchorNode.get())) : *this;
576     PositionIterator currentPos = lastVisible;
577     bool startEditable = startNode->hasEditableStyle();
578     Node* lastNode = startNode;
579     bool boundaryCrossed = false;
580     for (; !currentPos.atStart(); currentPos.decrement()) {
581         Node* currentNode = currentPos.node();
582         
583         // Don't check for an editability change if we haven't moved to a different node,
584         // to avoid the expense of computing hasEditableStyle().
585         if (currentNode != lastNode) {
586             // Don't change editability.
587             bool currentEditable = currentNode->hasEditableStyle();
588             if (startEditable != currentEditable) {
589                 if (rule == CannotCrossEditingBoundary)
590                     break;
591                 boundaryCrossed = true;
592             }
593             lastNode = currentNode;
594         }
595
596         // If we've moved to a position that is visually distinct, return the last saved position. There 
597         // is code below that terminates early if we're *about* to move to a visually distinct position.
598         if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentNode != boundary)
599             return lastVisible;
600
601         // skip position in unrendered or invisible node
602         RenderObject* renderer = currentNode->renderer();
603         if (!renderer || renderer->style().visibility() != VISIBLE)
604             continue;
605                  
606         if (rule == CanCrossEditingBoundary && boundaryCrossed) {
607             lastVisible = currentPos;
608             break;
609         }
610         
611         // track last visible streamer position
612         if (isStreamer(currentPos))
613             lastVisible = currentPos;
614         
615         // Don't move past a position that is visually distinct.  We could rely on code above to terminate and 
616         // return lastVisible on the next iteration, but we terminate early to avoid doing a computeNodeIndex() call.
617         if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentPos.atStartOfNode())
618             return lastVisible;
619
620         // Return position after tables and nodes which have content that can be ignored.
621         if (editingIgnoresContent(currentNode) || isRenderedTable(currentNode)) {
622             if (currentPos.atEndOfNode())
623                 return positionAfterNode(currentNode);
624             continue;
625         }
626
627         // return current position if it is in rendered text
628         if (renderer->isText()) {
629             auto& textRenderer = toRenderText(*renderer);
630             textRenderer.ensureLineBoxes();
631
632             if (!textRenderer.firstTextBox())
633                 continue;
634             if (currentNode != startNode) {
635                 // This assertion fires in layout tests in the case-transform.html test because
636                 // of a mix-up between offsets in the text in the DOM tree with text in the
637                 // render tree which can have a different length due to case transformation.
638                 // Until we resolve that, disable this so we can run the layout tests!
639                 //ASSERT(currentOffset >= renderer->caretMaxOffset());
640                 return createLegacyEditingPosition(currentNode, renderer->caretMaxOffset());
641             }
642
643             unsigned textOffset = currentPos.offsetInLeafNode();
644             auto lastTextBox = textRenderer.lastTextBox();
645             for (auto box = textRenderer.firstTextBox(); box; box = box->nextTextBox()) {
646                 if (textOffset <= box->start() + box->len()) {
647                     if (textOffset > box->start())
648                         return currentPos;
649                     continue;
650                 }
651
652                 if (box == lastTextBox || textOffset != box->start() + box->len() + 1)
653                     continue;
654
655                 // The text continues on the next line only if the last text box is not on this line and
656                 // none of the boxes on this line have a larger start offset.
657
658                 bool continuesOnNextLine = true;
659                 InlineBox* otherBox = box;
660                 while (continuesOnNextLine) {
661                     otherBox = otherBox->nextLeafChild();
662                     if (!otherBox)
663                         break;
664                     if (otherBox == lastTextBox || (&otherBox->renderer() == &textRenderer && toInlineTextBox(otherBox)->start() > textOffset))
665                         continuesOnNextLine = false;
666                 }
667
668                 otherBox = box;
669                 while (continuesOnNextLine) {
670                     otherBox = otherBox->prevLeafChild();
671                     if (!otherBox)
672                         break;
673                     if (otherBox == lastTextBox || (&otherBox->renderer() == &textRenderer && toInlineTextBox(otherBox)->start() > textOffset))
674                         continuesOnNextLine = false;
675                 }
676
677                 if (continuesOnNextLine)
678                     return currentPos;
679             }
680         }
681     }
682
683     return lastVisible;
684 }
685
686 // This function and upstream() are used for moving back and forth between visually equivalent candidates.
687 // For example, for the text node "foo     bar" where whitespace is collapsible, there are two candidates 
688 // that map to the VisiblePosition between 'b' and the space.  This function will return the right candidate 
689 // and upstream() will return the left one.
690 // Also, downstream() will return the last position in the last atomic node in boundary for all of the positions
691 // in boundary after the last candidate, where endsOfNodeAreVisuallyDistinctPositions(boundary).
692 // FIXME: This function should never be called when the line box tree is dirty. See https://bugs.webkit.org/show_bug.cgi?id=97264
693 Position Position::downstream(EditingBoundaryCrossingRule rule) const
694 {
695     Node* startNode = deprecatedNode();
696     if (!startNode)
697         return Position();
698
699     // iterate forward from there, looking for a qualified position
700     Node* boundary = enclosingVisualBoundary(startNode);
701     // FIXME: PositionIterator should respect Before and After positions.
702     PositionIterator lastVisible = m_anchorType == PositionIsAfterAnchor ? createLegacyEditingPosition(m_anchorNode.get(), caretMaxOffset(m_anchorNode.get())) : *this;
703     PositionIterator currentPos = lastVisible;
704     bool startEditable = startNode->hasEditableStyle();
705     Node* lastNode = startNode;
706     bool boundaryCrossed = false;
707     for (; !currentPos.atEnd(); currentPos.increment()) {   
708         Node* currentNode = currentPos.node();
709         
710         // Don't check for an editability change if we haven't moved to a different node,
711         // to avoid the expense of computing hasEditableStyle().
712         if (currentNode != lastNode) {
713             // Don't change editability.
714             bool currentEditable = currentNode->hasEditableStyle();
715             if (startEditable != currentEditable) {
716                 if (rule == CannotCrossEditingBoundary)
717                     break;
718                 boundaryCrossed = true;
719             }
720                 
721             lastNode = currentNode;
722         }
723
724         // stop before going above the body, up into the head
725         // return the last visible streamer position
726         if (currentNode->hasTagName(bodyTag) && currentPos.atEndOfNode())
727             break;
728             
729         // Do not move to a visually distinct position.
730         if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentNode != boundary)
731             return lastVisible;
732         // Do not move past a visually disinct position.
733         // Note: The first position after the last in a node whose ends are visually distinct
734         // positions will be [boundary->parentNode(), originalBlock->computeNodeIndex() + 1].
735         if (boundary && boundary->parentNode() == currentNode)
736             return lastVisible;
737
738         // skip position in unrendered or invisible node
739         RenderObject* renderer = currentNode->renderer();
740         if (!renderer || renderer->style().visibility() != VISIBLE)
741             continue;
742             
743         if (rule == CanCrossEditingBoundary && boundaryCrossed) {
744             lastVisible = currentPos;
745             break;
746         }
747         
748         // track last visible streamer position
749         if (isStreamer(currentPos))
750             lastVisible = currentPos;
751
752         // Return position before tables and nodes which have content that can be ignored.
753         if (editingIgnoresContent(currentNode) || isRenderedTable(currentNode)) {
754             if (currentPos.offsetInLeafNode() <= renderer->caretMinOffset())
755                 return createLegacyEditingPosition(currentNode, renderer->caretMinOffset());
756             continue;
757         }
758
759         // return current position if it is in rendered text
760         if (renderer->isText()) {
761             auto& textRenderer = toRenderText(*renderer);
762             textRenderer.ensureLineBoxes();
763
764             if (!textRenderer.firstTextBox())
765                 continue;
766             if (currentNode != startNode) {
767                 ASSERT(currentPos.atStartOfNode());
768                 return createLegacyEditingPosition(currentNode, renderer->caretMinOffset());
769             }
770
771             unsigned textOffset = currentPos.offsetInLeafNode();
772             auto lastTextBox = textRenderer.lastTextBox();
773             for (auto box = textRenderer.firstTextBox(); box; box = box->nextTextBox()) {
774                 if (textOffset <= box->end()) {
775                     if (textOffset >= box->start())
776                         return currentPos;
777                     continue;
778                 }
779
780                 if (box == lastTextBox || textOffset != box->start() + box->len())
781                     continue;
782
783                 // The text continues on the next line only if the last text box is not on this line and
784                 // none of the boxes on this line have a larger start offset.
785
786                 bool continuesOnNextLine = true;
787                 InlineBox* otherBox = box;
788                 while (continuesOnNextLine) {
789                     otherBox = otherBox->nextLeafChild();
790                     if (!otherBox)
791                         break;
792                     if (otherBox == lastTextBox || (&otherBox->renderer() == &textRenderer && toInlineTextBox(otherBox)->start() >= textOffset))
793                         continuesOnNextLine = false;
794                 }
795
796                 otherBox = box;
797                 while (continuesOnNextLine) {
798                     otherBox = otherBox->prevLeafChild();
799                     if (!otherBox)
800                         break;
801                     if (otherBox == lastTextBox || (&otherBox->renderer() == &textRenderer && toInlineTextBox(otherBox)->start() >= textOffset))
802                         continuesOnNextLine = false;
803                 }
804
805                 if (continuesOnNextLine)
806                     return currentPos;
807             }
808         }
809     }
810     
811     return lastVisible;
812 }
813
814 unsigned Position::positionCountBetweenPositions(const Position& a, const Position& b)
815 {
816     if (a.isNull() || b.isNull())
817         return UINT_MAX;
818     
819     Position endPos;
820     Position pos;
821     if (a > b) {
822         endPos = a;
823         pos = b;
824     } else if (a < b) {
825         endPos = b;
826         pos = a;
827     } else
828         return 0;
829     
830     unsigned posCount = 0;
831     while (!pos.atEndOfTree() && pos != endPos) {
832         pos = pos.next();
833         ++posCount;
834     }
835     return posCount;
836 }
837
838 static int boundingBoxLogicalHeight(RenderObject *o, const IntRect &rect)
839 {
840     return o->style().isHorizontalWritingMode() ? rect.height() : rect.width();
841 }
842
843 bool Position::hasRenderedNonAnonymousDescendantsWithHeight(const RenderElement& renderer)
844 {
845     RenderObject* stop = renderer.nextInPreOrderAfterChildren();
846     for (RenderObject* o = renderer.firstChild(); o && o != stop; o = o->nextInPreOrder()) {
847         if (!o->nonPseudoNode())
848             continue;
849         if (o->isText()) {
850             if (boundingBoxLogicalHeight(o, toRenderText(o)->linesBoundingBox()))
851                 return true;
852             continue;
853         }
854         if (o->isLineBreak()) {
855             if (boundingBoxLogicalHeight(o, toRenderLineBreak(o)->linesBoundingBox()))
856                 return true;
857             continue;
858         }
859         if (o->isBox()) {
860             if (toRenderBox(o)->pixelSnappedLogicalHeight())
861                 return true;
862             continue;
863         }
864         if (o->isRenderInline()) {
865             const RenderInline& renderInline = toRenderInline(*o);
866             if (isEmptyInline(renderInline) && boundingBoxLogicalHeight(o, renderInline.linesBoundingBox()))
867                 return true;
868             continue;
869         }
870     }
871     return false;
872 }
873
874 bool Position::nodeIsUserSelectNone(Node* node)
875 {
876     return node && node->renderer() && node->renderer()->style().userSelect() == SELECT_NONE;
877 }
878
879 ContainerNode* Position::findParent(const Node* node)
880 {
881     return node->nonShadowBoundaryParentNode();
882 }
883
884 #if ENABLE(USERSELECT_ALL)
885 bool Position::nodeIsUserSelectAll(const Node* node)
886 {
887     return node && node->renderer() && node->renderer()->style().userSelect() == SELECT_ALL;
888 }
889
890 Node* Position::rootUserSelectAllForNode(Node* node)
891 {
892     if (!node || !nodeIsUserSelectAll(node))
893         return 0;
894     Node* parent = node->parentNode();
895     if (!parent)
896         return node;
897
898     Node* candidateRoot = node;
899     while (parent) {
900         if (!parent->renderer()) {
901             parent = parent->parentNode();
902             continue;
903         }
904         if (!nodeIsUserSelectAll(parent))
905             break;
906         candidateRoot = parent;
907         parent = candidateRoot->parentNode();
908     }
909     return candidateRoot;
910 }
911 #endif
912
913 bool Position::isCandidate() const
914 {
915     if (isNull())
916         return false;
917         
918     RenderObject* renderer = deprecatedNode()->renderer();
919     if (!renderer)
920         return false;
921     
922     if (renderer->style().visibility() != VISIBLE)
923         return false;
924
925     if (renderer->isBR())
926         // FIXME: The condition should be m_anchorType == PositionIsBeforeAnchor, but for now we still need to support legacy positions.
927         return !m_offset && m_anchorType != PositionIsAfterAnchor && !nodeIsUserSelectNone(deprecatedNode()->parentNode());
928
929     if (renderer->isText())
930         return !nodeIsUserSelectNone(deprecatedNode()) && toRenderText(renderer)->containsCaretOffset(m_offset);
931
932     if (isRenderedTable(deprecatedNode()) || editingIgnoresContent(deprecatedNode()))
933         return (atFirstEditingPositionForNode() || atLastEditingPositionForNode()) && !nodeIsUserSelectNone(deprecatedNode()->parentNode());
934
935     if (m_anchorNode->hasTagName(htmlTag))
936         return false;
937         
938     if (renderer->isRenderBlockFlow()) {
939         RenderBlockFlow& block = toRenderBlockFlow(*renderer);
940         if (block.logicalHeight() || m_anchorNode->hasTagName(bodyTag)) {
941             if (!Position::hasRenderedNonAnonymousDescendantsWithHeight(block))
942                 return atFirstEditingPositionForNode() && !Position::nodeIsUserSelectNone(deprecatedNode());
943             return m_anchorNode->hasEditableStyle() && !Position::nodeIsUserSelectNone(deprecatedNode()) && atEditingBoundary();
944         }
945         return false;
946     }
947
948     return m_anchorNode->hasEditableStyle() && !Position::nodeIsUserSelectNone(deprecatedNode()) && atEditingBoundary();
949 }
950
951 bool Position::isRenderedCharacter() const
952 {
953     if (isNull() || !is<Text>(deprecatedNode()))
954         return false;
955         
956     RenderText* renderer = downcast<Text>(*deprecatedNode()).renderer();
957     if (!renderer)
958         return false;
959     
960     return renderer->containsRenderedCharacterOffset(m_offset);
961 }
962
963 static bool inSameEnclosingBlockFlowElement(Node* a, Node* b)
964 {
965     return a && b && deprecatedEnclosingBlockFlowElement(a) == deprecatedEnclosingBlockFlowElement(b);
966 }
967
968 bool Position::rendersInDifferentPosition(const Position &pos) const
969 {
970     if (isNull() || pos.isNull())
971         return false;
972
973     RenderObject* renderer = deprecatedNode()->renderer();
974     if (!renderer)
975         return false;
976     
977     RenderObject* posRenderer = pos.deprecatedNode()->renderer();
978     if (!posRenderer)
979         return false;
980
981     if (renderer->style().visibility() != VISIBLE ||
982         posRenderer->style().visibility() != VISIBLE)
983         return false;
984     
985     if (deprecatedNode() == pos.deprecatedNode()) {
986         if (deprecatedNode()->hasTagName(brTag))
987             return false;
988
989         if (m_offset == pos.deprecatedEditingOffset())
990             return false;
991             
992         if (!deprecatedNode()->isTextNode() && !pos.deprecatedNode()->isTextNode()) {
993             if (m_offset != pos.deprecatedEditingOffset())
994                 return true;
995         }
996     }
997     
998     if (deprecatedNode()->hasTagName(brTag) && pos.isCandidate())
999         return true;
1000                 
1001     if (pos.deprecatedNode()->hasTagName(brTag) && isCandidate())
1002         return true;
1003                 
1004     if (!inSameEnclosingBlockFlowElement(deprecatedNode(), pos.deprecatedNode()))
1005         return true;
1006
1007     if (renderer->isText() && !toRenderText(renderer)->containsCaretOffset(m_offset))
1008         return false;
1009
1010     if (posRenderer->isText() && !toRenderText(posRenderer)->containsCaretOffset(pos.m_offset))
1011         return false;
1012
1013     int thisRenderedOffset = renderer->isText() ? toRenderText(renderer)->countRenderedCharacterOffsetsUntil(m_offset) : m_offset;
1014     int posRenderedOffset = posRenderer->isText() ? toRenderText(posRenderer)->countRenderedCharacterOffsetsUntil(pos.m_offset) : pos.m_offset;
1015
1016     if (renderer == posRenderer && thisRenderedOffset == posRenderedOffset)
1017         return false;
1018
1019     int ignoredCaretOffset;
1020     InlineBox* b1;
1021     getInlineBoxAndOffset(DOWNSTREAM, b1, ignoredCaretOffset);
1022     InlineBox* b2;
1023     pos.getInlineBoxAndOffset(DOWNSTREAM, b2, ignoredCaretOffset);
1024
1025     LOG(Editing, "renderer:               %p [%p]\n", renderer, b1);
1026     LOG(Editing, "thisRenderedOffset:         %d\n", thisRenderedOffset);
1027     LOG(Editing, "posRenderer:            %p [%p]\n", posRenderer, b2);
1028     LOG(Editing, "posRenderedOffset:      %d\n", posRenderedOffset);
1029     LOG(Editing, "node min/max:           %d:%d\n", caretMinOffset(deprecatedNode()), caretMaxOffset(deprecatedNode()));
1030     LOG(Editing, "pos node min/max:       %d:%d\n", caretMinOffset(pos.deprecatedNode()), caretMaxOffset(pos.deprecatedNode()));
1031     LOG(Editing, "----------------------------------------------------------------------\n");
1032
1033     if (!b1 || !b2) {
1034         return false;
1035     }
1036
1037     if (&b1->root() != &b2->root()) {
1038         return true;
1039     }
1040
1041     if (nextRenderedEditable(deprecatedNode()) == pos.deprecatedNode()
1042         && thisRenderedOffset == caretMaxOffset(deprecatedNode()) && !posRenderedOffset) {
1043         return false;
1044     }
1045     
1046     if (previousRenderedEditable(deprecatedNode()) == pos.deprecatedNode()
1047         && !thisRenderedOffset && posRenderedOffset == caretMaxOffset(pos.deprecatedNode())) {
1048         return false;
1049     }
1050
1051     return true;
1052 }
1053
1054 // This assumes that it starts in editable content.
1055 Position Position::leadingWhitespacePosition(EAffinity affinity, bool considerNonCollapsibleWhitespace) const
1056 {
1057     ASSERT(isEditablePosition(*this));
1058     if (isNull())
1059         return Position();
1060     
1061     if (upstream().deprecatedNode()->hasTagName(brTag))
1062         return Position();
1063
1064     Position prev = previousCharacterPosition(affinity);
1065     if (prev != *this && inSameEnclosingBlockFlowElement(deprecatedNode(), prev.deprecatedNode()) && is<Text>(prev.deprecatedNode())) {
1066         String string = downcast<Text>(*prev.deprecatedNode()).data();
1067         UChar c = string[prev.deprecatedEditingOffset()];
1068         if (considerNonCollapsibleWhitespace ? (isSpaceOrNewline(c) || c == noBreakSpace) : deprecatedIsCollapsibleWhitespace(c))
1069             if (isEditablePosition(prev))
1070                 return prev;
1071     }
1072
1073     return Position();
1074 }
1075
1076 // This assumes that it starts in editable content.
1077 Position Position::trailingWhitespacePosition(EAffinity, bool considerNonCollapsibleWhitespace) const
1078 {
1079     ASSERT(isEditablePosition(*this));
1080     if (isNull())
1081         return Position();
1082     
1083     VisiblePosition v(*this);
1084     UChar c = v.characterAfter();
1085     // The space must not be in another paragraph and it must be editable.
1086     if (!isEndOfParagraph(v) && v.next(CannotCrossEditingBoundary).isNotNull())
1087         if (considerNonCollapsibleWhitespace ? (isSpaceOrNewline(c) || c == noBreakSpace) : deprecatedIsCollapsibleWhitespace(c))
1088             return *this;
1089     
1090     return Position();
1091 }
1092
1093 void Position::getInlineBoxAndOffset(EAffinity affinity, InlineBox*& inlineBox, int& caretOffset) const
1094 {
1095     getInlineBoxAndOffset(affinity, primaryDirection(), inlineBox, caretOffset);
1096 }
1097
1098 static bool isNonTextLeafChild(RenderObject* object)
1099 {
1100     if (object->isText())
1101         return false;
1102     if (toRenderElement(object)->firstChild())
1103         return false;
1104     return true;
1105 }
1106
1107 static InlineTextBox* searchAheadForBetterMatch(RenderObject* renderer)
1108 {
1109     RenderBlock* container = renderer->containingBlock();
1110     RenderObject* next = renderer;
1111     while ((next = next->nextInPreOrder(container))) {
1112         if (next->isRenderBlock())
1113             return 0;
1114         if (next->isBR())
1115             return 0;
1116         if (isNonTextLeafChild(next))
1117             return 0;
1118         if (next->isText()) {
1119             InlineTextBox* match = 0;
1120             int minOffset = INT_MAX;
1121             for (InlineTextBox* box = toRenderText(next)->firstTextBox(); box; box = box->nextTextBox()) {
1122                 int caretMinOffset = box->caretMinOffset();
1123                 if (caretMinOffset < minOffset) {
1124                     match = box;
1125                     minOffset = caretMinOffset;
1126                 }
1127             }
1128             if (match)
1129                 return match;
1130         }
1131     }
1132     return 0;
1133 }
1134
1135 static Position downstreamIgnoringEditingBoundaries(Position position)
1136 {
1137     Position lastPosition;
1138     while (position != lastPosition) {
1139         lastPosition = position;
1140         position = position.downstream(CanCrossEditingBoundary);
1141     }
1142     return position;
1143 }
1144
1145 static Position upstreamIgnoringEditingBoundaries(Position position)
1146 {
1147     Position lastPosition;
1148     while (position != lastPosition) {
1149         lastPosition = position;
1150         position = position.upstream(CanCrossEditingBoundary);
1151     }
1152     return position;
1153 }
1154
1155 void Position::getInlineBoxAndOffset(EAffinity affinity, TextDirection primaryDirection, InlineBox*& inlineBox, int& caretOffset) const
1156 {
1157     caretOffset = deprecatedEditingOffset();
1158     RenderObject* renderer = deprecatedNode()->renderer();
1159
1160     if (renderer->isBR())
1161         inlineBox = !caretOffset ? toRenderLineBreak(renderer)->inlineBoxWrapper() : nullptr;
1162     else if (renderer->isText()) {
1163         auto textRenderer = toRenderText(renderer);
1164         textRenderer->ensureLineBoxes();
1165
1166         InlineTextBox* box;
1167         InlineTextBox* candidate = 0;
1168
1169         for (box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
1170             int caretMinOffset = box->caretMinOffset();
1171             int caretMaxOffset = box->caretMaxOffset();
1172
1173             if (caretOffset < caretMinOffset || caretOffset > caretMaxOffset || (caretOffset == caretMaxOffset && box->isLineBreak()))
1174                 continue;
1175
1176             if (caretOffset > caretMinOffset && caretOffset < caretMaxOffset) {
1177                 inlineBox = box;
1178                 return;
1179             }
1180
1181             if (((caretOffset == caretMaxOffset) ^ (affinity == DOWNSTREAM))
1182                 || ((caretOffset == caretMinOffset) ^ (affinity == UPSTREAM))
1183                 || (caretOffset == caretMaxOffset && box->nextLeafChild() && box->nextLeafChild()->isLineBreak()))
1184                 break;
1185
1186             candidate = box;
1187         }
1188         if (candidate && candidate == textRenderer->lastTextBox() && affinity == DOWNSTREAM) {
1189             box = searchAheadForBetterMatch(textRenderer);
1190             if (box)
1191                 caretOffset = box->caretMinOffset();
1192         }
1193         inlineBox = box ? box : candidate;
1194     } else {
1195         inlineBox = 0;
1196         if (canHaveChildrenForEditing(deprecatedNode()) && renderer->isRenderBlockFlow() && hasRenderedNonAnonymousDescendantsWithHeight(toRenderBlock(*renderer))) {
1197             // Try a visually equivalent position with possibly opposite editability. This helps in case |this| is in
1198             // an editable block but surrounded by non-editable positions. It acts to negate the logic at the beginning
1199             // of RenderObject::createVisiblePosition().
1200             Position equivalent = downstreamIgnoringEditingBoundaries(*this);
1201             if (equivalent == *this) {
1202                 equivalent = upstreamIgnoringEditingBoundaries(*this);
1203                 if (equivalent == *this || downstreamIgnoringEditingBoundaries(equivalent) == *this)
1204                     return;
1205             }
1206
1207             equivalent.getInlineBoxAndOffset(UPSTREAM, primaryDirection, inlineBox, caretOffset);
1208             return;
1209         }
1210         if (renderer->isBox()) {
1211             inlineBox = toRenderBox(renderer)->inlineBoxWrapper();
1212             if (!inlineBox || (caretOffset > inlineBox->caretMinOffset() && caretOffset < inlineBox->caretMaxOffset()))
1213                 return;
1214         }
1215     }
1216
1217     if (!inlineBox)
1218         return;
1219
1220     unsigned char level = inlineBox->bidiLevel();
1221
1222     if (inlineBox->direction() == primaryDirection) {
1223         if (caretOffset == inlineBox->caretRightmostOffset()) {
1224             InlineBox* nextBox = inlineBox->nextLeafChild();
1225             if (!nextBox || nextBox->bidiLevel() >= level)
1226                 return;
1227
1228             level = nextBox->bidiLevel();
1229             InlineBox* prevBox = inlineBox;
1230             do {
1231                 prevBox = prevBox->prevLeafChild();
1232             } while (prevBox && prevBox->bidiLevel() > level);
1233
1234             if (prevBox && prevBox->bidiLevel() == level)   // For example, abc FED 123 ^ CBA
1235                 return;
1236
1237             // For example, abc 123 ^ CBA
1238             while (InlineBox* nextBox = inlineBox->nextLeafChild()) {
1239                 if (nextBox->bidiLevel() < level)
1240                     break;
1241                 inlineBox = nextBox;
1242             }
1243             caretOffset = inlineBox->caretRightmostOffset();
1244         } else {
1245             InlineBox* prevBox = inlineBox->prevLeafChild();
1246             if (!prevBox || prevBox->bidiLevel() >= level)
1247                 return;
1248
1249             level = prevBox->bidiLevel();
1250             InlineBox* nextBox = inlineBox;
1251             do {
1252                 nextBox = nextBox->nextLeafChild();
1253             } while (nextBox && nextBox->bidiLevel() > level);
1254
1255             if (nextBox && nextBox->bidiLevel() == level)
1256                 return;
1257
1258             while (InlineBox* prevBox = inlineBox->prevLeafChild()) {
1259                 if (prevBox->bidiLevel() < level)
1260                     break;
1261                 inlineBox = prevBox;
1262             }
1263             caretOffset = inlineBox->caretLeftmostOffset();
1264         }
1265         return;
1266     }
1267
1268     if (caretOffset == inlineBox->caretLeftmostOffset()) {
1269         InlineBox* prevBox = inlineBox->prevLeafChildIgnoringLineBreak();
1270         if (!prevBox || prevBox->bidiLevel() < level) {
1271             // Left edge of a secondary run. Set to the right edge of the entire run.
1272             while (InlineBox* nextBox = inlineBox->nextLeafChildIgnoringLineBreak()) {
1273                 if (nextBox->bidiLevel() < level)
1274                     break;
1275                 inlineBox = nextBox;
1276             }
1277             caretOffset = inlineBox->caretRightmostOffset();
1278         } else if (prevBox->bidiLevel() > level) {
1279             // Right edge of a "tertiary" run. Set to the left edge of that run.
1280             while (InlineBox* tertiaryBox = inlineBox->prevLeafChildIgnoringLineBreak()) {
1281                 if (tertiaryBox->bidiLevel() <= level)
1282                     break;
1283                 inlineBox = tertiaryBox;
1284             }
1285             caretOffset = inlineBox->caretLeftmostOffset();
1286         }
1287     } else {
1288         InlineBox* nextBox = inlineBox->nextLeafChildIgnoringLineBreak();
1289         if (!nextBox || nextBox->bidiLevel() < level) {
1290             // Right edge of a secondary run. Set to the left edge of the entire run.
1291             while (InlineBox* prevBox = inlineBox->prevLeafChildIgnoringLineBreak()) {
1292                 if (prevBox->bidiLevel() < level)
1293                     break;
1294                 inlineBox = prevBox;
1295             }
1296             caretOffset = inlineBox->caretLeftmostOffset();
1297         } else if (nextBox->bidiLevel() > level) {
1298             // Left edge of a "tertiary" run. Set to the right edge of that run.
1299             while (InlineBox* tertiaryBox = inlineBox->nextLeafChildIgnoringLineBreak()) {
1300                 if (tertiaryBox->bidiLevel() <= level)
1301                     break;
1302                 inlineBox = tertiaryBox;
1303             }
1304             caretOffset = inlineBox->caretRightmostOffset();
1305         }
1306     }
1307 }
1308
1309 TextDirection Position::primaryDirection() const
1310 {
1311     if (!m_anchorNode->renderer())
1312         return LTR;
1313     if (auto* blockFlow = lineageOfType<RenderBlockFlow>(*m_anchorNode->renderer()).first())
1314         return blockFlow->style().direction();
1315     return LTR;
1316 }
1317
1318
1319 void Position::debugPosition(const char* msg) const
1320 {
1321     if (isNull())
1322         fprintf(stderr, "Position [%s]: null\n", msg);
1323     else
1324         fprintf(stderr, "Position [%s]: %s [%p] at %d\n", msg, deprecatedNode()->nodeName().utf8().data(), deprecatedNode(), m_offset);
1325 }
1326
1327 #ifndef NDEBUG
1328
1329 void Position::formatForDebugger(char* buffer, unsigned length) const
1330 {
1331     StringBuilder result;
1332
1333     if (isNull())
1334         result.appendLiteral("<null>");
1335     else {
1336         char s[1024];
1337         result.appendLiteral("offset ");
1338         result.appendNumber(m_offset);
1339         result.appendLiteral(" of ");
1340         deprecatedNode()->formatForDebugger(s, sizeof(s));
1341         result.append(s);
1342     }
1343
1344     strncpy(buffer, result.toString().utf8().data(), length - 1);
1345 }
1346
1347 void Position::showAnchorTypeAndOffset() const
1348 {
1349     if (m_isLegacyEditingPosition)
1350         fputs("legacy, ", stderr);
1351     switch (anchorType()) {
1352     case PositionIsOffsetInAnchor:
1353         fputs("offset", stderr);
1354         break;
1355     case PositionIsBeforeChildren:
1356         fputs("beforeChildren", stderr);
1357         break;
1358     case PositionIsAfterChildren:
1359         fputs("afterChildren", stderr);
1360         break;
1361     case PositionIsBeforeAnchor:
1362         fputs("before", stderr);
1363         break;
1364     case PositionIsAfterAnchor:
1365         fputs("after", stderr);
1366         break;
1367     }
1368     fprintf(stderr, ", offset:%d\n", m_offset);
1369 }
1370
1371 void Position::showTreeForThis() const
1372 {
1373     if (anchorNode()) {
1374         anchorNode()->showTreeForThis();
1375         showAnchorTypeAndOffset();
1376     }
1377 }
1378
1379 #endif
1380
1381
1382
1383 } // namespace WebCore
1384
1385 #ifndef NDEBUG
1386
1387 void showTree(const WebCore::Position& pos)
1388 {
1389     pos.showTreeForThis();
1390 }
1391
1392 void showTree(const WebCore::Position* pos)
1393 {
1394     if (pos)
1395         pos->showTreeForThis();
1396 }
1397
1398 #endif