Reduce use of deprecatedCharacters in WebCore
[WebKit-https.git] / Source / WebCore / editing / VisiblePosition.cpp
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
45 namespace WebCore {
46
47 using namespace HTMLNames;
48
49 VisiblePosition::VisiblePosition(const Position &pos, EAffinity affinity)
50 {
51     init(pos, affinity);
52 }
53
54 void 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
65 VisiblePosition 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
77 VisiblePosition 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
107 Position 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
255 VisiblePosition 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
272 Position 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
423 VisiblePosition 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
440 VisiblePosition 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
466 VisiblePosition 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
492 static 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
503 Position 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
570 UChar32 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
597 LayoutRect 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
619 IntRect VisiblePosition::absoluteCaretBounds() const
620 {
621     RenderObject* renderer = nullptr;
622     LayoutRect localRect = localCaretRectInRendererForCaretPainting(*this, renderer);
623     return absoluteBoundsForLocalCaretRect(renderer, localRect);
624 }
625
626 int 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
645 void 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
655 void VisiblePosition::formatForDebugger(char* buffer, unsigned length) const
656 {
657     m_deepPosition.formatForDebugger(buffer, length);
658 }
659
660 void VisiblePosition::showTreeForThis() const
661 {
662     m_deepPosition.showTreeForThis();
663 }
664
665 #endif
666
667 PassRefPtr<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
680 VisiblePosition startVisiblePosition(const Range *r, EAffinity affinity)
681 {
682     return VisiblePosition(r->startPosition(), affinity);
683 }
684
685 VisiblePosition endVisiblePosition(const Range *r, EAffinity affinity)
686 {
687     return VisiblePosition(r->endPosition(), affinity);
688 }
689
690 bool 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
700 bool 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?
711 Element* enclosingBlockFlowElement(const VisiblePosition& visiblePosition)
712 {
713     if (visiblePosition.isNull())
714         return NULL;
715
716     return deprecatedEnclosingBlockFlowElement(visiblePosition.deepEquivalent().deprecatedNode());
717 }
718
719 bool 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
731 bool 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
747 void showTree(const WebCore::VisiblePosition* vpos)
748 {
749     if (vpos)
750         vpos->showTreeForThis();
751 }
752
753 void showTree(const WebCore::VisiblePosition& vpos)
754 {
755     vpos.showTreeForThis();
756 }
757
758 #endif