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