WebCore:
[WebKit-https.git] / WebCore / editing / visible_units.cpp
1 /*
2  * Copyright (C) 2004 Apple Computer, 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 "RenderBlock.h"
33 #include "RenderLayer.h"
34 #include "TextBoundaries.h"
35 #include "TextBreakIterator.h"
36 #include "TextIterator.h"
37 #include "htmlediting.h"
38
39 namespace WebCore {
40
41 using namespace HTMLNames;
42
43 static VisiblePosition previousBoundary(const VisiblePosition &c, unsigned (*searchFunction)(const UChar *, unsigned))
44 {
45     Position pos = c.deepEquivalent();
46     Node *n = pos.node();
47     if (!n)
48         return VisiblePosition();
49     Document *d = n->document();
50     Node *de = d->documentElement();
51     if (!de)
52         return VisiblePosition();
53     Node *boundary = n->enclosingBlockFlowElement();
54     if (!boundary)
55         return VisiblePosition();
56     bool isContentEditable = boundary->isContentEditable();
57     while (boundary && boundary != de && boundary->parentNode() && isContentEditable == boundary->parentNode()->isContentEditable())
58         boundary = boundary->parentNode();
59
60     Position start = rangeCompliantEquivalent(Position(boundary, 0));
61     Position end = rangeCompliantEquivalent(pos);
62     RefPtr<Range> searchRange = new Range(d);
63     
64     int exception = 0;
65     searchRange->setStart(start.node(), start.offset(), exception);
66     searchRange->setEnd(end.node(), end.offset(), exception);
67     
68     ASSERT(!exception);
69     if (exception)
70         return VisiblePosition();
71         
72     SimplifiedBackwardsTextIterator it(searchRange.get());
73     Vector<UChar, 1024> string;
74     unsigned next = 0;
75     bool inTextSecurityMode = start.node() && start.node()->renderer() && start.node()->renderer()->style()->textSecurity() != TSNONE;
76     while (!it.atEnd()) {
77         // iterate to get chunks until the searchFunction returns a non-zero value.
78         if (!inTextSecurityMode) 
79             string.prepend(it.characters(), it.length());
80         else {
81             // Treat bullets used in the text security mode as regular characters when looking for boundaries
82             String iteratorString(it.characters(), it.length());
83             iteratorString = iteratorString.impl()->secure('x');
84             string.prepend(iteratorString.characters(), iteratorString.length());
85         }
86         
87         next = searchFunction(string.data(), string.size());
88         if (next != 0)
89             break;
90         it.advance();
91     }
92     
93     if (it.atEnd() && next == 0) {
94         pos = it.range()->startPosition();
95     } else if (next != 0) {
96         Node *node = it.range()->startContainer(exception);
97         if (node->isTextNode() || (node->renderer() && node->renderer()->isBR()))
98             // The next variable contains a usable index into a text node
99             pos = Position(node, next);
100         else {
101             // Use the end of the found range, the start is not guaranteed to
102             // be correct.
103             Position end = it.range()->endPosition();
104             VisiblePosition boundary(end);
105             unsigned i = it.length() - next;
106             while (i--)
107                 boundary = boundary.previous();
108             return boundary;
109         }
110     }
111
112     return VisiblePosition(pos, DOWNSTREAM);
113 }
114
115 static VisiblePosition nextBoundary(const VisiblePosition &c, unsigned (*searchFunction)(const UChar *, unsigned))
116 {
117     Position pos = c.deepEquivalent();
118     Node *n = pos.node();
119     if (!n)
120         return VisiblePosition();
121     Document *d = n->document();
122     Node *de = d->documentElement();
123     if (!de)
124         return VisiblePosition();
125     Node *boundary = n->enclosingBlockFlowElement();
126     if (!boundary)
127         return VisiblePosition();
128     bool isContentEditable = boundary->isContentEditable();
129     while (boundary && boundary != de && boundary->parentNode() && isContentEditable == boundary->parentNode()->isContentEditable())
130         boundary = boundary->parentNode();
131
132     RefPtr<Range> searchRange(d->createRange());
133     Position start(rangeCompliantEquivalent(pos));
134     ExceptionCode ec = 0;
135     searchRange->selectNodeContents(boundary, ec);
136     searchRange->setStart(start.node(), start.offset(), ec);
137     TextIterator it(searchRange.get(), true);
138     Vector<UChar, 1024> string;
139     unsigned next = 0;
140     bool inTextSecurityMode = start.node() && start.node()->renderer() && start.node()->renderer()->style()->textSecurity() != TSNONE;
141     while (!it.atEnd()) {
142         // Keep asking the iterator for chunks until the search function
143         // returns an end value not equal to the length of the string passed to it.
144         if (!inTextSecurityMode)
145             string.append(it.characters(), it.length());
146         else {
147             // Treat bullets used in the text security mode as regular characters when looking for boundaries
148             String iteratorString(it.characters(), it.length());
149             iteratorString = iteratorString.impl()->secure('x');
150             string.append(iteratorString.characters(), iteratorString.length());
151         }
152
153         next = searchFunction(string.data(), string.size());
154         if (next != string.size())
155             break;
156         it.advance();
157     }
158     
159     if (it.atEnd() && next == string.size()) {
160         pos = it.range()->startPosition();
161     } else if (next != 0) {
162         // Use the character iterator to translate the next value into a DOM position.
163         CharacterIterator charIt(searchRange.get(), true);
164         charIt.advance(next - 1);
165         pos = charIt.range()->endPosition();
166         
167         // FIXME: workaround for collapsed range (where only start position is correct) emitted for some emitted newlines (see rdar://5192593)
168         VisiblePosition visPos = VisiblePosition(pos);
169         if (visPos == VisiblePosition(charIt.range()->startPosition()))
170             pos = visPos.next(true).deepEquivalent();
171     }
172
173     // generate VisiblePosition, use UPSTREAM affinity if possible
174     return VisiblePosition(pos, VP_UPSTREAM_IF_POSSIBLE);
175 }
176
177 // ---------
178
179 static unsigned startWordBoundary(const UChar* characters, unsigned length)
180 {
181     int start, end;
182     findWordBoundary(characters, length, length, &start, &end);
183     return start;
184 }
185
186 VisiblePosition startOfWord(const VisiblePosition &c, EWordSide side)
187 {
188     // FIXME: This returns a null VP for c at the start of the document
189     // and side == LeftWordIfOnBoundary
190     VisiblePosition p = c;
191     if (side == RightWordIfOnBoundary) {
192         // at paragraph end, the startofWord is the current position
193         if (isEndOfParagraph(c))
194             return c;
195         
196         p = c.next();
197         if (p.isNull())
198             return c;
199     }
200     return previousBoundary(p, startWordBoundary);
201 }
202
203 static unsigned endWordBoundary(const UChar* characters, unsigned length)
204 {
205     int start, end;
206     findWordBoundary(characters, length, 0, &start, &end);
207     return end;
208 }
209
210 VisiblePosition endOfWord(const VisiblePosition &c, EWordSide side)
211 {
212     VisiblePosition p = c;
213     if (side == LeftWordIfOnBoundary) {
214         if (isStartOfParagraph(c))
215             return c;
216             
217         p = c.previous();
218         if (p.isNull())
219             return c;
220     } else if (isEndOfParagraph(c))
221         return c;
222     
223     return nextBoundary(p, endWordBoundary);
224 }
225
226 static unsigned previousWordPositionBoundary(const UChar* characters, unsigned length)
227 {
228     return findNextWordFromIndex(characters, length, length, false);
229 }
230
231 VisiblePosition previousWordPosition(const VisiblePosition &c)
232 {
233     VisiblePosition prev = previousBoundary(c, previousWordPositionBoundary);
234     return c.firstPositionWithSameEditabilityAtOrAfter(prev);
235 }
236
237 static unsigned nextWordPositionBoundary(const UChar* characters, unsigned length)
238 {
239     return findNextWordFromIndex(characters, length, 0, true);
240 }
241
242 VisiblePosition nextWordPosition(const VisiblePosition &c)
243 {
244     VisiblePosition next = nextBoundary(c, nextWordPositionBoundary);    
245     return c.lastPositionWithSameEditabilityAtOrBefore(next);
246 }
247
248 // ---------
249
250 static RootInlineBox *rootBoxForLine(const VisiblePosition &c)
251 {
252     Position p = c.deepEquivalent();
253     Node *node = p.node();
254     if (!node)
255         return 0;
256
257     RenderObject *renderer = node->renderer();
258     if (!renderer)
259         return 0;
260     
261     InlineBox *box = renderer->inlineBox(p.offset(), c.affinity());
262     if (!box)
263         return 0;
264     
265     return box->root();
266 }
267
268
269 static VisiblePosition startPositionForLine(const VisiblePosition& c)
270 {
271     if (c.isNull())
272         return VisiblePosition();
273         
274     RootInlineBox *rootBox = rootBoxForLine(c);
275     if (!rootBox) {
276         // There are VisiblePositions at offset 0 in blocks without
277         // RootInlineBoxes, like empty editable blocks and bordered blocks.
278         Position p = c.deepEquivalent();
279         if (p.node()->renderer() && p.node()->renderer()->isRenderBlock() && p.offset() == 0)
280             return c;
281         return VisiblePosition();
282     }
283     
284     // Generated content (e.g. list markers and CSS :before and :after
285     // pseudoelements) have no corresponding DOM element, and so cannot be
286     // represented by a VisiblePosition.  Use whatever follows instead.
287     InlineBox *startBox = rootBox->firstLeafChild();
288     Node *startNode;
289     while (1) {
290         if (!startBox)
291             return VisiblePosition();
292
293         RenderObject *startRenderer = startBox->object();
294         if (!startRenderer)
295             return VisiblePosition();
296
297         startNode = startRenderer->element();
298         if (startNode)
299             break;
300         
301         startBox = startBox->nextLeafChild();
302     }
303     
304     int startOffset = 0;
305     if (startBox->isInlineTextBox()) {
306         InlineTextBox *startTextBox = static_cast<InlineTextBox *>(startBox);
307         startOffset = startTextBox->m_start;
308     }
309   
310     VisiblePosition visPos = VisiblePosition(startNode, startOffset, DOWNSTREAM);
311
312     // return table offset 0 instead of the first VisiblePosition inside the table
313     VisiblePosition visPrevious = visPos.previous();
314     if (isLastPositionBeforeTable(visPrevious))
315         visPos = visPrevious;
316
317     return visPos;
318 }
319
320 VisiblePosition startOfLine(const VisiblePosition& c)
321 {
322     VisiblePosition visPos = startPositionForLine(c);
323     
324     if (visPos.isNotNull()) {
325         // Make sure the start of line is not greater than the given input position.  Else use the previous position to 
326         // obtain start of line.  This condition happens when the input position is before the space character at the end 
327         // of a soft-wrapped non-editable line. In this scenario, startPositionForLine would incorrectly hand back a position
328         // greater than the input position.  This fix is to account for the discrepancy between lines with webkit-line-break:after-white-space 
329         // style versus lines without that style, which would break before a space by default. 
330         Position p = visPos.deepEquivalent();
331         if (p.offset() > c.deepEquivalent().offset() && p.node()->isSameNode(c.deepEquivalent().node())) {
332             visPos = c.previous();
333             if (visPos.isNull())
334                 return VisiblePosition();
335             visPos = startPositionForLine(visPos);
336         }
337     }
338
339     return c.firstPositionWithSameEditabilityAtOrAfter(visPos);
340 }
341
342 static VisiblePosition endPositionForLine(const VisiblePosition& c)
343 {
344     if (c.isNull())
345         return VisiblePosition();
346         
347     RootInlineBox *rootBox = rootBoxForLine(c);
348     if (!rootBox) {
349         // There are VisiblePositions at offset 0 in blocks without
350         // RootInlineBoxes, like empty editable blocks and bordered blocks.
351         Position p = c.deepEquivalent();
352         if (p.node()->renderer() && p.node()->renderer()->isRenderBlock() && p.offset() == 0)
353             return c;
354         return VisiblePosition();
355     }
356     
357     // Generated content (e.g. list markers and CSS :before and :after
358     // pseudoelements) have no corresponding DOM element, and so cannot be
359     // represented by a VisiblePosition.  Use whatever precedes instead.
360     Node *endNode;
361     InlineBox *endBox = rootBox->lastLeafChild();
362     while (1) {
363         if (!endBox)
364             return VisiblePosition();
365
366         RenderObject *endRenderer = endBox->object();
367         if (!endRenderer)
368             return VisiblePosition();
369
370         endNode = endRenderer->element();
371         if (endNode)
372             break;
373         
374         endBox = endBox->prevLeafChild();
375     }
376     
377     int endOffset = 1;
378     if (endNode->hasTagName(brTag)) {
379         endOffset = 0;
380     } else if (endBox->isInlineTextBox()) {
381         InlineTextBox *endTextBox = static_cast<InlineTextBox *>(endBox);
382         endOffset = endTextBox->m_start;
383         if (!endTextBox->isLineBreak())
384             endOffset += endTextBox->m_len;
385     }
386     
387     return VisiblePosition(endNode, endOffset, VP_UPSTREAM_IF_POSSIBLE);
388 }
389
390 VisiblePosition endOfLine(const VisiblePosition& c)
391 {
392     VisiblePosition visPos = endPositionForLine(c);
393     
394     // Make sure the end of line is at the same line as the given input position.  Else use the previous position to 
395     // obtain end of line.  This condition happens when the input position is before the space character at the end 
396     // of a soft-wrapped non-editable line. In this scenario, endPositionForLine would incorrectly hand back a position
397     // in the next line instead. This fix is to account for the discrepancy between lines with webkit-line-break:after-white-space style
398     // versus lines without that style, which would break before a space by default. 
399     if (!inSameLine(c, visPos)) {
400         visPos = c.previous();
401         if (visPos.isNull())
402             return VisiblePosition();
403         visPos = endPositionForLine(visPos);
404     }
405     
406     return c.lastPositionWithSameEditabilityAtOrBefore(visPos);
407 }
408
409 bool inSameLine(const VisiblePosition &a, const VisiblePosition &b)
410 {
411     return a.isNotNull() && startOfLine(a) == startOfLine(b);
412 }
413
414 bool isStartOfLine(const VisiblePosition &p)
415 {
416     return p.isNotNull() && p == startOfLine(p);
417 }
418
419 bool isEndOfLine(const VisiblePosition &p)
420 {
421     return p.isNotNull() && p == endOfLine(p);
422 }
423
424 VisiblePosition previousLinePosition(const VisiblePosition &visiblePosition, int x)
425 {
426     Position p = visiblePosition.deepEquivalent();
427     Node *node = p.node();
428     Node* highestRoot = highestEditableRoot(p);
429     if (!node)
430         return VisiblePosition();
431     
432     node->document()->updateLayoutIgnorePendingStylesheets();
433     
434     RenderObject *renderer = node->renderer();
435     if (!renderer)
436         return VisiblePosition();
437
438     RenderBlock *containingBlock = 0;
439     RootInlineBox *root = 0;
440     InlineBox *box = renderer->inlineBox(p.offset(), visiblePosition.affinity());
441     if (box) {
442         root = box->root()->prevRootBox();
443         if (root)
444             containingBlock = renderer->containingBlock();
445     }
446
447     if (!root) {
448         // This containing editable block does not have a previous line.
449         // Need to move back to previous containing editable block in this root editable
450         // block and find the last root line box in that block.
451         Node* startBlock = enclosingBlock(node);
452         Node *n = node->previousEditable();
453         while (n && startBlock == enclosingBlock(n))
454             n = n->previousEditable();
455         while (n) {
456             if (highestEditableRoot(Position(n, 0)) != highestRoot)
457                 break;
458             Position pos(n, n->caretMinOffset());
459             if (pos.isCandidate()) {
460                 ASSERT(n->renderer());
461                 box = n->renderer()->inlineBox(n->caretMaxOffset());
462                 if (box) {
463                     // previous root line box found
464                     root = box->root();
465                     containingBlock = n->renderer()->containingBlock();
466                     break;
467                 }
468
469                 return VisiblePosition(pos, DOWNSTREAM);
470             }
471             n = n->previousEditable();
472         }
473     }
474     
475     if (root) {
476         // FIXME: Can be wrong for multi-column layout.
477         int absx, absy;
478         containingBlock->absolutePositionForContent(absx, absy);
479         if (containingBlock->hasOverflowClip())
480             containingBlock->layer()->subtractScrollOffset(absx, absy);
481         RenderObject *renderer = root->closestLeafChildForXPos(x - absx, isEditablePosition(p))->object();
482         Node* node = renderer->element();
483         if (editingIgnoresContent(node))
484             return Position(node->parent(), node->nodeIndex());
485         return renderer->positionForCoordinates(x - absx, root->topOverflow());
486     }
487     
488     // Could not find a previous line. This means we must already be on the first line.
489     // Move to the start of the content in this block, which effectively moves us
490     // to the start of the line we're on.
491     return VisiblePosition(node->rootEditableElement(), 0, DOWNSTREAM);
492 }
493
494 VisiblePosition nextLinePosition(const VisiblePosition &visiblePosition, int x)
495 {
496     Position p = visiblePosition.deepEquivalent();
497     Node *node = p.node();
498     Node* highestRoot = highestEditableRoot(p);
499     if (!node)
500         return VisiblePosition();
501     
502     node->document()->updateLayoutIgnorePendingStylesheets();
503
504     RenderObject *renderer = node->renderer();
505     if (!renderer)
506         return VisiblePosition();
507
508     RenderBlock *containingBlock = 0;
509     RootInlineBox *root = 0;
510     InlineBox *box = renderer->inlineBox(p.offset(), visiblePosition.affinity());
511     if (box) {
512         root = box->root()->nextRootBox();
513         if (root)
514             containingBlock = renderer->containingBlock();
515     }
516
517     if (!root) {
518         // This containing editable block does not have a next line.
519         // Need to move forward to next containing editable block in this root editable
520         // block and find the first root line box in that block.
521         Node* startBlock = enclosingBlock(node);
522         Node *n = node->nextEditable(p.offset());
523         while (n && startBlock == enclosingBlock(n))
524             n = n->nextEditable();
525         while (n) {
526             if (highestEditableRoot(Position(n, 0)) != highestRoot)
527                 break;
528             Position pos(n, n->caretMinOffset());
529             if (pos.isCandidate()) {
530                 ASSERT(n->renderer());
531                 box = n->renderer()->inlineBox(n->caretMinOffset());
532                 if (box) {
533                     // next root line box found
534                     root = box->root();
535                     containingBlock = n->renderer()->containingBlock();
536                     break;
537                 }
538
539                 return VisiblePosition(pos, DOWNSTREAM);
540             }
541             n = n->nextEditable();
542         }
543     }
544     
545     if (root) {
546         // FIXME: Can be wrong for multi-column layout.
547         int absx, absy;
548         containingBlock->absolutePositionForContent(absx, absy);
549         if (containingBlock->hasOverflowClip())
550             containingBlock->layer()->subtractScrollOffset(absx, absy);
551         RenderObject *renderer = root->closestLeafChildForXPos(x - absx, isEditablePosition(p))->object();
552         Node* node = renderer->element();
553         if (editingIgnoresContent(node))
554             return Position(node->parent(), node->nodeIndex());
555         return renderer->positionForCoordinates(x - absx, root->topOverflow());
556     }    
557
558     // Could not find a next line. This means we must already be on the last line.
559     // Move to the end of the content in this block, which effectively moves us
560     // to the end of the line we're on.
561     Element *rootElement = node->rootEditableElement();
562     return VisiblePosition(rootElement, rootElement ? rootElement->childNodeCount() : 0, DOWNSTREAM);
563 }
564
565 // ---------
566
567 static unsigned startSentenceBoundary(const UChar* characters, unsigned length)
568 {
569     TextBreakIterator* iterator = sentenceBreakIterator(characters, length);
570     // FIXME: The following function can return -1; we don't handle that.
571     return textBreakPreceding(iterator, length);
572 }
573
574 VisiblePosition startOfSentence(const VisiblePosition &c)
575 {
576     return previousBoundary(c, startSentenceBoundary);
577 }
578
579 static unsigned endSentenceBoundary(const UChar* characters, unsigned length)
580 {
581     TextBreakIterator* iterator = sentenceBreakIterator(characters, length);
582     return textBreakNext(iterator);
583 }
584
585 // FIXME: This includes the space after the punctuation that marks the end of the sentence.
586 VisiblePosition endOfSentence(const VisiblePosition &c)
587 {
588     return nextBoundary(c, endSentenceBoundary);
589 }
590
591 static unsigned previousSentencePositionBoundary(const UChar* characters, unsigned length)
592 {
593     // FIXME: This is identical to startSentenceBoundary. I'm pretty sure that's not right.
594     TextBreakIterator* iterator = sentenceBreakIterator(characters, length);
595     // FIXME: The following function can return -1; we don't handle that.
596     return textBreakPreceding(iterator, length);
597 }
598
599 VisiblePosition previousSentencePosition(const VisiblePosition &c)
600 {
601     VisiblePosition prev = previousBoundary(c, previousSentencePositionBoundary);
602     return c.firstPositionWithSameEditabilityAtOrAfter(prev);
603 }
604
605 static unsigned nextSentencePositionBoundary(const UChar* characters, unsigned length)
606 {
607     // FIXME: This is identical to endSentenceBoundary.  This isn't right, it needs to 
608     // move to the equivlant position in the following sentence.
609     TextBreakIterator* iterator = sentenceBreakIterator(characters, length);
610     return textBreakFollowing(iterator, 0);
611 }
612
613 VisiblePosition nextSentencePosition(const VisiblePosition &c)
614 {
615     VisiblePosition next = nextBoundary(c, nextSentencePositionBoundary);    
616     return c.lastPositionWithSameEditabilityAtOrBefore(next);
617 }
618
619 // FIXME: Broken for positions before/after images that aren't inline (5027702)
620 VisiblePosition startOfParagraph(const VisiblePosition &c)
621 {
622     Position p = c.deepEquivalent();
623     Node *startNode = p.node();
624
625     if (!startNode)
626         return VisiblePosition();
627     
628     if (startNode->renderer()
629         && ((startNode->renderer()->isTable() && !startNode->renderer()->isInline())
630             || startNode->renderer()->isHR())
631         && p.offset() == maxDeepOffset(startNode))
632         return VisiblePosition(Position(startNode, 0));
633
634     Node* startBlock = enclosingBlock(startNode);
635
636     Node *node = startNode;
637     int offset = p.offset();
638
639     Node *n = startNode;
640     while (n) {
641         if (n->isContentEditable() != startNode->isContentEditable())
642             break;
643         RenderObject *r = n->renderer();
644         if (!r) {
645             n = n->traversePreviousNodePostOrder(startBlock);
646             continue;
647         }
648         RenderStyle *style = r->style();
649         if (style->visibility() != VISIBLE) {
650             n = n->traversePreviousNodePostOrder(startBlock);
651             continue;
652         }
653         
654         if (r->isBR() || isBlock(n))
655             break;
656             
657         if (r->isText()) {
658             if (style->preserveNewline()) {
659                 const UChar* chars = static_cast<RenderText*>(r)->characters();
660                 int i = static_cast<RenderText*>(r)->textLength();
661                 int o = offset;
662                 if (n == startNode && o < i)
663                     i = max(0, o);
664                 while (--i >= 0)
665                     if (chars[i] == '\n')
666                         return VisiblePosition(n, i + 1, DOWNSTREAM);
667             }
668             node = n;
669             offset = 0;
670             n = n->traversePreviousNodePostOrder(startBlock);
671         } else if (editingIgnoresContent(n) || isTableElement(n)) {
672             node = n;
673             offset = 0;
674             n = n->previousSibling() ? n->previousSibling() : n->traversePreviousNodePostOrder(startBlock);
675         } else
676             n = n->traversePreviousNodePostOrder(startBlock);
677     }
678
679     return VisiblePosition(node, offset, DOWNSTREAM);
680 }
681
682 // FIXME: Broken for positions before/after images that aren't inline (5027702)
683 VisiblePosition endOfParagraph(const VisiblePosition &c)
684 {    
685     if (c.isNull())
686         return VisiblePosition();
687
688     Position p = c.deepEquivalent();
689     Node* startNode = p.node();
690
691     if (startNode->renderer()
692         && ((startNode->renderer()->isTable() && !startNode->renderer()->isInline())
693             || startNode->renderer()->isHR())
694         && p.offset() == 0)
695         return VisiblePosition(Position(startNode, maxDeepOffset(startNode)));
696     
697     Node* startBlock = enclosingBlock(startNode);
698     Node *stayInsideBlock = startBlock;
699     
700     Node *node = startNode;
701     int offset = p.offset();
702
703     Node *n = startNode;
704     while (n) {
705         if (n->isContentEditable() != startNode->isContentEditable())
706             break;
707         RenderObject *r = n->renderer();
708         if (!r) {
709             n = n->traverseNextNode(stayInsideBlock);
710             continue;
711         }
712         RenderStyle *style = r->style();
713         if (style->visibility() != VISIBLE) {
714             n = n->traverseNextNode(stayInsideBlock);
715             continue;
716         }
717         
718         if (r->isBR() || isBlock(n))
719             break;
720             
721         // FIXME: We avoid returning a position where the renderer can't accept the caret.
722         // We should probably do this in other cases such as startOfParagraph.
723         if (r->isText() && r->caretMaxRenderedOffset() > 0) {
724             int length = static_cast<RenderText*>(r)->textLength();
725             if (style->preserveNewline()) {
726                 const UChar* chars = static_cast<RenderText*>(r)->characters();
727                 int o = n == startNode ? offset : 0;
728                 for (int i = o; i < length; ++i)
729                     if (chars[i] == '\n')
730                         return VisiblePosition(n, i, DOWNSTREAM);
731             }
732             node = n;
733             offset = r->caretMaxOffset();
734             n = n->traverseNextNode(stayInsideBlock);
735         } else if (editingIgnoresContent(n) || isTableElement(n)) {
736             node = n;
737             offset = maxDeepOffset(n);
738             n = n->traverseNextSibling(stayInsideBlock);
739         } else
740             n = n->traverseNextNode(stayInsideBlock);
741     }
742
743     return VisiblePosition(node, offset, DOWNSTREAM);
744 }
745
746 bool inSameParagraph(const VisiblePosition &a, const VisiblePosition &b)
747 {
748     return a.isNotNull() && startOfParagraph(a) == startOfParagraph(b);
749 }
750
751 bool isStartOfParagraph(const VisiblePosition &pos)
752 {
753     return pos.isNotNull() && pos == startOfParagraph(pos);
754 }
755
756 bool isEndOfParagraph(const VisiblePosition &pos)
757 {
758     return pos.isNotNull() && pos == endOfParagraph(pos);
759 }
760
761 VisiblePosition previousParagraphPosition(const VisiblePosition &p, int x)
762 {
763     VisiblePosition pos = p;
764     do {
765         VisiblePosition n = previousLinePosition(pos, x);
766         if (n.isNull() || n == pos)
767             return p;
768         pos = n;
769     } while (inSameParagraph(p, pos));
770     return pos;
771 }
772
773 VisiblePosition nextParagraphPosition(const VisiblePosition &p, int x)
774 {
775     VisiblePosition pos = p;
776     do {
777         VisiblePosition n = nextLinePosition(pos, x);
778         if (n.isNull() || n == pos)
779             return p;
780         pos = n;
781     } while (inSameParagraph(p, pos));
782     return pos;
783 }
784
785 // ---------
786
787 VisiblePosition startOfBlock(const VisiblePosition &c)
788 {
789     Position p = c.deepEquivalent();
790     Node *startNode = p.node();
791     if (!startNode)
792         return VisiblePosition();
793     return VisiblePosition(Position(startNode->enclosingBlockFlowElement(), 0), DOWNSTREAM);
794 }
795
796 VisiblePosition endOfBlock(const VisiblePosition &c)
797 {
798     Position p = c.deepEquivalent();
799
800     Node *startNode = p.node();
801     if (!startNode)
802         return VisiblePosition();
803
804     Node *startBlock = startNode->enclosingBlockFlowElement();
805     
806     return VisiblePosition(startBlock, startBlock->childNodeCount(), VP_DEFAULT_AFFINITY);   
807 }
808
809 bool inSameBlock(const VisiblePosition &a, const VisiblePosition &b)
810 {
811     return !a.isNull() && enclosingBlockFlowElement(a) == enclosingBlockFlowElement(b);
812 }
813
814 bool isStartOfBlock(const VisiblePosition &pos)
815 {
816     return pos.isNotNull() && pos == startOfBlock(pos);
817 }
818
819 bool isEndOfBlock(const VisiblePosition &pos)
820 {
821     return pos.isNotNull() && pos == endOfBlock(pos);
822 }
823
824 // ---------
825
826 VisiblePosition startOfDocument(const Node* node)
827 {
828     if (!node)
829         return VisiblePosition();
830     
831     return VisiblePosition(node->document()->documentElement(), 0, DOWNSTREAM);
832 }
833
834 VisiblePosition startOfDocument(const VisiblePosition &c)
835 {
836     return startOfDocument(c.deepEquivalent().node());
837 }
838
839 VisiblePosition endOfDocument(const Node* node)
840 {
841     if (!node || !node->document())
842         return VisiblePosition();
843     
844     Element* doc = node->document()->documentElement();
845     return VisiblePosition(doc, doc->childNodeCount(), DOWNSTREAM);
846 }
847
848 VisiblePosition endOfDocument(const VisiblePosition &c)
849 {
850     return endOfDocument(c.deepEquivalent().node());
851 }
852
853 bool inSameDocument(const VisiblePosition &a, const VisiblePosition &b)
854 {
855     Position ap = a.deepEquivalent();
856     Node *an = ap.node();
857     if (!an)
858         return false;
859     Position bp = b.deepEquivalent();
860     Node *bn = bp.node();
861     if (an == bn)
862         return true;
863
864     return an->document() == bn->document();
865 }
866
867 bool isStartOfDocument(const VisiblePosition &p)
868 {
869     return p.isNotNull() && p.previous().isNull();
870 }
871
872 bool isEndOfDocument(const VisiblePosition &p)
873 {
874     return p.isNotNull() && p.next().isNull();
875 }
876
877 // ---------
878
879 VisiblePosition startOfEditableContent(const VisiblePosition& visiblePosition)
880 {
881     Node* highestRoot = highestEditableRoot(visiblePosition.deepEquivalent());
882     if (!highestRoot)
883         return VisiblePosition();
884
885     return VisiblePosition(highestRoot, 0, DOWNSTREAM);
886 }
887
888 VisiblePosition endOfEditableContent(const VisiblePosition& visiblePosition)
889 {
890     Node* highestRoot = highestEditableRoot(visiblePosition.deepEquivalent());
891     if (!highestRoot)
892         return VisiblePosition();
893
894     return VisiblePosition(highestRoot, maxDeepOffset(highestRoot), DOWNSTREAM);
895 }
896
897 }