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