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