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