initial import
[vuplus_webkit] / Source / WebCore / editing / visible_units.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 "visible_units.h"
28
29 #include "Document.h"
30 #include "Element.h"
31 #include "HTMLNames.h"
32 #include "InlineTextBox.h"
33 #include "Position.h"
34 #include "RenderBlock.h"
35 #include "RenderLayer.h"
36 #include "RenderObject.h"
37 #include "RenderedPosition.h"
38 #include "Text.h"
39 #include "TextBoundaries.h"
40 #include "TextBreakIterator.h"
41 #include "TextIterator.h"
42 #include "VisiblePosition.h"
43 #include "VisibleSelection.h"
44 #include "htmlediting.h"
45 #include <wtf/unicode/Unicode.h>
46
47 namespace WebCore {
48
49 using namespace HTMLNames;
50 using namespace WTF::Unicode;
51
52 enum BoundarySearchContextAvailability { DontHaveMoreContext, MayHaveMoreContext };
53
54 typedef unsigned (*BoundarySearchFunction)(const UChar*, unsigned length, unsigned offset, BoundarySearchContextAvailability, bool& needMoreContext);
55
56 static VisiblePosition previousBoundary(const VisiblePosition& c, BoundarySearchFunction searchFunction)
57 {
58     Position pos = c.deepEquivalent();
59     Node* boundary = pos.parentEditingBoundary();
60     if (!boundary)
61         return VisiblePosition();
62
63     Document* d = boundary->document();
64     Position start = createLegacyEditingPosition(boundary, 0).parentAnchoredEquivalent();
65     Position end = pos.parentAnchoredEquivalent();
66     RefPtr<Range> searchRange = Range::create(d);
67     
68     Vector<UChar, 1024> string;
69     unsigned suffixLength = 0;
70
71     ExceptionCode ec = 0;
72     if (requiresContextForWordBoundary(c.characterBefore())) {
73         RefPtr<Range> forwardsScanRange(d->createRange());
74         forwardsScanRange->setEndAfter(boundary, ec);
75         forwardsScanRange->setStart(end.deprecatedNode(), end.deprecatedEditingOffset(), ec);
76         TextIterator forwardsIterator(forwardsScanRange.get());
77         while (!forwardsIterator.atEnd()) {
78             const UChar* characters = forwardsIterator.characters();
79             int length = forwardsIterator.length();
80             int i = endOfFirstWordBoundaryContext(characters, length);
81             string.append(characters, i);
82             suffixLength += i;
83             if (i < length)
84                 break;
85             forwardsIterator.advance();
86         }
87     }
88
89     searchRange->setStart(start.deprecatedNode(), start.deprecatedEditingOffset(), ec);
90     searchRange->setEnd(end.deprecatedNode(), end.deprecatedEditingOffset(), ec);
91     
92     ASSERT(!ec);
93     if (ec)
94         return VisiblePosition();
95
96     SimplifiedBackwardsTextIterator it(searchRange.get());
97     unsigned next = 0;
98     bool inTextSecurityMode = start.deprecatedNode() && start.deprecatedNode()->renderer() && start.deprecatedNode()->renderer()->style()->textSecurity() != TSNONE;
99     bool needMoreContext = false;
100     while (!it.atEnd()) {
101         // iterate to get chunks until the searchFunction returns a non-zero value.
102         if (!inTextSecurityMode) 
103             string.prepend(it.characters(), it.length());
104         else {
105             // Treat bullets used in the text security mode as regular characters when looking for boundaries
106             String iteratorString(it.characters(), it.length());
107             iteratorString.fill('x');
108             string.prepend(iteratorString.characters(), iteratorString.length());
109         }
110         next = searchFunction(string.data(), string.size(), string.size() - suffixLength, MayHaveMoreContext, needMoreContext);
111         if (next != 0)
112             break;
113         it.advance();
114     }
115     if (needMoreContext) {
116         // The last search returned the beginning of the buffer and asked for more context,
117         // but there is no earlier text. Force a search with what's available.
118         next = searchFunction(string.data(), string.size(), string.size() - suffixLength, DontHaveMoreContext, needMoreContext);
119         ASSERT(!needMoreContext);
120     }
121
122     if (!next)
123         return VisiblePosition(it.atEnd() ? it.range()->startPosition() : pos, DOWNSTREAM);
124
125     Node* node = it.range()->startContainer(ec);
126     if ((node->isTextNode() && static_cast<int>(next) <= node->maxCharacterOffset()) || (node->renderer() && node->renderer()->isBR() && !next))
127         // The next variable contains a usable index into a text node
128         return VisiblePosition(createLegacyEditingPosition(node, next), DOWNSTREAM);
129
130     // Use the character iterator to translate the next value into a DOM position.
131     BackwardsCharacterIterator charIt(searchRange.get());
132     charIt.advance(string.size() - suffixLength - next);
133     // FIXME: charIt can get out of shadow host.
134     return VisiblePosition(charIt.range()->endPosition(), DOWNSTREAM);
135 }
136
137 static VisiblePosition nextBoundary(const VisiblePosition& c, BoundarySearchFunction searchFunction)
138 {
139     Position pos = c.deepEquivalent();
140     Node* boundary = pos.parentEditingBoundary();
141     if (!boundary)
142         return VisiblePosition();
143
144     Document* d = boundary->document();
145     RefPtr<Range> searchRange(d->createRange());
146     Position start(pos.parentAnchoredEquivalent());
147
148     Vector<UChar, 1024> string;
149     unsigned prefixLength = 0;
150
151     ExceptionCode ec = 0;
152     if (requiresContextForWordBoundary(c.characterAfter())) {
153         RefPtr<Range> backwardsScanRange(d->createRange());
154         backwardsScanRange->setEnd(start.deprecatedNode(), start.deprecatedEditingOffset(), ec);
155         SimplifiedBackwardsTextIterator backwardsIterator(backwardsScanRange.get());
156         while (!backwardsIterator.atEnd()) {
157             const UChar* characters = backwardsIterator.characters();
158             int length = backwardsIterator.length();
159             int i = startOfLastWordBoundaryContext(characters, length);
160             string.prepend(characters + i, length - i);
161             prefixLength += length - i;
162             if (i > 0)
163                 break;
164             backwardsIterator.advance();
165         }
166     }
167
168     searchRange->selectNodeContents(boundary, ec);
169     searchRange->setStart(start.deprecatedNode(), start.deprecatedEditingOffset(), ec);
170     TextIterator it(searchRange.get(), TextIteratorEmitsCharactersBetweenAllVisiblePositions);
171     unsigned next = 0;
172     bool inTextSecurityMode = start.deprecatedNode() && start.deprecatedNode()->renderer() && start.deprecatedNode()->renderer()->style()->textSecurity() != TSNONE;
173     bool needMoreContext = false;
174     while (!it.atEnd()) {
175         // Keep asking the iterator for chunks until the search function
176         // returns an end value not equal to the length of the string passed to it.
177         if (!inTextSecurityMode)
178             string.append(it.characters(), it.length());
179         else {
180             // Treat bullets used in the text security mode as regular characters when looking for boundaries
181             String iteratorString(it.characters(), it.length());
182             iteratorString.fill('x');
183             string.append(iteratorString.characters(), iteratorString.length());
184         }
185         next = searchFunction(string.data(), string.size(), prefixLength, MayHaveMoreContext, needMoreContext);
186         if (next != string.size())
187             break;
188         it.advance();
189     }
190     if (needMoreContext) {
191         // The last search returned the end of the buffer and asked for more context,
192         // but there is no further text. Force a search with what's available.
193         next = searchFunction(string.data(), string.size(), prefixLength, DontHaveMoreContext, needMoreContext);
194         ASSERT(!needMoreContext);
195     }
196     
197     if (it.atEnd() && next == string.size()) {
198         pos = it.range()->startPosition();
199     } else if (next != prefixLength) {
200         // Use the character iterator to translate the next value into a DOM position.
201         CharacterIterator charIt(searchRange.get(), TextIteratorEmitsCharactersBetweenAllVisiblePositions);
202         charIt.advance(next - prefixLength - 1);
203         RefPtr<Range> characterRange = charIt.range();
204         pos = characterRange->endPosition();
205         
206         if (*charIt.characters() == '\n') {
207             // FIXME: workaround for collapsed range (where only start position is correct) emitted for some emitted newlines (see rdar://5192593)
208             VisiblePosition visPos = VisiblePosition(pos);
209             if (visPos == VisiblePosition(characterRange->startPosition())) {
210                 charIt.advance(1);
211                 pos = charIt.range()->startPosition();
212             }
213         }
214     }
215
216     // generate VisiblePosition, use UPSTREAM affinity if possible
217     return VisiblePosition(pos, VP_UPSTREAM_IF_POSSIBLE);
218 }
219
220 // ---------
221
222 static unsigned startWordBoundary(const UChar* characters, unsigned length, unsigned offset, BoundarySearchContextAvailability mayHaveMoreContext, bool& needMoreContext)
223 {
224     ASSERT(offset);
225     if (mayHaveMoreContext && !startOfLastWordBoundaryContext(characters, offset)) {
226         needMoreContext = true;
227         return 0;
228     }
229     needMoreContext = false;
230     int start, end;
231     U16_BACK_1(characters, 0, offset);
232     findWordBoundary(characters, length, offset, &start, &end);
233     return start;
234 }
235
236 VisiblePosition startOfWord(const VisiblePosition &c, EWordSide side)
237 {
238     // FIXME: This returns a null VP for c at the start of the document
239     // and side == LeftWordIfOnBoundary
240     VisiblePosition p = c;
241     if (side == RightWordIfOnBoundary) {
242         // at paragraph end, the startofWord is the current position
243         if (isEndOfParagraph(c))
244             return c;
245         
246         p = c.next();
247         if (p.isNull())
248             return c;
249     }
250     return previousBoundary(p, startWordBoundary);
251 }
252
253 static unsigned endWordBoundary(const UChar* characters, unsigned length, unsigned offset, BoundarySearchContextAvailability mayHaveMoreContext, bool& needMoreContext)
254 {
255     ASSERT(offset <= length);
256     if (mayHaveMoreContext && endOfFirstWordBoundaryContext(characters + offset, length - offset) == static_cast<int>(length - offset)) {
257         needMoreContext = true;
258         return length;
259     }
260     needMoreContext = false;
261     int start, end;
262     findWordBoundary(characters, length, offset, &start, &end);
263     return end;
264 }
265
266 VisiblePosition endOfWord(const VisiblePosition &c, EWordSide side)
267 {
268     VisiblePosition p = c;
269     if (side == LeftWordIfOnBoundary) {
270         if (isStartOfParagraph(c))
271             return c;
272             
273         p = c.previous();
274         if (p.isNull())
275             return c;
276     } else if (isEndOfParagraph(c))
277         return c;
278     
279     return nextBoundary(p, endWordBoundary);
280 }
281
282 static unsigned previousWordPositionBoundary(const UChar* characters, unsigned length, unsigned offset, BoundarySearchContextAvailability mayHaveMoreContext, bool& needMoreContext)
283 {
284     if (mayHaveMoreContext && !startOfLastWordBoundaryContext(characters, offset)) {
285         needMoreContext = true;
286         return 0;
287     }
288     needMoreContext = false;
289     return findNextWordFromIndex(characters, length, offset, false);
290 }
291
292 VisiblePosition previousWordPosition(const VisiblePosition &c)
293 {
294     VisiblePosition prev = previousBoundary(c, previousWordPositionBoundary);
295     return c.honorEditingBoundaryAtOrBefore(prev);
296 }
297
298 static unsigned nextWordPositionBoundary(const UChar* characters, unsigned length, unsigned offset, BoundarySearchContextAvailability mayHaveMoreContext, bool& needMoreContext)
299 {
300     if (mayHaveMoreContext && endOfFirstWordBoundaryContext(characters + offset, length - offset) == static_cast<int>(length - offset)) {
301         needMoreContext = true;
302         return length;
303     }
304     needMoreContext = false;
305     return findNextWordFromIndex(characters, length, offset, true);
306 }
307
308 VisiblePosition nextWordPosition(const VisiblePosition &c)
309 {
310     VisiblePosition next = nextBoundary(c, nextWordPositionBoundary);    
311     return c.honorEditingBoundaryAtOrAfter(next);
312 }
313
314 bool isStartOfWord(const VisiblePosition& p)
315 {
316     return p.isNotNull() && p == startOfWord(p, RightWordIfOnBoundary);
317 }
318
319 // ---------
320
321 static VisiblePosition positionAvoidingFirstPositionInTable(const VisiblePosition& c)
322 {
323     // return table offset 0 instead of the first VisiblePosition inside the table
324     VisiblePosition previous = c.previous();
325     if (isLastPositionBeforeTable(previous) && isEditablePosition(previous.deepEquivalent()))
326         return previous;
327
328     return c;
329 }
330
331 static VisiblePosition startPositionForLine(const VisiblePosition& c)
332 {
333     if (c.isNull())
334         return VisiblePosition();
335
336     RootInlineBox* rootBox = RenderedPosition(c).rootBox();
337     if (!rootBox) {
338         // There are VisiblePositions at offset 0 in blocks without
339         // RootInlineBoxes, like empty editable blocks and bordered blocks.
340         Position p = c.deepEquivalent();
341         if (p.deprecatedNode()->renderer() && p.deprecatedNode()->renderer()->isRenderBlock() && !p.deprecatedEditingOffset())
342             return positionAvoidingFirstPositionInTable(c);
343         
344         return VisiblePosition();
345     }
346     
347     // Generated content (e.g. list markers and CSS :before and :after
348     // pseudoelements) have no corresponding DOM element, and so cannot be
349     // represented by a VisiblePosition.  Use whatever follows instead.
350     InlineBox *startBox = rootBox->firstLeafChild();
351     Node *startNode;
352     while (1) {
353         if (!startBox)
354             return VisiblePosition();
355
356         RenderObject *startRenderer = startBox->renderer();
357         if (!startRenderer)
358             return VisiblePosition();
359
360         startNode = startRenderer->node();
361         if (startNode)
362             break;
363         
364         startBox = startBox->nextLeafChild();
365     }
366     
367     VisiblePosition visPos = startNode->isTextNode() ? VisiblePosition(Position(static_cast<Text*>(startNode), static_cast<InlineTextBox*>(startBox)->start()), DOWNSTREAM)
368                                                      : VisiblePosition(positionBeforeNode(startNode), DOWNSTREAM);
369     return positionAvoidingFirstPositionInTable(visPos);
370 }
371
372 VisiblePosition startOfLine(const VisiblePosition& c)
373 {
374     VisiblePosition visPos = startPositionForLine(c);
375
376     return c.honorEditingBoundaryAtOrBefore(visPos);
377 }
378
379 static VisiblePosition endPositionForLine(const VisiblePosition& c)
380 {
381     if (c.isNull())
382         return VisiblePosition();
383
384     RootInlineBox* rootBox = RenderedPosition(c).rootBox();
385     if (!rootBox) {
386         // There are VisiblePositions at offset 0 in blocks without
387         // RootInlineBoxes, like empty editable blocks and bordered blocks.
388         Position p = c.deepEquivalent();
389         if (p.deprecatedNode()->renderer() && p.deprecatedNode()->renderer()->isRenderBlock() && !p.deprecatedEditingOffset())
390             return c;
391         return VisiblePosition();
392     }
393     
394     // Generated content (e.g. list markers and CSS :before and :after
395     // pseudoelements) have no corresponding DOM element, and so cannot be
396     // represented by a VisiblePosition.  Use whatever precedes instead.
397     Node *endNode;
398     InlineBox *endBox = rootBox->lastLeafChild();
399     while (1) {
400         if (!endBox)
401             return VisiblePosition();
402
403         RenderObject *endRenderer = endBox->renderer();
404         if (!endRenderer)
405             return VisiblePosition();
406
407         endNode = endRenderer->node();
408         if (endNode)
409             break;
410         
411         endBox = endBox->prevLeafChild();
412     }
413     
414     Position pos;
415     if (endNode->hasTagName(brTag)) {
416         pos = positionBeforeNode(endNode);
417     } else if (endBox->isInlineTextBox() && endNode->isTextNode()) {
418         InlineTextBox* endTextBox = static_cast<InlineTextBox *>(endBox);
419         int endOffset = endTextBox->start();
420         if (!endTextBox->isLineBreak())
421             endOffset += endTextBox->len();
422         pos = Position(static_cast<Text*>(endNode), endOffset);
423     } else
424         pos = positionAfterNode(endNode);
425     
426     return VisiblePosition(pos, VP_UPSTREAM_IF_POSSIBLE);
427 }
428
429 VisiblePosition endOfLine(const VisiblePosition& c)
430 {
431     VisiblePosition visPos = endPositionForLine(c);
432     
433     // Make sure the end of line is at the same line as the given input position.  Else use the previous position to 
434     // obtain end of line.  This condition happens when the input position is before the space character at the end 
435     // of a soft-wrapped non-editable line. In this scenario, endPositionForLine would incorrectly hand back a position
436     // in the next line instead. This fix is to account for the discrepancy between lines with webkit-line-break:after-white-space style
437     // versus lines without that style, which would break before a space by default. 
438     if (!inSameLine(c, visPos)) {
439         visPos = c.previous();
440         if (visPos.isNull())
441             return VisiblePosition();
442         visPos = endPositionForLine(visPos);
443     }
444     
445     return c.honorEditingBoundaryAtOrAfter(visPos);
446 }
447
448 bool inSameLine(const VisiblePosition &a, const VisiblePosition &b)
449 {
450     return a.isNotNull() && startOfLine(a) == startOfLine(b);
451 }
452
453 bool isStartOfLine(const VisiblePosition &p)
454 {
455     return p.isNotNull() && p == startOfLine(p);
456 }
457
458 bool isEndOfLine(const VisiblePosition &p)
459 {
460     return p.isNotNull() && p == endOfLine(p);
461 }
462
463 // The first leaf before node that has the same editability as node.
464 static Node* previousLeafWithSameEditability(Node* node)
465 {
466     bool editable = node->rendererIsEditable();
467     Node* n = node->previousLeafNode();
468     while (n) {
469         if (editable == n->rendererIsEditable())
470             return n;
471         n = n->previousLeafNode();
472     }
473     return 0;
474 }
475
476 static Node* enclosingNodeWithNonInlineRenderer(Node* n)
477 {
478     for (Node* p = n; p; p = p->parentNode()) {
479         if (p->renderer() && !p->renderer()->isInline())
480             return p;
481     }
482     return 0;
483 }
484
485 static inline IntPoint absoluteLineDirectionPointToLocalPointInBlock(RootInlineBox* root, int lineDirectionPoint)
486 {
487     ASSERT(root);
488     RenderBlock* containingBlock = root->block();
489     FloatPoint absoluteBlockPoint = containingBlock->localToAbsolute(FloatPoint());
490     if (containingBlock->hasOverflowClip())
491         absoluteBlockPoint -= containingBlock->layer()->scrolledContentOffset();
492
493     if (root->block()->isHorizontalWritingMode())
494         return IntPoint(lineDirectionPoint - absoluteBlockPoint.x(), root->blockDirectionPointInLine());
495
496     return IntPoint(root->selectionTop(), lineDirectionPoint - absoluteBlockPoint.y());
497 }
498
499 VisiblePosition previousLinePosition(const VisiblePosition &visiblePosition, int lineDirectionPoint)
500 {
501     Position p = visiblePosition.deepEquivalent();
502     Node* node = p.deprecatedNode();
503     Node* highestRoot = highestEditableRoot(p);
504     if (!node)
505         return VisiblePosition();
506     
507     node->document()->updateLayoutIgnorePendingStylesheets();
508     
509     RenderObject *renderer = node->renderer();
510     if (!renderer)
511         return VisiblePosition();
512
513     RootInlineBox *root = 0;
514     InlineBox* box;
515     int ignoredCaretOffset;
516     visiblePosition.getInlineBoxAndOffset(box, ignoredCaretOffset);
517     if (box) {
518         root = box->root()->prevRootBox();
519         // We want to skip zero height boxes.
520         // This could happen in case it is a TrailingFloatsRootInlineBox.
521         if (!root || !root->logicalHeight())
522             root = 0;
523     }
524
525     if (!root) {
526         // This containing editable block does not have a previous line.
527         // Need to move back to previous containing editable block in this root editable
528         // block and find the last root line box in that block.
529         Node* startBlock = enclosingNodeWithNonInlineRenderer(node);
530         Node* n = previousLeafWithSameEditability(node);
531         while (n && startBlock == enclosingNodeWithNonInlineRenderer(n))
532             n = previousLeafWithSameEditability(n);
533         while (n) {
534             if (highestEditableRoot(firstPositionInOrBeforeNode(n)) != highestRoot)
535                 break;
536             Position pos = n->hasTagName(brTag) ? positionBeforeNode(n) : createLegacyEditingPosition(n, caretMaxOffset(n));
537             if (pos.isCandidate()) {
538                 pos.getInlineBoxAndOffset(DOWNSTREAM, box, ignoredCaretOffset);
539                 if (box) {
540                     // previous root line box found
541                     root = box->root();
542                     break;
543                 }
544
545                 return VisiblePosition(pos, DOWNSTREAM);
546             }
547             n = previousLeafWithSameEditability(n);
548         }
549     }
550     
551     if (root) {
552         // FIXME: Can be wrong for multi-column layout and with transforms.
553         IntPoint pointInLine = absoluteLineDirectionPointToLocalPointInBlock(root, lineDirectionPoint);
554         RenderObject* renderer = root->closestLeafChildForPoint(pointInLine, isEditablePosition(p))->renderer();
555         Node* node = renderer->node();
556         if (node && editingIgnoresContent(node))
557             return positionInParentBeforeNode(node);
558         return renderer->positionForPoint(pointInLine);
559     }
560     
561     // Could not find a previous line. This means we must already be on the first line.
562     // Move to the start of the content in this block, which effectively moves us
563     // to the start of the line we're on.
564     Element* rootElement = node->rendererIsEditable() ? node->rootEditableElement() : node->document()->documentElement();
565     if (!rootElement)
566         return VisiblePosition();
567     return VisiblePosition(firstPositionInNode(rootElement), DOWNSTREAM);
568 }
569
570 static Node* nextLeafWithSameEditability(Node* node, int offset)
571 {
572     bool editable = node->rendererIsEditable();
573     ASSERT(offset >= 0);
574     Node* child = node->childNode(offset);
575     Node* n = child ? child->nextLeafNode() : node->lastDescendant()->nextLeafNode();
576     while (n) {
577         if (editable == n->rendererIsEditable())
578             return n;
579         n = n->nextLeafNode();
580     }
581     return 0;
582 }
583
584 static Node* nextLeafWithSameEditability(Node* node)
585 {
586     if (!node)
587         return 0;
588     
589     bool editable = node->rendererIsEditable();
590     Node* n = node->nextLeafNode();
591     while (n) {
592         if (editable == n->rendererIsEditable())
593             return n;
594         n = n->nextLeafNode();
595     }
596     return 0;
597 }
598
599 VisiblePosition nextLinePosition(const VisiblePosition &visiblePosition, int lineDirectionPoint)
600 {
601     Position p = visiblePosition.deepEquivalent();
602     Node* node = p.deprecatedNode();
603     Node* highestRoot = highestEditableRoot(p);
604     if (!node)
605         return VisiblePosition();
606     
607     node->document()->updateLayoutIgnorePendingStylesheets();
608
609     RenderObject *renderer = node->renderer();
610     if (!renderer)
611         return VisiblePosition();
612
613     RootInlineBox *root = 0;
614     InlineBox* box;
615     int ignoredCaretOffset;
616     visiblePosition.getInlineBoxAndOffset(box, ignoredCaretOffset);
617     if (box) {
618         root = box->root()->nextRootBox();
619         // We want to skip zero height boxes.
620         // This could happen in case it is a TrailingFloatsRootInlineBox.
621         if (!root || !root->logicalHeight())
622             root = 0;
623     }
624
625     if (!root) {
626         // This containing editable block does not have a next line.
627         // Need to move forward to next containing editable block in this root editable
628         // block and find the first root line box in that block.
629         Node* startBlock = enclosingNodeWithNonInlineRenderer(node);
630         Node* n = nextLeafWithSameEditability(node, p.deprecatedEditingOffset());
631         while (n && startBlock == enclosingNodeWithNonInlineRenderer(n))
632             n = nextLeafWithSameEditability(n);
633         while (n) {
634             if (highestEditableRoot(firstPositionInOrBeforeNode(n)) != highestRoot)
635                 break;
636             Position pos = createLegacyEditingPosition(n, caretMinOffset(n));
637             if (pos.isCandidate()) {
638                 ASSERT(n->renderer());
639                 pos.getInlineBoxAndOffset(DOWNSTREAM, box, ignoredCaretOffset);
640                 if (box) {
641                     // next root line box found
642                     root = box->root();
643                     break;
644                 }
645
646                 return VisiblePosition(pos, DOWNSTREAM);
647             }
648             n = nextLeafWithSameEditability(n);
649         }
650     }
651     
652     if (root) {
653         // FIXME: Can be wrong for multi-column layout and with transforms.
654         IntPoint pointInLine = absoluteLineDirectionPointToLocalPointInBlock(root, lineDirectionPoint);
655         RenderObject* renderer = root->closestLeafChildForPoint(pointInLine, isEditablePosition(p))->renderer();
656         Node* node = renderer->node();
657         if (node && editingIgnoresContent(node))
658             return positionInParentBeforeNode(node);
659         return renderer->positionForPoint(pointInLine);
660     }
661
662     // Could not find a next line. This means we must already be on the last line.
663     // Move to the end of the content in this block, which effectively moves us
664     // to the end of the line we're on.
665     Element* rootElement = node->rendererIsEditable() ? node->rootEditableElement() : node->document()->documentElement();
666     if (!rootElement)
667         return VisiblePosition();
668     return VisiblePosition(lastPositionInNode(rootElement), DOWNSTREAM);
669 }
670
671 // ---------
672
673 static unsigned startSentenceBoundary(const UChar* characters, unsigned length, unsigned, BoundarySearchContextAvailability, bool&)
674 {
675     TextBreakIterator* iterator = sentenceBreakIterator(characters, length);
676     // FIXME: The following function can return -1; we don't handle that.
677     return textBreakPreceding(iterator, length);
678 }
679
680 VisiblePosition startOfSentence(const VisiblePosition &c)
681 {
682     return previousBoundary(c, startSentenceBoundary);
683 }
684
685 static unsigned endSentenceBoundary(const UChar* characters, unsigned length, unsigned, BoundarySearchContextAvailability, bool&)
686 {
687     TextBreakIterator* iterator = sentenceBreakIterator(characters, length);
688     return textBreakNext(iterator);
689 }
690
691 // FIXME: This includes the space after the punctuation that marks the end of the sentence.
692 VisiblePosition endOfSentence(const VisiblePosition &c)
693 {
694     return nextBoundary(c, endSentenceBoundary);
695 }
696
697 static unsigned previousSentencePositionBoundary(const UChar* characters, unsigned length, unsigned, BoundarySearchContextAvailability, bool&)
698 {
699     // FIXME: This is identical to startSentenceBoundary. I'm pretty sure that's not right.
700     TextBreakIterator* iterator = sentenceBreakIterator(characters, length);
701     // FIXME: The following function can return -1; we don't handle that.
702     return textBreakPreceding(iterator, length);
703 }
704
705 VisiblePosition previousSentencePosition(const VisiblePosition &c)
706 {
707     VisiblePosition prev = previousBoundary(c, previousSentencePositionBoundary);
708     return c.honorEditingBoundaryAtOrBefore(prev);
709 }
710
711 static unsigned nextSentencePositionBoundary(const UChar* characters, unsigned length, unsigned, BoundarySearchContextAvailability, bool&)
712 {
713     // FIXME: This is identical to endSentenceBoundary.  This isn't right, it needs to 
714     // move to the equivlant position in the following sentence.
715     TextBreakIterator* iterator = sentenceBreakIterator(characters, length);
716     return textBreakFollowing(iterator, 0);
717 }
718
719 VisiblePosition nextSentencePosition(const VisiblePosition &c)
720 {
721     VisiblePosition next = nextBoundary(c, nextSentencePositionBoundary);    
722     return c.honorEditingBoundaryAtOrAfter(next);
723 }
724
725 VisiblePosition startOfParagraph(const VisiblePosition& c, EditingBoundaryCrossingRule boundaryCrossingRule)
726 {
727     Position p = c.deepEquivalent();
728     Node* startNode = p.deprecatedNode();
729
730     if (!startNode)
731         return VisiblePosition();
732     
733     if (isRenderedAsNonInlineTableImageOrHR(startNode))
734         return positionBeforeNode(startNode);
735
736     Node* startBlock = enclosingBlock(startNode);
737
738     Node* node = startNode;
739     Node* highestRoot = highestEditableRoot(p);
740     int offset = p.deprecatedEditingOffset();
741     Position::AnchorType type = p.anchorType();
742
743     Node* n = startNode;
744     while (n) {
745         if (boundaryCrossingRule == CannotCrossEditingBoundary && n->rendererIsEditable() != startNode->rendererIsEditable())
746             break;
747         if (boundaryCrossingRule == CanSkipOverEditingBoundary) {
748             while (n && n->rendererIsEditable() != startNode->rendererIsEditable())
749                 n = n->traversePreviousNodePostOrder(startBlock);
750             if (!n || !n->isDescendantOf(highestRoot))
751                 break;
752         }
753         RenderObject *r = n->renderer();
754         if (!r) {
755             n = n->traversePreviousNodePostOrder(startBlock);
756             continue;
757         }
758         RenderStyle *style = r->style();
759         if (style->visibility() != VISIBLE) {
760             n = n->traversePreviousNodePostOrder(startBlock);
761             continue;
762         }
763         
764         if (r->isBR() || isBlock(n))
765             break;
766
767         if (r->isText() && r->caretMaxRenderedOffset() > 0) {
768             ASSERT(n->isTextNode());
769             type = Position::PositionIsOffsetInAnchor;
770             if (style->preserveNewline()) {
771                 const UChar* chars = toRenderText(r)->characters();
772                 int i = toRenderText(r)->textLength();
773                 int o = offset;
774                 if (n == startNode && o < i)
775                     i = max(0, o);
776                 while (--i >= 0) {
777                     if (chars[i] == '\n')
778                         return VisiblePosition(Position(static_cast<Text*>(n), i + 1), DOWNSTREAM);
779                 }
780             }
781             node = n;
782             offset = 0;
783             n = n->traversePreviousNodePostOrder(startBlock);
784         } else if (editingIgnoresContent(n) || isTableElement(n)) {
785             node = n;
786             type = Position::PositionIsBeforeAnchor;
787             n = n->previousSibling() ? n->previousSibling() : n->traversePreviousNodePostOrder(startBlock);
788         } else
789             n = n->traversePreviousNodePostOrder(startBlock);
790     }
791
792     if (type == Position::PositionIsOffsetInAnchor) {
793         ASSERT(type == Position::PositionIsOffsetInAnchor || !offset);
794         return VisiblePosition(Position(node, offset, type), DOWNSTREAM);
795     }
796
797     return VisiblePosition(Position(node, type), DOWNSTREAM);
798 }
799
800 VisiblePosition endOfParagraph(const VisiblePosition &c, EditingBoundaryCrossingRule boundaryCrossingRule)
801 {    
802     if (c.isNull())
803         return VisiblePosition();
804
805     Position p = c.deepEquivalent();
806     Node* startNode = p.deprecatedNode();
807
808     if (isRenderedAsNonInlineTableImageOrHR(startNode))
809         return positionAfterNode(startNode);
810     
811     Node* startBlock = enclosingBlock(startNode);
812     Node* stayInsideBlock = startBlock;
813     
814     Node* node = startNode;
815     Node* highestRoot = highestEditableRoot(p);
816     int offset = p.deprecatedEditingOffset();
817     Position::AnchorType type = p.anchorType();
818
819     Node* n = startNode;
820     while (n) {
821         if (boundaryCrossingRule == CannotCrossEditingBoundary && n->rendererIsEditable() != startNode->rendererIsEditable())
822             break;
823         if (boundaryCrossingRule == CanSkipOverEditingBoundary) {
824             while (n && n->rendererIsEditable() != startNode->rendererIsEditable())
825                 n = n->traverseNextNode(stayInsideBlock);
826             if (!n || !n->isDescendantOf(highestRoot))
827                 break;
828         }
829
830         RenderObject *r = n->renderer();
831         if (!r) {
832             n = n->traverseNextNode(stayInsideBlock);
833             continue;
834         }
835         RenderStyle *style = r->style();
836         if (style->visibility() != VISIBLE) {
837             n = n->traverseNextNode(stayInsideBlock);
838             continue;
839         }
840         
841         if (r->isBR() || isBlock(n))
842             break;
843
844         // FIXME: We avoid returning a position where the renderer can't accept the caret.
845         if (r->isText() && r->caretMaxRenderedOffset() > 0) {
846             ASSERT(n->isTextNode());
847             int length = toRenderText(r)->textLength();
848             type = Position::PositionIsOffsetInAnchor;
849             if (style->preserveNewline()) {
850                 const UChar* chars = toRenderText(r)->characters();
851                 int o = n == startNode ? offset : 0;
852                 for (int i = o; i < length; ++i) {
853                     if (chars[i] == '\n')
854                         return VisiblePosition(Position(static_cast<Text*>(n), i), DOWNSTREAM);
855                 }
856             }
857             node = n;
858             offset = r->caretMaxOffset();
859             n = n->traverseNextNode(stayInsideBlock);
860         } else if (editingIgnoresContent(n) || isTableElement(n)) {
861             node = n;
862             type = Position::PositionIsAfterAnchor;
863             n = n->traverseNextSibling(stayInsideBlock);
864         } else
865             n = n->traverseNextNode(stayInsideBlock);
866     }
867
868     if (type == Position::PositionIsOffsetInAnchor)
869         return VisiblePosition(Position(node, offset, type), DOWNSTREAM);
870
871     return VisiblePosition(Position(node, type), DOWNSTREAM);
872 }
873
874 // FIXME: isStartOfParagraph(startOfNextParagraph(pos)) is not always true
875 VisiblePosition startOfNextParagraph(const VisiblePosition& visiblePosition)
876 {
877     VisiblePosition paragraphEnd(endOfParagraph(visiblePosition, CanSkipOverEditingBoundary));
878     VisiblePosition afterParagraphEnd(paragraphEnd.next(CannotCrossEditingBoundary));
879     // The position after the last position in the last cell of a table
880     // is not the start of the next paragraph.
881     if (isFirstPositionAfterTable(afterParagraphEnd))
882         return afterParagraphEnd.next(CannotCrossEditingBoundary);
883     return afterParagraphEnd;
884 }
885
886 bool inSameParagraph(const VisiblePosition &a, const VisiblePosition &b, EditingBoundaryCrossingRule boundaryCrossingRule)
887 {
888     return a.isNotNull() && startOfParagraph(a, boundaryCrossingRule) == startOfParagraph(b, boundaryCrossingRule);
889 }
890
891 bool isStartOfParagraph(const VisiblePosition &pos, EditingBoundaryCrossingRule boundaryCrossingRule)
892 {
893     return pos.isNotNull() && pos == startOfParagraph(pos, boundaryCrossingRule);
894 }
895
896 bool isEndOfParagraph(const VisiblePosition &pos, EditingBoundaryCrossingRule boundaryCrossingRule)
897 {
898     return pos.isNotNull() && pos == endOfParagraph(pos, boundaryCrossingRule);
899 }
900
901 VisiblePosition previousParagraphPosition(const VisiblePosition& p, int x)
902 {
903     VisiblePosition pos = p;
904     do {
905         VisiblePosition n = previousLinePosition(pos, x);
906         if (n.isNull() || n == pos)
907             break;
908         pos = n;
909     } while (inSameParagraph(p, pos));
910     return pos;
911 }
912
913 VisiblePosition nextParagraphPosition(const VisiblePosition& p, int x)
914 {
915     VisiblePosition pos = p;
916     do {
917         VisiblePosition n = nextLinePosition(pos, x);
918         if (n.isNull() || n == pos)
919             break;
920         pos = n;
921     } while (inSameParagraph(p, pos));
922     return pos;
923 }
924
925 // ---------
926
927 VisiblePosition startOfBlock(const VisiblePosition& visiblePosition, EditingBoundaryCrossingRule rule)
928 {
929     Position position = visiblePosition.deepEquivalent();
930     Node* startBlock;
931     if (!position.containerNode() || !(startBlock = enclosingBlock(position.containerNode(), rule)))
932         return VisiblePosition();
933     return firstPositionInNode(startBlock);
934 }
935
936 VisiblePosition endOfBlock(const VisiblePosition& visiblePosition, EditingBoundaryCrossingRule rule)
937 {
938     Position position = visiblePosition.deepEquivalent();
939     Node* endBlock;
940     if (!position.containerNode() || !(endBlock = enclosingBlock(position.containerNode(), rule)))
941         return VisiblePosition();
942     return lastPositionInNode(endBlock);
943 }
944
945 bool inSameBlock(const VisiblePosition &a, const VisiblePosition &b)
946 {
947     return !a.isNull() && enclosingBlock(a.deepEquivalent().containerNode()) == enclosingBlock(b.deepEquivalent().containerNode());
948 }
949
950 bool isStartOfBlock(const VisiblePosition &pos)
951 {
952     return pos.isNotNull() && pos == startOfBlock(pos, CanCrossEditingBoundary);
953 }
954
955 bool isEndOfBlock(const VisiblePosition &pos)
956 {
957     return pos.isNotNull() && pos == endOfBlock(pos, CanCrossEditingBoundary);
958 }
959
960 // ---------
961
962 VisiblePosition startOfDocument(const Node* node)
963 {
964     if (!node || !node->document() || !node->document()->documentElement())
965         return VisiblePosition();
966     
967     return VisiblePosition(firstPositionInNode(node->document()->documentElement()), DOWNSTREAM);
968 }
969
970 VisiblePosition startOfDocument(const VisiblePosition &c)
971 {
972     return startOfDocument(c.deepEquivalent().deprecatedNode());
973 }
974
975 VisiblePosition endOfDocument(const Node* node)
976 {
977     if (!node || !node->document() || !node->document()->documentElement())
978         return VisiblePosition();
979     
980     Element* doc = node->document()->documentElement();
981     return VisiblePosition(lastPositionInNode(doc), DOWNSTREAM);
982 }
983
984 VisiblePosition endOfDocument(const VisiblePosition &c)
985 {
986     return endOfDocument(c.deepEquivalent().deprecatedNode());
987 }
988
989 bool inSameDocument(const VisiblePosition &a, const VisiblePosition &b)
990 {
991     Position ap = a.deepEquivalent();
992     Node* an = ap.deprecatedNode();
993     if (!an)
994         return false;
995     Position bp = b.deepEquivalent();
996     Node* bn = bp.deprecatedNode();
997     if (an == bn)
998         return true;
999
1000     return an->document() == bn->document();
1001 }
1002
1003 bool isStartOfDocument(const VisiblePosition &p)
1004 {
1005     return p.isNotNull() && p.previous().isNull();
1006 }
1007
1008 bool isEndOfDocument(const VisiblePosition &p)
1009 {
1010     return p.isNotNull() && p.next().isNull();
1011 }
1012
1013 // ---------
1014
1015 VisiblePosition startOfEditableContent(const VisiblePosition& visiblePosition)
1016 {
1017     Node* highestRoot = highestEditableRoot(visiblePosition.deepEquivalent());
1018     if (!highestRoot)
1019         return VisiblePosition();
1020
1021     return firstPositionInNode(highestRoot);
1022 }
1023
1024 VisiblePosition endOfEditableContent(const VisiblePosition& visiblePosition)
1025 {
1026     Node* highestRoot = highestEditableRoot(visiblePosition.deepEquivalent());
1027     if (!highestRoot)
1028         return VisiblePosition();
1029
1030     return lastPositionInNode(highestRoot);
1031 }
1032
1033 static VisiblePosition logicalStartPositionForLine(const VisiblePosition& c)
1034 {
1035     if (c.isNull())
1036         return VisiblePosition();
1037
1038     RootInlineBox* rootBox = RenderedPosition(c).rootBox();
1039     if (!rootBox) {
1040         // There are VisiblePositions at offset 0 in blocks without
1041         // RootInlineBoxes, like empty editable blocks and bordered blocks.
1042         Position p = c.deepEquivalent();
1043         if (p.deprecatedNode()->renderer() && p.deprecatedNode()->renderer()->isRenderBlock() && !p.deprecatedEditingOffset())
1044             return positionAvoidingFirstPositionInTable(c);
1045         
1046         return VisiblePosition();
1047     }
1048     
1049     InlineBox* logicalStartBox;
1050     Node* logicalStartNode = rootBox->getLogicalStartBoxWithNode(logicalStartBox);
1051
1052     if (!logicalStartNode)
1053         return VisiblePosition();
1054
1055     VisiblePosition visPos = logicalStartNode->isTextNode() ? VisiblePosition(Position(logicalStartNode, logicalStartBox->caretMinOffset(), Position::PositionIsOffsetInAnchor), DOWNSTREAM)
1056                                                             : VisiblePosition(positionBeforeNode(logicalStartNode), DOWNSTREAM);
1057     return positionAvoidingFirstPositionInTable(visPos);
1058 }
1059
1060 VisiblePosition logicalStartOfLine(const VisiblePosition& c)
1061 {
1062     // TODO: this is the current behavior that might need to be fixed.
1063     // Please refer to https://bugs.webkit.org/show_bug.cgi?id=49107 for detail.
1064     VisiblePosition visPos = logicalStartPositionForLine(c);
1065
1066     if (Node* editableRoot = highestEditableRoot(c.deepEquivalent())) {
1067         if (!editableRoot->contains(visPos.deepEquivalent().containerNode()))
1068             return firstPositionInNode(editableRoot);
1069     }
1070     return c.honorEditingBoundaryAtOrBefore(visPos);
1071 }
1072
1073 static VisiblePosition logicalEndPositionForLine(const VisiblePosition& c)
1074 {
1075     if (c.isNull())
1076         return VisiblePosition();
1077
1078     RootInlineBox* rootBox = RenderedPosition(c).rootBox();
1079     if (!rootBox) {
1080         // There are VisiblePositions at offset 0 in blocks without
1081         // RootInlineBoxes, like empty editable blocks and bordered blocks.
1082         Position p = c.deepEquivalent();
1083         if (p.deprecatedNode()->renderer() && p.deprecatedNode()->renderer()->isRenderBlock() && !p.deprecatedEditingOffset())
1084             return c;
1085         return VisiblePosition();
1086     }
1087     
1088     InlineBox* logicalEndBox;
1089     Node* logicalEndNode = rootBox->getLogicalEndBoxWithNode(logicalEndBox);
1090
1091     if (!logicalEndNode)
1092         return VisiblePosition();
1093     
1094     Position pos;
1095     if (logicalEndNode->hasTagName(brTag))
1096         pos = positionBeforeNode(logicalEndNode);
1097     else if (logicalEndBox->isInlineTextBox()) {
1098         InlineTextBox* endTextBox = static_cast<InlineTextBox*>(logicalEndBox);
1099         int endOffset = endTextBox->start();
1100         if (!endTextBox->isLineBreak())
1101             endOffset += endTextBox->len();
1102         pos = Position(logicalEndNode, endOffset, Position::PositionIsOffsetInAnchor);
1103     } else
1104         pos = positionAfterNode(logicalEndNode);
1105     
1106     return VisiblePosition(pos, VP_UPSTREAM_IF_POSSIBLE);
1107 }
1108
1109 bool inSameLogicalLine(const VisiblePosition& a, const VisiblePosition& b)
1110 {
1111     return a.isNotNull() && logicalStartOfLine(a) == logicalStartOfLine(b);
1112 }
1113
1114 VisiblePosition logicalEndOfLine(const VisiblePosition& c)
1115 {
1116     // TODO: this is the current behavior that might need to be fixed.
1117     // Please refer to https://bugs.webkit.org/show_bug.cgi?id=49107 for detail.
1118
1119     VisiblePosition visPos = logicalEndPositionForLine(c);
1120     
1121     // Make sure the end of line is at the same line as the given input position. For a wrapping line, the logical end
1122     // position for the not-last-2-lines might incorrectly hand back the logical beginning of the next line. 
1123     // For example, <div contenteditable dir="rtl" style="line-break:before-white-space">abcdefg abcdefg abcdefg
1124     // a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg </div>
1125     // In this case, use the previous position of the computed logical end position.
1126     if (!inSameLogicalLine(c, visPos))
1127         visPos = visPos.previous();
1128
1129     if (Node* editableRoot = highestEditableRoot(c.deepEquivalent())) {
1130         if (!editableRoot->contains(visPos.deepEquivalent().containerNode()))
1131             return lastPositionInNode(editableRoot);
1132     }
1133     return c.honorEditingBoundaryAtOrAfter(visPos);
1134 }
1135
1136 VisiblePosition leftBoundaryOfLine(const VisiblePosition& c, TextDirection direction)
1137 {
1138     return direction == LTR ? logicalStartOfLine(c) : logicalEndOfLine(c);
1139 }
1140
1141 VisiblePosition rightBoundaryOfLine(const VisiblePosition& c, TextDirection direction)
1142 {
1143     return direction == LTR ? logicalEndOfLine(c) : logicalStartOfLine(c);
1144 }
1145
1146 static const int invalidOffset = -1;
1147 static const int offsetNotFound = -1;
1148
1149 static bool isBoxVisuallyLastInLine(const InlineBox* box, TextDirection blockDirection)
1150 {
1151     return blockDirection == LTR ? !box->nextLeafChild() || box->nextLeafChild()->renderer()->isBR()
1152         : !box->prevLeafChild() || box->prevLeafChild()->renderer()->isBR();
1153 }
1154
1155 static bool positionIsInBox(const VisiblePosition& wordBreak, const InlineBox* box, int& offsetOfWordBreak)
1156 {
1157     if (wordBreak.isNull())
1158         return false;
1159
1160     InlineBox* boxOfWordBreak;
1161     wordBreak.getInlineBoxAndOffset(boxOfWordBreak, offsetOfWordBreak);
1162     return box == boxOfWordBreak;
1163 }
1164
1165 static VisiblePosition previousWordBreakInBoxInsideBlockWithSameDirectionality(const InlineBox* box, const VisiblePosition& previousWordBreak, int& offsetOfWordBreak)
1166 {
1167     // In a LTR block, the word break should be on the left boundary of a word.
1168     // In a RTL block, the word break should be on the right boundary of a word.
1169     // Because nextWordPosition() returns the word break on the right boundary of the word for LTR text,
1170     // we need to use previousWordPosition() to traverse words within the inline boxes from right to left
1171     // to find the previous word break (i.e. the first word break on the left). The same applies to RTL text.
1172     
1173     bool hasSeenWordBreakInThisBox = previousWordBreak.isNotNull();
1174
1175     VisiblePosition wordBreak;
1176
1177     if (hasSeenWordBreakInThisBox)
1178         wordBreak = previousWordBreak;
1179     else {
1180         wordBreak = createLegacyEditingPosition(box->renderer()->node(), box->caretMaxOffset());
1181
1182         // Return the rightmost word boundary of LTR box or leftmost word boundary of RTL box if
1183         // it is not in the previously visited boxes. For example, given a logical text 
1184         // "abc def     hij opq", there are 2 boxes: the "abc def " (starts at 0 and length is 8) 
1185         // and the "hij opq" (starts at 12 and length is 7). The word breaks are 
1186         // "abc |def |    hij |opq". We normally catch the word break between "def" and "hij" when
1187         // we visit the box that contains "hij opq", but this word break doesn't exist in the box
1188         // that contains "hij opq" when there are multiple spaces. So we detect it when we're
1189         // traversing the box that contains "abc def " instead.
1190
1191         if ((box->isLeftToRightDirection() && box->nextLeafChild())
1192             || (!box->isLeftToRightDirection() && box->prevLeafChild())) {
1193
1194             VisiblePosition positionAfterWord = nextBoundary(wordBreak, nextWordPositionBoundary);
1195             if (positionAfterWord.isNotNull()) {
1196                 VisiblePosition positionBeforeWord = previousBoundary(positionAfterWord, previousWordPositionBoundary);
1197             
1198                 if (positionIsInBox(positionBeforeWord, box, offsetOfWordBreak))
1199                     return positionBeforeWord;
1200             }
1201         }
1202     }
1203   
1204     wordBreak = previousBoundary(wordBreak, previousWordPositionBoundary);
1205     if (previousWordBreak == wordBreak)
1206         return VisiblePosition();
1207
1208     return positionIsInBox(wordBreak, box, offsetOfWordBreak) ? wordBreak : VisiblePosition();
1209 }
1210
1211 static VisiblePosition leftmostPositionInRTLBoxInLTRBlock(const InlineBox* box)
1212 {
1213     // FIXME: Probably need to take care of bidi level too.
1214     Node* node = box->renderer()->node();
1215     InlineBox* previousLeaf = box->prevLeafChild();
1216     InlineBox* nextLeaf = box->nextLeafChild();   
1217     
1218     if (previousLeaf && !previousLeaf->isLeftToRightDirection())
1219         return createLegacyEditingPosition(node, box->caretMaxOffset());
1220
1221     if (nextLeaf && !nextLeaf->isLeftToRightDirection()) {
1222         if (previousLeaf)
1223             return createLegacyEditingPosition(previousLeaf->renderer()->node(), previousLeaf->caretMaxOffset());
1224
1225         InlineBox* lastRTLLeaf;
1226         do {
1227             lastRTLLeaf = nextLeaf;
1228             nextLeaf = nextLeaf->nextLeafChild();
1229         } while (nextLeaf && !nextLeaf->isLeftToRightDirection());
1230         return createLegacyEditingPosition(lastRTLLeaf->renderer()->node(), lastRTLLeaf->caretMinOffset());
1231     }
1232
1233     return createLegacyEditingPosition(node, box->caretMinOffset());
1234 }
1235
1236 static VisiblePosition rightmostPositionInLTRBoxInRTLBlock(const InlineBox* box)
1237 {
1238     // FIXME: Probably need to take care of bidi level too.
1239     Node* node = box->renderer()->node();
1240     InlineBox* previousLeaf = box->prevLeafChild();
1241     InlineBox* nextLeaf = box->nextLeafChild();   
1242     
1243     if (nextLeaf && nextLeaf->isLeftToRightDirection())    
1244         return createLegacyEditingPosition(node, box->caretMaxOffset());
1245
1246     if (previousLeaf && previousLeaf->isLeftToRightDirection()) {
1247         if (nextLeaf)
1248             return createLegacyEditingPosition(nextLeaf->renderer()->node(), nextLeaf->caretMaxOffset());
1249
1250         InlineBox* firstLTRLeaf;
1251         do {
1252             firstLTRLeaf = previousLeaf;
1253             previousLeaf = previousLeaf->prevLeafChild();
1254         } while (previousLeaf && previousLeaf->isLeftToRightDirection());
1255         return createLegacyEditingPosition(firstLTRLeaf->renderer()->node(), firstLTRLeaf->caretMinOffset());
1256     }
1257
1258     return createLegacyEditingPosition(node, box->caretMinOffset());
1259 }
1260     
1261 static VisiblePosition lastWordBreakInBox(const InlineBox* box, int& offsetOfWordBreak)
1262 {
1263     // Add the leftmost word break for RTL box or rightmost word break for LTR box.
1264     InlineBox* previousLeaf = box->prevLeafChild();
1265     InlineBox* nextLeaf = box->nextLeafChild();
1266     VisiblePosition boundaryPosition;
1267     if (box->direction() == RTL && (!previousLeaf || previousLeaf->isLeftToRightDirection()))
1268         boundaryPosition = leftmostPositionInRTLBoxInLTRBlock(box);
1269     else if (box->direction() == LTR && (!nextLeaf || !nextLeaf->isLeftToRightDirection()))
1270         boundaryPosition = rightmostPositionInLTRBoxInRTLBlock(box);
1271
1272     if (boundaryPosition.isNull())
1273         return VisiblePosition();            
1274
1275     VisiblePosition wordBreak = nextBoundary(boundaryPosition, nextWordPositionBoundary);
1276     if (wordBreak.isNull())
1277         wordBreak = boundaryPosition;
1278     else if (wordBreak != boundaryPosition)
1279         wordBreak = previousBoundary(wordBreak, previousWordPositionBoundary);
1280
1281     return positionIsInBox(wordBreak, box, offsetOfWordBreak) ? wordBreak : VisiblePosition();    
1282 }
1283
1284 static bool positionIsVisuallyOrderedInBoxInBlockWithDifferentDirectionality(const VisiblePosition& wordBreak, const InlineBox* box, int& offsetOfWordBreak)
1285 {
1286     int previousOffset = offsetOfWordBreak;
1287     return positionIsInBox(wordBreak, box, offsetOfWordBreak)
1288         && (previousOffset == invalidOffset || previousOffset < offsetOfWordBreak);
1289 }
1290     
1291 static VisiblePosition nextWordBreakInBoxInsideBlockWithDifferentDirectionality(
1292     const InlineBox* box, const VisiblePosition& previousWordBreak, int& offsetOfWordBreak, bool& isLastWordBreakInBox)
1293 {
1294     // FIXME: Probably need to take care of bidi level too.
1295     
1296     // In a LTR block, the word break should be on the left boundary of a word.
1297     // In a RTL block, the word break should be on the right boundary of a word.
1298     // Because previousWordPosition() returns the word break on the right boundary of the word for RTL text,
1299     // we need to use nextWordPosition() to traverse words within the inline boxes from right to left to find the next word break.
1300     // The same applies to LTR text, in which words are traversed within the inline boxes from left to right.
1301     
1302     bool hasSeenWordBreakInThisBox = previousWordBreak.isNotNull();
1303     VisiblePosition wordBreak = hasSeenWordBreakInThisBox ? previousWordBreak : 
1304         createLegacyEditingPosition(box->renderer()->node(), box->caretMinOffset());
1305
1306     wordBreak = nextBoundary(wordBreak, nextWordPositionBoundary);
1307   
1308     // Given RTL box "ABC DEF" either follows a LTR box or is the first visual box in an LTR block as an example,
1309     // the visual display of the RTL box is: "(0)J(10)I(9)H(8) (7)F(6)E(5)D(4) (3)C(2)B(1)A(11)",
1310     // where the number in parenthesis represents offset in visiblePosition. 
1311     // Start at offset 0, the first word break is at offset 3, the 2nd word break is at offset 7, and the 3rd word break should be at offset 0.
1312     // But nextWordPosition() of offset 7 is offset 11, which should be ignored, 
1313     // and the position at offset 0 should be manually added as the last word break within the box.
1314     if (wordBreak != previousWordBreak && positionIsVisuallyOrderedInBoxInBlockWithDifferentDirectionality(wordBreak, box, offsetOfWordBreak)) {
1315         isLastWordBreakInBox = false;
1316         return wordBreak;
1317     }
1318     
1319     isLastWordBreakInBox = true;
1320     return lastWordBreakInBox(box, offsetOfWordBreak);
1321 }
1322
1323 struct WordBoundaryEntry {
1324     WordBoundaryEntry()
1325         : offsetInInlineBox(invalidOffset) 
1326     { 
1327     }
1328
1329     WordBoundaryEntry(const VisiblePosition& position, int offset)
1330         : visiblePosition(position)
1331         , offsetInInlineBox(offset) 
1332     { 
1333     }
1334
1335     VisiblePosition visiblePosition;
1336     int offsetInInlineBox;
1337 };
1338     
1339 typedef Vector<WordBoundaryEntry, 50> WordBoundaryVector;
1340     
1341 static void appendPositionAtLogicalEndOfLine(const InlineBox* box, WordBoundaryVector& orderedWordBoundaries)
1342 {
1343     VisiblePosition endOfBlock = logicalEndOfLine(createLegacyEditingPosition(box->renderer()->node(), box->caretMaxOffset()));
1344
1345     int offsetOfEndOfBlock;
1346     if (positionIsInBox(endOfBlock, box, offsetOfEndOfBlock))
1347         orderedWordBoundaries.append(WordBoundaryEntry(endOfBlock, offsetOfEndOfBlock));
1348 }
1349     
1350 static void collectWordBreaksInBoxInsideBlockWithSameDirectionality(const InlineBox* box, WordBoundaryVector& orderedWordBoundaries)
1351 {
1352     orderedWordBoundaries.clear();
1353
1354     if (!box->renderer()->isBR() && isBoxVisuallyLastInLine(box, box->direction()))
1355         appendPositionAtLogicalEndOfLine(box, orderedWordBoundaries);
1356     
1357     VisiblePosition wordBreak;
1358     int offsetOfWordBreak = invalidOffset;
1359     while (1) {
1360         wordBreak = previousWordBreakInBoxInsideBlockWithSameDirectionality(box, wordBreak, offsetOfWordBreak);
1361         if (wordBreak.isNull())
1362             break;
1363         WordBoundaryEntry wordBoundaryEntry(wordBreak, offsetOfWordBreak);
1364         orderedWordBoundaries.append(wordBoundaryEntry);
1365     }
1366 }
1367
1368 static void collectWordBreaksInBoxInsideBlockWithDifferntDirectionality(const InlineBox* box, WordBoundaryVector& orderedWordBoundaries)
1369 {
1370     orderedWordBoundaries.clear();
1371     
1372     if (!box->renderer()->isBR() && isBoxVisuallyLastInLine(box, box->direction() == LTR ? RTL : LTR))
1373         appendPositionAtLogicalEndOfLine(box, orderedWordBoundaries);
1374     
1375     VisiblePosition wordBreak;
1376     int offsetOfWordBreak = invalidOffset;
1377     bool isLastWordBreakInBox = false;
1378     while (1) {
1379         wordBreak = nextWordBreakInBoxInsideBlockWithDifferentDirectionality(box, wordBreak, offsetOfWordBreak, isLastWordBreakInBox);
1380         if (wordBreak.isNotNull()) {
1381             WordBoundaryEntry wordBoundaryEntry(wordBreak, offsetOfWordBreak);
1382             orderedWordBoundaries.append(wordBoundaryEntry);
1383         }
1384         if (isLastWordBreakInBox)
1385             break;
1386     }
1387 }
1388
1389 static void collectWordBreaksInBox(const InlineBox* box, WordBoundaryVector& orderedWordBoundaries, TextDirection blockDirection)
1390 {
1391     if (box->direction() == blockDirection)
1392         collectWordBreaksInBoxInsideBlockWithSameDirectionality(box, orderedWordBoundaries);
1393     else
1394         collectWordBreaksInBoxInsideBlockWithDifferntDirectionality(box, orderedWordBoundaries);        
1395 }
1396     
1397 static VisiblePosition previousWordBoundaryInBox(const InlineBox* box, int offset)
1398 {
1399     int offsetOfWordBreak = 0;
1400     VisiblePosition wordBreak;
1401     while (true) {
1402         wordBreak = previousWordBreakInBoxInsideBlockWithSameDirectionality(box, wordBreak, offsetOfWordBreak);
1403         if (wordBreak.isNull())
1404             break;
1405         if (offset == invalidOffset || offsetOfWordBreak != offset)
1406             return wordBreak;
1407     }        
1408     return VisiblePosition();
1409 }
1410
1411 static VisiblePosition nextWordBoundaryInBox(const InlineBox* box, int offset)
1412 {
1413     int offsetOfWordBreak = 0;
1414     VisiblePosition wordBreak;
1415     bool isLastWordBreakInBox = false;
1416     do {
1417         wordBreak = nextWordBreakInBoxInsideBlockWithDifferentDirectionality(box, wordBreak, offsetOfWordBreak, isLastWordBreakInBox);
1418         if (wordBreak.isNotNull() && (offset == invalidOffset || offsetOfWordBreak != offset))
1419             return wordBreak;
1420     } while (!isLastWordBreakInBox);       
1421     return VisiblePosition();
1422 }
1423     
1424 static VisiblePosition visuallyLastWordBoundaryInBox(const InlineBox* box, int offset, TextDirection blockDirection)
1425 {
1426     WordBoundaryVector orderedWordBoundaries;
1427     collectWordBreaksInBox(box, orderedWordBoundaries, blockDirection);
1428     if (!orderedWordBoundaries.size()) 
1429         return VisiblePosition();
1430     if (offset == invalidOffset || orderedWordBoundaries[orderedWordBoundaries.size() - 1].offsetInInlineBox != offset)
1431         return orderedWordBoundaries[orderedWordBoundaries.size() - 1].visiblePosition;
1432     if (orderedWordBoundaries.size() > 1)
1433         return orderedWordBoundaries[orderedWordBoundaries.size() - 2].visiblePosition;
1434     return VisiblePosition();
1435 }
1436         
1437 static int greatestOffsetUnder(int offset, bool boxAndBlockAreInSameDirection, const WordBoundaryVector& orderedWordBoundaries)
1438 {
1439     if (!orderedWordBoundaries.size())
1440         return offsetNotFound;
1441     // FIXME: binary search.
1442     if (boxAndBlockAreInSameDirection) {
1443         for (unsigned i = 0; i < orderedWordBoundaries.size(); ++i) {
1444             if (orderedWordBoundaries[i].offsetInInlineBox < offset)
1445                 return i;
1446         }
1447         return offsetNotFound;
1448     }
1449     for (int i = orderedWordBoundaries.size() - 1; i >= 0; --i) {
1450         if (orderedWordBoundaries[i].offsetInInlineBox < offset)
1451             return i;
1452     }
1453     return offsetNotFound;
1454 }
1455
1456 static int smallestOffsetAbove(int offset, bool boxAndBlockAreInSameDirection, const WordBoundaryVector& orderedWordBoundaries)
1457 {
1458     if (!orderedWordBoundaries.size())
1459         return offsetNotFound;
1460     // FIXME: binary search.
1461     if (boxAndBlockAreInSameDirection) {
1462         for (int i = orderedWordBoundaries.size() - 1; i >= 0; --i) {
1463             if (orderedWordBoundaries[i].offsetInInlineBox > offset)
1464                 return i;
1465         }
1466         return offsetNotFound;
1467     }
1468     for (unsigned i = 0; i < orderedWordBoundaries.size(); ++i) {
1469         if (orderedWordBoundaries[i].offsetInInlineBox > offset)
1470             return i;
1471     }
1472     return offsetNotFound;
1473 }
1474
1475 static const InlineBox* leftInlineBox(const InlineBox* box, TextDirection blockDirection)
1476 {
1477     if (box->prevLeafChild())
1478         return box->prevLeafChild();
1479     
1480     const RootInlineBox* rootBox = box->root();
1481     const bool isBlockLTR = blockDirection == LTR;
1482     const InlineFlowBox* leftLineBox = isBlockLTR ? rootBox->prevLineBox() : rootBox->nextLineBox();
1483     if (leftLineBox)
1484         return leftLineBox->lastLeafChild();
1485
1486     return 0;
1487 }
1488
1489 static const InlineBox* rightInlineBox(const InlineBox* box, TextDirection blockDirection)
1490 {
1491     if (box->nextLeafChild())
1492         return box->nextLeafChild();
1493     
1494     const RootInlineBox* rootBox = box->root();
1495     const bool isBlockLTR = blockDirection == LTR;
1496     const InlineFlowBox* rightLineBox = isBlockLTR ? rootBox->nextLineBox() : rootBox->prevLineBox();
1497     if (rightLineBox)
1498         return rightLineBox->firstLeafChild();
1499
1500     return 0;
1501 }
1502
1503 static VisiblePosition leftWordBoundary(const InlineBox* box, int offset, TextDirection blockDirection)
1504 {
1505     VisiblePosition wordBreak;
1506     for  (const InlineBox* adjacentBox = box; adjacentBox; adjacentBox = leftInlineBox(adjacentBox, blockDirection)) {
1507         if (blockDirection == LTR) {
1508             if (adjacentBox->isLeftToRightDirection()) 
1509                 wordBreak = previousWordBoundaryInBox(adjacentBox, adjacentBox == box ? offset : invalidOffset);
1510             else
1511                 wordBreak = nextWordBoundaryInBox(adjacentBox, adjacentBox == box ? offset : invalidOffset);
1512         } else 
1513             wordBreak = visuallyLastWordBoundaryInBox(adjacentBox, adjacentBox == box ? offset : invalidOffset, blockDirection);            
1514         if (wordBreak.isNotNull())
1515             return wordBreak;
1516     }
1517     return VisiblePosition();
1518 }
1519  
1520 static VisiblePosition rightWordBoundary(const InlineBox* box, int offset, TextDirection blockDirection)
1521 {
1522     
1523     VisiblePosition wordBreak;
1524     for (const InlineBox* adjacentBox = box; adjacentBox; adjacentBox = rightInlineBox(adjacentBox, blockDirection)) {
1525         if (blockDirection == RTL) {
1526             if (adjacentBox->isLeftToRightDirection())
1527                 wordBreak = nextWordBoundaryInBox(adjacentBox, adjacentBox == box ? offset : invalidOffset);
1528             else
1529                 wordBreak = previousWordBoundaryInBox(adjacentBox, adjacentBox == box ? offset : invalidOffset);
1530         } else 
1531             wordBreak = visuallyLastWordBoundaryInBox(adjacentBox, adjacentBox == box ? offset : invalidOffset, blockDirection);            
1532         if (!wordBreak.isNull())
1533             return wordBreak;
1534     }
1535     return VisiblePosition();
1536 }
1537     
1538 static bool positionIsInBoxButNotOnBoundary(const VisiblePosition& wordBreak, const InlineBox* box)
1539 {
1540     int offsetOfWordBreak;
1541     return positionIsInBox(wordBreak, box, offsetOfWordBreak)
1542         && offsetOfWordBreak != box->caretMaxOffset() && offsetOfWordBreak != box->caretMinOffset();
1543 }
1544
1545 static VisiblePosition leftWordPositionIgnoringEditingBoundary(const VisiblePosition& visiblePosition)
1546 {
1547     InlineBox* box;
1548     int offset;
1549     visiblePosition.getInlineBoxAndOffset(box, offset);
1550
1551     if (!box)
1552         return VisiblePosition();
1553
1554     TextDirection blockDirection = directionOfEnclosingBlock(visiblePosition.deepEquivalent());
1555
1556     // FIXME: If the box's directionality is the same as that of the enclosing block, when the offset is at the box boundary
1557     // and the direction is towards inside the box, do I still need to make it a special case? For example, a LTR box inside a LTR block,
1558     // when offset is at box's caretMinOffset and the direction is DirectionRight, should it be taken care as a general case?
1559     if (offset == box->caretLeftmostOffset())
1560         return leftWordBoundary(leftInlineBox(box, blockDirection), invalidOffset, blockDirection);
1561     if (offset == box->caretRightmostOffset())
1562         return leftWordBoundary(box, offset, blockDirection);
1563     
1564     
1565     VisiblePosition wordBreak;
1566     if (blockDirection == LTR) {
1567         if (box->direction() == blockDirection)
1568             wordBreak = previousBoundary(visiblePosition, previousWordPositionBoundary);
1569         else
1570             wordBreak = nextBoundary(visiblePosition, nextWordPositionBoundary);
1571     }
1572     if (wordBreak.isNotNull() && positionIsInBoxButNotOnBoundary(wordBreak, box))
1573         return wordBreak;
1574     
1575     WordBoundaryVector orderedWordBoundaries;
1576     collectWordBreaksInBox(box, orderedWordBoundaries, blockDirection);
1577
1578     int index = box->isLeftToRightDirection() ? greatestOffsetUnder(offset, blockDirection == LTR, orderedWordBoundaries)
1579         : smallestOffsetAbove(offset, blockDirection == RTL, orderedWordBoundaries);
1580     if (index >= 0)
1581         return orderedWordBoundaries[index].visiblePosition;
1582     
1583     return leftWordBoundary(leftInlineBox(box, blockDirection), invalidOffset, blockDirection);
1584 }
1585
1586 static VisiblePosition rightWordPositionIgnoringEditingBoundary(const VisiblePosition& visiblePosition)
1587 {
1588     InlineBox* box;
1589     int offset;
1590     visiblePosition.getInlineBoxAndOffset(box, offset);
1591
1592     if (!box)
1593         return VisiblePosition();
1594
1595     TextDirection blockDirection = directionOfEnclosingBlock(visiblePosition.deepEquivalent());
1596     
1597     if (offset == box->caretLeftmostOffset())
1598         return rightWordBoundary(box, offset, blockDirection);
1599     if (offset == box->caretRightmostOffset())
1600         return rightWordBoundary(rightInlineBox(box, blockDirection), invalidOffset, blockDirection);
1601  
1602     VisiblePosition wordBreak;
1603     if (blockDirection == RTL) {
1604         if (box->direction() == blockDirection)
1605             wordBreak = previousBoundary(visiblePosition, previousWordPositionBoundary);
1606         else
1607             wordBreak = nextBoundary(visiblePosition, nextWordPositionBoundary);
1608     }
1609     if (wordBreak.isNotNull() && positionIsInBoxButNotOnBoundary(wordBreak, box))
1610         return wordBreak;
1611     
1612     WordBoundaryVector orderedWordBoundaries;
1613     collectWordBreaksInBox(box, orderedWordBoundaries, blockDirection);
1614     
1615     int index = box->isLeftToRightDirection() ? smallestOffsetAbove(offset, blockDirection == LTR, orderedWordBoundaries)
1616         : greatestOffsetUnder(offset, blockDirection == RTL, orderedWordBoundaries);
1617     if (index >= 0)
1618         return orderedWordBoundaries[index].visiblePosition;
1619     
1620     return rightWordBoundary(rightInlineBox(box, blockDirection), invalidOffset, blockDirection);
1621 }
1622
1623 VisiblePosition leftWordPosition(const VisiblePosition& visiblePosition)
1624 {
1625     if (visiblePosition.isNull())
1626         return VisiblePosition();
1627
1628     VisiblePosition leftWordBreak = leftWordPositionIgnoringEditingBoundary(visiblePosition);
1629     return visiblePosition.honorEditingBoundaryAtOrBefore(leftWordBreak);
1630 }
1631
1632 VisiblePosition rightWordPosition(const VisiblePosition& visiblePosition)
1633 {
1634     if (visiblePosition.isNull())
1635         return VisiblePosition();
1636
1637     VisiblePosition rightWordBreak = rightWordPositionIgnoringEditingBoundary(visiblePosition);
1638     return visiblePosition.honorEditingBoundaryAtOrBefore(rightWordBreak);
1639 }
1640
1641 }