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