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