Unreviewed, rolling out r161840.
[WebKit-https.git] / Source / WebCore / editing / VisibleUnits.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 "VisibleUnits.h"
28
29 #include "Document.h"
30 #include "Element.h"
31 #include "HTMLNames.h"
32 #include "InlineTextBox.h"
33 #include "NodeTraversal.h"
34 #include "RenderBlockFlow.h"
35 #include "RenderObject.h"
36 #include "RenderedPosition.h"
37 #include "Text.h"
38 #include "TextBoundaries.h"
39 #include "TextBreakIterator.h"
40 #include "TextIterator.h"
41 #include "VisibleSelection.h"
42 #include "htmlediting.h"
43
44 namespace WebCore {
45
46 using namespace HTMLNames;
47 using namespace WTF::Unicode;
48
49 static Node* previousLeafWithSameEditability(Node* node, EditableType editableType)
50 {
51     bool editable = node->hasEditableStyle(editableType);
52     node = previousLeafNode(node);
53     while (node) {
54         if (editable == node->hasEditableStyle(editableType))
55             return node;
56         node = previousLeafNode(node);
57     }
58     return 0;
59 }
60
61 static Node* nextLeafWithSameEditability(Node* node, EditableType editableType = ContentIsEditable)
62 {
63     if (!node)
64         return 0;
65     
66     bool editable = node->hasEditableStyle(editableType);
67     node = nextLeafNode(node);
68     while (node) {
69         if (editable == node->hasEditableStyle(editableType))
70             return node;
71         node = nextLeafNode(node);
72     }
73     return 0;
74 }
75
76 // FIXME: consolidate with code in previousLinePosition.
77 static Position previousRootInlineBoxCandidatePosition(Node* node, const VisiblePosition& visiblePosition, EditableType editableType)
78 {
79     Node* highestRoot = highestEditableRoot(visiblePosition.deepEquivalent(), editableType);
80     Node* previousNode = previousLeafWithSameEditability(node, editableType);
81
82     while (previousNode && (!previousNode->renderer() || inSameLine(firstPositionInOrBeforeNode(previousNode), visiblePosition)))
83         previousNode = previousLeafWithSameEditability(previousNode, editableType);
84
85     while (previousNode && !previousNode->isShadowRoot()) {
86         if (highestEditableRoot(firstPositionInOrBeforeNode(previousNode), editableType) != highestRoot)
87             break;
88
89         Position pos = previousNode->hasTagName(brTag) ? positionBeforeNode(previousNode) :
90             createLegacyEditingPosition(previousNode, caretMaxOffset(previousNode));
91         
92         if (pos.isCandidate())
93             return pos;
94
95         previousNode = previousLeafWithSameEditability(previousNode, editableType);
96     }
97     return Position();
98 }
99
100 static Position nextRootInlineBoxCandidatePosition(Node* node, const VisiblePosition& visiblePosition, EditableType editableType)
101 {
102     Node* highestRoot = highestEditableRoot(visiblePosition.deepEquivalent(), editableType);
103     Node* nextNode = nextLeafWithSameEditability(node, editableType);
104     while (nextNode && (!nextNode->renderer() || inSameLine(firstPositionInOrBeforeNode(nextNode), visiblePosition)))
105         nextNode = nextLeafWithSameEditability(nextNode, ContentIsEditable);
106
107     while (nextNode && !nextNode->isShadowRoot()) {
108         if (highestEditableRoot(firstPositionInOrBeforeNode(nextNode), editableType) != highestRoot)
109             break;
110
111         Position pos;
112         pos = createLegacyEditingPosition(nextNode, caretMinOffset(nextNode));
113         
114         if (pos.isCandidate())
115             return pos;
116
117         nextNode = nextLeafWithSameEditability(nextNode, editableType);
118     }
119     return Position();
120 }
121
122 class CachedLogicallyOrderedLeafBoxes {
123 public:
124     CachedLogicallyOrderedLeafBoxes();
125
126     const InlineBox* previousTextOrLineBreakBox(const RootInlineBox*, const InlineTextBox*);
127     const InlineBox* nextTextOrLineBreakBox(const RootInlineBox*, const InlineTextBox*);
128
129     size_t size() const { return m_leafBoxes.size(); }
130     const InlineBox* firstBox() const { return m_leafBoxes[0]; }
131
132 private:
133     const Vector<InlineBox*>& collectBoxes(const RootInlineBox*);
134     int boxIndexInLeaves(const InlineTextBox*) const;
135
136     const RootInlineBox* m_rootInlineBox;
137     Vector<InlineBox*> m_leafBoxes;
138 };
139
140 CachedLogicallyOrderedLeafBoxes::CachedLogicallyOrderedLeafBoxes() : m_rootInlineBox(0) { };
141
142 const InlineBox* CachedLogicallyOrderedLeafBoxes::previousTextOrLineBreakBox(const RootInlineBox* root, const InlineTextBox* box)
143 {
144     if (!root)
145         return 0;
146
147     collectBoxes(root);
148
149     // If box is null, root is box's previous RootInlineBox, and previousBox is the last logical box in root.
150     int boxIndex = m_leafBoxes.size() - 1;
151     if (box)
152         boxIndex = boxIndexInLeaves(box) - 1;
153
154     for (int i = boxIndex; i >= 0; --i) {
155         InlineBox* box = m_leafBoxes[i];
156         if (box->isInlineTextBox() || box->renderer().isBR())
157             return box;
158     }
159
160     return 0;
161 }
162
163 const InlineBox* CachedLogicallyOrderedLeafBoxes::nextTextOrLineBreakBox(const RootInlineBox* root, const InlineTextBox* box)
164 {
165     if (!root)
166         return 0;
167
168     collectBoxes(root);
169
170     // If box is null, root is box's next RootInlineBox, and nextBox is the first logical box in root.
171     // Otherwise, root is box's RootInlineBox, and nextBox is the next logical box in the same line.
172     size_t nextBoxIndex = 0;
173     if (box)
174         nextBoxIndex = boxIndexInLeaves(box) + 1;
175
176     for (size_t i = nextBoxIndex; i < m_leafBoxes.size(); ++i) {
177         InlineBox* box = m_leafBoxes[i];
178         if (box->isInlineTextBox() || box->renderer().isBR())
179             return box;
180     }
181
182     return 0;
183 }
184
185 const Vector<InlineBox*>& CachedLogicallyOrderedLeafBoxes::collectBoxes(const RootInlineBox* root)
186 {
187     if (m_rootInlineBox != root) {
188         m_rootInlineBox = root;
189         m_leafBoxes.clear();
190         root->collectLeafBoxesInLogicalOrder(m_leafBoxes);
191     }
192     return m_leafBoxes;
193 }
194
195 int CachedLogicallyOrderedLeafBoxes::boxIndexInLeaves(const InlineTextBox* box) const
196 {
197     for (size_t i = 0; i < m_leafBoxes.size(); ++i) {
198         if (box == m_leafBoxes[i])
199             return i;
200     }
201     return 0;
202 }
203
204 static const InlineBox* logicallyPreviousBox(const VisiblePosition& visiblePosition, const InlineTextBox* textBox,
205     bool& previousBoxInDifferentBlock, CachedLogicallyOrderedLeafBoxes& leafBoxes)
206 {
207     const InlineBox* startBox = textBox;
208
209     const InlineBox* previousBox = leafBoxes.previousTextOrLineBreakBox(&startBox->root(), textBox);
210     if (previousBox)
211         return previousBox;
212
213     previousBox = leafBoxes.previousTextOrLineBreakBox(startBox->root().prevRootBox(), 0);
214     if (previousBox)
215         return previousBox;
216
217     while (1) {
218         Node* startNode = startBox->renderer().nonPseudoNode();
219         if (!startNode)
220             break;
221
222         Position position = previousRootInlineBoxCandidatePosition(startNode, visiblePosition, ContentIsEditable);
223         if (position.isNull())
224             break;
225
226         RenderedPosition renderedPosition(position, DOWNSTREAM);
227         RootInlineBox* previousRoot = renderedPosition.rootBox();
228         if (!previousRoot)
229             break;
230
231         previousBox = leafBoxes.previousTextOrLineBreakBox(previousRoot, 0);
232         if (previousBox) {
233             previousBoxInDifferentBlock = true;
234             return previousBox;
235         }
236
237         if (!leafBoxes.size())
238             break;
239         startBox = leafBoxes.firstBox();
240     }
241     return 0;
242 }
243
244
245 static const InlineBox* logicallyNextBox(const VisiblePosition& visiblePosition, const InlineTextBox* textBox,
246     bool& nextBoxInDifferentBlock, CachedLogicallyOrderedLeafBoxes& leafBoxes)
247 {
248     const InlineBox* startBox = textBox;
249
250     const InlineBox* nextBox = leafBoxes.nextTextOrLineBreakBox(&startBox->root(), textBox);
251     if (nextBox)
252         return nextBox;
253
254     nextBox = leafBoxes.nextTextOrLineBreakBox(startBox->root().nextRootBox(), 0);
255     if (nextBox)
256         return nextBox;
257
258     while (1) {
259         Node* startNode = startBox->renderer().nonPseudoNode();
260         if (!startNode)
261             break;
262
263         Position position = nextRootInlineBoxCandidatePosition(startNode, visiblePosition, ContentIsEditable);
264         if (position.isNull())
265             break;
266
267         RenderedPosition renderedPosition(position, DOWNSTREAM);
268         RootInlineBox* nextRoot = renderedPosition.rootBox();
269         if (!nextRoot)
270             break;
271
272         nextBox = leafBoxes.nextTextOrLineBreakBox(nextRoot, 0);
273         if (nextBox) {
274             nextBoxInDifferentBlock = true;
275             return nextBox;
276         }
277
278         if (!leafBoxes.size())
279             break;
280         startBox = leafBoxes.firstBox();
281     }
282     return 0;
283 }
284
285 static TextBreakIterator* wordBreakIteratorForMinOffsetBoundary(const VisiblePosition& visiblePosition, const InlineTextBox* textBox,
286     int& previousBoxLength, bool& previousBoxInDifferentBlock, Vector<UChar, 1024>& string, CachedLogicallyOrderedLeafBoxes& leafBoxes)
287 {
288     previousBoxInDifferentBlock = false;
289
290     // FIXME: Handle the case when we don't have an inline text box.
291     const InlineBox* previousBox = logicallyPreviousBox(visiblePosition, textBox, previousBoxInDifferentBlock, leafBoxes);
292
293     int len = 0;
294     string.clear();
295     if (previousBox && previousBox->isInlineTextBox()) {
296         const InlineTextBox* previousTextBox = toInlineTextBox(previousBox);
297         previousBoxLength = previousTextBox->len();
298         string.append(previousTextBox->renderer().text()->deprecatedCharacters() + previousTextBox->start(), previousBoxLength);
299         len += previousBoxLength;
300     }
301     string.append(textBox->renderer().text()->deprecatedCharacters() + textBox->start(), textBox->len());
302     len += textBox->len();
303
304     return wordBreakIterator(string.data(), len);
305
306
307 static TextBreakIterator* wordBreakIteratorForMaxOffsetBoundary(const VisiblePosition& visiblePosition, const InlineTextBox* textBox,
308     bool& nextBoxInDifferentBlock, Vector<UChar, 1024>& string, CachedLogicallyOrderedLeafBoxes& leafBoxes)
309 {
310     nextBoxInDifferentBlock = false;
311
312     // FIXME: Handle the case when we don't have an inline text box.
313     const InlineBox* nextBox = logicallyNextBox(visiblePosition, textBox, nextBoxInDifferentBlock, leafBoxes);
314
315     int len = 0;
316     string.clear();
317     string.append(textBox->renderer().text()->deprecatedCharacters() + textBox->start(), textBox->len());
318     len += textBox->len();
319     if (nextBox && nextBox->isInlineTextBox()) {
320         const InlineTextBox* nextTextBox = toInlineTextBox(nextBox);
321         string.append(nextTextBox->renderer().text()->deprecatedCharacters() + nextTextBox->start(), nextTextBox->len());
322         len += nextTextBox->len();
323     }
324
325     return wordBreakIterator(string.data(), len);
326
327
328 static bool isLogicalStartOfWord(TextBreakIterator* iter, int position, bool hardLineBreak)
329 {
330     bool boundary = hardLineBreak ? true : isTextBreak(iter, position);
331     if (!boundary)
332         return false;
333
334     textBreakFollowing(iter, position);
335     // isWordTextBreak returns true after moving across a word and false after moving across a punctuation/space.
336     return isWordTextBreak(iter);
337 }
338
339 static bool islogicalEndOfWord(TextBreakIterator* iter, int position, bool hardLineBreak)
340 {
341     bool boundary = isTextBreak(iter, position);
342     return (hardLineBreak || boundary) && isWordTextBreak(iter);
343 }
344
345 enum CursorMovementDirection { MoveLeft, MoveRight };
346
347 static VisiblePosition visualWordPosition(const VisiblePosition& visiblePosition, CursorMovementDirection direction, 
348     bool skipsSpaceWhenMovingRight)
349 {
350     if (visiblePosition.isNull())
351         return VisiblePosition();
352
353     TextDirection blockDirection = directionOfEnclosingBlock(visiblePosition.deepEquivalent());
354     InlineBox* previouslyVisitedBox = 0;
355     VisiblePosition current = visiblePosition;
356     TextBreakIterator* iter = 0;
357
358     CachedLogicallyOrderedLeafBoxes leafBoxes;
359     Vector<UChar, 1024> string;
360
361     while (1) {
362         VisiblePosition adjacentCharacterPosition = direction == MoveRight ? current.right(true) : current.left(true); 
363         if (adjacentCharacterPosition == current || adjacentCharacterPosition.isNull())
364             return VisiblePosition();
365     
366         InlineBox* box;
367         int offsetInBox;
368         adjacentCharacterPosition.deepEquivalent().getInlineBoxAndOffset(UPSTREAM, box, offsetInBox);
369     
370         if (!box)
371             break;
372         if (!box->isInlineTextBox()) {
373             current = adjacentCharacterPosition;
374             continue;
375         }
376
377         InlineTextBox* textBox = toInlineTextBox(box);
378         int previousBoxLength = 0;
379         bool previousBoxInDifferentBlock = false;
380         bool nextBoxInDifferentBlock = false;
381         bool movingIntoNewBox = previouslyVisitedBox != box;
382
383         if (offsetInBox == box->caretMinOffset())
384             iter = wordBreakIteratorForMinOffsetBoundary(visiblePosition, textBox, previousBoxLength, previousBoxInDifferentBlock, string, leafBoxes);
385         else if (offsetInBox == box->caretMaxOffset())
386             iter = wordBreakIteratorForMaxOffsetBoundary(visiblePosition, textBox, nextBoxInDifferentBlock, string, leafBoxes);
387         else if (movingIntoNewBox) {
388             iter = wordBreakIterator(textBox->renderer().text()->deprecatedCharacters() + textBox->start(), textBox->len());
389             previouslyVisitedBox = box;
390         }
391
392         if (!iter)
393             break;
394
395         textBreakFirst(iter);
396         int offsetInIterator = offsetInBox - textBox->start() + previousBoxLength;
397
398         bool isWordBreak;
399         bool boxHasSameDirectionalityAsBlock = box->direction() == blockDirection;
400         bool movingBackward = (direction == MoveLeft && box->direction() == LTR) || (direction == MoveRight && box->direction() == RTL);
401         if ((skipsSpaceWhenMovingRight && boxHasSameDirectionalityAsBlock)
402             || (!skipsSpaceWhenMovingRight && movingBackward)) {
403             bool logicalStartInRenderer = offsetInBox == static_cast<int>(textBox->start()) && previousBoxInDifferentBlock;
404             isWordBreak = isLogicalStartOfWord(iter, offsetInIterator, logicalStartInRenderer);
405         } else {
406             bool logicalEndInRenderer = offsetInBox == static_cast<int>(textBox->start() + textBox->len()) && nextBoxInDifferentBlock;
407             isWordBreak = islogicalEndOfWord(iter, offsetInIterator, logicalEndInRenderer);
408         }      
409
410         if (isWordBreak)
411             return adjacentCharacterPosition;
412     
413         current = adjacentCharacterPosition;
414     }
415     return VisiblePosition();
416 }
417
418 VisiblePosition leftWordPosition(const VisiblePosition& visiblePosition, bool skipsSpaceWhenMovingRight)
419 {
420     VisiblePosition leftWordBreak = visualWordPosition(visiblePosition, MoveLeft, skipsSpaceWhenMovingRight);
421     leftWordBreak = visiblePosition.honorEditingBoundaryAtOrBefore(leftWordBreak);
422     
423     // FIXME: How should we handle a non-editable position?
424     if (leftWordBreak.isNull() && isEditablePosition(visiblePosition.deepEquivalent())) {
425         TextDirection blockDirection = directionOfEnclosingBlock(visiblePosition.deepEquivalent());
426         leftWordBreak = blockDirection == LTR ? startOfEditableContent(visiblePosition) : endOfEditableContent(visiblePosition);
427     }
428     return leftWordBreak;
429 }
430
431 VisiblePosition rightWordPosition(const VisiblePosition& visiblePosition, bool skipsSpaceWhenMovingRight)
432 {
433     VisiblePosition rightWordBreak = visualWordPosition(visiblePosition, MoveRight, skipsSpaceWhenMovingRight);
434     rightWordBreak = visiblePosition.honorEditingBoundaryAtOrBefore(rightWordBreak);
435
436     // FIXME: How should we handle a non-editable position?
437     if (rightWordBreak.isNull() && isEditablePosition(visiblePosition.deepEquivalent())) {
438         TextDirection blockDirection = directionOfEnclosingBlock(visiblePosition.deepEquivalent());
439         rightWordBreak = blockDirection == LTR ? endOfEditableContent(visiblePosition) : startOfEditableContent(visiblePosition);
440     }
441     return rightWordBreak;
442 }
443
444
445 enum BoundarySearchContextAvailability { DontHaveMoreContext, MayHaveMoreContext };
446
447 typedef unsigned (*BoundarySearchFunction)(const UChar*, unsigned length, unsigned offset, BoundarySearchContextAvailability, bool& needMoreContext);
448
449 static VisiblePosition previousBoundary(const VisiblePosition& c, BoundarySearchFunction searchFunction)
450 {
451     Position pos = c.deepEquivalent();
452     Node* boundary = pos.parentEditingBoundary();
453     if (!boundary)
454         return VisiblePosition();
455
456     Document& boundaryDocument = boundary->document();
457     Position start = createLegacyEditingPosition(boundary, 0).parentAnchoredEquivalent();
458     Position end = pos.parentAnchoredEquivalent();
459     RefPtr<Range> searchRange = Range::create(boundaryDocument);
460     
461     Vector<UChar, 1024> string;
462     unsigned suffixLength = 0;
463
464     ExceptionCode ec = 0;
465     if (requiresContextForWordBoundary(c.characterBefore())) {
466         RefPtr<Range> forwardsScanRange(boundaryDocument.createRange());
467         forwardsScanRange->setEndAfter(boundary, ec);
468         forwardsScanRange->setStart(end.deprecatedNode(), end.deprecatedEditingOffset(), ec);
469         TextIterator forwardsIterator(forwardsScanRange.get());
470         while (!forwardsIterator.atEnd()) {
471             const UChar* characters = forwardsIterator.characters();
472             int length = forwardsIterator.length();
473             int i = endOfFirstWordBoundaryContext(characters, length);
474             string.append(characters, i);
475             suffixLength += i;
476             if (i < length)
477                 break;
478             forwardsIterator.advance();
479         }
480     }
481
482     searchRange->setStart(start.deprecatedNode(), start.deprecatedEditingOffset(), ec);
483     searchRange->setEnd(end.deprecatedNode(), end.deprecatedEditingOffset(), ec);
484
485     ASSERT(!ec);
486     if (ec)
487         return VisiblePosition();
488
489     SimplifiedBackwardsTextIterator it(searchRange.get());
490     unsigned next = 0;
491     bool needMoreContext = false;
492     while (!it.atEnd()) {
493         bool inTextSecurityMode = it.node() && it.node()->renderer() && it.node()->renderer()->style().textSecurity() != TSNONE;
494         // iterate to get chunks until the searchFunction returns a non-zero value.
495         if (!inTextSecurityMode) 
496             string.insert(0, it.characters(), it.length());
497         else {
498             // Treat bullets used in the text security mode as regular characters when looking for boundaries
499             String iteratorString(it.characters(), it.length());
500 #if PLATFORM(IOS)
501             iteratorString = iteratorString.impl()->fill('x');
502 #else
503             iteratorString.fill('x');
504 #endif
505             string.insert(0, iteratorString.deprecatedCharacters(), iteratorString.length());
506         }
507         next = searchFunction(string.data(), string.size(), string.size() - suffixLength, MayHaveMoreContext, needMoreContext);
508         if (next > 1) // FIXME: This is a work around for https://webkit.org/b/115070. We need to provide more contexts in general case.
509             break;
510         it.advance();
511     }
512     if (needMoreContext) {
513         // The last search returned the beginning of the buffer and asked for more context,
514         // but there is no earlier text. Force a search with what's available.
515         next = searchFunction(string.data(), string.size(), string.size() - suffixLength, DontHaveMoreContext, needMoreContext);
516         ASSERT(!needMoreContext);
517     }
518
519     if (!next)
520         return VisiblePosition(it.atEnd() ? it.range()->startPosition() : pos, DOWNSTREAM);
521
522     Node* node = it.range()->startContainer();
523     if ((node->isTextNode() && static_cast<int>(next) <= node->maxCharacterOffset()) || (node->renderer() && node->renderer()->isBR() && !next))
524         // The next variable contains a usable index into a text node
525         return VisiblePosition(createLegacyEditingPosition(node, next), DOWNSTREAM);
526
527     // Use the character iterator to translate the next value into a DOM position.
528     BackwardsCharacterIterator charIt(searchRange.get());
529     charIt.advance(string.size() - suffixLength - next);
530     // FIXME: charIt can get out of shadow host.
531     return VisiblePosition(charIt.range()->endPosition(), DOWNSTREAM);
532 }
533
534 static VisiblePosition nextBoundary(const VisiblePosition& c, BoundarySearchFunction searchFunction)
535 {
536     Position pos = c.deepEquivalent();
537     Node* boundary = pos.parentEditingBoundary();
538     if (!boundary)
539         return VisiblePosition();
540
541     Document& boundaryDocument = boundary->document();
542     RefPtr<Range> searchRange(boundaryDocument.createRange());
543     Position start(pos.parentAnchoredEquivalent());
544
545     Vector<UChar, 1024> string;
546     unsigned prefixLength = 0;
547
548     if (requiresContextForWordBoundary(c.characterAfter())) {
549         RefPtr<Range> backwardsScanRange(boundaryDocument.createRange());
550         backwardsScanRange->setEnd(start.deprecatedNode(), start.deprecatedEditingOffset(), IGNORE_EXCEPTION);
551         SimplifiedBackwardsTextIterator backwardsIterator(backwardsScanRange.get());
552         while (!backwardsIterator.atEnd()) {
553             const UChar* characters = backwardsIterator.characters();
554             int length = backwardsIterator.length();
555             int i = startOfLastWordBoundaryContext(characters, length);
556             string.insert(0, characters + i, length - i);
557             prefixLength += length - i;
558             if (i > 0)
559                 break;
560             backwardsIterator.advance();
561         }
562     }
563
564     searchRange->selectNodeContents(boundary, IGNORE_EXCEPTION);
565     searchRange->setStart(start.deprecatedNode(), start.deprecatedEditingOffset(), IGNORE_EXCEPTION);
566     TextIterator it(searchRange.get(), TextIteratorEmitsCharactersBetweenAllVisiblePositions);
567     unsigned next = 0;
568     bool needMoreContext = false;
569     while (!it.atEnd()) {
570         bool inTextSecurityMode = it.node() && it.node()->renderer() && it.node()->renderer()->style().textSecurity() != TSNONE;
571         // Keep asking the iterator for chunks until the search function
572         // returns an end value not equal to the length of the string passed to it.
573         if (!inTextSecurityMode)
574             string.append(it.characters(), it.length());
575         else {
576             // Treat bullets used in the text security mode as regular characters when looking for boundaries
577             String iteratorString(it.characters(), it.length());
578 #if PLATFORM(IOS)
579             iteratorString = iteratorString.impl()->fill('x');
580 #else
581             iteratorString.fill('x');
582 #endif
583             string.append(iteratorString.deprecatedCharacters(), iteratorString.length());
584         }
585         next = searchFunction(string.data(), string.size(), prefixLength, MayHaveMoreContext, needMoreContext);
586         if (next != string.size())
587             break;
588         it.advance();
589     }
590     if (needMoreContext) {
591         // The last search returned the end of the buffer and asked for more context,
592         // but there is no further text. Force a search with what's available.
593         next = searchFunction(string.data(), string.size(), prefixLength, DontHaveMoreContext, needMoreContext);
594         ASSERT(!needMoreContext);
595     }
596     
597     if (it.atEnd() && next == string.size()) {
598         pos = it.range()->startPosition();
599     } else if (next != prefixLength) {
600         // Use the character iterator to translate the next value into a DOM position.
601         CharacterIterator charIt(searchRange.get(), TextIteratorEmitsCharactersBetweenAllVisiblePositions);
602         charIt.advance(next - prefixLength - 1);
603         RefPtr<Range> characterRange = charIt.range();
604         pos = characterRange->endPosition();
605         
606         if (*charIt.characters() == '\n') {
607             // FIXME: workaround for collapsed range (where only start position is correct) emitted for some emitted newlines (see rdar://5192593)
608             VisiblePosition visPos = VisiblePosition(pos);
609             if (visPos == VisiblePosition(characterRange->startPosition())) {
610                 charIt.advance(1);
611                 pos = charIt.range()->startPosition();
612             }
613         }
614     }
615
616     // generate VisiblePosition, use UPSTREAM affinity if possible
617     return VisiblePosition(pos, VP_UPSTREAM_IF_POSSIBLE);
618 }
619
620 // ---------
621
622 static unsigned startWordBoundary(const UChar* characters, unsigned length, unsigned offset, BoundarySearchContextAvailability mayHaveMoreContext, bool& needMoreContext)
623 {
624     ASSERT(offset);
625     if (mayHaveMoreContext && !startOfLastWordBoundaryContext(characters, offset)) {
626         needMoreContext = true;
627         return 0;
628     }
629     needMoreContext = false;
630     int start, end;
631     U16_BACK_1(characters, 0, offset);
632     findWordBoundary(characters, length, offset, &start, &end);
633     return start;
634 }
635
636 VisiblePosition startOfWord(const VisiblePosition &c, EWordSide side)
637 {
638     // FIXME: This returns a null VP for c at the start of the document
639     // and side == LeftWordIfOnBoundary
640     VisiblePosition p = c;
641     if (side == RightWordIfOnBoundary) {
642         // at paragraph end, the startofWord is the current position
643         if (isEndOfParagraph(c))
644             return c;
645         
646         p = c.next();
647         if (p.isNull())
648             return c;
649     }
650     return previousBoundary(p, startWordBoundary);
651 }
652
653 static unsigned endWordBoundary(const UChar* characters, unsigned length, unsigned offset, BoundarySearchContextAvailability mayHaveMoreContext, bool& needMoreContext)
654 {
655     ASSERT(offset <= length);
656     if (mayHaveMoreContext && endOfFirstWordBoundaryContext(characters + offset, length - offset) == static_cast<int>(length - offset)) {
657         needMoreContext = true;
658         return length;
659     }
660     needMoreContext = false;
661 #if PLATFORM(IOS)
662     // FIXME: Bug 126830: [iOS] Implement WebCore::findEndWordBoundary()
663     int start, end;
664     findWordBoundary(characters, length, offset, &start, &end);
665 #else
666     int end;
667     findEndWordBoundary(characters, length, offset, &end);
668 #endif
669     return end;
670 }
671
672 VisiblePosition endOfWord(const VisiblePosition &c, EWordSide side)
673 {
674     VisiblePosition p = c;
675     if (side == LeftWordIfOnBoundary) {
676         if (isStartOfParagraph(c))
677             return c;
678             
679         p = c.previous();
680         if (p.isNull())
681             return c;
682     } else if (isEndOfParagraph(c))
683         return c;
684     
685     return nextBoundary(p, endWordBoundary);
686 }
687
688 static unsigned previousWordPositionBoundary(const UChar* characters, unsigned length, unsigned offset, BoundarySearchContextAvailability mayHaveMoreContext, bool& needMoreContext)
689 {
690     if (mayHaveMoreContext && !startOfLastWordBoundaryContext(characters, offset)) {
691         needMoreContext = true;
692         return 0;
693     }
694     needMoreContext = false;
695     return findNextWordFromIndex(characters, length, offset, false);
696 }
697
698 VisiblePosition previousWordPosition(const VisiblePosition &c)
699 {
700     VisiblePosition prev = previousBoundary(c, previousWordPositionBoundary);
701     return c.honorEditingBoundaryAtOrBefore(prev);
702 }
703
704 static unsigned nextWordPositionBoundary(const UChar* characters, unsigned length, unsigned offset, BoundarySearchContextAvailability mayHaveMoreContext, bool& needMoreContext)
705 {
706     if (mayHaveMoreContext && endOfFirstWordBoundaryContext(characters + offset, length - offset) == static_cast<int>(length - offset)) {
707         needMoreContext = true;
708         return length;
709     }
710     needMoreContext = false;
711     return findNextWordFromIndex(characters, length, offset, true);
712 }
713
714 VisiblePosition nextWordPosition(const VisiblePosition &c)
715 {
716     VisiblePosition next = nextBoundary(c, nextWordPositionBoundary);    
717     return c.honorEditingBoundaryAtOrAfter(next);
718 }
719
720 bool isStartOfWord(const VisiblePosition& p)
721 {
722     return p.isNotNull() && p == startOfWord(p, RightWordIfOnBoundary);
723 }
724
725 // ---------
726
727 enum LineEndpointComputationMode { UseLogicalOrdering, UseInlineBoxOrdering };
728 static VisiblePosition startPositionForLine(const VisiblePosition& c, LineEndpointComputationMode mode)
729 {
730     if (c.isNull())
731         return VisiblePosition();
732
733     RootInlineBox* rootBox = RenderedPosition(c).rootBox();
734     if (!rootBox) {
735         // There are VisiblePositions at offset 0 in blocks without
736         // RootInlineBoxes, like empty editable blocks and bordered blocks.
737         Position p = c.deepEquivalent();
738         if (p.deprecatedNode()->renderer() && p.deprecatedNode()->renderer()->isRenderBlock() && !p.deprecatedEditingOffset())
739             return c;
740
741         return VisiblePosition();
742     }
743
744     Node* startNode;
745     InlineBox* startBox;
746     if (mode == UseLogicalOrdering) {
747         startNode = rootBox->getLogicalStartBoxWithNode(startBox);
748         if (!startNode)
749             return VisiblePosition();
750     } else {
751         // Generated content (e.g. list markers and CSS :before and :after pseudoelements) have no corresponding DOM element,
752         // and so cannot be represented by a VisiblePosition. Use whatever follows instead.
753         startBox = rootBox->firstLeafChild();
754         while (true) {
755             if (!startBox)
756                 return VisiblePosition();
757
758             startNode = startBox->renderer().nonPseudoNode();
759             if (startNode)
760                 break;
761
762             startBox = startBox->nextLeafChild();
763         }
764     }
765
766     return startNode->isTextNode() ? Position(toText(startNode), toInlineTextBox(startBox)->start())
767         : positionBeforeNode(startNode);
768 }
769
770 static VisiblePosition startOfLine(const VisiblePosition& c, LineEndpointComputationMode mode)
771 {
772     // TODO: this is the current behavior that might need to be fixed.
773     // Please refer to https://bugs.webkit.org/show_bug.cgi?id=49107 for detail.
774     VisiblePosition visPos = startPositionForLine(c, mode);
775
776     if (mode == UseLogicalOrdering) {
777         if (Node* editableRoot = highestEditableRoot(c.deepEquivalent())) {
778             if (!editableRoot->contains(visPos.deepEquivalent().containerNode()))
779                 return firstPositionInNode(editableRoot);
780         }
781     }
782
783     return c.honorEditingBoundaryAtOrBefore(visPos);
784 }
785
786 // FIXME: Rename this function to reflect the fact it ignores bidi levels.
787 VisiblePosition startOfLine(const VisiblePosition& currentPosition)
788 {
789     return startOfLine(currentPosition, UseInlineBoxOrdering);
790 }
791
792 VisiblePosition logicalStartOfLine(const VisiblePosition& currentPosition)
793 {
794     return startOfLine(currentPosition, UseLogicalOrdering);
795 }
796
797 static VisiblePosition endPositionForLine(const VisiblePosition& c, LineEndpointComputationMode mode)
798 {
799     if (c.isNull())
800         return VisiblePosition();
801
802     RootInlineBox* rootBox = RenderedPosition(c).rootBox();
803     if (!rootBox) {
804         // There are VisiblePositions at offset 0 in blocks without
805         // RootInlineBoxes, like empty editable blocks and bordered blocks.
806         Position p = c.deepEquivalent();
807         if (p.deprecatedNode()->renderer() && p.deprecatedNode()->renderer()->isRenderBlock() && !p.deprecatedEditingOffset())
808             return c;
809         return VisiblePosition();
810     }
811
812     Node* endNode;
813     InlineBox* endBox;
814     if (mode == UseLogicalOrdering) {
815         endNode = rootBox->getLogicalEndBoxWithNode(endBox);
816         if (!endNode)
817             return VisiblePosition();
818     } else {
819         // Generated content (e.g. list markers and CSS :before and :after pseudoelements) have no corresponding DOM element,
820         // and so cannot be represented by a VisiblePosition. Use whatever precedes instead.
821         endBox = rootBox->lastLeafChild();
822         while (true) {
823             if (!endBox)
824                 return VisiblePosition();
825
826             endNode = endBox->renderer().nonPseudoNode();
827             if (endNode)
828                 break;
829             
830             endBox = endBox->prevLeafChild();
831         }
832     }
833
834     Position pos;
835     if (endNode->hasTagName(brTag))
836         pos = positionBeforeNode(endNode);
837     else if (endBox->isInlineTextBox() && endNode->isTextNode()) {
838         InlineTextBox* endTextBox = toInlineTextBox(endBox);
839         int endOffset = endTextBox->start();
840         if (!endTextBox->isLineBreak())
841             endOffset += endTextBox->len();
842         pos = Position(toText(endNode), endOffset);
843     } else
844         pos = positionAfterNode(endNode);
845     
846     return VisiblePosition(pos, VP_UPSTREAM_IF_POSSIBLE);
847 }
848
849 static bool inSameLogicalLine(const VisiblePosition& a, const VisiblePosition& b)
850 {
851     return a.isNotNull() && logicalStartOfLine(a) == logicalStartOfLine(b);
852 }
853
854 static VisiblePosition endOfLine(const VisiblePosition& c, LineEndpointComputationMode mode)
855 {
856     // TODO: this is the current behavior that might need to be fixed.
857     // Please refer to https://bugs.webkit.org/show_bug.cgi?id=49107 for detail.
858     VisiblePosition visPos = endPositionForLine(c, mode);
859
860     if (mode == UseLogicalOrdering) {
861         // Make sure the end of line is at the same line as the given input position. For a wrapping line, the logical end
862         // position for the not-last-2-lines might incorrectly hand back the logical beginning of the next line. 
863         // For example, <div contenteditable dir="rtl" style="line-break:before-white-space">abcdefg abcdefg abcdefg
864         // a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg </div>
865         // In this case, use the previous position of the computed logical end position.
866         if (!inSameLogicalLine(c, visPos))
867             visPos = visPos.previous();
868
869         if (Node* editableRoot = highestEditableRoot(c.deepEquivalent())) {
870             if (!editableRoot->contains(visPos.deepEquivalent().containerNode()))
871                 return lastPositionInNode(editableRoot);
872         }
873
874         return c.honorEditingBoundaryAtOrAfter(visPos);
875     }
876
877     // Make sure the end of line is at the same line as the given input position. Else use the previous position to 
878     // obtain end of line. This condition happens when the input position is before the space character at the end 
879     // of a soft-wrapped non-editable line. In this scenario, endPositionForLine would incorrectly hand back a position
880     // in the next line instead. This fix is to account for the discrepancy between lines with webkit-line-break:after-white-space style
881     // versus lines without that style, which would break before a space by default. 
882     if (!inSameLine(c, visPos)) {
883         visPos = c.previous();
884         if (visPos.isNull())
885             return VisiblePosition();
886         visPos = endPositionForLine(visPos, UseInlineBoxOrdering);
887     }
888     
889     return c.honorEditingBoundaryAtOrAfter(visPos);
890 }
891
892 // FIXME: Rename this function to reflect the fact it ignores bidi levels.
893 VisiblePosition endOfLine(const VisiblePosition& currentPosition)
894 {
895     return endOfLine(currentPosition, UseInlineBoxOrdering);
896 }
897
898 VisiblePosition logicalEndOfLine(const VisiblePosition& currentPosition)
899 {
900     return endOfLine(currentPosition, UseLogicalOrdering);
901 }
902
903 bool inSameLine(const VisiblePosition &a, const VisiblePosition &b)
904 {
905     return a.isNotNull() && startOfLine(a) == startOfLine(b);
906 }
907
908 bool isStartOfLine(const VisiblePosition &p)
909 {
910     return p.isNotNull() && p == startOfLine(p);
911 }
912
913 bool isEndOfLine(const VisiblePosition &p)
914 {
915     return p.isNotNull() && p == endOfLine(p);
916 }
917
918 static inline IntPoint absoluteLineDirectionPointToLocalPointInBlock(RootInlineBox* root, int lineDirectionPoint)
919 {
920     ASSERT(root);
921     RenderBlockFlow& containingBlock = root->blockFlow();
922     FloatPoint absoluteBlockPoint = containingBlock.localToAbsolute(FloatPoint());
923     if (containingBlock.hasOverflowClip())
924         absoluteBlockPoint -= containingBlock.scrolledContentOffset();
925
926     if (containingBlock.isHorizontalWritingMode())
927         return IntPoint(lineDirectionPoint - absoluteBlockPoint.x(), root->blockDirectionPointInLine());
928
929     return IntPoint(root->blockDirectionPointInLine(), lineDirectionPoint - absoluteBlockPoint.y());
930 }
931
932 VisiblePosition previousLinePosition(const VisiblePosition &visiblePosition, int lineDirectionPoint, EditableType editableType)
933 {
934     Position p = visiblePosition.deepEquivalent();
935     Node* node = p.deprecatedNode();
936
937     if (!node)
938         return VisiblePosition();
939     
940     node->document().updateLayoutIgnorePendingStylesheets();
941     
942     RenderObject* renderer = node->renderer();
943     if (!renderer)
944         return VisiblePosition();
945
946     RootInlineBox* root = 0;
947     InlineBox* box;
948     int ignoredCaretOffset;
949     visiblePosition.getInlineBoxAndOffset(box, ignoredCaretOffset);
950     if (box) {
951         root = box->root().prevRootBox();
952         // We want to skip zero height boxes.
953         // This could happen in case it is a TrailingFloatsRootInlineBox.
954         if (!root || !root->logicalHeight() || !root->firstLeafChild())
955             root = 0;
956     }
957
958     if (!root) {
959         Position position = previousRootInlineBoxCandidatePosition(node, visiblePosition, editableType);
960         if (position.isNotNull()) {
961             RenderedPosition renderedPosition(position);
962             root = renderedPosition.rootBox();
963             if (!root)
964                 return position;
965         }
966     }
967     
968     if (root) {
969         // FIXME: Can be wrong for multi-column layout and with transforms.
970         IntPoint pointInLine = absoluteLineDirectionPointToLocalPointInBlock(root, lineDirectionPoint);
971         RenderObject& renderer = root->closestLeafChildForPoint(pointInLine, isEditablePosition(p))->renderer();
972         Node* node = renderer.node();
973         if (node && editingIgnoresContent(node))
974             return positionInParentBeforeNode(node);
975         return renderer.positionForPoint(pointInLine);
976     }
977     
978     // Could not find a previous line. This means we must already be on the first line.
979     // Move to the start of the content in this block, which effectively moves us
980     // to the start of the line we're on.
981     Element* rootElement = node->hasEditableStyle(editableType) ? node->rootEditableElement(editableType) : node->document().documentElement();
982     if (!rootElement)
983         return VisiblePosition();
984     return VisiblePosition(firstPositionInNode(rootElement), DOWNSTREAM);
985 }
986
987 VisiblePosition nextLinePosition(const VisiblePosition &visiblePosition, int lineDirectionPoint, EditableType editableType)
988 {
989     Position p = visiblePosition.deepEquivalent();
990     Node* node = p.deprecatedNode();
991
992     if (!node)
993         return VisiblePosition();
994     
995     node->document().updateLayoutIgnorePendingStylesheets();
996
997     RenderObject* renderer = node->renderer();
998     if (!renderer)
999         return VisiblePosition();
1000
1001     RootInlineBox* root = 0;
1002     InlineBox* box;
1003     int ignoredCaretOffset;
1004     visiblePosition.getInlineBoxAndOffset(box, ignoredCaretOffset);
1005     if (box) {
1006         root = box->root().nextRootBox();
1007         // We want to skip zero height boxes.
1008         // This could happen in case it is a TrailingFloatsRootInlineBox.
1009         if (!root || !root->logicalHeight() || !root->firstLeafChild())
1010             root = 0;
1011     }
1012
1013     if (!root) {
1014         // FIXME: We need do the same in previousLinePosition.
1015         Node* child = node->childNode(p.deprecatedEditingOffset());
1016         node = child ? child : node->lastDescendant();
1017         Position position = nextRootInlineBoxCandidatePosition(node, visiblePosition, editableType);
1018         if (position.isNotNull()) {
1019             RenderedPosition renderedPosition(position);
1020             root = renderedPosition.rootBox();
1021             if (!root)
1022                 return position;
1023         }
1024     }
1025     
1026     if (root) {
1027         // FIXME: Can be wrong for multi-column layout and with transforms.
1028         IntPoint pointInLine = absoluteLineDirectionPointToLocalPointInBlock(root, lineDirectionPoint);
1029         RenderObject& renderer = root->closestLeafChildForPoint(pointInLine, isEditablePosition(p))->renderer();
1030         Node* node = renderer.node();
1031         if (node && editingIgnoresContent(node))
1032             return positionInParentBeforeNode(node);
1033         return renderer.positionForPoint(pointInLine);
1034     }
1035
1036     // Could not find a next line. This means we must already be on the last line.
1037     // Move to the end of the content in this block, which effectively moves us
1038     // to the end of the line we're on.
1039     Element* rootElement = node->hasEditableStyle(editableType) ? node->rootEditableElement(editableType) : node->document().documentElement();
1040     if (!rootElement)
1041         return VisiblePosition();
1042     return VisiblePosition(lastPositionInNode(rootElement), DOWNSTREAM);
1043 }
1044
1045 // ---------
1046
1047 static unsigned startSentenceBoundary(const UChar* characters, unsigned length, unsigned, BoundarySearchContextAvailability, bool&)
1048 {
1049     TextBreakIterator* iterator = sentenceBreakIterator(characters, length);
1050     // FIXME: The following function can return -1; we don't handle that.
1051     return textBreakPreceding(iterator, length);
1052 }
1053
1054 VisiblePosition startOfSentence(const VisiblePosition &c)
1055 {
1056     return previousBoundary(c, startSentenceBoundary);
1057 }
1058
1059 static unsigned endSentenceBoundary(const UChar* characters, unsigned length, unsigned, BoundarySearchContextAvailability, bool&)
1060 {
1061     TextBreakIterator* iterator = sentenceBreakIterator(characters, length);
1062     return textBreakNext(iterator);
1063 }
1064
1065 // FIXME: This includes the space after the punctuation that marks the end of the sentence.
1066 VisiblePosition endOfSentence(const VisiblePosition &c)
1067 {
1068     return nextBoundary(c, endSentenceBoundary);
1069 }
1070
1071 static unsigned previousSentencePositionBoundary(const UChar* characters, unsigned length, unsigned, BoundarySearchContextAvailability, bool&)
1072 {
1073     // FIXME: This is identical to startSentenceBoundary. I'm pretty sure that's not right.
1074     TextBreakIterator* iterator = sentenceBreakIterator(characters, length);
1075     // FIXME: The following function can return -1; we don't handle that.
1076     return textBreakPreceding(iterator, length);
1077 }
1078
1079 VisiblePosition previousSentencePosition(const VisiblePosition &c)
1080 {
1081     VisiblePosition prev = previousBoundary(c, previousSentencePositionBoundary);
1082     return c.honorEditingBoundaryAtOrBefore(prev);
1083 }
1084
1085 static unsigned nextSentencePositionBoundary(const UChar* characters, unsigned length, unsigned, BoundarySearchContextAvailability, bool&)
1086 {
1087     // FIXME: This is identical to endSentenceBoundary. This isn't right, it needs to 
1088     // move to the equivlant position in the following sentence.
1089     TextBreakIterator* iterator = sentenceBreakIterator(characters, length);
1090     return textBreakFollowing(iterator, 0);
1091 }
1092
1093 VisiblePosition nextSentencePosition(const VisiblePosition &c)
1094 {
1095     VisiblePosition next = nextBoundary(c, nextSentencePositionBoundary);    
1096     return c.honorEditingBoundaryAtOrAfter(next);
1097 }
1098
1099 VisiblePosition startOfParagraph(const VisiblePosition& c, EditingBoundaryCrossingRule boundaryCrossingRule)
1100 {
1101     Position p = c.deepEquivalent();
1102     Node* startNode = p.deprecatedNode();
1103
1104     if (!startNode)
1105         return VisiblePosition();
1106     
1107     if (isRenderedAsNonInlineTableImageOrHR(startNode))
1108         return positionBeforeNode(startNode);
1109
1110     Node* startBlock = enclosingBlock(startNode);
1111
1112     Node* node = startNode;
1113     Node* highestRoot = highestEditableRoot(p);
1114     int offset = p.deprecatedEditingOffset();
1115     Position::AnchorType type = p.anchorType();
1116
1117     Node* n = startNode;
1118     while (n) {
1119 #if ENABLE(USERSELECT_ALL)
1120         if (boundaryCrossingRule == CannotCrossEditingBoundary && !Position::nodeIsUserSelectAll(n) && n->hasEditableStyle() != startNode->hasEditableStyle())
1121 #else
1122         if (boundaryCrossingRule == CannotCrossEditingBoundary && n->hasEditableStyle() != startNode->hasEditableStyle())
1123 #endif
1124             break;
1125         if (boundaryCrossingRule == CanSkipOverEditingBoundary) {
1126             while (n && n->hasEditableStyle() != startNode->hasEditableStyle())
1127                 n = NodeTraversal::previousPostOrder(n, startBlock);
1128             if (!n || !n->isDescendantOf(highestRoot))
1129                 break;
1130         }
1131         RenderObject* r = n->renderer();
1132         if (!r) {
1133             n = NodeTraversal::previousPostOrder(n, startBlock);
1134             continue;
1135         }
1136         const RenderStyle& style = r->style();
1137         if (style.visibility() != VISIBLE) {
1138             n = NodeTraversal::previousPostOrder(n, startBlock);
1139             continue;
1140         }
1141         
1142         if (r->isBR() || isBlock(n))
1143             break;
1144
1145         if (r->isText() && toRenderText(r)->hasRenderedText()) {
1146             ASSERT_WITH_SECURITY_IMPLICATION(n->isTextNode());
1147             type = Position::PositionIsOffsetInAnchor;
1148             if (style.preserveNewline()) {
1149                 const UChar* chars = toRenderText(r)->characters();
1150                 int i = toRenderText(r)->textLength();
1151                 int o = offset;
1152                 if (n == startNode && o < i)
1153                     i = std::max(0, o);
1154                 while (--i >= 0) {
1155                     if (chars[i] == '\n')
1156                         return VisiblePosition(Position(toText(n), i + 1), DOWNSTREAM);
1157                 }
1158             }
1159             node = n;
1160             offset = 0;
1161             n = NodeTraversal::previousPostOrder(n, startBlock);
1162         } else if (editingIgnoresContent(n) || isTableElement(n)) {
1163             node = n;
1164             type = Position::PositionIsBeforeAnchor;
1165             n = n->previousSibling() ? n->previousSibling() : NodeTraversal::previousPostOrder(n, startBlock);
1166         } else
1167             n = NodeTraversal::previousPostOrder(n, startBlock);
1168     }
1169
1170     if (type == Position::PositionIsOffsetInAnchor) {
1171         ASSERT(type == Position::PositionIsOffsetInAnchor || !offset);
1172         return VisiblePosition(Position(node, offset, type), DOWNSTREAM);
1173     }
1174
1175     return VisiblePosition(Position(node, type), DOWNSTREAM);
1176 }
1177
1178 VisiblePosition endOfParagraph(const VisiblePosition &c, EditingBoundaryCrossingRule boundaryCrossingRule)
1179 {    
1180     if (c.isNull())
1181         return VisiblePosition();
1182
1183     Position p = c.deepEquivalent();
1184     Node* startNode = p.deprecatedNode();
1185
1186     if (isRenderedAsNonInlineTableImageOrHR(startNode))
1187         return positionAfterNode(startNode);
1188     
1189     Node* startBlock = enclosingBlock(startNode);
1190     Node* stayInsideBlock = startBlock;
1191     
1192     Node* node = startNode;
1193     Node* highestRoot = highestEditableRoot(p);
1194     int offset = p.deprecatedEditingOffset();
1195     Position::AnchorType type = p.anchorType();
1196
1197     Node* n = startNode;
1198     while (n) {
1199 #if ENABLE(USERSELECT_ALL)
1200         if (boundaryCrossingRule == CannotCrossEditingBoundary && !Position::nodeIsUserSelectAll(n) && n->hasEditableStyle() != startNode->hasEditableStyle())
1201 #else
1202         if (boundaryCrossingRule == CannotCrossEditingBoundary && n->hasEditableStyle() != startNode->hasEditableStyle())
1203 #endif
1204             break;
1205         if (boundaryCrossingRule == CanSkipOverEditingBoundary) {
1206             while (n && n->hasEditableStyle() != startNode->hasEditableStyle())
1207                 n = NodeTraversal::next(n, stayInsideBlock);
1208             if (!n || !n->isDescendantOf(highestRoot))
1209                 break;
1210         }
1211
1212         RenderObject* r = n->renderer();
1213         if (!r) {
1214             n = NodeTraversal::next(n, stayInsideBlock);
1215             continue;
1216         }
1217         const RenderStyle& style = r->style();
1218         if (style.visibility() != VISIBLE) {
1219             n = NodeTraversal::next(n, stayInsideBlock);
1220             continue;
1221         }
1222         
1223         if (r->isBR() || isBlock(n))
1224             break;
1225
1226         // FIXME: We avoid returning a position where the renderer can't accept the caret.
1227         if (r->isText() && toRenderText(r)->hasRenderedText()) {
1228             ASSERT_WITH_SECURITY_IMPLICATION(n->isTextNode());
1229             int length = toRenderText(r)->textLength();
1230             type = Position::PositionIsOffsetInAnchor;
1231             if (style.preserveNewline()) {
1232                 const UChar* chars = toRenderText(r)->characters();
1233                 int o = n == startNode ? offset : 0;
1234                 for (int i = o; i < length; ++i) {
1235                     if (chars[i] == '\n')
1236                         return VisiblePosition(Position(toText(n), i), DOWNSTREAM);
1237                 }
1238             }
1239             node = n;
1240             offset = r->caretMaxOffset();
1241             n = NodeTraversal::next(n, stayInsideBlock);
1242         } else if (editingIgnoresContent(n) || isTableElement(n)) {
1243             node = n;
1244             type = Position::PositionIsAfterAnchor;
1245             n = NodeTraversal::nextSkippingChildren(n, stayInsideBlock);
1246         } else
1247             n = NodeTraversal::next(n, stayInsideBlock);
1248     }
1249
1250     if (type == Position::PositionIsOffsetInAnchor)
1251         return VisiblePosition(Position(node, offset, type), DOWNSTREAM);
1252
1253     return VisiblePosition(Position(node, type), DOWNSTREAM);
1254 }
1255
1256 // FIXME: isStartOfParagraph(startOfNextParagraph(pos)) is not always true
1257 VisiblePosition startOfNextParagraph(const VisiblePosition& visiblePosition)
1258 {
1259     VisiblePosition paragraphEnd(endOfParagraph(visiblePosition, CanSkipOverEditingBoundary));
1260     VisiblePosition afterParagraphEnd(paragraphEnd.next(CannotCrossEditingBoundary));
1261     // The position after the last position in the last cell of a table
1262     // is not the start of the next paragraph.
1263     if (isFirstPositionAfterTable(afterParagraphEnd))
1264         return afterParagraphEnd.next(CannotCrossEditingBoundary);
1265     return afterParagraphEnd;
1266 }
1267
1268 bool inSameParagraph(const VisiblePosition &a, const VisiblePosition &b, EditingBoundaryCrossingRule boundaryCrossingRule)
1269 {
1270     return a.isNotNull() && startOfParagraph(a, boundaryCrossingRule) == startOfParagraph(b, boundaryCrossingRule);
1271 }
1272
1273 bool isStartOfParagraph(const VisiblePosition &pos, EditingBoundaryCrossingRule boundaryCrossingRule)
1274 {
1275     return pos.isNotNull() && pos == startOfParagraph(pos, boundaryCrossingRule);
1276 }
1277
1278 bool isEndOfParagraph(const VisiblePosition &pos, EditingBoundaryCrossingRule boundaryCrossingRule)
1279 {
1280     return pos.isNotNull() && pos == endOfParagraph(pos, boundaryCrossingRule);
1281 }
1282
1283 VisiblePosition previousParagraphPosition(const VisiblePosition& p, int x)
1284 {
1285     VisiblePosition pos = p;
1286     do {
1287         VisiblePosition n = previousLinePosition(pos, x);
1288         if (n.isNull() || n == pos)
1289             break;
1290         pos = n;
1291     } while (inSameParagraph(p, pos));
1292     return pos;
1293 }
1294
1295 VisiblePosition nextParagraphPosition(const VisiblePosition& p, int x)
1296 {
1297     VisiblePosition pos = p;
1298     do {
1299         VisiblePosition n = nextLinePosition(pos, x);
1300         if (n.isNull() || n == pos)
1301             break;
1302         pos = n;
1303     } while (inSameParagraph(p, pos));
1304     return pos;
1305 }
1306
1307 // ---------
1308
1309 VisiblePosition startOfBlock(const VisiblePosition& visiblePosition, EditingBoundaryCrossingRule rule)
1310 {
1311     Position position = visiblePosition.deepEquivalent();
1312     Node* startBlock;
1313     if (!position.containerNode() || !(startBlock = enclosingBlock(position.containerNode(), rule)))
1314         return VisiblePosition();
1315     return firstPositionInNode(startBlock);
1316 }
1317
1318 VisiblePosition endOfBlock(const VisiblePosition& visiblePosition, EditingBoundaryCrossingRule rule)
1319 {
1320     Position position = visiblePosition.deepEquivalent();
1321     Node* endBlock;
1322     if (!position.containerNode() || !(endBlock = enclosingBlock(position.containerNode(), rule)))
1323         return VisiblePosition();
1324     return lastPositionInNode(endBlock);
1325 }
1326
1327 bool inSameBlock(const VisiblePosition &a, const VisiblePosition &b)
1328 {
1329     return !a.isNull() && enclosingBlock(a.deepEquivalent().containerNode()) == enclosingBlock(b.deepEquivalent().containerNode());
1330 }
1331
1332 bool isStartOfBlock(const VisiblePosition &pos)
1333 {
1334     return pos.isNotNull() && pos == startOfBlock(pos, CanCrossEditingBoundary);
1335 }
1336
1337 bool isEndOfBlock(const VisiblePosition &pos)
1338 {
1339     return pos.isNotNull() && pos == endOfBlock(pos, CanCrossEditingBoundary);
1340 }
1341
1342 // ---------
1343
1344 VisiblePosition startOfDocument(const Node* node)
1345 {
1346     if (!node || !node->document().documentElement())
1347         return VisiblePosition();
1348     
1349 #if PLATFORM(IOS)
1350     // The canonicalization of the position at (documentElement, 0) can turn the visible
1351     // position to null, even when there's a valid candidate to be had, because the root HTML element
1352     // is not content editable.  So we construct directly from the valid candidate.
1353     // FIXME: Merge this to Open Source. https://bugs.webkit.org/show_bug.cgi?id=56437
1354     Position firstCandidate = nextCandidate(createLegacyEditingPosition(node->document().documentElement(), 0));
1355     if (firstCandidate.isNull())
1356         return VisiblePosition();
1357     return VisiblePosition(firstCandidate);
1358 #else
1359     return VisiblePosition(firstPositionInNode(node->document().documentElement()), DOWNSTREAM);
1360 #endif
1361 }
1362
1363 VisiblePosition startOfDocument(const VisiblePosition &c)
1364 {
1365     return startOfDocument(c.deepEquivalent().deprecatedNode());
1366 }
1367
1368 VisiblePosition endOfDocument(const Node* node)
1369 {
1370     if (!node || !node->document().documentElement())
1371         return VisiblePosition();
1372     
1373 #if PLATFORM(IOS)
1374     // (As above, in startOfDocument.)  The canonicalization can reject valid visible positions
1375     // when descending from the root element, so we construct the visible position directly from a
1376     // valid candidate.
1377     // FIXME: Merge this to Open Source. https://bugs.webkit.org/show_bug.cgi?id=56437
1378 #endif
1379     Element* doc = node->document().documentElement();
1380 #if PLATFORM(IOS)
1381     Position lastPosition = createLegacyEditingPosition(node->document().documentElement(), doc->childNodeCount());
1382     Position lastCandidate = previousCandidate(lastPosition);
1383     if (lastCandidate.isNull())
1384         return VisiblePosition();
1385     return VisiblePosition(lastCandidate);
1386 #endif
1387     return VisiblePosition(lastPositionInNode(doc), DOWNSTREAM);
1388 }
1389
1390 VisiblePosition endOfDocument(const VisiblePosition &c)
1391 {
1392     return endOfDocument(c.deepEquivalent().deprecatedNode());
1393 }
1394
1395 bool inSameDocument(const VisiblePosition &a, const VisiblePosition &b)
1396 {
1397     Position ap = a.deepEquivalent();
1398     Node* an = ap.deprecatedNode();
1399     if (!an)
1400         return false;
1401     Position bp = b.deepEquivalent();
1402     Node* bn = bp.deprecatedNode();
1403     if (an == bn)
1404         return true;
1405
1406     return &an->document() == &bn->document();
1407 }
1408
1409 bool isStartOfDocument(const VisiblePosition &p)
1410 {
1411     return p.isNotNull() && p.previous(CanCrossEditingBoundary).isNull();
1412 }
1413
1414 bool isEndOfDocument(const VisiblePosition &p)
1415 {
1416     return p.isNotNull() && p.next(CanCrossEditingBoundary).isNull();
1417 }
1418
1419 // ---------
1420
1421 VisiblePosition startOfEditableContent(const VisiblePosition& visiblePosition)
1422 {
1423     Node* highestRoot = highestEditableRoot(visiblePosition.deepEquivalent());
1424     if (!highestRoot)
1425         return VisiblePosition();
1426
1427     return firstPositionInNode(highestRoot);
1428 }
1429
1430 VisiblePosition endOfEditableContent(const VisiblePosition& visiblePosition)
1431 {
1432     Node* highestRoot = highestEditableRoot(visiblePosition.deepEquivalent());
1433     if (!highestRoot)
1434         return VisiblePosition();
1435
1436     return lastPositionInNode(highestRoot);
1437 }
1438
1439 bool isEndOfEditableOrNonEditableContent(const VisiblePosition &p)
1440 {
1441     return p.isNotNull() && p.next().isNull();
1442 }
1443
1444 VisiblePosition leftBoundaryOfLine(const VisiblePosition& c, TextDirection direction)
1445 {
1446     return direction == LTR ? logicalStartOfLine(c) : logicalEndOfLine(c);
1447 }
1448
1449 VisiblePosition rightBoundaryOfLine(const VisiblePosition& c, TextDirection direction)
1450 {
1451     return direction == LTR ? logicalEndOfLine(c) : logicalStartOfLine(c);
1452 }
1453
1454 #if PLATFORM(IOS)
1455 static bool directionIsDownstream(SelectionDirection direction)
1456 {
1457     if (direction == DirectionBackward)
1458         return false;
1459     else if (direction == DirectionForward)
1460         return true;
1461
1462     // FIXME: this code doesn't take into account the original direction of the element.
1463     // I'm not fixing this now because I'm afraid there is some code in UIKit relying on
1464     // this wrong behavior.
1465     return direction == DirectionRight;
1466 }
1467
1468 bool atBoundaryOfGranularity(const VisiblePosition& vp, TextGranularity granularity, SelectionDirection direction)
1469 {
1470     if (granularity == CharacterGranularity)
1471         return true;
1472
1473     VisiblePosition boundary;
1474
1475     bool useDownstream = directionIsDownstream(direction);
1476
1477     switch (granularity) {
1478     case WordGranularity:
1479         // visible_units claims erroneously that the start and the end
1480         // of a paragraph are the end and start of a word, respectively.
1481         if ((useDownstream && isStartOfParagraph(vp)) || (!useDownstream && isEndOfParagraph(vp)))
1482             return false;
1483
1484         // Note that "Left" and "Right" in this context apparently mean "upstream/previous" and "downstream/next".
1485         boundary = useDownstream ? endOfWord(vp, LeftWordIfOnBoundary) : startOfWord(vp, RightWordIfOnBoundary);
1486         break;
1487
1488     case SentenceGranularity:
1489         boundary = useDownstream ? endOfSentence(vp) : startOfSentence(vp);
1490         break;
1491
1492     case LineGranularity:
1493         // Affinity has to be set to get right boundary of the line.
1494         boundary = vp;
1495         boundary.setAffinity(useDownstream ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM);
1496         boundary = useDownstream ? endOfLine(boundary) : startOfLine(boundary);
1497         break;
1498
1499     case ParagraphGranularity:
1500         boundary = useDownstream ? endOfParagraph(vp) : startOfParagraph(vp);
1501         break;
1502
1503     case DocumentGranularity:
1504         boundary = useDownstream ? endOfDocument(vp) : startOfDocument(vp);
1505         break;
1506
1507     default:
1508         ASSERT_NOT_REACHED();
1509         break;
1510     }
1511
1512     return vp == boundary;
1513 }
1514
1515 bool withinTextUnitOfGranularity(const VisiblePosition& vp, TextGranularity granularity, SelectionDirection direction)
1516 {
1517     if (granularity == CharacterGranularity || granularity == DocumentGranularity)
1518         return true;
1519
1520     bool useDownstream = directionIsDownstream(direction);
1521
1522     VisiblePosition prevBoundary;
1523     VisiblePosition nextBoundary;
1524     
1525     switch (granularity) {
1526     case WordGranularity:
1527         // Note that "Left" and "Right" in this context apparently mean "upstream/previous" and "downstream/next".
1528         prevBoundary = startOfWord(vp, (useDownstream ? RightWordIfOnBoundary : LeftWordIfOnBoundary));
1529         nextBoundary = endOfWord(vp, (useDownstream ? RightWordIfOnBoundary : LeftWordIfOnBoundary));
1530     
1531         // Workaround for <rdar://problem/7259611> Word boundary code on iPhone gives different results than desktop
1532         if (endOfWord(prevBoundary, RightWordIfOnBoundary) != nextBoundary)
1533             return false;
1534
1535         break;
1536
1537     case SentenceGranularity:
1538         prevBoundary = startOfSentence(vp);
1539         nextBoundary = endOfSentence(vp);
1540         break;
1541
1542     case LineGranularity:
1543         prevBoundary = startOfLine(vp);
1544         nextBoundary = endOfLine(vp);
1545
1546         if (prevBoundary == nextBoundary) {
1547             nextBoundary = nextLinePosition(nextBoundary, 0);
1548             nextBoundary.setAffinity(UPSTREAM);
1549             if (!inSameLine(prevBoundary, nextBoundary))
1550                 nextBoundary = vp.next();
1551         }
1552         break;
1553
1554     case ParagraphGranularity:
1555         prevBoundary = startOfParagraph(vp);
1556         nextBoundary = endOfParagraph(vp);
1557         break;
1558
1559     default:
1560         ASSERT_NOT_REACHED();
1561         break;
1562     }
1563
1564     if (prevBoundary == nextBoundary)
1565         return false;
1566
1567     if (vp == prevBoundary)
1568         return useDownstream;
1569
1570     if (vp == nextBoundary)
1571         return !useDownstream;
1572
1573     return (prevBoundary < vp && vp < nextBoundary);
1574 }
1575
1576 static VisiblePosition nextCharacterBoundaryInDirection(const VisiblePosition& vp, SelectionDirection direction)
1577 {
1578     return directionIsDownstream(direction) ? vp.next() : vp.previous();
1579 }
1580
1581 static VisiblePosition nextWordBoundaryInDirection(const VisiblePosition& vp, SelectionDirection direction)
1582 {
1583     bool useDownstream = directionIsDownstream(direction);
1584     bool withinUnitOfGranularity = withinTextUnitOfGranularity(vp, WordGranularity, direction);
1585     VisiblePosition result;
1586     
1587     if (useDownstream) {
1588         if (withinUnitOfGranularity)
1589             result = endOfWord(vp, RightWordIfOnBoundary);
1590         else {
1591             VisiblePosition start = startOfWord(vp, RightWordIfOnBoundary);
1592             if (start > vp && start != endOfWord(start))
1593                 result = start;
1594             else {
1595                 // Do same thing as backwards traveling below.
1596                 start = vp;
1597                 while (true) {
1598                     result = startOfWord(nextWordPosition(start), RightWordIfOnBoundary);
1599
1600                     if (result == start)
1601                         break;
1602
1603                     // We failed to find a word boundary.
1604                     if (result.isNull() || result < start)
1605                         return VisiblePosition();
1606
1607                     // We consider successs also the case where start is before element and result is after.
1608                     // This covers moving past images like words.
1609                     if (result != endOfWord(result)
1610                         || (result.deepEquivalent().anchorNode() == start.deepEquivalent().anchorNode()
1611                             && result.deepEquivalent().anchorType() == Position::PositionIsAfterAnchor
1612                             && start.deepEquivalent().anchorType() == Position::PositionIsBeforeAnchor))
1613                         break;
1614
1615                     start = result;
1616                 }
1617             }
1618         }
1619     } else {
1620         if (withinUnitOfGranularity)
1621             result = startOfWord(vp, LeftWordIfOnBoundary);
1622         else {
1623             // This is complicated because:
1624             //   When given "Blah blah.|", endOfWord is "Blah blah|.", and previousWordPosition is "Blah| blah."
1625             //   When given "Blah blah. |", endOfWord is "Blah blah.| ", and previousWordPosition is "Blah |blah. ".
1626             VisiblePosition end = endOfWord(vp, LeftWordIfOnBoundary);
1627             if (end < vp && end != startOfWord(end))
1628                 result = end;
1629             else {
1630                 end = vp;
1631                 while (true) {
1632                     result = endOfWord(previousWordPosition(end), RightWordIfOnBoundary);
1633
1634                     if (result == end)
1635                         break;
1636
1637                     if (result.isNull() || result > end)
1638                         return VisiblePosition();
1639
1640                     if (result != startOfWord(result))
1641                         break;
1642
1643                     end = result;
1644                 }
1645             }
1646         }
1647     }
1648     
1649     if (result == vp)
1650         return VisiblePosition();
1651     
1652     return result;
1653 }
1654
1655 static VisiblePosition nextSentenceBoundaryInDirection(const VisiblePosition& vp, SelectionDirection direction)
1656 {
1657     bool useDownstream = directionIsDownstream(direction);
1658     bool withinUnitOfGranularity = withinTextUnitOfGranularity(vp, SentenceGranularity, direction);
1659     VisiblePosition result;
1660
1661     if (withinUnitOfGranularity)
1662         result = useDownstream ? endOfSentence(vp) : startOfSentence(vp);
1663     else {
1664         result = useDownstream ? nextSentencePosition(vp) : previousSentencePosition(vp);
1665         if (result.isNull() || result == vp)
1666             return VisiblePosition();
1667
1668         result = useDownstream ? startOfSentence(vp) : endOfSentence(vp);
1669     }
1670
1671     if (result == vp)
1672         return VisiblePosition();
1673
1674     ASSERT(useDownstream ? (result > vp) : (result < vp));
1675
1676     return result;
1677 }
1678
1679 static VisiblePosition nextLineBoundaryInDirection(const VisiblePosition& vp, SelectionDirection direction)
1680 {
1681     bool useDownstream = directionIsDownstream(direction);
1682     VisiblePosition result = vp;
1683
1684     if (useDownstream) {
1685         result.setAffinity(DOWNSTREAM);
1686         result = isEndOfLine(result) ? startOfLine(nextLinePosition(result, result.lineDirectionPointForBlockDirectionNavigation())) : endOfLine(result);
1687     } else {
1688         result.setAffinity(VP_UPSTREAM_IF_POSSIBLE);
1689         result = isStartOfLine(result) ? endOfLine(previousLinePosition(result, result.lineDirectionPointForBlockDirectionNavigation())) : startOfLine(result);
1690     }
1691
1692     return result;
1693 }
1694
1695 static VisiblePosition nextParagraphBoundaryInDirection(const VisiblePosition& vp, SelectionDirection direction)
1696 {
1697     bool useDownstream = directionIsDownstream(direction);
1698     bool withinUnitOfGranularity = withinTextUnitOfGranularity(vp, ParagraphGranularity, direction);
1699     VisiblePosition result;
1700
1701     if (!withinUnitOfGranularity)
1702         result =  useDownstream ? startOfParagraph(nextParagraphPosition(vp, vp.lineDirectionPointForBlockDirectionNavigation())) : endOfParagraph(previousParagraphPosition(vp, vp.lineDirectionPointForBlockDirectionNavigation()));
1703     else
1704         result = useDownstream ? endOfParagraph(vp) : startOfParagraph(vp);
1705
1706     return result;
1707 }
1708
1709 static VisiblePosition nextDocumentBoundaryInDirection(const VisiblePosition& vp, SelectionDirection direction)
1710 {
1711     return directionIsDownstream(direction) ? endOfDocument(vp) : startOfDocument(vp);
1712 }
1713
1714 VisiblePosition positionOfNextBoundaryOfGranularity(const VisiblePosition& vp, TextGranularity granularity, SelectionDirection direction)
1715 {
1716     switch (granularity) {
1717     case CharacterGranularity:
1718         return nextCharacterBoundaryInDirection(vp, direction);
1719     case WordGranularity:
1720         return nextWordBoundaryInDirection(vp, direction);
1721     case SentenceGranularity:
1722         return nextSentenceBoundaryInDirection(vp, direction);
1723     case LineGranularity:
1724         return nextLineBoundaryInDirection(vp, direction);
1725     case ParagraphGranularity:
1726         return nextParagraphBoundaryInDirection(vp, direction);
1727     case DocumentGranularity:
1728         return nextDocumentBoundaryInDirection(vp, direction);
1729     default:
1730         ASSERT_NOT_REACHED();
1731         return VisiblePosition();
1732     }
1733 }
1734
1735 PassRefPtr<Range> enclosingTextUnitOfGranularity(const VisiblePosition& vp, TextGranularity granularity, SelectionDirection direction)
1736 {
1737     // This is particularly inefficient.  We could easily obtain the answer with the boundaries computed below.
1738     if (!withinTextUnitOfGranularity(vp, granularity, direction))
1739         return 0;
1740
1741     VisiblePosition prevBoundary;
1742     VisiblePosition nextBoundary;
1743     bool useDownstream = directionIsDownstream(direction);
1744
1745     switch (granularity) {
1746         case CharacterGranularity:
1747             prevBoundary = vp;
1748             nextBoundary = prevBoundary.next();
1749             break;
1750
1751         case WordGranularity:
1752             // NB: "Left" and "Right" in this context apparently mean "upstream/previous" and "downstream/next".
1753             if (useDownstream) {
1754                 prevBoundary = startOfWord(vp, RightWordIfOnBoundary);
1755                 nextBoundary = endOfWord(vp, RightWordIfOnBoundary);
1756             } else {
1757                 prevBoundary = startOfWord(vp, LeftWordIfOnBoundary);
1758                 nextBoundary = endOfWord(vp, LeftWordIfOnBoundary);
1759             }
1760             break;
1761
1762         case SentenceGranularity:
1763             prevBoundary = startOfSentence(vp);
1764             nextBoundary = endOfSentence(vp);
1765             break;
1766
1767         case LineGranularity:
1768             prevBoundary = startOfLine(vp);
1769             nextBoundary = endOfLine(vp);
1770
1771             if (prevBoundary == nextBoundary) {
1772                 nextBoundary = nextLinePosition(nextBoundary, 0);
1773                 nextBoundary.setAffinity(UPSTREAM);
1774                 if (!inSameLine(prevBoundary, nextBoundary))
1775                     nextBoundary = vp.next();
1776             }
1777             break;
1778
1779         case ParagraphGranularity:
1780             prevBoundary = startOfParagraph(vp);
1781             nextBoundary = endOfParagraph(vp);
1782             break;
1783
1784         case DocumentGranularity:
1785             prevBoundary = startOfDocument(vp);
1786             nextBoundary = endOfDocument(vp);
1787             break;
1788
1789         default:
1790             ASSERT_NOT_REACHED();
1791             return 0;
1792     }
1793
1794     if (prevBoundary.isNull() || nextBoundary.isNull())
1795         return 0;
1796
1797     if (vp < prevBoundary || vp > nextBoundary)
1798         return 0;
1799
1800     RefPtr<Range> range = Range::create(prevBoundary.deepEquivalent().deprecatedNode()->document(), prevBoundary, nextBoundary);
1801
1802     return range;
1803 }
1804
1805 int distanceBetweenPositions(const VisiblePosition& vp, const VisiblePosition& other)
1806 {
1807     if (vp.isNull() || other.isNull())
1808         return 0;
1809
1810     bool thisIsStart = (vp < other);
1811
1812     // Start must come first in the Range constructor.
1813     RefPtr<Range> range = Range::create(vp.deepEquivalent().deprecatedNode()->document(),
1814                                         (thisIsStart ? vp : other),
1815                                         (thisIsStart ? other : vp));
1816     int distance = TextIterator::rangeLength(range.get());
1817
1818     return (thisIsStart ? -distance : distance);
1819 }
1820
1821 PassRefPtr<Range> wordRangeFromPosition(const VisiblePosition& position)
1822 {
1823     ASSERT(position.isNotNull());
1824
1825     RefPtr<Range> range = enclosingTextUnitOfGranularity(position, WordGranularity, DirectionBackward);
1826
1827     if (!range) {
1828         // We could be at the start of a word, try forward.
1829         range = enclosingTextUnitOfGranularity(position, WordGranularity, DirectionForward);
1830     }
1831     if (range)
1832         return range;
1833
1834     VisiblePosition currentPosition = position;
1835     do {
1836         currentPosition = positionOfNextBoundaryOfGranularity(currentPosition, WordGranularity, DirectionBackward);
1837     } while (currentPosition.isNotNull() && !atBoundaryOfGranularity(currentPosition, WordGranularity, DirectionBackward));
1838
1839     // If the position is an empty paragraph and at the end of the document
1840     // the word iterator could not pass the paragraph boundary, therefore iterating to
1841     // the previous line is required.
1842     if (currentPosition.isNull() && isEndOfDocument(position)) {
1843         VisiblePosition previousLinePosition = positionOfNextBoundaryOfGranularity(position, LineGranularity, DirectionBackward);
1844         if (previousLinePosition.isNotNull()) {
1845             currentPosition = positionOfNextBoundaryOfGranularity(previousLinePosition, WordGranularity, DirectionBackward);
1846             if (currentPosition.isNull())
1847                 currentPosition = previousLinePosition;
1848         }
1849     }
1850
1851     if (currentPosition.isNull())
1852         currentPosition = positionOfNextBoundaryOfGranularity(position, WordGranularity, DirectionForward);
1853
1854     if (currentPosition.isNotNull()) {
1855         range = Range::create(position.deepEquivalent().deprecatedNode()->document(), currentPosition, position);
1856         ASSERT(range);
1857     }
1858     return range;
1859 }
1860
1861 VisiblePosition closestWordBoundaryForPosition(const VisiblePosition& position)
1862 {
1863     VisiblePosition result;
1864
1865     // move the the position at the end of the word
1866     if (atBoundaryOfGranularity(position, LineGranularity, DirectionForward)) {
1867         // Don't cross line boundaries.
1868         result = position;
1869     } else if (withinTextUnitOfGranularity(position, WordGranularity, DirectionForward)) {
1870         // The position lies within a word.
1871         RefPtr<Range> wordRange = enclosingTextUnitOfGranularity(position, WordGranularity, DirectionForward);
1872
1873         result = wordRange->startPosition();
1874         if (distanceBetweenPositions(position, result) > 1)
1875             result = wordRange->endPosition();
1876     } else if (atBoundaryOfGranularity(position, WordGranularity, DirectionBackward)) {
1877         // The position is at the end of a word.
1878         result = position;
1879     } else {
1880         // The position is not within a word.
1881         // Go to the next boundary.
1882         result = positionOfNextBoundaryOfGranularity(position, WordGranularity, DirectionForward);
1883
1884         // If there is no such boundary we go to the end of the element.
1885         if (result.isNull())
1886             result = endOfEditableContent(position);
1887     }
1888     return result;
1889 }
1890
1891 #endif
1892
1893 }