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