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