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