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