Home | History | Annotate | Download | only in editing
      1 /*
      2  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "VisiblePosition.h"
     28 
     29 #include "CString.h"
     30 #include "Document.h"
     31 #include "FloatQuad.h"
     32 #include "HTMLElement.h"
     33 #include "HTMLNames.h"
     34 #include "InlineTextBox.h"
     35 #include "Logging.h"
     36 #include "Range.h"
     37 #include "Text.h"
     38 #include "htmlediting.h"
     39 #include "visible_units.h"
     40 #include <stdio.h>
     41 
     42 namespace WebCore {
     43 
     44 using namespace HTMLNames;
     45 
     46 VisiblePosition::VisiblePosition(const Position &pos, EAffinity affinity)
     47 {
     48     init(pos, affinity);
     49 }
     50 
     51 VisiblePosition::VisiblePosition(Node *node, int offset, EAffinity affinity)
     52 {
     53     ASSERT(offset >= 0);
     54     init(Position(node, offset), affinity);
     55 }
     56 
     57 void VisiblePosition::init(const Position& position, EAffinity affinity)
     58 {
     59     m_affinity = affinity;
     60 
     61     m_deepPosition = canonicalPosition(position);
     62 
     63     // When not at a line wrap, make sure to end up with DOWNSTREAM affinity.
     64     if (m_affinity == UPSTREAM && (isNull() || inSameLine(VisiblePosition(position, DOWNSTREAM), *this)))
     65         m_affinity = DOWNSTREAM;
     66 }
     67 
     68 VisiblePosition VisiblePosition::next(bool stayInEditableContent) const
     69 {
     70     VisiblePosition next(nextVisuallyDistinctCandidate(m_deepPosition), m_affinity);
     71 
     72     if (!stayInEditableContent)
     73         return next;
     74 
     75     return honorEditableBoundaryAtOrAfter(next);
     76 }
     77 
     78 VisiblePosition VisiblePosition::previous(bool stayInEditableContent) const
     79 {
     80     // find first previous DOM position that is visible
     81     Position pos = previousVisuallyDistinctCandidate(m_deepPosition);
     82 
     83     // return null visible position if there is no previous visible position
     84     if (pos.atStartOfTree())
     85         return VisiblePosition();
     86 
     87     VisiblePosition prev = VisiblePosition(pos, DOWNSTREAM);
     88     ASSERT(prev != *this);
     89 
     90 #ifndef NDEBUG
     91     // we should always be able to make the affinity DOWNSTREAM, because going previous from an
     92     // UPSTREAM position can never yield another UPSTREAM position (unless line wrap length is 0!).
     93     if (prev.isNotNull() && m_affinity == UPSTREAM) {
     94         VisiblePosition temp = prev;
     95         temp.setAffinity(UPSTREAM);
     96         ASSERT(inSameLine(temp, prev));
     97     }
     98 #endif
     99 
    100     if (!stayInEditableContent)
    101         return prev;
    102 
    103     return honorEditableBoundaryAtOrBefore(prev);
    104 }
    105 
    106 Position VisiblePosition::leftVisuallyDistinctCandidate() const
    107 {
    108     Position p = m_deepPosition;
    109     if (!p.node())
    110         return Position();
    111 
    112     Position downstreamStart = p.downstream();
    113     TextDirection primaryDirection = LTR;
    114     for (RenderObject* r = p.node()->renderer(); r; r = r->parent()) {
    115         if (r->isBlockFlow()) {
    116             primaryDirection = r->style()->direction();
    117             break;
    118         }
    119     }
    120 
    121     while (true) {
    122         InlineBox* box;
    123         int offset;
    124         p.getInlineBoxAndOffset(m_affinity, primaryDirection, box, offset);
    125         if (!box)
    126             return primaryDirection == LTR ? previousVisuallyDistinctCandidate(m_deepPosition) : nextVisuallyDistinctCandidate(m_deepPosition);
    127 
    128         RenderObject* renderer = box->renderer();
    129 
    130         while (true) {
    131             if ((renderer->isReplaced() || renderer->isBR()) && offset == box->caretRightmostOffset())
    132                 return box->direction() == LTR ? previousVisuallyDistinctCandidate(m_deepPosition) : nextVisuallyDistinctCandidate(m_deepPosition);
    133 
    134             offset = box->direction() == LTR ? renderer->previousOffset(offset) : renderer->nextOffset(offset);
    135 
    136             int caretMinOffset = box->caretMinOffset();
    137             int caretMaxOffset = box->caretMaxOffset();
    138 
    139             if (offset > caretMinOffset && offset < caretMaxOffset)
    140                 break;
    141 
    142             if (box->direction() == LTR ? offset < caretMinOffset : offset > caretMaxOffset) {
    143                 // Overshot to the left.
    144                 InlineBox* prevBox = box->prevLeafChild();
    145                 if (!prevBox)
    146                     return primaryDirection == LTR ? previousVisuallyDistinctCandidate(m_deepPosition) : nextVisuallyDistinctCandidate(m_deepPosition);
    147 
    148                 // Reposition at the other logical position corresponding to our edge's visual position and go for another round.
    149                 box = prevBox;
    150                 renderer = box->renderer();
    151                 offset = prevBox->caretRightmostOffset();
    152                 continue;
    153             }
    154 
    155             ASSERT(offset == box->caretLeftmostOffset());
    156 
    157             unsigned char level = box->bidiLevel();
    158             InlineBox* prevBox = box->prevLeafChild();
    159 
    160             if (box->direction() == primaryDirection) {
    161                 if (!prevBox || prevBox->bidiLevel() >= level)
    162                     break;
    163 
    164                 level = prevBox->bidiLevel();
    165 
    166                 InlineBox* nextBox = box;
    167                 do {
    168                     nextBox = nextBox->nextLeafChild();
    169                 } while (nextBox && nextBox->bidiLevel() > level);
    170 
    171                 if (nextBox && nextBox->bidiLevel() == level)
    172                     break;
    173 
    174                 while (InlineBox* prevBox = box->prevLeafChild()) {
    175                     if (prevBox->bidiLevel() < level)
    176                         break;
    177                     box = prevBox;
    178                 }
    179                 renderer = box->renderer();
    180                 offset = box->caretRightmostOffset();
    181                 if (box->direction() == primaryDirection)
    182                     break;
    183                 continue;
    184             }
    185 
    186             if (prevBox) {
    187                 box = prevBox;
    188                 renderer = box->renderer();
    189                 offset = box->caretRightmostOffset();
    190                 if (box->bidiLevel() > level) {
    191                     do {
    192                         prevBox = box->prevLeafChild();
    193                     } while (prevBox && prevBox->bidiLevel() > level);
    194 
    195                     if (!prevBox || prevBox->bidiLevel() < level)
    196                         continue;
    197                 }
    198             } else {
    199                 // Trailing edge of a secondary run. Set to the leading edge of the entire run.
    200                 while (true) {
    201                     while (InlineBox* nextBox = box->nextLeafChild()) {
    202                         if (nextBox->bidiLevel() < level)
    203                             break;
    204                         box = nextBox;
    205                     }
    206                     if (box->bidiLevel() == level)
    207                         break;
    208                     level = box->bidiLevel();
    209                     while (InlineBox* prevBox = box->prevLeafChild()) {
    210                         if (prevBox->bidiLevel() < level)
    211                             break;
    212                         box = prevBox;
    213                     }
    214                     if (box->bidiLevel() == level)
    215                         break;
    216                     level = box->bidiLevel();
    217                 }
    218                 renderer = box->renderer();
    219                 offset = primaryDirection == LTR ? box->caretMinOffset() : box->caretMaxOffset();
    220             }
    221             break;
    222         }
    223 
    224         p = Position(renderer->node(), offset);
    225 
    226         if ((p.isCandidate() && p.downstream() != downstreamStart) || p.atStartOfTree() || p.atEndOfTree())
    227             return p;
    228     }
    229 }
    230 
    231 VisiblePosition VisiblePosition::left(bool stayInEditableContent) const
    232 {
    233     Position pos = leftVisuallyDistinctCandidate();
    234     // FIXME: Why can't we move left from the last position in a tree?
    235     if (pos.atStartOfTree() || pos.atEndOfTree())
    236         return VisiblePosition();
    237 
    238     VisiblePosition left = VisiblePosition(pos, DOWNSTREAM);
    239     ASSERT(left != *this);
    240 
    241     if (!stayInEditableContent)
    242         return left;
    243 
    244     // FIXME: This may need to do something different from "before".
    245     return honorEditableBoundaryAtOrBefore(left);
    246 }
    247 
    248 Position VisiblePosition::rightVisuallyDistinctCandidate() const
    249 {
    250     Position p = m_deepPosition;
    251     if (!p.node())
    252         return Position();
    253 
    254     Position downstreamStart = p.downstream();
    255     TextDirection primaryDirection = LTR;
    256     for (RenderObject* r = p.node()->renderer(); r; r = r->parent()) {
    257         if (r->isBlockFlow()) {
    258             primaryDirection = r->style()->direction();
    259             break;
    260         }
    261     }
    262 
    263     while (true) {
    264         InlineBox* box;
    265         int offset;
    266         p.getInlineBoxAndOffset(m_affinity, primaryDirection, box, offset);
    267         if (!box)
    268             return primaryDirection == LTR ? nextVisuallyDistinctCandidate(m_deepPosition) : previousVisuallyDistinctCandidate(m_deepPosition);
    269 
    270         RenderObject* renderer = box->renderer();
    271 
    272         while (true) {
    273             if ((renderer->isReplaced() || renderer->isBR()) && offset == box->caretLeftmostOffset())
    274                 return box->direction() == LTR ? nextVisuallyDistinctCandidate(m_deepPosition) : previousVisuallyDistinctCandidate(m_deepPosition);
    275 
    276             offset = box->direction() == LTR ? renderer->nextOffset(offset) : renderer->previousOffset(offset);
    277 
    278             int caretMinOffset = box->caretMinOffset();
    279             int caretMaxOffset = box->caretMaxOffset();
    280 
    281             if (offset > caretMinOffset && offset < caretMaxOffset)
    282                 break;
    283 
    284             if (box->direction() == LTR ? offset > caretMaxOffset : offset < caretMinOffset) {
    285                 // Overshot to the right.
    286                 InlineBox* nextBox = box->nextLeafChild();
    287                 if (!nextBox)
    288                     return primaryDirection == LTR ? nextVisuallyDistinctCandidate(m_deepPosition) : previousVisuallyDistinctCandidate(m_deepPosition);
    289 
    290                 // Reposition at the other logical position corresponding to our edge's visual position and go for another round.
    291                 box = nextBox;
    292                 renderer = box->renderer();
    293                 offset = nextBox->caretLeftmostOffset();
    294                 continue;
    295             }
    296 
    297             ASSERT(offset == box->caretRightmostOffset());
    298 
    299             unsigned char level = box->bidiLevel();
    300             InlineBox* nextBox = box->nextLeafChild();
    301 
    302             if (box->direction() == primaryDirection) {
    303                 if (!nextBox || nextBox->bidiLevel() >= level)
    304                     break;
    305 
    306                 level = nextBox->bidiLevel();
    307 
    308                 InlineBox* prevBox = box;
    309                 do {
    310                     prevBox = prevBox->prevLeafChild();
    311                 } while (prevBox && prevBox->bidiLevel() > level);
    312 
    313                 if (prevBox && prevBox->bidiLevel() == level)   // For example, abc FED 123 ^ CBA
    314                     break;
    315 
    316                 // For example, abc 123 ^ CBA
    317                 while (InlineBox* nextBox = box->nextLeafChild()) {
    318                     if (nextBox->bidiLevel() < level)
    319                         break;
    320                     box = nextBox;
    321                 }
    322                 renderer = box->renderer();
    323                 offset = box->caretLeftmostOffset();
    324                 if (box->direction() == primaryDirection)
    325                     break;
    326                 continue;
    327             }
    328 
    329             if (nextBox) {
    330                 box = nextBox;
    331                 renderer = box->renderer();
    332                 offset = box->caretLeftmostOffset();
    333                 if (box->bidiLevel() > level) {
    334                     do {
    335                         nextBox = box->nextLeafChild();
    336                     } while (nextBox && nextBox->bidiLevel() > level);
    337 
    338                     if (!nextBox || nextBox->bidiLevel() < level)
    339                         continue;
    340                 }
    341             } else {
    342                 // Trailing edge of a secondary run. Set to the leading edge of the entire run.
    343                 while (true) {
    344                     while (InlineBox* prevBox = box->prevLeafChild()) {
    345                         if (prevBox->bidiLevel() < level)
    346                             break;
    347                         box = prevBox;
    348                     }
    349                     if (box->bidiLevel() == level)
    350                         break;
    351                     level = box->bidiLevel();
    352                     while (InlineBox* nextBox = box->nextLeafChild()) {
    353                         if (nextBox->bidiLevel() < level)
    354                             break;
    355                         box = nextBox;
    356                     }
    357                     if (box->bidiLevel() == level)
    358                         break;
    359                     level = box->bidiLevel();
    360                 }
    361                 renderer = box->renderer();
    362                 offset = primaryDirection == LTR ? box->caretMaxOffset() : box->caretMinOffset();
    363             }
    364             break;
    365         }
    366 
    367         p = Position(renderer->node(), offset);
    368 
    369         if ((p.isCandidate() && p.downstream() != downstreamStart) || p.atStartOfTree() || p.atEndOfTree())
    370             return p;
    371     }
    372 }
    373 
    374 VisiblePosition VisiblePosition::right(bool stayInEditableContent) const
    375 {
    376     Position pos = rightVisuallyDistinctCandidate();
    377     // FIXME: Why can't we move left from the last position in a tree?
    378     if (pos.atStartOfTree() || pos.atEndOfTree())
    379         return VisiblePosition();
    380 
    381     VisiblePosition right = VisiblePosition(pos, DOWNSTREAM);
    382     ASSERT(right != *this);
    383 
    384     if (!stayInEditableContent)
    385         return right;
    386 
    387     // FIXME: This may need to do something different from "after".
    388     return honorEditableBoundaryAtOrAfter(right);
    389 }
    390 
    391 VisiblePosition VisiblePosition::honorEditableBoundaryAtOrBefore(const VisiblePosition &pos) const
    392 {
    393     if (pos.isNull())
    394         return pos;
    395 
    396     Node* highestRoot = highestEditableRoot(deepEquivalent());
    397 
    398     // Return empty position if pos is not somewhere inside the editable region containing this position
    399     if (highestRoot && !pos.deepEquivalent().node()->isDescendantOf(highestRoot))
    400         return VisiblePosition();
    401 
    402     // Return pos itself if the two are from the very same editable region, or both are non-editable
    403     // FIXME: In the non-editable case, just because the new position is non-editable doesn't mean movement
    404     // to it is allowed.  VisibleSelection::adjustForEditableContent has this problem too.
    405     if (highestEditableRoot(pos.deepEquivalent()) == highestRoot)
    406         return pos;
    407 
    408     // Return empty position if this position is non-editable, but pos is editable
    409     // FIXME: Move to the previous non-editable region.
    410     if (!highestRoot)
    411         return VisiblePosition();
    412 
    413     // Return the last position before pos that is in the same editable region as this position
    414     return lastEditablePositionBeforePositionInRoot(pos.deepEquivalent(), highestRoot);
    415 }
    416 
    417 VisiblePosition VisiblePosition::honorEditableBoundaryAtOrAfter(const VisiblePosition &pos) const
    418 {
    419     if (pos.isNull())
    420         return pos;
    421 
    422     Node* highestRoot = highestEditableRoot(deepEquivalent());
    423 
    424     // Return empty position if pos is not somewhere inside the editable region containing this position
    425     if (highestRoot && !pos.deepEquivalent().node()->isDescendantOf(highestRoot))
    426         return VisiblePosition();
    427 
    428     // Return pos itself if the two are from the very same editable region, or both are non-editable
    429     // FIXME: In the non-editable case, just because the new position is non-editable doesn't mean movement
    430     // to it is allowed.  VisibleSelection::adjustForEditableContent has this problem too.
    431     if (highestEditableRoot(pos.deepEquivalent()) == highestRoot)
    432         return pos;
    433 
    434     // Return empty position if this position is non-editable, but pos is editable
    435     // FIXME: Move to the next non-editable region.
    436     if (!highestRoot)
    437         return VisiblePosition();
    438 
    439     // Return the next position after pos that is in the same editable region as this position
    440     return firstEditablePositionAfterPositionInRoot(pos.deepEquivalent(), highestRoot);
    441 }
    442 
    443 static Position canonicalizeCandidate(const Position& candidate)
    444 {
    445     if (candidate.isNull())
    446         return Position();
    447     ASSERT(candidate.isCandidate());
    448     Position upstream = candidate.upstream();
    449     if (upstream.isCandidate())
    450         return upstream;
    451     return candidate;
    452 }
    453 
    454 Position VisiblePosition::canonicalPosition(const Position& position)
    455 {
    456     // FIXME (9535):  Canonicalizing to the leftmost candidate means that if we're at a line wrap, we will
    457     // ask renderers to paint downstream carets for other renderers.
    458     // To fix this, we need to either a) add code to all paintCarets to pass the responsibility off to
    459     // the appropriate renderer for VisiblePosition's like these, or b) canonicalize to the rightmost candidate
    460     // unless the affinity is upstream.
    461     Node* node = position.node();
    462     if (!node)
    463         return Position();
    464 
    465     node->document()->updateLayoutIgnorePendingStylesheets();
    466 
    467     Position candidate = position.upstream();
    468     if (candidate.isCandidate())
    469         return candidate;
    470     candidate = position.downstream();
    471     if (candidate.isCandidate())
    472         return candidate;
    473 
    474     // When neither upstream or downstream gets us to a candidate (upstream/downstream won't leave
    475     // blocks or enter new ones), we search forward and backward until we find one.
    476     Position next = canonicalizeCandidate(nextCandidate(position));
    477     Position prev = canonicalizeCandidate(previousCandidate(position));
    478     Node* nextNode = next.node();
    479     Node* prevNode = prev.node();
    480 
    481     // The new position must be in the same editable element. Enforce that first.
    482     // Unless the descent is from a non-editable html element to an editable body.
    483     if (node->hasTagName(htmlTag) && !node->isContentEditable() && node->document()->body() && node->document()->body()->isContentEditable())
    484         return next.isNotNull() ? next : prev;
    485 
    486     Node* editingRoot = editableRootForPosition(position);
    487 
    488     // If the html element is editable, descending into its body will look like a descent
    489     // from non-editable to editable content since rootEditableElement() always stops at the body.
    490     if ((editingRoot && editingRoot->hasTagName(htmlTag)) || position.node()->isDocumentNode())
    491         return next.isNotNull() ? next : prev;
    492 
    493     bool prevIsInSameEditableElement = prevNode && editableRootForPosition(prev) == editingRoot;
    494     bool nextIsInSameEditableElement = nextNode && editableRootForPosition(next) == editingRoot;
    495     if (prevIsInSameEditableElement && !nextIsInSameEditableElement)
    496         return prev;
    497 
    498     if (nextIsInSameEditableElement && !prevIsInSameEditableElement)
    499         return next;
    500 
    501     if (!nextIsInSameEditableElement && !prevIsInSameEditableElement)
    502         return Position();
    503 
    504     // The new position should be in the same block flow element. Favor that.
    505     Node *originalBlock = node->enclosingBlockFlowElement();
    506     bool nextIsOutsideOriginalBlock = !nextNode->isDescendantOf(originalBlock) && nextNode != originalBlock;
    507     bool prevIsOutsideOriginalBlock = !prevNode->isDescendantOf(originalBlock) && prevNode != originalBlock;
    508     if (nextIsOutsideOriginalBlock && !prevIsOutsideOriginalBlock)
    509         return prev;
    510 
    511     return next;
    512 }
    513 
    514 UChar32 VisiblePosition::characterAfter() const
    515 {
    516     // We canonicalize to the first of two equivalent candidates, but the second of the two candidates
    517     // is the one that will be inside the text node containing the character after this visible position.
    518     Position pos = m_deepPosition.downstream();
    519     Node* node = pos.node();
    520     if (!node || !node->isTextNode())
    521         return 0;
    522     Text* textNode = static_cast<Text*>(pos.node());
    523     unsigned offset = pos.deprecatedEditingOffset();
    524     unsigned length = textNode->length();
    525     if (offset >= length)
    526         return 0;
    527 
    528     UChar32 ch;
    529     const UChar* characters = textNode->data().characters();
    530     U16_NEXT(characters, offset, length, ch);
    531     return ch;
    532 }
    533 
    534 IntRect VisiblePosition::localCaretRect(RenderObject*& renderer) const
    535 {
    536     Node* node = m_deepPosition.node();
    537     if (!node) {
    538         renderer = 0;
    539         return IntRect();
    540     }
    541 
    542     renderer = node->renderer();
    543     if (!renderer)
    544         return IntRect();
    545 
    546     InlineBox* inlineBox;
    547     int caretOffset;
    548     getInlineBoxAndOffset(inlineBox, caretOffset);
    549 
    550     if (inlineBox)
    551         renderer = inlineBox->renderer();
    552 
    553     return renderer->localCaretRect(inlineBox, caretOffset);
    554 }
    555 
    556 IntRect VisiblePosition::absoluteCaretBounds() const
    557 {
    558     RenderObject* renderer;
    559     IntRect localRect = localCaretRect(renderer);
    560     if (localRect.isEmpty() || !renderer)
    561         return IntRect();
    562 
    563     return renderer->localToAbsoluteQuad(FloatRect(localRect)).enclosingBoundingBox();
    564 }
    565 
    566 int VisiblePosition::xOffsetForVerticalNavigation() const
    567 {
    568     RenderObject* renderer;
    569     IntRect localRect = localCaretRect(renderer);
    570     if (localRect.isEmpty() || !renderer)
    571         return 0;
    572 
    573     // This ignores transforms on purpose, for now. Vertical navigation is done
    574     // without consulting transforms, so that 'up' in transformed text is 'up'
    575     // relative to the text, not absolute 'up'.
    576     return renderer->localToAbsolute(localRect.location()).x();
    577 }
    578 
    579 void VisiblePosition::debugPosition(const char* msg) const
    580 {
    581     if (isNull())
    582         fprintf(stderr, "Position [%s]: null\n", msg);
    583     else
    584         fprintf(stderr, "Position [%s]: %s [%p] at %d\n", msg, m_deepPosition.node()->nodeName().utf8().data(), m_deepPosition.node(), m_deepPosition.deprecatedEditingOffset());
    585 }
    586 
    587 #ifndef NDEBUG
    588 
    589 void VisiblePosition::formatForDebugger(char* buffer, unsigned length) const
    590 {
    591     m_deepPosition.formatForDebugger(buffer, length);
    592 }
    593 
    594 void VisiblePosition::showTreeForThis() const
    595 {
    596     m_deepPosition.showTreeForThis();
    597 }
    598 
    599 #endif
    600 
    601 PassRefPtr<Range> makeRange(const VisiblePosition &start, const VisiblePosition &end)
    602 {
    603     if (start.isNull() || end.isNull())
    604         return 0;
    605 
    606     Position s = rangeCompliantEquivalent(start);
    607     Position e = rangeCompliantEquivalent(end);
    608     return Range::create(s.node()->document(), s.node(), s.deprecatedEditingOffset(), e.node(), e.deprecatedEditingOffset());
    609 }
    610 
    611 VisiblePosition startVisiblePosition(const Range *r, EAffinity affinity)
    612 {
    613     int exception = 0;
    614     return VisiblePosition(r->startContainer(exception), r->startOffset(exception), affinity);
    615 }
    616 
    617 VisiblePosition endVisiblePosition(const Range *r, EAffinity affinity)
    618 {
    619     int exception = 0;
    620     return VisiblePosition(r->endContainer(exception), r->endOffset(exception), affinity);
    621 }
    622 
    623 bool setStart(Range *r, const VisiblePosition &visiblePosition)
    624 {
    625     if (!r)
    626         return false;
    627     Position p = rangeCompliantEquivalent(visiblePosition);
    628     int code = 0;
    629     r->setStart(p.node(), p.deprecatedEditingOffset(), code);
    630     return code == 0;
    631 }
    632 
    633 bool setEnd(Range *r, const VisiblePosition &visiblePosition)
    634 {
    635     if (!r)
    636         return false;
    637     Position p = rangeCompliantEquivalent(visiblePosition);
    638     int code = 0;
    639     r->setEnd(p.node(), p.deprecatedEditingOffset(), code);
    640     return code == 0;
    641 }
    642 
    643 Node *enclosingBlockFlowElement(const VisiblePosition &visiblePosition)
    644 {
    645     if (visiblePosition.isNull())
    646         return NULL;
    647 
    648     return visiblePosition.deepEquivalent().node()->enclosingBlockFlowElement();
    649 }
    650 
    651 bool isFirstVisiblePositionInNode(const VisiblePosition &visiblePosition, const Node *node)
    652 {
    653     if (visiblePosition.isNull())
    654         return false;
    655 
    656     if (!visiblePosition.deepEquivalent().node()->isDescendantOf(node))
    657         return false;
    658 
    659     VisiblePosition previous = visiblePosition.previous();
    660     return previous.isNull() || !previous.deepEquivalent().node()->isDescendantOf(node);
    661 }
    662 
    663 bool isLastVisiblePositionInNode(const VisiblePosition &visiblePosition, const Node *node)
    664 {
    665     if (visiblePosition.isNull())
    666         return false;
    667 
    668     if (!visiblePosition.deepEquivalent().node()->isDescendantOf(node))
    669         return false;
    670 
    671     VisiblePosition next = visiblePosition.next();
    672     return next.isNull() || !next.deepEquivalent().node()->isDescendantOf(node);
    673 }
    674 
    675 }  // namespace WebCore
    676 
    677 #ifndef NDEBUG
    678 
    679 void showTree(const WebCore::VisiblePosition* vpos)
    680 {
    681     if (vpos)
    682         vpos->showTreeForThis();
    683 }
    684 
    685 void showTree(const WebCore::VisiblePosition& vpos)
    686 {
    687     vpos.showTreeForThis();
    688 }
    689 
    690 #endif
    691