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