1/*
2 * Copyright (C) 2004, 2005, 2006 Apple Inc.  All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "VisibleSelection.h"
28
29#include "Document.h"
30#include "Element.h"
31#include "HTMLInputElement.h"
32#include "TextIterator.h"
33#include "VisibleUnits.h"
34#include "htmlediting.h"
35#include <stdio.h>
36#include <wtf/Assertions.h>
37#include <wtf/text/CString.h>
38#include <wtf/text/StringBuilder.h>
39#include <wtf/unicode/CharacterNames.h>
40
41namespace WebCore {
42
43VisibleSelection::VisibleSelection()
44    : m_affinity(DOWNSTREAM)
45    , m_selectionType(NoSelection)
46    , m_baseIsFirst(true)
47    , m_isDirectional(false)
48{
49}
50
51VisibleSelection::VisibleSelection(const Position& pos, EAffinity affinity, bool isDirectional)
52    : m_base(pos)
53    , m_extent(pos)
54    , m_affinity(affinity)
55    , m_isDirectional(isDirectional)
56{
57    validate();
58}
59
60VisibleSelection::VisibleSelection(const Position& base, const Position& extent, EAffinity affinity, bool isDirectional)
61    : m_base(base)
62    , m_extent(extent)
63    , m_affinity(affinity)
64    , m_isDirectional(isDirectional)
65{
66    validate();
67}
68
69VisibleSelection::VisibleSelection(const VisiblePosition& pos, bool isDirectional)
70    : m_base(pos.deepEquivalent())
71    , m_extent(pos.deepEquivalent())
72    , m_affinity(pos.affinity())
73    , m_isDirectional(isDirectional)
74{
75    validate();
76}
77
78VisibleSelection::VisibleSelection(const VisiblePosition& base, const VisiblePosition& extent, bool isDirectional)
79    : m_base(base.deepEquivalent())
80    , m_extent(extent.deepEquivalent())
81    , m_affinity(base.affinity())
82    , m_isDirectional(isDirectional)
83{
84    validate();
85}
86
87VisibleSelection::VisibleSelection(const Range* range, EAffinity affinity, bool isDirectional)
88    : m_base(range->startPosition())
89    , m_extent(range->endPosition())
90    , m_affinity(affinity)
91    , m_isDirectional(isDirectional)
92{
93    validate();
94}
95
96VisibleSelection VisibleSelection::selectionFromContentsOfNode(Node* node)
97{
98    ASSERT(!editingIgnoresContent(node));
99    return VisibleSelection(firstPositionInNode(node), lastPositionInNode(node), DOWNSTREAM);
100}
101
102void VisibleSelection::setBase(const Position& position)
103{
104    m_base = position;
105    validate();
106}
107
108void VisibleSelection::setBase(const VisiblePosition& visiblePosition)
109{
110    m_base = visiblePosition.deepEquivalent();
111    validate();
112}
113
114void VisibleSelection::setExtent(const Position& position)
115{
116    m_extent = position;
117    validate();
118}
119
120void VisibleSelection::setExtent(const VisiblePosition& visiblePosition)
121{
122    m_extent = visiblePosition.deepEquivalent();
123    validate();
124}
125
126PassRefPtr<Range> VisibleSelection::firstRange() const
127{
128    if (isNone())
129        return 0;
130    Position start = m_start.parentAnchoredEquivalent();
131    Position end = m_end.parentAnchoredEquivalent();
132    return Range::create(start.anchorNode()->document(), start, end);
133}
134
135PassRefPtr<Range> VisibleSelection::toNormalizedRange() const
136{
137    if (isNone())
138        return 0;
139
140    // Make sure we have an updated layout since this function is called
141    // in the course of running edit commands which modify the DOM.
142    // Failing to call this can result in equivalentXXXPosition calls returning
143    // incorrect results.
144    m_start.anchorNode()->document().updateLayout();
145
146    // Check again, because updating layout can clear the selection.
147    if (isNone())
148        return 0;
149
150    Position s, e;
151    if (isCaret()) {
152        // If the selection is a caret, move the range start upstream. This helps us match
153        // the conventions of text editors tested, which make style determinations based
154        // on the character before the caret, if any.
155        s = m_start.upstream().parentAnchoredEquivalent();
156        e = s;
157    } else {
158        // If the selection is a range, select the minimum range that encompasses the selection.
159        // Again, this is to match the conventions of text editors tested, which make style
160        // determinations based on the first character of the selection.
161        // For instance, this operation helps to make sure that the "X" selected below is the
162        // only thing selected. The range should not be allowed to "leak" out to the end of the
163        // previous text node, or to the beginning of the next text node, each of which has a
164        // different style.
165        //
166        // On a treasure map, <b>X</b> marks the spot.
167        //                       ^ selected
168        //
169        ASSERT(isRange());
170        s = m_start.downstream();
171        e = m_end.upstream();
172        if (comparePositions(s, e) > 0) {
173            // Make sure the start is before the end.
174            // The end can wind up before the start if collapsed whitespace is the only thing selected.
175            Position tmp = s;
176            s = e;
177            e = tmp;
178        }
179        s = s.parentAnchoredEquivalent();
180        e = e.parentAnchoredEquivalent();
181    }
182
183    if (!s.containerNode() || !e.containerNode())
184        return 0;
185
186    // VisibleSelections are supposed to always be valid.  This constructor will ASSERT
187    // if a valid range could not be created, which is fine for this callsite.
188    return Range::create(s.anchorNode()->document(), s, e);
189}
190
191bool VisibleSelection::expandUsingGranularity(TextGranularity granularity)
192{
193    if (isNone())
194        return false;
195
196    validate(granularity);
197    return true;
198}
199
200static PassRefPtr<Range> makeSearchRange(const Position& pos)
201{
202    Node* n = pos.deprecatedNode();
203    if (!n)
204        return 0;
205    Node* de = n->document().documentElement();
206    if (!de)
207        return 0;
208    Element* boundary = deprecatedEnclosingBlockFlowElement(n);
209    if (!boundary)
210        return 0;
211
212    RefPtr<Range> searchRange(Range::create(n->document()));
213    ExceptionCode ec = 0;
214
215    Position start(pos.parentAnchoredEquivalent());
216    searchRange->selectNodeContents(boundary, ec);
217    searchRange->setStart(start.containerNode(), start.offsetInContainerNode(), ec);
218
219    ASSERT(!ec);
220    if (ec)
221        return 0;
222
223    return searchRange.release();
224}
225
226bool VisibleSelection::isAll(EditingBoundaryCrossingRule rule) const
227{
228    return !nonBoundaryShadowTreeRootNode() && visibleStart().previous(rule).isNull() && visibleEnd().next(rule).isNull();
229}
230
231void VisibleSelection::appendTrailingWhitespace()
232{
233    RefPtr<Range> searchRange = makeSearchRange(m_end);
234    if (!searchRange)
235        return;
236
237    CharacterIterator charIt(*searchRange, TextIteratorEmitsCharactersBetweenAllVisiblePositions);
238
239    for (; !charIt.atEnd() && charIt.text().length(); charIt.advance(1)) {
240        UChar c = charIt.text()[0];
241        if ((!isSpaceOrNewline(c) && c != noBreakSpace) || c == '\n')
242            break;
243        m_end = charIt.range()->endPosition();
244    }
245}
246
247void VisibleSelection::setBaseAndExtentToDeepEquivalents()
248{
249    // Move the selection to rendered positions, if possible.
250    bool baseAndExtentEqual = m_base == m_extent;
251    if (m_base.isNotNull()) {
252        m_base = VisiblePosition(m_base, m_affinity).deepEquivalent();
253        if (baseAndExtentEqual)
254            m_extent = m_base;
255    }
256    if (m_extent.isNotNull() && !baseAndExtentEqual)
257        m_extent = VisiblePosition(m_extent, m_affinity).deepEquivalent();
258
259    // Make sure we do not have a dangling base or extent.
260    if (m_base.isNull() && m_extent.isNull())
261        m_baseIsFirst = true;
262    else if (m_base.isNull()) {
263        m_base = m_extent;
264        m_baseIsFirst = true;
265    } else if (m_extent.isNull()) {
266        m_extent = m_base;
267        m_baseIsFirst = true;
268    } else
269        m_baseIsFirst = comparePositions(m_base, m_extent) <= 0;
270}
271
272void VisibleSelection::setStartAndEndFromBaseAndExtentRespectingGranularity(TextGranularity granularity)
273{
274    if (m_baseIsFirst) {
275        m_start = m_base;
276        m_end = m_extent;
277    } else {
278        m_start = m_extent;
279        m_end = m_base;
280    }
281
282    switch (granularity) {
283        case CharacterGranularity:
284            // Don't do any expansion.
285            break;
286        case WordGranularity: {
287            // General case: Select the word the caret is positioned inside of, or at the start of (RightWordIfOnBoundary).
288            // Edge case: If the caret is after the last word in a soft-wrapped line or the last word in
289            // the document, select that last word (LeftWordIfOnBoundary).
290            // Edge case: If the caret is after the last word in a paragraph, select from the the end of the
291            // last word to the line break (also RightWordIfOnBoundary);
292            VisiblePosition start = VisiblePosition(m_start, m_affinity);
293            VisiblePosition originalEnd(m_end, m_affinity);
294            EWordSide side = RightWordIfOnBoundary;
295            if (isEndOfEditableOrNonEditableContent(start) || (isEndOfLine(start) && !isStartOfLine(start) && !isEndOfParagraph(start)))
296                side = LeftWordIfOnBoundary;
297            m_start = startOfWord(start, side).deepEquivalent();
298            side = RightWordIfOnBoundary;
299            if (isEndOfEditableOrNonEditableContent(originalEnd) || (isEndOfLine(originalEnd) && !isStartOfLine(originalEnd) && !isEndOfParagraph(originalEnd)))
300                side = LeftWordIfOnBoundary;
301
302            VisiblePosition wordEnd(endOfWord(originalEnd, side));
303            VisiblePosition end(wordEnd);
304
305            if (isEndOfParagraph(originalEnd) && !isEmptyTableCell(m_start.deprecatedNode())) {
306                // Select the paragraph break (the space from the end of a paragraph to the start of
307                // the next one) to match TextEdit.
308                end = wordEnd.next();
309
310                if (Node* table = isFirstPositionAfterTable(end)) {
311                    // The paragraph break after the last paragraph in the last cell of a block table ends
312                    // at the start of the paragraph after the table.
313                    if (isBlock(table))
314                        end = end.next(CannotCrossEditingBoundary);
315                    else
316                        end = wordEnd;
317                }
318
319                if (end.isNull())
320                    end = wordEnd;
321
322            }
323
324            m_end = end.deepEquivalent();
325#if PLATFORM(IOS)
326            // End must not be before start.
327            if (m_start.deprecatedNode() == m_end.deprecatedNode() && m_start.deprecatedEditingOffset() > m_end.deprecatedEditingOffset()) {
328                Position swap(m_start);
329                m_start = m_end;
330                m_end = swap;
331            }
332#endif
333            break;
334        }
335        case SentenceGranularity: {
336            m_start = startOfSentence(VisiblePosition(m_start, m_affinity)).deepEquivalent();
337            m_end = endOfSentence(VisiblePosition(m_end, m_affinity)).deepEquivalent();
338            break;
339        }
340        case LineGranularity: {
341            m_start = startOfLine(VisiblePosition(m_start, m_affinity)).deepEquivalent();
342            VisiblePosition end = endOfLine(VisiblePosition(m_end, m_affinity));
343            // If the end of this line is at the end of a paragraph, include the space
344            // after the end of the line in the selection.
345            if (isEndOfParagraph(end)) {
346                VisiblePosition next = end.next();
347                if (next.isNotNull())
348                    end = next;
349            }
350            m_end = end.deepEquivalent();
351            break;
352        }
353        case LineBoundary:
354            m_start = startOfLine(VisiblePosition(m_start, m_affinity)).deepEquivalent();
355            m_end = endOfLine(VisiblePosition(m_end, m_affinity)).deepEquivalent();
356            break;
357        case ParagraphGranularity: {
358            VisiblePosition pos(m_start, m_affinity);
359            if (isStartOfLine(pos) && isEndOfEditableOrNonEditableContent(pos))
360                pos = pos.previous();
361            m_start = startOfParagraph(pos).deepEquivalent();
362            VisiblePosition visibleParagraphEnd = endOfParagraph(VisiblePosition(m_end, m_affinity));
363
364            // Include the "paragraph break" (the space from the end of this paragraph to the start
365            // of the next one) in the selection.
366            VisiblePosition end(visibleParagraphEnd.next());
367
368            if (Node* table = isFirstPositionAfterTable(end)) {
369                // The paragraph break after the last paragraph in the last cell of a block table ends
370                // at the start of the paragraph after the table, not at the position just after the table.
371                if (isBlock(table))
372                    end = end.next(CannotCrossEditingBoundary);
373                // There is no parargraph break after the last paragraph in the last cell of an inline table.
374                else
375                    end = visibleParagraphEnd;
376            }
377
378            if (end.isNull())
379                end = visibleParagraphEnd;
380
381            m_end = end.deepEquivalent();
382            break;
383        }
384        case DocumentBoundary:
385            m_start = startOfDocument(VisiblePosition(m_start, m_affinity)).deepEquivalent();
386            m_end = endOfDocument(VisiblePosition(m_end, m_affinity)).deepEquivalent();
387            break;
388        case ParagraphBoundary:
389            m_start = startOfParagraph(VisiblePosition(m_start, m_affinity)).deepEquivalent();
390            m_end = endOfParagraph(VisiblePosition(m_end, m_affinity)).deepEquivalent();
391            break;
392        case SentenceBoundary:
393            m_start = startOfSentence(VisiblePosition(m_start, m_affinity)).deepEquivalent();
394            m_end = endOfSentence(VisiblePosition(m_end, m_affinity)).deepEquivalent();
395            break;
396#if PLATFORM(IOS)
397        case DocumentGranularity:
398            ASSERT_NOT_REACHED();
399            break;
400#endif
401    }
402
403    // Make sure we do not have a dangling start or end.
404    if (m_start.isNull())
405        m_start = m_end;
406    if (m_end.isNull())
407        m_end = m_start;
408}
409
410void VisibleSelection::updateSelectionType()
411{
412    if (m_start.isNull()) {
413        ASSERT(m_end.isNull());
414        m_selectionType = NoSelection;
415    } else if (m_start == m_end || m_start.upstream() == m_end.upstream()) {
416        m_selectionType = CaretSelection;
417    } else
418        m_selectionType = RangeSelection;
419
420    // Affinity only makes sense for a caret
421    if (m_selectionType != CaretSelection)
422        m_affinity = DOWNSTREAM;
423}
424
425void VisibleSelection::validate(TextGranularity granularity)
426{
427    setBaseAndExtentToDeepEquivalents();
428    setStartAndEndFromBaseAndExtentRespectingGranularity(granularity);
429    adjustSelectionToAvoidCrossingShadowBoundaries();
430    adjustSelectionToAvoidCrossingEditingBoundaries();
431    updateSelectionType();
432
433    if (selectionType() == RangeSelection) {
434        // "Constrain" the selection to be the smallest equivalent range of nodes.
435        // This is a somewhat arbitrary choice, but experience shows that it is
436        // useful to make to make the selection "canonical" (if only for
437        // purposes of comparing selections). This is an ideal point of the code
438        // to do this operation, since all selection changes that result in a RANGE
439        // come through here before anyone uses it.
440        // FIXME: Canonicalizing is good, but haven't we already done it (when we
441        // set these two positions to VisiblePosition deepEquivalent()s above)?
442        m_start = m_start.downstream();
443        m_end = m_end.upstream();
444
445        // FIXME: Position::downstream() or Position::upStream() might violate editing boundaries
446        // if an anchor node has a Shadow DOM. So we adjust selection to avoid crossing editing
447        // boundaries again. See https://bugs.webkit.org/show_bug.cgi?id=87463
448        adjustSelectionToAvoidCrossingEditingBoundaries();
449    }
450}
451
452// FIXME: This function breaks the invariant of this class.
453// But because we use VisibleSelection to store values in editing commands for use when
454// undoing the command, we need to be able to create a selection that while currently
455// invalid, will be valid once the changes are undone. This is a design problem.
456// To fix it we either need to change the invariants of VisibleSelection or create a new
457// class for editing to use that can manipulate selections that are not currently valid.
458void VisibleSelection::setWithoutValidation(const Position& base, const Position& extent)
459{
460    ASSERT(!base.isNull());
461    ASSERT(!extent.isNull());
462    ASSERT(m_affinity == DOWNSTREAM);
463    m_base = base;
464    m_extent = extent;
465    m_baseIsFirst = comparePositions(base, extent) <= 0;
466    if (m_baseIsFirst) {
467        m_start = base;
468        m_end = extent;
469    } else {
470        m_start = extent;
471        m_end = base;
472    }
473    m_selectionType = base == extent ? CaretSelection : RangeSelection;
474}
475
476static Position adjustPositionForEnd(const Position& currentPosition, Node* startContainerNode)
477{
478    TreeScope& treeScope = startContainerNode->treeScope();
479
480    ASSERT(&currentPosition.containerNode()->treeScope() != &treeScope);
481
482    if (Node* ancestor = treeScope.ancestorInThisScope(currentPosition.containerNode())) {
483        if (ancestor->contains(startContainerNode))
484            return positionAfterNode(ancestor);
485        return positionBeforeNode(ancestor);
486    }
487
488    if (Node* lastChild = treeScope.rootNode().lastChild())
489        return positionAfterNode(lastChild);
490
491    return Position();
492}
493
494static Position adjustPositionForStart(const Position& currentPosition, Node* endContainerNode)
495{
496    TreeScope& treeScope = endContainerNode->treeScope();
497
498    ASSERT(&currentPosition.containerNode()->treeScope() != &treeScope);
499
500    if (Node* ancestor = treeScope.ancestorInThisScope(currentPosition.containerNode())) {
501        if (ancestor->contains(endContainerNode))
502            return positionBeforeNode(ancestor);
503        return positionAfterNode(ancestor);
504    }
505
506    if (Node* firstChild = treeScope.rootNode().firstChild())
507        return positionBeforeNode(firstChild);
508
509    return Position();
510}
511
512void VisibleSelection::adjustSelectionToAvoidCrossingShadowBoundaries()
513{
514    if (m_base.isNull() || m_start.isNull() || m_end.isNull())
515        return;
516
517    if (&m_start.anchorNode()->treeScope() == &m_end.anchorNode()->treeScope())
518        return;
519
520    if (m_baseIsFirst) {
521        m_extent = adjustPositionForEnd(m_end, m_start.containerNode());
522        m_end = m_extent;
523    } else {
524        m_extent = adjustPositionForStart(m_start, m_end.containerNode());
525        m_start = m_extent;
526    }
527
528    ASSERT(&m_start.anchorNode()->treeScope() == &m_end.anchorNode()->treeScope());
529}
530
531void VisibleSelection::adjustSelectionToAvoidCrossingEditingBoundaries()
532{
533    if (m_base.isNull() || m_start.isNull() || m_end.isNull())
534        return;
535
536#if PLATFORM(IOS)
537    // Early return in the caret case (the state hasn't actually been set yet, so we can't use isCaret()) to avoid the
538    // expense of computing highestEditableRoot.
539    if (m_base == m_start && m_base == m_end)
540        return;
541#endif
542
543    Node* baseRoot = highestEditableRoot(m_base);
544    Node* startRoot = highestEditableRoot(m_start);
545    Node* endRoot = highestEditableRoot(m_end);
546
547    Node* baseEditableAncestor = lowestEditableAncestor(m_base.containerNode());
548
549    // The base, start and end are all in the same region.  No adjustment necessary.
550    if (baseRoot == startRoot && baseRoot == endRoot)
551        return;
552
553    // The selection is based in editable content.
554    if (baseRoot) {
555        // If the start is outside the base's editable root, cap it at the start of that root.
556        // If the start is in non-editable content that is inside the base's editable root, put it
557        // at the first editable position after start inside the base's editable root.
558        if (startRoot != baseRoot) {
559            VisiblePosition first = firstEditablePositionAfterPositionInRoot(m_start, baseRoot);
560            m_start = first.deepEquivalent();
561            if (m_start.isNull()) {
562                ASSERT_NOT_REACHED();
563                m_start = m_end;
564            }
565        }
566        // If the end is outside the base's editable root, cap it at the end of that root.
567        // If the end is in non-editable content that is inside the base's root, put it
568        // at the last editable position before the end inside the base's root.
569        if (endRoot != baseRoot) {
570            VisiblePosition last = lastEditablePositionBeforePositionInRoot(m_end, baseRoot);
571            m_end = last.deepEquivalent();
572            if (m_end.isNull())
573                m_end = m_start;
574        }
575    // The selection is based in non-editable content.
576    } else {
577        // FIXME: Non-editable pieces inside editable content should be atomic, in the same way that editable
578        // pieces in non-editable content are atomic.
579
580        // The selection ends in editable content or non-editable content inside a different editable ancestor,
581        // move backward until non-editable content inside the same lowest editable ancestor is reached.
582        Node* endEditableAncestor = lowestEditableAncestor(m_end.containerNode());
583        if (endRoot || endEditableAncestor != baseEditableAncestor) {
584
585            Position p = previousVisuallyDistinctCandidate(m_end);
586            Node* shadowAncestor = endRoot ? endRoot->shadowHost() : 0;
587            if (p.isNull() && shadowAncestor)
588                p = positionAfterNode(shadowAncestor);
589            while (p.isNotNull() && !(lowestEditableAncestor(p.containerNode()) == baseEditableAncestor && !isEditablePosition(p))) {
590                Node* root = editableRootForPosition(p);
591                shadowAncestor = root ? root->shadowHost() : 0;
592                p = isAtomicNode(p.containerNode()) ? positionInParentBeforeNode(p.containerNode()) : previousVisuallyDistinctCandidate(p);
593                if (p.isNull() && shadowAncestor)
594                    p = positionAfterNode(shadowAncestor);
595            }
596            VisiblePosition previous(p);
597
598            if (previous.isNull()) {
599                // The selection crosses an Editing boundary.  This is a
600                // programmer error in the editing code.  Happy debugging!
601                ASSERT_NOT_REACHED();
602                m_base = Position();
603                m_extent = Position();
604                validate();
605                return;
606            }
607            m_end = previous.deepEquivalent();
608        }
609
610        // The selection starts in editable content or non-editable content inside a different editable ancestor,
611        // move forward until non-editable content inside the same lowest editable ancestor is reached.
612        Node* startEditableAncestor = lowestEditableAncestor(m_start.containerNode());
613        if (startRoot || startEditableAncestor != baseEditableAncestor) {
614            Position p = nextVisuallyDistinctCandidate(m_start);
615            Node* shadowAncestor = startRoot ? startRoot->shadowHost() : 0;
616            if (p.isNull() && shadowAncestor)
617                p = positionBeforeNode(shadowAncestor);
618            while (p.isNotNull() && !(lowestEditableAncestor(p.containerNode()) == baseEditableAncestor && !isEditablePosition(p))) {
619                Node* root = editableRootForPosition(p);
620                shadowAncestor = root ? root->shadowHost() : 0;
621                p = isAtomicNode(p.containerNode()) ? positionInParentAfterNode(p.containerNode()) : nextVisuallyDistinctCandidate(p);
622                if (p.isNull() && shadowAncestor)
623                    p = positionBeforeNode(shadowAncestor);
624            }
625            VisiblePosition next(p);
626
627            if (next.isNull()) {
628                // The selection crosses an Editing boundary.  This is a
629                // programmer error in the editing code.  Happy debugging!
630                ASSERT_NOT_REACHED();
631                m_base = Position();
632                m_extent = Position();
633                validate();
634                return;
635            }
636            m_start = next.deepEquivalent();
637        }
638    }
639
640    // Correct the extent if necessary.
641    if (baseEditableAncestor != lowestEditableAncestor(m_extent.containerNode()))
642        m_extent = m_baseIsFirst ? m_end : m_start;
643}
644
645bool VisibleSelection::isContentEditable() const
646{
647    return isEditablePosition(start());
648}
649
650bool VisibleSelection::hasEditableStyle() const
651{
652    return isEditablePosition(start(), ContentIsEditable, DoNotUpdateStyle);
653}
654
655bool VisibleSelection::isContentRichlyEditable() const
656{
657    return isRichlyEditablePosition(start());
658}
659
660Element* VisibleSelection::rootEditableElement() const
661{
662    return editableRootForPosition(start());
663}
664
665Node* VisibleSelection::nonBoundaryShadowTreeRootNode() const
666{
667    return start().deprecatedNode() ? start().deprecatedNode()->nonBoundaryShadowTreeRootNode() : 0;
668}
669
670bool VisibleSelection::isInPasswordField() const
671{
672    HTMLTextFormControlElement* textControl = enclosingTextFormControl(start());
673    return textControl && isHTMLInputElement(textControl) && toHTMLInputElement(textControl)->isPasswordField();
674}
675
676#ifndef NDEBUG
677
678void VisibleSelection::debugPosition() const
679{
680    fprintf(stderr, "VisibleSelection ===============\n");
681
682    if (!m_start.anchorNode())
683        fputs("pos:   null", stderr);
684    else if (m_start == m_end) {
685        fprintf(stderr, "pos:   %s ", m_start.anchorNode()->nodeName().utf8().data());
686        m_start.showAnchorTypeAndOffset();
687    } else {
688        fprintf(stderr, "start: %s ", m_start.anchorNode()->nodeName().utf8().data());
689        m_start.showAnchorTypeAndOffset();
690        fprintf(stderr, "end:   %s ", m_end.anchorNode()->nodeName().utf8().data());
691        m_end.showAnchorTypeAndOffset();
692    }
693
694    fprintf(stderr, "================================\n");
695}
696
697void VisibleSelection::formatForDebugger(char* buffer, unsigned length) const
698{
699    StringBuilder result;
700    String s;
701
702    if (isNone()) {
703        result.appendLiteral("<none>");
704    } else {
705        const int FormatBufferSize = 1024;
706        char s[FormatBufferSize];
707        result.appendLiteral("from ");
708        start().formatForDebugger(s, FormatBufferSize);
709        result.append(s);
710        result.appendLiteral(" to ");
711        end().formatForDebugger(s, FormatBufferSize);
712        result.append(s);
713    }
714
715    strncpy(buffer, result.toString().utf8().data(), length - 1);
716}
717
718void VisibleSelection::showTreeForThis() const
719{
720    if (start().anchorNode()) {
721        start().anchorNode()->showTreeAndMark(start().anchorNode(), "S", end().anchorNode(), "E");
722        fputs("start: ", stderr);
723        start().showAnchorTypeAndOffset();
724        fputs("end: ", stderr);
725        end().showAnchorTypeAndOffset();
726    }
727}
728
729#endif
730
731} // namespace WebCore
732
733#ifndef NDEBUG
734
735void showTree(const WebCore::VisibleSelection& sel)
736{
737    sel.showTreeForThis();
738}
739
740void showTree(const WebCore::VisibleSelection* sel)
741{
742    if (sel)
743        sel->showTreeForThis();
744}
745
746#endif
747