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
52namespace WebCore {
53
54using namespace HTMLNames;
55
56static 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
67static 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
79static 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
91Position::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
101Position::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
114Position::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
125Position::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
134void 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}
143void 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
151Node* 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
169Text* 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
186int 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
207int 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.
216Position 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->childNodeCount())
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
238Node* 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
259Node* 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
280Position::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
291Element* Position::element() const
292{
293    Node* n = anchorNode();
294    while (n && !n->isElementNode())
295        n = n->parentNode();
296    return toElement(n);
297}
298
299Position 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
336Position 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
368int Position::uncheckedPreviousOffset(const Node* n, int current)
369{
370    return n->renderer() ? n->renderer()->previousOffset(current) : current - 1;
371}
372
373int Position::uncheckedPreviousOffsetForBackwardDeletion(const Node* n, int current)
374{
375    return n->renderer() ? n->renderer()->previousOffsetForBackwardDeletion(current) : current - 1;
376}
377
378int Position::uncheckedNextOffset(const Node* n, int current)
379{
380    return n->renderer() ? n->renderer()->nextOffset(current) : current + 1;
381}
382
383bool 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
403bool 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.
419bool 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
433Node* 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
450bool Position::atStartOfTree() const
451{
452    if (isNull())
453        return true;
454    return !findParent(deprecatedNode()) && m_offset <= 0;
455}
456
457bool 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"
465Position 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"
493Position 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.
524static 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
540static 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.
550static 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.
567Position 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
694Position 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
815unsigned 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
839static int boundingBoxLogicalHeight(RenderObject *o, const IntRect &rect)
840{
841    return o->style().isHorizontalWritingMode() ? rect.height() : rect.width();
842}
843
844bool 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
875bool Position::nodeIsUserSelectNone(Node* node)
876{
877    return node && node->renderer() && node->renderer()->style().userSelect() == SELECT_NONE;
878}
879
880ContainerNode* Position::findParent(const Node* node)
881{
882    return node->nonShadowBoundaryParentNode();
883}
884
885#if ENABLE(USERSELECT_ALL)
886bool Position::nodeIsUserSelectAll(const Node* node)
887{
888    return node && node->renderer() && node->renderer()->style().userSelect() == SELECT_ALL;
889}
890
891Node* 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
914bool 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
952bool 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
964static bool inSameEnclosingBlockFlowElement(Node* a, Node* b)
965{
966    return a && b && deprecatedEnclosingBlockFlowElement(a) == deprecatedEnclosingBlockFlowElement(b);
967}
968
969bool 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.
1056Position 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.
1078Position 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
1094void Position::getInlineBoxAndOffset(EAffinity affinity, InlineBox*& inlineBox, int& caretOffset) const
1095{
1096    getInlineBoxAndOffset(affinity, primaryDirection(), inlineBox, caretOffset);
1097}
1098
1099static 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
1108static 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
1136static 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
1146static 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
1156void 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
1310TextDirection 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
1320void 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
1330void 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
1348void 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
1372void 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
1388void showTree(const WebCore::Position& pos)
1389{
1390    pos.showTreeForThis();
1391}
1392
1393void showTree(const WebCore::Position* pos)
1394{
1395    if (pos)
1396        pos->showTreeForThis();
1397}
1398
1399#endif
1400