1/*
2 * Copyright (C) 2004, 2005, 2006 Apple Computer, 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/editing/VisibleSelection.h"
28
29#include "bindings/core/v8/ExceptionState.h"
30#include "core/dom/Document.h"
31#include "core/dom/Element.h"
32#include "core/dom/Range.h"
33#include "core/editing/TextIterator.h"
34#include "core/editing/VisibleUnits.h"
35#include "core/editing/htmlediting.h"
36#include "core/rendering/RenderObject.h"
37#include "platform/geometry/LayoutPoint.h"
38#include "wtf/Assertions.h"
39#include "wtf/text/CString.h"
40#include "wtf/text/StringBuilder.h"
41#include "wtf/unicode/CharacterNames.h"
42
43#ifndef NDEBUG
44#include <stdio.h>
45#endif
46
47namespace blink {
48
49VisibleSelection::VisibleSelection()
50    : m_affinity(DOWNSTREAM)
51    , m_changeObserver(nullptr)
52    , m_selectionType(NoSelection)
53    , m_baseIsFirst(true)
54    , m_isDirectional(false)
55{
56}
57
58VisibleSelection::VisibleSelection(const Position& pos, EAffinity affinity, bool isDirectional)
59    : m_base(pos)
60    , m_extent(pos)
61    , m_affinity(affinity)
62    , m_changeObserver(nullptr)
63    , m_isDirectional(isDirectional)
64{
65    validate();
66}
67
68VisibleSelection::VisibleSelection(const Position& base, const Position& extent, EAffinity affinity, bool isDirectional)
69    : m_base(base)
70    , m_extent(extent)
71    , m_affinity(affinity)
72    , m_changeObserver(nullptr)
73    , m_isDirectional(isDirectional)
74{
75    validate();
76}
77
78VisibleSelection::VisibleSelection(const VisiblePosition& pos, bool isDirectional)
79    : m_base(pos.deepEquivalent())
80    , m_extent(pos.deepEquivalent())
81    , m_affinity(pos.affinity())
82    , m_changeObserver(nullptr)
83    , m_isDirectional(isDirectional)
84{
85    validate();
86}
87
88VisibleSelection::VisibleSelection(const VisiblePosition& base, const VisiblePosition& extent, bool isDirectional)
89    : m_base(base.deepEquivalent())
90    , m_extent(extent.deepEquivalent())
91    , m_affinity(base.affinity())
92    , m_changeObserver(nullptr)
93    , m_isDirectional(isDirectional)
94{
95    validate();
96}
97
98VisibleSelection::VisibleSelection(const Range* range, EAffinity affinity, bool isDirectional)
99    : m_base(range->startPosition())
100    , m_extent(range->endPosition())
101    , m_affinity(affinity)
102    , m_changeObserver(nullptr)
103    , m_isDirectional(isDirectional)
104{
105    validate();
106}
107
108VisibleSelection::VisibleSelection(const VisibleSelection& other)
109    : m_base(other.m_base)
110    , m_extent(other.m_extent)
111    , m_start(other.m_start)
112    , m_end(other.m_end)
113    , m_affinity(other.m_affinity)
114    , m_changeObserver(nullptr) // Observer is associated with only one VisibleSelection, so this should not be copied.
115    , m_selectionType(other.m_selectionType)
116    , m_baseIsFirst(other.m_baseIsFirst)
117    , m_isDirectional(other.m_isDirectional)
118{
119}
120
121VisibleSelection& VisibleSelection::operator=(const VisibleSelection& other)
122{
123    didChange();
124
125    m_base = other.m_base;
126    m_extent = other.m_extent;
127    m_start = other.m_start;
128    m_end = other.m_end;
129    m_affinity = other.m_affinity;
130    m_changeObserver = nullptr;
131    m_selectionType = other.m_selectionType;
132    m_baseIsFirst = other.m_baseIsFirst;
133    m_isDirectional = other.m_isDirectional;
134    return *this;
135}
136
137VisibleSelection::~VisibleSelection()
138{
139#if !ENABLE(OILPAN)
140    didChange();
141#endif
142}
143
144VisibleSelection VisibleSelection::selectionFromContentsOfNode(Node* node)
145{
146    ASSERT(!editingIgnoresContent(node));
147    return VisibleSelection(firstPositionInNode(node), lastPositionInNode(node), DOWNSTREAM);
148}
149
150void VisibleSelection::setBase(const Position& position)
151{
152    Position oldBase = m_base;
153    m_base = position;
154    validate();
155    if (m_base != oldBase)
156        didChange();
157}
158
159void VisibleSelection::setBase(const VisiblePosition& visiblePosition)
160{
161    Position oldBase = m_base;
162    m_base = visiblePosition.deepEquivalent();
163    validate();
164    if (m_base != oldBase)
165        didChange();
166}
167
168void VisibleSelection::setExtent(const Position& position)
169{
170    Position oldExtent = m_extent;
171    m_extent = position;
172    validate();
173    if (m_extent != oldExtent)
174        didChange();
175}
176
177void VisibleSelection::setExtent(const VisiblePosition& visiblePosition)
178{
179    Position oldExtent = m_extent;
180    m_extent = visiblePosition.deepEquivalent();
181    validate();
182    if (m_extent != oldExtent)
183        didChange();
184}
185
186PassRefPtrWillBeRawPtr<Range> VisibleSelection::firstRange() const
187{
188    if (isNone())
189        return nullptr;
190    Position start = m_start.parentAnchoredEquivalent();
191    Position end = m_end.parentAnchoredEquivalent();
192    return Range::create(*start.document(), start, end);
193}
194
195bool VisibleSelection::intersectsNode(Node* node) const
196{
197    if (isNone())
198        return false;
199    Position start = m_start.parentAnchoredEquivalent();
200    Position end = m_end.parentAnchoredEquivalent();
201    TrackExceptionState exceptionState;
202    return Range::intersectsNode(node, start, end, exceptionState) && !exceptionState.hadException();
203}
204
205PassRefPtrWillBeRawPtr<Range> VisibleSelection::toNormalizedRange() const
206{
207    Position start, end;
208    if (toNormalizedPositions(start, end))
209        return Range::create(*start.document(), start, end);
210    return nullptr;
211}
212
213bool VisibleSelection::toNormalizedPositions(Position& start, Position& end) const
214{
215    if (isNone())
216        return false;
217
218    // Make sure we have an updated layout since this function is called
219    // in the course of running edit commands which modify the DOM.
220    // Failing to call this can result in equivalentXXXPosition calls returning
221    // incorrect results.
222    m_start.document()->updateLayout();
223
224    // Check again, because updating layout can clear the selection.
225    if (isNone())
226        return false;
227
228    if (isCaret()) {
229        // If the selection is a caret, move the range start upstream. This helps us match
230        // the conventions of text editors tested, which make style determinations based
231        // on the character before the caret, if any.
232        start = m_start.upstream().parentAnchoredEquivalent();
233        end = start;
234    } else {
235        // If the selection is a range, select the minimum range that encompasses the selection.
236        // Again, this is to match the conventions of text editors tested, which make style
237        // determinations based on the first character of the selection.
238        // For instance, this operation helps to make sure that the "X" selected below is the
239        // only thing selected. The range should not be allowed to "leak" out to the end of the
240        // previous text node, or to the beginning of the next text node, each of which has a
241        // different style.
242        //
243        // On a treasure map, <b>X</b> marks the spot.
244        //                       ^ selected
245        //
246        ASSERT(isRange());
247        start = m_start.downstream();
248        end = m_end.upstream();
249        if (comparePositions(start, end) > 0) {
250            // Make sure the start is before the end.
251            // The end can wind up before the start if collapsed whitespace is the only thing selected.
252            Position tmp = start;
253            start = end;
254            end = tmp;
255        }
256        start = start.parentAnchoredEquivalent();
257        end = end.parentAnchoredEquivalent();
258    }
259
260    if (!start.containerNode() || !end.containerNode())
261        return false;
262
263    return true;
264}
265
266bool VisibleSelection::expandUsingGranularity(TextGranularity granularity)
267{
268    if (isNone())
269        return false;
270
271    // FIXME: Do we need to check all of them?
272    Position oldBase = m_base;
273    Position oldExtent = m_extent;
274    Position oldStart = m_start;
275    Position oldEnd = m_end;
276    validate(granularity);
277    if (m_base != oldBase || m_extent != oldExtent || m_start != oldStart || m_end != oldEnd)
278        didChange();
279    return true;
280}
281
282static PassRefPtrWillBeRawPtr<Range> makeSearchRange(const Position& pos)
283{
284    Node* node = pos.deprecatedNode();
285    if (!node)
286        return nullptr;
287    Document& document = node->document();
288    if (!document.documentElement())
289        return nullptr;
290    Element* boundary = enclosingBlockFlowElement(*node);
291    if (!boundary)
292        return nullptr;
293
294    RefPtrWillBeRawPtr<Range> searchRange(Range::create(document));
295    TrackExceptionState exceptionState;
296
297    Position start(pos.parentAnchoredEquivalent());
298    searchRange->selectNodeContents(boundary, exceptionState);
299    searchRange->setStart(start.containerNode(), start.offsetInContainerNode(), exceptionState);
300
301    ASSERT(!exceptionState.hadException());
302    if (exceptionState.hadException())
303        return nullptr;
304
305    return searchRange.release();
306}
307
308void VisibleSelection::appendTrailingWhitespace()
309{
310    RefPtrWillBeRawPtr<Range> searchRange = makeSearchRange(m_end);
311    if (!searchRange)
312        return;
313
314    CharacterIterator charIt(searchRange.get(), TextIteratorEmitsCharactersBetweenAllVisiblePositions);
315    bool changed = false;
316
317    for (; charIt.length(); charIt.advance(1)) {
318        UChar c = charIt.characterAt(0);
319        if ((!isSpaceOrNewline(c) && c != noBreakSpace) || c == '\n')
320            break;
321        m_end = charIt.endPosition();
322        changed = true;
323    }
324    if (changed)
325        didChange();
326}
327
328void VisibleSelection::setBaseAndExtentToDeepEquivalents()
329{
330    // Move the selection to rendered positions, if possible.
331    bool baseAndExtentEqual = m_base == m_extent;
332    if (m_base.isNotNull()) {
333        m_base = VisiblePosition(m_base, m_affinity).deepEquivalent();
334        if (baseAndExtentEqual)
335            m_extent = m_base;
336    }
337    if (m_extent.isNotNull() && !baseAndExtentEqual)
338        m_extent = VisiblePosition(m_extent, m_affinity).deepEquivalent();
339
340    // Make sure we do not have a dangling base or extent.
341    if (m_base.isNull() && m_extent.isNull())
342        m_baseIsFirst = true;
343    else if (m_base.isNull()) {
344        m_base = m_extent;
345        m_baseIsFirst = true;
346    } else if (m_extent.isNull()) {
347        m_extent = m_base;
348        m_baseIsFirst = true;
349    } else
350        m_baseIsFirst = comparePositions(m_base, m_extent) <= 0;
351}
352
353void VisibleSelection::setStartAndEndFromBaseAndExtentRespectingGranularity(TextGranularity granularity)
354{
355    if (m_baseIsFirst) {
356        m_start = m_base;
357        m_end = m_extent;
358    } else {
359        m_start = m_extent;
360        m_end = m_base;
361    }
362
363    switch (granularity) {
364        case CharacterGranularity:
365            // Don't do any expansion.
366            break;
367        case WordGranularity: {
368            // General case: Select the word the caret is positioned inside of, or at the start of (RightWordIfOnBoundary).
369            // Edge case: If the caret is after the last word in a soft-wrapped line or the last word in
370            // the document, select that last word (LeftWordIfOnBoundary).
371            // Edge case: If the caret is after the last word in a paragraph, select from the the end of the
372            // last word to the line break (also RightWordIfOnBoundary);
373            VisiblePosition start = VisiblePosition(m_start, m_affinity);
374            VisiblePosition originalEnd(m_end, m_affinity);
375            EWordSide side = RightWordIfOnBoundary;
376            if (isEndOfEditableOrNonEditableContent(start) || (isEndOfLine(start) && !isStartOfLine(start) && !isEndOfParagraph(start)))
377                side = LeftWordIfOnBoundary;
378            m_start = startOfWord(start, side).deepEquivalent();
379            side = RightWordIfOnBoundary;
380            if (isEndOfEditableOrNonEditableContent(originalEnd) || (isEndOfLine(originalEnd) && !isStartOfLine(originalEnd) && !isEndOfParagraph(originalEnd)))
381                side = LeftWordIfOnBoundary;
382
383            VisiblePosition wordEnd(endOfWord(originalEnd, side));
384            VisiblePosition end(wordEnd);
385
386            if (isEndOfParagraph(originalEnd) && !isEmptyTableCell(m_start.deprecatedNode())) {
387                // Select the paragraph break (the space from the end of a paragraph to the start of
388                // the next one) to match TextEdit.
389                end = wordEnd.next();
390
391                if (Element* table = isFirstPositionAfterTable(end)) {
392                    // The paragraph break after the last paragraph in the last cell of a block table ends
393                    // at the start of the paragraph after the table.
394                    if (isBlock(table))
395                        end = end.next(CannotCrossEditingBoundary);
396                    else
397                        end = wordEnd;
398                }
399
400                if (end.isNull())
401                    end = wordEnd;
402
403            }
404
405            m_end = end.deepEquivalent();
406            break;
407        }
408        case SentenceGranularity: {
409            m_start = startOfSentence(VisiblePosition(m_start, m_affinity)).deepEquivalent();
410            m_end = endOfSentence(VisiblePosition(m_end, m_affinity)).deepEquivalent();
411            break;
412        }
413        case LineGranularity: {
414            m_start = startOfLine(VisiblePosition(m_start, m_affinity)).deepEquivalent();
415            VisiblePosition end = endOfLine(VisiblePosition(m_end, m_affinity));
416            // If the end of this line is at the end of a paragraph, include the space
417            // after the end of the line in the selection.
418            if (isEndOfParagraph(end)) {
419                VisiblePosition next = end.next();
420                if (next.isNotNull())
421                    end = next;
422            }
423            m_end = end.deepEquivalent();
424            break;
425        }
426        case LineBoundary:
427            m_start = startOfLine(VisiblePosition(m_start, m_affinity)).deepEquivalent();
428            m_end = endOfLine(VisiblePosition(m_end, m_affinity)).deepEquivalent();
429            break;
430        case ParagraphGranularity: {
431            VisiblePosition pos(m_start, m_affinity);
432            if (isStartOfLine(pos) && isEndOfEditableOrNonEditableContent(pos))
433                pos = pos.previous();
434            m_start = startOfParagraph(pos).deepEquivalent();
435            VisiblePosition visibleParagraphEnd = endOfParagraph(VisiblePosition(m_end, m_affinity));
436
437            // Include the "paragraph break" (the space from the end of this paragraph to the start
438            // of the next one) in the selection.
439            VisiblePosition end(visibleParagraphEnd.next());
440
441            if (Element* table = isFirstPositionAfterTable(end)) {
442                // The paragraph break after the last paragraph in the last cell of a block table ends
443                // at the start of the paragraph after the table, not at the position just after the table.
444                if (isBlock(table))
445                    end = end.next(CannotCrossEditingBoundary);
446                // There is no parargraph break after the last paragraph in the last cell of an inline table.
447                else
448                    end = visibleParagraphEnd;
449            }
450
451            if (end.isNull())
452                end = visibleParagraphEnd;
453
454            m_end = end.deepEquivalent();
455            break;
456        }
457        case DocumentBoundary:
458            m_start = startOfDocument(VisiblePosition(m_start, m_affinity)).deepEquivalent();
459            m_end = endOfDocument(VisiblePosition(m_end, m_affinity)).deepEquivalent();
460            break;
461        case ParagraphBoundary:
462            m_start = startOfParagraph(VisiblePosition(m_start, m_affinity)).deepEquivalent();
463            m_end = endOfParagraph(VisiblePosition(m_end, m_affinity)).deepEquivalent();
464            break;
465        case SentenceBoundary:
466            m_start = startOfSentence(VisiblePosition(m_start, m_affinity)).deepEquivalent();
467            m_end = endOfSentence(VisiblePosition(m_end, m_affinity)).deepEquivalent();
468            break;
469    }
470
471    // Make sure we do not have a dangling start or end.
472    if (m_start.isNull())
473        m_start = m_end;
474    if (m_end.isNull())
475        m_end = m_start;
476}
477
478void VisibleSelection::updateSelectionType()
479{
480    if (m_start.isNull()) {
481        ASSERT(m_end.isNull());
482        m_selectionType = NoSelection;
483    } else if (m_start == m_end || m_start.upstream() == m_end.upstream()) {
484        m_selectionType = CaretSelection;
485    } else
486        m_selectionType = RangeSelection;
487
488    // Affinity only makes sense for a caret
489    if (m_selectionType != CaretSelection)
490        m_affinity = DOWNSTREAM;
491}
492
493void VisibleSelection::validate(TextGranularity granularity)
494{
495    setBaseAndExtentToDeepEquivalents();
496    setStartAndEndFromBaseAndExtentRespectingGranularity(granularity);
497    adjustSelectionToAvoidCrossingShadowBoundaries();
498    adjustSelectionToAvoidCrossingEditingBoundaries();
499    updateSelectionType();
500
501    if (selectionType() == RangeSelection) {
502        // "Constrain" the selection to be the smallest equivalent range of nodes.
503        // This is a somewhat arbitrary choice, but experience shows that it is
504        // useful to make to make the selection "canonical" (if only for
505        // purposes of comparing selections). This is an ideal point of the code
506        // to do this operation, since all selection changes that result in a RANGE
507        // come through here before anyone uses it.
508        // FIXME: Canonicalizing is good, but haven't we already done it (when we
509        // set these two positions to VisiblePosition deepEquivalent()s above)?
510        m_start = m_start.downstream();
511        m_end = m_end.upstream();
512
513        // FIXME: Position::downstream() or Position::upStream() might violate editing boundaries
514        // if an anchor node has a Shadow DOM. So we adjust selection to avoid crossing editing
515        // boundaries again. See https://bugs.webkit.org/show_bug.cgi?id=87463
516        adjustSelectionToAvoidCrossingEditingBoundaries();
517    }
518}
519
520// FIXME: This function breaks the invariant of this class.
521// But because we use VisibleSelection to store values in editing commands for use when
522// undoing the command, we need to be able to create a selection that while currently
523// invalid, will be valid once the changes are undone. This is a design problem.
524// To fix it we either need to change the invariants of VisibleSelection or create a new
525// class for editing to use that can manipulate selections that are not currently valid.
526void VisibleSelection::setWithoutValidation(const Position& base, const Position& extent)
527{
528    ASSERT(!base.isNull());
529    ASSERT(!extent.isNull());
530    ASSERT(m_affinity == DOWNSTREAM);
531    m_base = base;
532    m_extent = extent;
533    m_baseIsFirst = comparePositions(base, extent) <= 0;
534    if (m_baseIsFirst) {
535        m_start = base;
536        m_end = extent;
537    } else {
538        m_start = extent;
539        m_end = base;
540    }
541    m_selectionType = base == extent ? CaretSelection : RangeSelection;
542    didChange();
543}
544
545static Position adjustPositionForEnd(const Position& currentPosition, Node* startContainerNode)
546{
547    TreeScope& treeScope = startContainerNode->treeScope();
548
549    ASSERT(currentPosition.containerNode()->treeScope() != treeScope);
550
551    if (Node* ancestor = treeScope.ancestorInThisScope(currentPosition.containerNode())) {
552        if (ancestor->contains(startContainerNode))
553            return positionAfterNode(ancestor);
554        return positionBeforeNode(ancestor);
555    }
556
557    if (Node* lastChild = treeScope.rootNode().lastChild())
558        return positionAfterNode(lastChild);
559
560    return Position();
561}
562
563static Position adjustPositionForStart(const Position& currentPosition, Node* endContainerNode)
564{
565    TreeScope& treeScope = endContainerNode->treeScope();
566
567    ASSERT(currentPosition.containerNode()->treeScope() != treeScope);
568
569    if (Node* ancestor = treeScope.ancestorInThisScope(currentPosition.containerNode())) {
570        if (ancestor->contains(endContainerNode))
571            return positionBeforeNode(ancestor);
572        return positionAfterNode(ancestor);
573    }
574
575    if (Node* firstChild = treeScope.rootNode().firstChild())
576        return positionBeforeNode(firstChild);
577
578    return Position();
579}
580
581void VisibleSelection::adjustSelectionToAvoidCrossingShadowBoundaries()
582{
583    if (m_base.isNull() || m_start.isNull() || m_end.isNull())
584        return;
585
586    if (m_start.anchorNode()->treeScope() == m_end.anchorNode()->treeScope())
587        return;
588
589    if (m_baseIsFirst) {
590        m_extent = adjustPositionForEnd(m_end, m_start.containerNode());
591        m_end = m_extent;
592    } else {
593        m_extent = adjustPositionForStart(m_start, m_end.containerNode());
594        m_start = m_extent;
595    }
596
597    ASSERT(m_start.anchorNode()->treeScope() == m_end.anchorNode()->treeScope());
598}
599
600void VisibleSelection::adjustSelectionToAvoidCrossingEditingBoundaries()
601{
602    if (m_base.isNull() || m_start.isNull() || m_end.isNull())
603        return;
604
605    ContainerNode* baseRoot = highestEditableRoot(m_base);
606    ContainerNode* startRoot = highestEditableRoot(m_start);
607    ContainerNode* endRoot = highestEditableRoot(m_end);
608
609    Element* baseEditableAncestor = lowestEditableAncestor(m_base.containerNode());
610
611    // The base, start and end are all in the same region.  No adjustment necessary.
612    if (baseRoot == startRoot && baseRoot == endRoot)
613        return;
614
615    // The selection is based in editable content.
616    if (baseRoot) {
617        // If the start is outside the base's editable root, cap it at the start of that root.
618        // If the start is in non-editable content that is inside the base's editable root, put it
619        // at the first editable position after start inside the base's editable root.
620        if (startRoot != baseRoot) {
621            VisiblePosition first = firstEditableVisiblePositionAfterPositionInRoot(m_start, baseRoot);
622            m_start = first.deepEquivalent();
623            if (m_start.isNull()) {
624                ASSERT_NOT_REACHED();
625                m_start = m_end;
626            }
627        }
628        // If the end is outside the base's editable root, cap it at the end of that root.
629        // If the end is in non-editable content that is inside the base's root, put it
630        // at the last editable position before the end inside the base's root.
631        if (endRoot != baseRoot) {
632            VisiblePosition last = lastEditableVisiblePositionBeforePositionInRoot(m_end, baseRoot);
633            m_end = last.deepEquivalent();
634            if (m_end.isNull())
635                m_end = m_start;
636        }
637    // The selection is based in non-editable content.
638    } else {
639        // FIXME: Non-editable pieces inside editable content should be atomic, in the same way that editable
640        // pieces in non-editable content are atomic.
641
642        // The selection ends in editable content or non-editable content inside a different editable ancestor,
643        // move backward until non-editable content inside the same lowest editable ancestor is reached.
644        Element* endEditableAncestor = lowestEditableAncestor(m_end.containerNode());
645        if (endRoot || endEditableAncestor != baseEditableAncestor) {
646
647            Position p = previousVisuallyDistinctCandidate(m_end);
648            Element* shadowAncestor = endRoot ? endRoot->shadowHost() : 0;
649            if (p.isNull() && shadowAncestor)
650                p = positionAfterNode(shadowAncestor);
651            while (p.isNotNull() && !(lowestEditableAncestor(p.containerNode()) == baseEditableAncestor && !isEditablePosition(p))) {
652                Element* root = editableRootForPosition(p);
653                shadowAncestor = root ? root->shadowHost() : 0;
654                p = isAtomicNode(p.containerNode()) ? positionInParentBeforeNode(*p.containerNode()) : previousVisuallyDistinctCandidate(p);
655                if (p.isNull() && shadowAncestor)
656                    p = positionAfterNode(shadowAncestor);
657            }
658            VisiblePosition previous(p);
659
660            if (previous.isNull()) {
661                // The selection crosses an Editing boundary.  This is a
662                // programmer error in the editing code.  Happy debugging!
663                ASSERT_NOT_REACHED();
664                m_base = Position();
665                m_extent = Position();
666                validate();
667                return;
668            }
669            m_end = previous.deepEquivalent();
670        }
671
672        // The selection starts in editable content or non-editable content inside a different editable ancestor,
673        // move forward until non-editable content inside the same lowest editable ancestor is reached.
674        Element* startEditableAncestor = lowestEditableAncestor(m_start.containerNode());
675        if (startRoot || startEditableAncestor != baseEditableAncestor) {
676            Position p = nextVisuallyDistinctCandidate(m_start);
677            Element* shadowAncestor = startRoot ? startRoot->shadowHost() : 0;
678            if (p.isNull() && shadowAncestor)
679                p = positionBeforeNode(shadowAncestor);
680            while (p.isNotNull() && !(lowestEditableAncestor(p.containerNode()) == baseEditableAncestor && !isEditablePosition(p))) {
681                Element* root = editableRootForPosition(p);
682                shadowAncestor = root ? root->shadowHost() : 0;
683                p = isAtomicNode(p.containerNode()) ? positionInParentAfterNode(*p.containerNode()) : nextVisuallyDistinctCandidate(p);
684                if (p.isNull() && shadowAncestor)
685                    p = positionBeforeNode(shadowAncestor);
686            }
687            VisiblePosition next(p);
688
689            if (next.isNull()) {
690                // The selection crosses an Editing boundary.  This is a
691                // programmer error in the editing code.  Happy debugging!
692                ASSERT_NOT_REACHED();
693                m_base = Position();
694                m_extent = Position();
695                validate();
696                return;
697            }
698            m_start = next.deepEquivalent();
699        }
700    }
701
702    // Correct the extent if necessary.
703    if (baseEditableAncestor != lowestEditableAncestor(m_extent.containerNode()))
704        m_extent = m_baseIsFirst ? m_end : m_start;
705}
706
707VisiblePosition VisibleSelection::visiblePositionRespectingEditingBoundary(const LayoutPoint& localPoint, Node* targetNode) const
708{
709    if (!targetNode->renderer())
710        return VisiblePosition();
711
712    LayoutPoint selectionEndPoint = localPoint;
713    Element* editableElement = rootEditableElement();
714
715    if (editableElement && !editableElement->contains(targetNode)) {
716        if (!editableElement->renderer())
717            return VisiblePosition();
718
719        FloatPoint absolutePoint = targetNode->renderer()->localToAbsolute(FloatPoint(selectionEndPoint));
720        selectionEndPoint = roundedLayoutPoint(editableElement->renderer()->absoluteToLocal(absolutePoint));
721        targetNode = editableElement;
722    }
723
724    return VisiblePosition(targetNode->renderer()->positionForPoint(selectionEndPoint));
725}
726
727
728bool VisibleSelection::isContentEditable() const
729{
730    return isEditablePosition(start());
731}
732
733bool VisibleSelection::hasEditableStyle() const
734{
735    return isEditablePosition(start(), ContentIsEditable, DoNotUpdateStyle);
736}
737
738bool VisibleSelection::isContentRichlyEditable() const
739{
740    return isRichlyEditablePosition(start());
741}
742
743Element* VisibleSelection::rootEditableElement() const
744{
745    return editableRootForPosition(start());
746}
747
748Node* VisibleSelection::nonBoundaryShadowTreeRootNode() const
749{
750    return start().deprecatedNode() ? start().deprecatedNode()->nonBoundaryShadowTreeRootNode() : 0;
751}
752
753VisibleSelection::ChangeObserver::ChangeObserver()
754{
755}
756
757VisibleSelection::ChangeObserver::~ChangeObserver()
758{
759}
760
761void VisibleSelection::setChangeObserver(ChangeObserver& observer)
762{
763    ASSERT(!m_changeObserver);
764    m_changeObserver = &observer;
765}
766
767void VisibleSelection::clearChangeObserver()
768{
769    ASSERT(m_changeObserver);
770    m_changeObserver = nullptr;
771}
772
773void VisibleSelection::didChange()
774{
775    if (m_changeObserver)
776        m_changeObserver->didChangeVisibleSelection();
777}
778
779void VisibleSelection::trace(Visitor* visitor)
780{
781    visitor->trace(m_base);
782    visitor->trace(m_extent);
783    visitor->trace(m_start);
784    visitor->trace(m_end);
785    visitor->trace(m_changeObserver);
786}
787
788static bool isValidPosition(const Position& position)
789{
790    if (!position.inDocument())
791        return false;
792
793    if (position.anchorType() != Position::PositionIsOffsetInAnchor)
794        return true;
795
796    if (position.offsetInContainerNode() < 0)
797        return false;
798
799    const unsigned offset = static_cast<unsigned>(position.offsetInContainerNode());
800    const unsigned nodeLength = position.anchorNode()->lengthOfContents();
801    return offset <= nodeLength;
802}
803
804void VisibleSelection::validatePositionsIfNeeded()
805{
806    if (!isValidPosition(m_base) || !isValidPosition(m_extent) || !isValidPosition(m_start) || !isValidPosition(m_end))
807        validate();
808}
809
810#ifndef NDEBUG
811
812void VisibleSelection::debugPosition() const
813{
814    fprintf(stderr, "VisibleSelection ===============\n");
815
816    if (!m_start.anchorNode())
817        fputs("pos:   null", stderr);
818    else if (m_start == m_end) {
819        fprintf(stderr, "pos:   %s ", m_start.anchorNode()->nodeName().utf8().data());
820        m_start.showAnchorTypeAndOffset();
821    } else {
822        fprintf(stderr, "start: %s ", m_start.anchorNode()->nodeName().utf8().data());
823        m_start.showAnchorTypeAndOffset();
824        fprintf(stderr, "end:   %s ", m_end.anchorNode()->nodeName().utf8().data());
825        m_end.showAnchorTypeAndOffset();
826    }
827
828    fprintf(stderr, "================================\n");
829}
830
831void VisibleSelection::formatForDebugger(char* buffer, unsigned length) const
832{
833    StringBuilder result;
834    String s;
835
836    if (isNone()) {
837        result.appendLiteral("<none>");
838    } else {
839        const int FormatBufferSize = 1024;
840        char s[FormatBufferSize];
841        result.appendLiteral("from ");
842        start().formatForDebugger(s, FormatBufferSize);
843        result.append(s);
844        result.appendLiteral(" to ");
845        end().formatForDebugger(s, FormatBufferSize);
846        result.append(s);
847    }
848
849    strncpy(buffer, result.toString().utf8().data(), length - 1);
850}
851
852void VisibleSelection::showTreeForThis() const
853{
854    if (start().anchorNode()) {
855        start().anchorNode()->showTreeAndMark(start().anchorNode(), "S", end().anchorNode(), "E");
856        fputs("start: ", stderr);
857        start().showAnchorTypeAndOffset();
858        fputs("end: ", stderr);
859        end().showAnchorTypeAndOffset();
860    }
861}
862
863#endif
864
865} // namespace blink
866
867#ifndef NDEBUG
868
869void showTree(const blink::VisibleSelection& sel)
870{
871    sel.showTreeForThis();
872}
873
874void showTree(const blink::VisibleSelection* sel)
875{
876    if (sel)
877        sel->showTreeForThis();
878}
879
880#endif
881