Fix inconsistent text selection behavior with option-shift-left/right/up/down.
[WebKit-https.git] / Source / WebCore / editing / FrameSelection.cpp
1 /*
2  * Copyright (C) 2004, 2008, 2009, 2010 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 "FrameSelection.h"
28
29 #include "CharacterData.h"
30 #include "DeleteSelectionCommand.h"
31 #include "Document.h"
32 #include "Editor.h"
33 #include "EditorClient.h"
34 #include "Element.h"
35 #include "EventHandler.h"
36 #include "ExceptionCode.h"
37 #include "FloatQuad.h"
38 #include "FocusController.h"
39 #include "Frame.h"
40 #include "FrameTree.h"
41 #include "FrameView.h"
42 #include "GraphicsContext.h"
43 #include "HTMLFormElement.h"
44 #include "HTMLFrameElementBase.h"
45 #include "HTMLInputElement.h"
46 #include "HTMLSelectElement.h"
47 #include "HTMLNames.h"
48 #include "HitTestRequest.h"
49 #include "HitTestResult.h"
50 #include "InlineTextBox.h"
51 #include "Page.h"
52 #include "Range.h"
53 #include "RenderLayer.h"
54 #include "RenderText.h"
55 #include "RenderTextControl.h"
56 #include "RenderTheme.h"
57 #include "RenderView.h"
58 #include "RenderWidget.h"
59 #include "RenderedPosition.h"
60 #include "SecureTextInput.h"
61 #include "Settings.h"
62 #include "SpatialNavigation.h"
63 #include "TextIterator.h"
64 #include "TypingCommand.h"
65 #include "htmlediting.h"
66 #include "visible_units.h"
67 #include <limits.h>
68 #include <stdio.h>
69 #include <wtf/text/CString.h>
70
71 #define EDIT_DEBUG 0
72
73 namespace WebCore {
74
75 using namespace HTMLNames;
76
77 static inline LayoutUnit NoXPosForVerticalArrowNavigation()
78 {
79     return std::numeric_limits<LayoutUnit>::min();
80 }
81
82 CaretBase::CaretBase(CaretVisibility visibility)
83     : m_caretRectNeedsUpdate(true)
84     , m_caretVisibility(visibility)
85 {
86 }
87
88 DragCaretController::DragCaretController()
89     : CaretBase(Visible)
90 {
91 }
92
93 PassOwnPtr<DragCaretController> DragCaretController::create()
94 {
95     return adoptPtr(new DragCaretController);
96 }
97
98 bool DragCaretController::isContentRichlyEditable() const
99 {
100     return isRichlyEditablePosition(m_position.deepEquivalent());
101 }
102
103 static inline bool shouldAlwaysUseDirectionalSelection(Frame* frame)
104 {
105     return !frame || frame->editor()->behavior().shouldConsiderSelectionAsDirectional();
106 }
107
108 FrameSelection::FrameSelection(Frame* frame)
109     : m_frame(frame)
110     , m_xPosForVerticalArrowNavigation(NoXPosForVerticalArrowNavigation())
111     , m_granularity(CharacterGranularity)
112     , m_caretBlinkTimer(this, &FrameSelection::caretBlinkTimerFired)
113     , m_absCaretBoundsDirty(true)
114     , m_caretPaint(true)
115     , m_isCaretBlinkingSuspended(false)
116     , m_focused(frame && frame->page() && frame->page()->focusController()->focusedFrame() == frame)
117 {
118     if (shouldAlwaysUseDirectionalSelection(m_frame))
119         m_selection.setIsDirectional(true);
120 }
121
122 Element* FrameSelection::rootEditableElementOrDocumentElement() const
123 {
124     Element* selectionRoot = m_selection.rootEditableElement();
125     return selectionRoot ? selectionRoot : m_frame->document()->documentElement();
126 }
127
128 void FrameSelection::moveTo(const VisiblePosition &pos, EUserTriggered userTriggered, CursorAlignOnScroll align)
129 {
130     SetSelectionOptions options = CloseTyping | ClearTypingStyle | userTriggered;
131     setSelection(VisibleSelection(pos.deepEquivalent(), pos.deepEquivalent(), pos.affinity(), m_selection.isDirectional()), options, align);
132 }
133
134 void FrameSelection::moveTo(const VisiblePosition &base, const VisiblePosition &extent, EUserTriggered userTriggered)
135 {
136     const bool selectionHasDirection = true;
137     SetSelectionOptions options = CloseTyping | ClearTypingStyle | userTriggered;
138     setSelection(VisibleSelection(base.deepEquivalent(), extent.deepEquivalent(), base.affinity(), selectionHasDirection), options);
139 }
140
141 void FrameSelection::moveTo(const Position &pos, EAffinity affinity, EUserTriggered userTriggered)
142 {
143     SetSelectionOptions options = CloseTyping | ClearTypingStyle | userTriggered;
144     setSelection(VisibleSelection(pos, affinity, m_selection.isDirectional()), options);
145 }
146
147 void FrameSelection::moveTo(const Range *r, EAffinity affinity, EUserTriggered userTriggered)
148 {
149     SetSelectionOptions options = CloseTyping | ClearTypingStyle | userTriggered;
150     VisibleSelection selection = r ? VisibleSelection(r->startPosition(), r->endPosition(), affinity) : VisibleSelection(Position(), Position(), affinity);
151     setSelection(selection, options);
152 }
153
154 void FrameSelection::moveTo(const Position &base, const Position &extent, EAffinity affinity, EUserTriggered userTriggered)
155 {
156     const bool selectionHasDirection = true;
157     SetSelectionOptions options = CloseTyping | ClearTypingStyle | userTriggered;
158     setSelection(VisibleSelection(base, extent, affinity, selectionHasDirection), options);
159 }
160
161 void DragCaretController::setCaretPosition(const VisiblePosition& position)
162 {
163     if (Node* node = m_position.deepEquivalent().deprecatedNode())
164         invalidateCaretRect(node);
165     m_position = position;
166     setCaretRectNeedsUpdate();
167     Document* document = 0;
168     if (Node* node = m_position.deepEquivalent().deprecatedNode()) {
169         invalidateCaretRect(node);
170         document = node->document();
171     }
172     if (m_position.isNull() || m_position.isOrphan())
173         clearCaretRect();
174     else
175         updateCaretRect(document, m_position);
176 }
177
178 static void adjustEndpointsAtBidiBoundary(VisiblePosition& visibleBase, VisiblePosition& visibleExtent)
179 {
180     RenderedPosition base(visibleBase);
181     RenderedPosition extent(visibleExtent);
182
183     if (base.isNull() || extent.isNull() || base.isEquivalent(extent))
184         return;
185
186     if (base.atLeftBoundaryOfBidiRun()) {
187         if (!extent.atRightBoundaryOfBidiRun(base.bidiLevelOnRight())
188             && base.isEquivalent(extent.leftBoundaryOfBidiRun(base.bidiLevelOnRight()))) {
189             visibleBase = base.positionAtLeftBoundaryOfBiDiRun();
190             return;
191         }
192         return;
193     }
194
195     if (base.atRightBoundaryOfBidiRun()) {
196         if (!extent.atLeftBoundaryOfBidiRun(base.bidiLevelOnLeft())
197             && base.isEquivalent(extent.rightBoundaryOfBidiRun(base.bidiLevelOnLeft()))) {
198             visibleBase = base.positionAtRightBoundaryOfBiDiRun();
199             return;
200         }
201         return;
202     }
203
204     if (extent.atLeftBoundaryOfBidiRun() && extent.isEquivalent(base.leftBoundaryOfBidiRun(extent.bidiLevelOnRight()))) {
205         visibleExtent = extent.positionAtLeftBoundaryOfBiDiRun();
206         return;
207     }
208
209     if (extent.atRightBoundaryOfBidiRun() && extent.isEquivalent(base.rightBoundaryOfBidiRun(extent.bidiLevelOnLeft()))) {
210         visibleExtent = extent.positionAtRightBoundaryOfBiDiRun();
211         return;
212     }
213 }
214
215 void FrameSelection::setNonDirectionalSelectionIfNeeded(const VisibleSelection& passedNewSelection, TextGranularity granularity,
216     EndPointsAdjustmentMode endpointsAdjustmentMode)
217 {
218     VisibleSelection newSelection = passedNewSelection;
219     bool isDirectional = shouldAlwaysUseDirectionalSelection(m_frame) || newSelection.isDirectional();
220
221     VisiblePosition base = m_originalBase.isNotNull() ? m_originalBase : newSelection.visibleBase();
222     VisiblePosition newBase = base;
223     VisiblePosition newExtent = newSelection.visibleExtent();
224     if (endpointsAdjustmentMode == AdjustEndpointsAtBidiBoundary)
225         adjustEndpointsAtBidiBoundary(newBase, newExtent);
226
227     if (newBase != base || newExtent != newSelection.visibleExtent()) {
228         m_originalBase = base;
229         newSelection.setBase(newBase);
230         newSelection.setExtent(newExtent);
231     } else if (m_originalBase.isNotNull()) {
232         if (m_selection.base() == newSelection.base())
233             newSelection.setBase(m_originalBase);
234         m_originalBase.clear();
235     }
236
237     newSelection.setIsDirectional(isDirectional); // Adjusting base and extent will make newSelection always directional
238     if (m_selection == newSelection || !shouldChangeSelection(newSelection))
239         return;
240
241     setSelection(newSelection, granularity);
242 }
243
244 void FrameSelection::setSelection(const VisibleSelection& newSelection, SetSelectionOptions options, CursorAlignOnScroll align, TextGranularity granularity)
245 {
246     bool closeTyping = options & CloseTyping;
247     bool shouldClearTypingStyle = options & ClearTypingStyle;
248     EUserTriggered userTriggered = selectionOptionsToUserTriggered(options);
249
250     VisibleSelection s = newSelection;
251     if (shouldAlwaysUseDirectionalSelection(m_frame))
252         s.setIsDirectional(true);
253
254     if (!m_frame) {
255         m_selection = s;
256         return;
257     }
258
259     // <http://bugs.webkit.org/show_bug.cgi?id=23464>: Infinite recursion at FrameSelection::setSelection
260     // if document->frame() == m_frame we can get into an infinite loop
261     if (s.base().anchorNode()) {
262         Document* document = s.base().anchorNode()->document();
263         if (document && document->frame() && document->frame() != m_frame && document != m_frame->document()) {
264             document->frame()->selection()->setSelection(s, options, align, granularity);
265             return;
266         }
267     }
268
269     m_granularity = granularity;
270
271     if (closeTyping)
272         TypingCommand::closeTyping(m_frame);
273
274     if (shouldClearTypingStyle)
275         clearTypingStyle();
276
277     if (m_selection == s) {
278         // Even if selection was not changed, selection offsets may have been changed.
279         notifyRendererOfSelectionChange(userTriggered);
280         return;
281     }
282
283     VisibleSelection oldSelection = m_selection;
284
285     m_selection = s;
286     setCaretRectNeedsUpdate();
287     
288     if (!s.isNone() && !(options & DoNotSetFocus))
289         setFocusedNodeIfNeeded();
290     
291     updateAppearance();
292
293     // Always clear the x position used for vertical arrow navigation.
294     // It will be restored by the vertical arrow navigation code if necessary.
295     m_xPosForVerticalArrowNavigation = NoXPosForVerticalArrowNavigation();
296     selectFrameElementInParentIfFullySelected();
297     notifyRendererOfSelectionChange(userTriggered);
298     m_frame->editor()->respondToChangedSelection(oldSelection, options);
299     if (userTriggered == UserTriggered) {
300         ScrollAlignment alignment;
301
302         if (m_frame->editor()->behavior().shouldCenterAlignWhenSelectionIsRevealed())
303             alignment = (align == AlignCursorOnScrollAlways) ? ScrollAlignment::alignCenterAlways : ScrollAlignment::alignCenterIfNeeded;
304         else
305             alignment = (align == AlignCursorOnScrollAlways) ? ScrollAlignment::alignTopAlways : ScrollAlignment::alignToEdgeIfNeeded;
306
307         revealSelection(alignment, true);
308     }
309
310     notifyAccessibilityForSelectionChange();
311     m_frame->document()->enqueueDocumentEvent(Event::create(eventNames().selectionchangeEvent, false, false));
312 }
313
314 static bool removingNodeRemovesPosition(Node* node, const Position& position)
315 {
316     if (!position.anchorNode())
317         return false;
318
319     if (position.anchorNode() == node)
320         return true;
321
322     if (!node->isElementNode())
323         return false;
324
325     Element* element = static_cast<Element*>(node);
326     return element->contains(position.anchorNode()) || element->contains(position.anchorNode()->shadowAncestorNode());
327 }
328
329 static void clearRenderViewSelection(const Position& position)
330 {
331     RefPtr<Document> document = position.anchorNode()->document();
332     document->updateStyleIfNeeded();
333     if (RenderView* view = toRenderView(document->renderer()))
334         view->clearSelection();
335 }
336
337 void DragCaretController::nodeWillBeRemoved(Node* node)
338 {
339     if (!hasCaret() || (node && !node->inDocument()))
340         return;
341
342     if (!removingNodeRemovesPosition(node, m_position.deepEquivalent()))
343         return;
344
345     clearRenderViewSelection(m_position.deepEquivalent());
346     clear();
347 }
348
349 void FrameSelection::nodeWillBeRemoved(Node* node)
350 {
351     // There can't be a selection inside a fragment, so if a fragment's node is being removed,
352     // the selection in the document that created the fragment needs no adjustment.
353     if (isNone() || (node && !node->inDocument()))
354         return;
355
356     respondToNodeModification(node, removingNodeRemovesPosition(node, m_selection.base()), removingNodeRemovesPosition(node, m_selection.extent()),
357         removingNodeRemovesPosition(node, m_selection.start()), removingNodeRemovesPosition(node, m_selection.end()));
358 }
359
360 void FrameSelection::respondToNodeModification(Node* node, bool baseRemoved, bool extentRemoved, bool startRemoved, bool endRemoved)
361 {
362     bool clearRenderTreeSelection = false;
363     bool clearDOMTreeSelection = false;
364
365     if (startRemoved || endRemoved) {
366         Position start = m_selection.start();
367         Position end = m_selection.end();
368         if (startRemoved)
369             updatePositionForNodeRemoval(start, node);
370         if (endRemoved)
371             updatePositionForNodeRemoval(end, node);
372
373         if (start.isNotNull() && end.isNotNull()) {
374             if (m_selection.isBaseFirst())
375                 m_selection.setWithoutValidation(start, end);
376             else
377                 m_selection.setWithoutValidation(end, start);
378         } else
379             clearDOMTreeSelection = true;
380
381         clearRenderTreeSelection = true;
382     } else if (baseRemoved || extentRemoved) {
383         // The base and/or extent are about to be removed, but the start and end aren't.
384         // Change the base and extent to the start and end, but don't re-validate the
385         // selection, since doing so could move the start and end into the node
386         // that is about to be removed.
387         if (m_selection.isBaseFirst())
388             m_selection.setWithoutValidation(m_selection.start(), m_selection.end());
389         else
390             m_selection.setWithoutValidation(m_selection.end(), m_selection.start());
391     } else if (RefPtr<Range> range = m_selection.firstRange()) {
392         ExceptionCode ec = 0;
393         Range::CompareResults compareResult = range->compareNode(node, ec);
394         if (!ec && (compareResult == Range::NODE_BEFORE_AND_AFTER || compareResult == Range::NODE_INSIDE)) {
395             // If we did nothing here, when this node's renderer was destroyed, the rect that it 
396             // occupied would be invalidated, but, selection gaps that change as a result of 
397             // the removal wouldn't be invalidated.
398             // FIXME: Don't do so much unnecessary invalidation.
399             clearRenderTreeSelection = true;
400         }
401     }
402
403     if (clearRenderTreeSelection)
404         clearRenderViewSelection(m_selection.start());
405
406     if (clearDOMTreeSelection)
407         setSelection(VisibleSelection(), DoNotSetFocus);
408 }
409
410 static void updatePositionAfterAdoptingTextReplacement(Position& position, CharacterData* node, unsigned offset, unsigned oldLength, unsigned newLength)
411 {
412     if (!position.anchorNode() || position.anchorNode() != node || position.anchorType() != Position::PositionIsOffsetInAnchor)
413         return;
414
415     // See: http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Mutation
416     ASSERT(position.offsetInContainerNode() >= 0);
417     unsigned positionOffset = static_cast<unsigned>(position.offsetInContainerNode());
418     // Replacing text can be viewed as a deletion followed by insertion.
419     if (positionOffset >= offset && positionOffset <= offset + oldLength)
420         position.moveToOffset(offset);
421
422     // Adjust the offset if the position is after the end of the deleted contents
423     // (positionOffset > offset + oldLength) to avoid having a stale offset.
424     if (positionOffset > offset + oldLength)
425         position.moveToOffset(positionOffset - oldLength + newLength);
426 }
427
428 void FrameSelection::textWillBeReplaced(CharacterData* node, unsigned offset, unsigned oldLength, unsigned newLength)
429 {
430     // The fragment check is a performance optimization. See http://trac.webkit.org/changeset/30062.
431     if (isNone() || !node || highestAncestor(node)->nodeType() == Node::DOCUMENT_FRAGMENT_NODE)
432         return;
433
434     Position base = m_selection.base();
435     Position extent = m_selection.extent();
436     Position start = m_selection.start();
437     Position end = m_selection.end();
438     updatePositionAfterAdoptingTextReplacement(base, node, offset, oldLength, newLength);
439     updatePositionAfterAdoptingTextReplacement(extent, node, offset, oldLength, newLength);
440     updatePositionAfterAdoptingTextReplacement(start, node, offset, oldLength, newLength);
441     updatePositionAfterAdoptingTextReplacement(end, node, offset, oldLength, newLength);
442
443     if (base != m_selection.base() || extent != m_selection.extent() || start != m_selection.start() || end != m_selection.end()) {
444         VisibleSelection newSelection;
445         newSelection.setWithoutValidation(base, extent);
446         m_frame->document()->updateLayout();
447         setSelection(newSelection, DoNotSetFocus);
448     }
449 }
450
451 TextDirection FrameSelection::directionOfEnclosingBlock()
452 {
453     return WebCore::directionOfEnclosingBlock(m_selection.extent());
454 }
455
456 TextDirection FrameSelection::directionOfSelection()
457 {
458     InlineBox* startBox = 0;
459     InlineBox* endBox = 0;
460     int unusedOffset;
461     if (m_selection.start().isNotNull())
462         m_selection.visibleStart().getInlineBoxAndOffset(startBox, unusedOffset);
463     if (m_selection.end().isNotNull())
464         m_selection.visibleEnd().getInlineBoxAndOffset(endBox, unusedOffset);
465     if (startBox && endBox && startBox->direction() == endBox->direction())
466         return startBox->direction();
467
468     return directionOfEnclosingBlock();
469 }
470
471 void FrameSelection::willBeModified(EAlteration alter, SelectionDirection direction)
472 {
473     if (alter != AlterationExtend)
474         return;
475
476     Position start = m_selection.start();
477     Position end = m_selection.end();
478
479     bool baseIsStart = true;
480
481     if (m_selection.isDirectional()) {
482         // Make base and extent match start and end so we extend the user-visible selection.
483         // This only matters for cases where base and extend point to different positions than
484         // start and end (e.g. after a double-click to select a word).
485         if (m_selection.isBaseFirst())
486             baseIsStart = true;
487         else
488             baseIsStart = false;
489     } else {
490         switch (direction) {
491         case DirectionRight:
492             if (directionOfSelection() == LTR)
493                 baseIsStart = true;
494             else
495                 baseIsStart = false;
496             break;
497         case DirectionForward:
498             baseIsStart = true;
499             break;
500         case DirectionLeft:
501             if (directionOfSelection() == LTR)
502                 baseIsStart = false;
503             else
504                 baseIsStart = true;
505             break;
506         case DirectionBackward:
507             baseIsStart = false;
508             break;
509         }
510     }
511     if (baseIsStart) {
512         m_selection.setBase(start);
513         m_selection.setExtent(end);
514     } else {
515         m_selection.setBase(end);
516         m_selection.setExtent(start);
517     }
518 }
519
520 VisiblePosition FrameSelection::positionForPlatform(bool isGetStart) const
521 {
522     Settings* settings = m_frame ? m_frame->settings() : 0;
523     if (settings && settings->editingBehaviorType() == EditingMacBehavior)
524         return isGetStart ? m_selection.visibleStart() : m_selection.visibleEnd();
525     // Linux and Windows always extend selections from the extent endpoint.
526     // FIXME: VisibleSelection should be fixed to ensure as an invariant that
527     // base/extent always point to the same nodes as start/end, but which points
528     // to which depends on the value of isBaseFirst. Then this can be changed
529     // to just return m_sel.extent().
530     return m_selection.isBaseFirst() ? m_selection.visibleEnd() : m_selection.visibleStart();
531 }
532
533 VisiblePosition FrameSelection::startForPlatform() const
534 {
535     return positionForPlatform(true);
536 }
537
538 VisiblePosition FrameSelection::endForPlatform() const
539 {
540     return positionForPlatform(false);
541 }
542
543 VisiblePosition FrameSelection::modifyExtendingRight(TextGranularity granularity)
544 {
545     VisiblePosition pos(m_selection.extent(), m_selection.affinity());
546
547     // The difference between modifyExtendingRight and modifyExtendingForward is:
548     // modifyExtendingForward always extends forward logically.
549     // modifyExtendingRight behaves the same as modifyExtendingForward except for extending character or word,
550     // it extends forward logically if the enclosing block is LTR direction,
551     // but it extends backward logically if the enclosing block is RTL direction.
552     switch (granularity) {
553     case CharacterGranularity:
554         if (directionOfEnclosingBlock() == LTR)
555             pos = pos.next(CannotCrossEditingBoundary);
556         else
557             pos = pos.previous(CannotCrossEditingBoundary);
558         break;
559     case WordGranularity:
560         if (directionOfEnclosingBlock() == LTR)
561             pos = nextWordPosition(pos);
562         else
563             pos = previousWordPosition(pos);
564         break;
565     case LineBoundary:
566         if (directionOfEnclosingBlock() == LTR)
567             pos = modifyExtendingForward(granularity);
568         else
569             pos = modifyExtendingBackward(granularity);
570         break;
571     case SentenceGranularity:
572     case LineGranularity:
573     case ParagraphGranularity:
574     case SentenceBoundary:
575     case ParagraphBoundary:
576     case DocumentBoundary:
577         // FIXME: implement all of the above?
578         pos = modifyExtendingForward(granularity);
579         break;
580     }
581     return pos;
582 }
583
584 VisiblePosition FrameSelection::modifyExtendingForward(TextGranularity granularity)
585 {
586     VisiblePosition pos(m_selection.extent(), m_selection.affinity());
587     switch (granularity) {
588     case CharacterGranularity:
589         pos = pos.next(CannotCrossEditingBoundary);
590         break;
591     case WordGranularity:
592         pos = nextWordPosition(pos);
593         break;
594     case SentenceGranularity:
595         pos = nextSentencePosition(pos);
596         break;
597     case LineGranularity:
598         pos = nextLinePosition(pos, lineDirectionPointForBlockDirectionNavigation(EXTENT));
599         break;
600     case ParagraphGranularity:
601         pos = nextParagraphPosition(pos, lineDirectionPointForBlockDirectionNavigation(EXTENT));
602         break;
603     case SentenceBoundary:
604         pos = endOfSentence(endForPlatform());
605         break;
606     case LineBoundary:
607         pos = logicalEndOfLine(endForPlatform());
608         break;
609     case ParagraphBoundary:
610         pos = endOfParagraph(endForPlatform());
611         break;
612     case DocumentBoundary:
613         pos = endForPlatform();
614         if (isEditablePosition(pos.deepEquivalent()))
615             pos = endOfEditableContent(pos);
616         else
617             pos = endOfDocument(pos);
618         break;
619     }
620     
621     return pos;
622 }
623
624 VisiblePosition FrameSelection::modifyMovingRight(TextGranularity granularity)
625 {
626     VisiblePosition pos;
627     switch (granularity) {
628     case CharacterGranularity:
629         if (isRange()) {
630             if (directionOfSelection() == LTR)
631                 pos = VisiblePosition(m_selection.end(), m_selection.affinity());
632             else
633                 pos = VisiblePosition(m_selection.start(), m_selection.affinity());
634         } else
635             pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).right(true);
636         break;
637     case WordGranularity:
638         if (visualWordMovementEnabled()
639             || (m_frame && m_frame->editor()->behavior().shouldMoveLeftRightByWordInVisualOrder())) {
640             pos = rightWordPosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
641             break;
642         }
643     case SentenceGranularity:
644     case LineGranularity:
645     case ParagraphGranularity:
646     case SentenceBoundary:
647     case ParagraphBoundary:
648     case DocumentBoundary:
649         // FIXME: Implement all of the above.
650         pos = modifyMovingForward(granularity);
651         break;
652     case LineBoundary:
653         pos = rightBoundaryOfLine(startForPlatform(), directionOfEnclosingBlock());
654         break;
655     }
656     return pos;
657 }
658
659 VisiblePosition FrameSelection::modifyMovingForward(TextGranularity granularity)
660 {
661     VisiblePosition pos;
662     // FIXME: Stay in editable content for the less common granularities.
663     switch (granularity) {
664     case CharacterGranularity:
665         if (isRange())
666             pos = VisiblePosition(m_selection.end(), m_selection.affinity());
667         else
668             pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).next(CannotCrossEditingBoundary);
669         break;
670     case WordGranularity:
671         pos = nextWordPosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
672         break;
673     case SentenceGranularity:
674         pos = nextSentencePosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
675         break;
676     case LineGranularity: {
677         // down-arrowing from a range selection that ends at the start of a line needs
678         // to leave the selection at that line start (no need to call nextLinePosition!)
679         pos = endForPlatform();
680         if (!isRange() || !isStartOfLine(pos))
681             pos = nextLinePosition(pos, lineDirectionPointForBlockDirectionNavigation(START));
682         break;
683     }
684     case ParagraphGranularity:
685         pos = nextParagraphPosition(endForPlatform(), lineDirectionPointForBlockDirectionNavigation(START));
686         break;
687     case SentenceBoundary:
688         pos = endOfSentence(endForPlatform());
689         break;
690     case LineBoundary:
691         pos = logicalEndOfLine(endForPlatform());
692         break;
693     case ParagraphBoundary:
694         pos = endOfParagraph(endForPlatform());
695         break;
696     case DocumentBoundary:
697         pos = endForPlatform();
698         if (isEditablePosition(pos.deepEquivalent()))
699             pos = endOfEditableContent(pos);
700         else
701             pos = endOfDocument(pos);
702         break;
703     }
704     return pos;
705 }
706
707 VisiblePosition FrameSelection::modifyExtendingLeft(TextGranularity granularity)
708 {
709     VisiblePosition pos(m_selection.extent(), m_selection.affinity());
710
711     // The difference between modifyExtendingLeft and modifyExtendingBackward is:
712     // modifyExtendingBackward always extends backward logically.
713     // modifyExtendingLeft behaves the same as modifyExtendingBackward except for extending character or word,
714     // it extends backward logically if the enclosing block is LTR direction,
715     // but it extends forward logically if the enclosing block is RTL direction.
716     switch (granularity) {
717     case CharacterGranularity:
718         if (directionOfEnclosingBlock() == LTR)
719             pos = pos.previous(CannotCrossEditingBoundary);
720         else
721             pos = pos.next(CannotCrossEditingBoundary);
722         break;
723     case WordGranularity:
724         if (directionOfEnclosingBlock() == LTR)
725             pos = previousWordPosition(pos);
726         else
727             pos = nextWordPosition(pos);
728         break;
729     case LineBoundary:
730         if (directionOfEnclosingBlock() == LTR)
731             pos = modifyExtendingBackward(granularity);
732         else
733             pos = modifyExtendingForward(granularity);
734         break;
735     case SentenceGranularity:
736     case LineGranularity:
737     case ParagraphGranularity:
738     case SentenceBoundary:
739     case ParagraphBoundary:
740     case DocumentBoundary:
741         pos = modifyExtendingBackward(granularity);
742         break;
743     }
744     return pos;
745 }
746        
747 VisiblePosition FrameSelection::modifyExtendingBackward(TextGranularity granularity)
748 {
749     VisiblePosition pos(m_selection.extent(), m_selection.affinity());
750
751     // Extending a selection backward by word or character from just after a table selects
752     // the table.  This "makes sense" from the user perspective, esp. when deleting.
753     // It was done here instead of in VisiblePosition because we want VPs to iterate
754     // over everything.
755     switch (granularity) {
756     case CharacterGranularity:
757         pos = pos.previous(CannotCrossEditingBoundary);
758         break;
759     case WordGranularity:
760         pos = previousWordPosition(pos);
761         break;
762     case SentenceGranularity:
763         pos = previousSentencePosition(pos);
764         break;
765     case LineGranularity:
766         pos = previousLinePosition(pos, lineDirectionPointForBlockDirectionNavigation(EXTENT));
767         break;
768     case ParagraphGranularity:
769         pos = previousParagraphPosition(pos, lineDirectionPointForBlockDirectionNavigation(EXTENT));
770         break;
771     case SentenceBoundary:
772         pos = startOfSentence(startForPlatform());
773         break;
774     case LineBoundary:
775         pos = logicalStartOfLine(startForPlatform());
776         break;
777     case ParagraphBoundary:
778         pos = startOfParagraph(startForPlatform());
779         break;
780     case DocumentBoundary:
781         pos = startForPlatform();
782         if (isEditablePosition(pos.deepEquivalent()))
783             pos = startOfEditableContent(pos);
784         else
785             pos = startOfDocument(pos);
786         break;
787     }
788     return pos;
789 }
790
791 VisiblePosition FrameSelection::modifyMovingLeft(TextGranularity granularity)
792 {
793     VisiblePosition pos;
794     switch (granularity) {
795     case CharacterGranularity:
796         if (isRange())
797             if (directionOfSelection() == LTR)
798                 pos = VisiblePosition(m_selection.start(), m_selection.affinity());
799             else
800                 pos = VisiblePosition(m_selection.end(), m_selection.affinity());
801         else
802             pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).left(true);
803         break;
804     case WordGranularity:
805         if (visualWordMovementEnabled()
806             || (m_frame && m_frame->editor()->behavior().shouldMoveLeftRightByWordInVisualOrder())) {
807             pos = leftWordPosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
808             break;
809         }
810     case SentenceGranularity:
811     case LineGranularity:
812     case ParagraphGranularity:
813     case SentenceBoundary:
814     case ParagraphBoundary:
815     case DocumentBoundary:
816         // FIXME: Implement all of the above.
817         pos = modifyMovingBackward(granularity);
818         break;
819     case LineBoundary:
820         pos = leftBoundaryOfLine(startForPlatform(), directionOfEnclosingBlock());
821         break;
822     }
823     return pos;
824 }
825
826 VisiblePosition FrameSelection::modifyMovingBackward(TextGranularity granularity)
827 {
828     VisiblePosition pos;
829     switch (granularity) {
830     case CharacterGranularity:
831         if (isRange())
832             pos = VisiblePosition(m_selection.start(), m_selection.affinity());
833         else
834             pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).previous(CannotCrossEditingBoundary);
835         break;
836     case WordGranularity:
837         pos = previousWordPosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
838         break;
839     case SentenceGranularity:
840         pos = previousSentencePosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
841         break;
842     case LineGranularity:
843         pos = previousLinePosition(startForPlatform(), lineDirectionPointForBlockDirectionNavigation(START));
844         break;
845     case ParagraphGranularity:
846         pos = previousParagraphPosition(startForPlatform(), lineDirectionPointForBlockDirectionNavigation(START));
847         break;
848     case SentenceBoundary:
849         pos = startOfSentence(startForPlatform());
850         break;
851     case LineBoundary:
852         pos = logicalStartOfLine(startForPlatform());
853         break;
854     case ParagraphBoundary:
855         pos = startOfParagraph(startForPlatform());
856         break;
857     case DocumentBoundary:
858         pos = startForPlatform();
859         if (isEditablePosition(pos.deepEquivalent()))
860             pos = startOfEditableContent(pos);
861         else
862             pos = startOfDocument(pos);
863         break;
864     }
865     return pos;
866 }
867
868 static bool isBoundary(TextGranularity granularity)
869 {
870     return granularity == LineBoundary || granularity == ParagraphBoundary || granularity == DocumentBoundary;
871 }    
872
873 bool FrameSelection::modify(EAlteration alter, SelectionDirection direction, TextGranularity granularity, EUserTriggered userTriggered)
874 {
875     if (userTriggered == UserTriggered) {
876         FrameSelection trialFrameSelection;
877         trialFrameSelection.setSelection(m_selection);
878         trialFrameSelection.modify(alter, direction, granularity, NotUserTriggered);
879
880         bool change = shouldChangeSelection(trialFrameSelection.selection());
881         if (!change)
882             return false;
883
884         if (trialFrameSelection.selection().isRange() && m_selection.isCaret() && !dispatchSelectStart())
885             return false;
886     }
887
888     willBeModified(alter, direction);
889
890     bool wasRange = m_selection.isRange();
891     Position originalStartPosition = m_selection.start();
892     VisiblePosition position;
893     switch (direction) {
894     case DirectionRight:
895         if (alter == AlterationMove)
896             position = modifyMovingRight(granularity);
897         else
898             position = modifyExtendingRight(granularity);
899         break;
900     case DirectionForward:
901         if (alter == AlterationExtend)
902             position = modifyExtendingForward(granularity);
903         else
904             position = modifyMovingForward(granularity);
905         break;
906     case DirectionLeft:
907         if (alter == AlterationMove)
908             position = modifyMovingLeft(granularity);
909         else
910             position = modifyExtendingLeft(granularity);
911         break;
912     case DirectionBackward:
913         if (alter == AlterationExtend)
914             position = modifyExtendingBackward(granularity);
915         else
916             position = modifyMovingBackward(granularity);
917         break;
918     }
919
920     if (position.isNull())
921         return false;
922
923     if (isSpatialNavigationEnabled(m_frame))
924         if (!wasRange && alter == AlterationMove && position == originalStartPosition)
925             return false;
926
927     // Some of the above operations set an xPosForVerticalArrowNavigation.
928     // Setting a selection will clear it, so save it to possibly restore later.
929     // Note: the START position type is arbitrary because it is unused, it would be
930     // the requested position type if there were no xPosForVerticalArrowNavigation set.
931     LayoutUnit x = lineDirectionPointForBlockDirectionNavigation(START);
932     m_selection.setIsDirectional(shouldAlwaysUseDirectionalSelection(m_frame) || alter == AlterationExtend);
933
934     switch (alter) {
935     case AlterationMove:
936         moveTo(position, userTriggered);
937         break;
938     case AlterationExtend:
939         if (!m_selection.isCaret()
940             && (granularity == WordGranularity || granularity == ParagraphGranularity || granularity == LineGranularity)
941             && m_frame && !m_frame->editor()->behavior().shouldExtendSelectionByWordOrLineAcrossCaret()) {
942             // Don't let the selection go across the base position directly. Needed to match mac
943             // behavior when, for instance, word-selecting backwards starting with the caret in
944             // the middle of a word and then word-selecting forward, leaving the caret in the
945             // same place where it was, instead of directly selecting to the end of the word.
946             VisibleSelection newSelection = m_selection;
947             newSelection.setExtent(position);
948             if (m_selection.isBaseFirst() != newSelection.isBaseFirst())
949                 position = m_selection.base();
950         }
951
952         // Standard Mac behavior when extending to a boundary is grow the selection rather than leaving the
953         // base in place and moving the extent. Matches NSTextView.
954         if (!m_frame || !m_frame->editor()->behavior().shouldAlwaysGrowSelectionWhenExtendingToBoundary() || m_selection.isCaret() || !isBoundary(granularity))
955             setExtent(position, userTriggered);
956         else {
957             TextDirection textDirection = directionOfEnclosingBlock();
958             if (direction == DirectionForward || (textDirection == LTR && direction == DirectionRight) || (textDirection == RTL && direction == DirectionLeft))
959                 setEnd(position, userTriggered);
960             else
961                 setStart(position, userTriggered);
962         }
963         break;
964     }
965     
966     if (granularity == LineGranularity || granularity == ParagraphGranularity)
967         m_xPosForVerticalArrowNavigation = x;
968
969     if (userTriggered == UserTriggered)
970         m_granularity = CharacterGranularity;
971
972     setCaretRectNeedsUpdate();
973
974     return true;
975 }
976
977 // FIXME: Maybe baseline would be better?
978 static bool absoluteCaretY(const VisiblePosition &c, LayoutUnit &y)
979 {
980     LayoutRect rect = c.absoluteCaretBounds();
981     if (rect.isEmpty())
982         return false;
983     y = rect.y() + rect.height() / 2;
984     return true;
985 }
986
987 bool FrameSelection::modify(EAlteration alter, unsigned verticalDistance, VerticalDirection direction, EUserTriggered userTriggered, CursorAlignOnScroll align)
988 {
989     if (!verticalDistance)
990         return false;
991
992     if (userTriggered == UserTriggered) {
993         FrameSelection trialFrameSelection;
994         trialFrameSelection.setSelection(m_selection);
995         trialFrameSelection.modify(alter, verticalDistance, direction, NotUserTriggered);
996
997         bool change = shouldChangeSelection(trialFrameSelection.selection());
998         if (!change)
999             return false;
1000     }
1001
1002     willBeModified(alter, direction == DirectionUp ? DirectionBackward : DirectionForward);
1003
1004     VisiblePosition pos;
1005     LayoutUnit xPos = 0;
1006     switch (alter) {
1007     case AlterationMove:
1008         pos = VisiblePosition(direction == DirectionUp ? m_selection.start() : m_selection.end(), m_selection.affinity());
1009         xPos = lineDirectionPointForBlockDirectionNavigation(direction == DirectionUp ? START : END);
1010         m_selection.setAffinity(direction == DirectionUp ? UPSTREAM : DOWNSTREAM);
1011         break;
1012     case AlterationExtend:
1013         pos = VisiblePosition(m_selection.extent(), m_selection.affinity());
1014         xPos = lineDirectionPointForBlockDirectionNavigation(EXTENT);
1015         m_selection.setAffinity(DOWNSTREAM);
1016         break;
1017     }
1018
1019     LayoutUnit startY;
1020     if (!absoluteCaretY(pos, startY))
1021         return false;
1022     if (direction == DirectionUp)
1023         startY = -startY;
1024     LayoutUnit lastY = startY;
1025
1026     VisiblePosition result;
1027     VisiblePosition next;
1028     for (VisiblePosition p = pos; ; p = next) {
1029         if (direction == DirectionUp)
1030             next = previousLinePosition(p, xPos);
1031         else
1032             next = nextLinePosition(p, xPos);
1033
1034         if (next.isNull() || next == p)
1035             break;
1036         LayoutUnit nextY;
1037         if (!absoluteCaretY(next, nextY))
1038             break;
1039         if (direction == DirectionUp)
1040             nextY = -nextY;
1041         if (nextY - startY > static_cast<LayoutUnit>(verticalDistance))
1042             break;
1043         if (nextY >= lastY) {
1044             lastY = nextY;
1045             result = next;
1046         }
1047     }
1048
1049     if (result.isNull())
1050         return false;
1051
1052     switch (alter) {
1053     case AlterationMove:
1054         moveTo(result, userTriggered, align);
1055         break;
1056     case AlterationExtend:
1057         setExtent(result, userTriggered);
1058         break;
1059     }
1060
1061     if (userTriggered == UserTriggered)
1062         m_granularity = CharacterGranularity;
1063
1064     m_selection.setIsDirectional(shouldAlwaysUseDirectionalSelection(m_frame) || alter == AlterationExtend);
1065
1066     return true;
1067 }
1068
1069 LayoutUnit FrameSelection::lineDirectionPointForBlockDirectionNavigation(EPositionType type)
1070 {
1071     LayoutUnit x = 0;
1072
1073     if (isNone())
1074         return x;
1075
1076     Position pos;
1077     switch (type) {
1078     case START:
1079         pos = m_selection.start();
1080         break;
1081     case END:
1082         pos = m_selection.end();
1083         break;
1084     case BASE:
1085         pos = m_selection.base();
1086         break;
1087     case EXTENT:
1088         pos = m_selection.extent();
1089         break;
1090     }
1091
1092     Frame* frame = pos.anchorNode()->document()->frame();
1093     if (!frame)
1094         return x;
1095         
1096     if (m_xPosForVerticalArrowNavigation == NoXPosForVerticalArrowNavigation()) {
1097         VisiblePosition visiblePosition(pos, m_selection.affinity());
1098         // VisiblePosition creation can fail here if a node containing the selection becomes visibility:hidden
1099         // after the selection is created and before this function is called.
1100         x = visiblePosition.isNotNull() ? visiblePosition.lineDirectionPointForBlockDirectionNavigation() : 0;
1101         m_xPosForVerticalArrowNavigation = x;
1102     } else
1103         x = m_xPosForVerticalArrowNavigation;
1104         
1105     return x;
1106 }
1107
1108 void FrameSelection::clear()
1109 {
1110     m_granularity = CharacterGranularity;
1111     setSelection(VisibleSelection());
1112 }
1113
1114 void FrameSelection::setStart(const VisiblePosition &pos, EUserTriggered trigger)
1115 {
1116     if (m_selection.isBaseFirst())
1117         setBase(pos, trigger);
1118     else
1119         setExtent(pos, trigger);
1120 }
1121
1122 void FrameSelection::setEnd(const VisiblePosition &pos, EUserTriggered trigger)
1123 {
1124     if (m_selection.isBaseFirst())
1125         setExtent(pos, trigger);
1126     else
1127         setBase(pos, trigger);
1128 }
1129
1130 void FrameSelection::setBase(const VisiblePosition &pos, EUserTriggered userTriggered)
1131 {
1132     const bool selectionHasDirection = true;
1133     setSelection(VisibleSelection(pos.deepEquivalent(), m_selection.extent(), pos.affinity(), selectionHasDirection), CloseTyping | ClearTypingStyle | userTriggered);
1134 }
1135
1136 void FrameSelection::setExtent(const VisiblePosition &pos, EUserTriggered userTriggered)
1137 {
1138     const bool selectionHasDirection = true;
1139     setSelection(VisibleSelection(m_selection.base(), pos.deepEquivalent(), pos.affinity(), selectionHasDirection), CloseTyping | ClearTypingStyle | userTriggered);
1140 }
1141
1142 void FrameSelection::setBase(const Position &pos, EAffinity affinity, EUserTriggered userTriggered)
1143 {
1144     const bool selectionHasDirection = true;
1145     setSelection(VisibleSelection(pos, m_selection.extent(), affinity, selectionHasDirection), CloseTyping | ClearTypingStyle | userTriggered);
1146 }
1147
1148 void FrameSelection::setExtent(const Position &pos, EAffinity affinity, EUserTriggered userTriggered)
1149 {
1150     const bool selectionHasDirection = true;
1151     setSelection(VisibleSelection(m_selection.base(), pos, affinity, selectionHasDirection), CloseTyping | ClearTypingStyle | userTriggered);
1152 }
1153
1154 void CaretBase::clearCaretRect()
1155 {
1156     m_caretLocalRect = LayoutRect();
1157 }
1158
1159 bool CaretBase::updateCaretRect(Document* document, const VisiblePosition& caretPosition)
1160 {
1161     document->updateStyleIfNeeded();
1162     m_caretLocalRect = LayoutRect();
1163
1164     m_caretRectNeedsUpdate = false;
1165
1166     if (caretPosition.isNull())
1167         return false;
1168
1169     ASSERT(caretPosition.deepEquivalent().deprecatedNode()->renderer());
1170
1171     // First compute a rect local to the renderer at the selection start.
1172     RenderObject* renderer;
1173     LayoutRect localRect = caretPosition.localCaretRect(renderer);
1174
1175     // Get the renderer that will be responsible for painting the caret
1176     // (which is either the renderer we just found, or one of its containers).
1177     RenderObject* caretPainter = caretRenderer(caretPosition.deepEquivalent().deprecatedNode());
1178
1179     // Compute an offset between the renderer and the caretPainter.
1180     bool unrooted = false;
1181     while (renderer != caretPainter) {
1182         RenderObject* containerObject = renderer->container();
1183         if (!containerObject) {
1184             unrooted = true;
1185             break;
1186         }
1187         localRect.move(renderer->offsetFromContainer(containerObject, localRect.location()));
1188         renderer = containerObject;
1189     }
1190
1191     if (!unrooted)
1192         m_caretLocalRect = localRect;
1193
1194     return true;
1195 }
1196
1197 static inline bool caretRendersInsideNode(Node* node)
1198 {
1199     return node && !isTableElement(node) && !editingIgnoresContent(node);
1200 }
1201
1202 RenderObject* CaretBase::caretRenderer(Node* node) const
1203 {
1204     if (!node)
1205         return 0;
1206
1207     RenderObject* renderer = node->renderer();
1208     if (!renderer)
1209         return 0;
1210
1211     // if caretNode is a block and caret is inside it then caret should be painted by that block
1212     bool paintedByBlock = renderer->isBlockFlow() && caretRendersInsideNode(node);
1213     return paintedByBlock ? renderer : renderer->containingBlock();
1214 }
1215
1216 RenderObject* FrameSelection::caretRenderer() const
1217 {
1218     return CaretBase::caretRenderer(m_selection.start().deprecatedNode());
1219 }
1220
1221 RenderObject* DragCaretController::caretRenderer() const
1222 {
1223     return CaretBase::caretRenderer(m_position.deepEquivalent().deprecatedNode());
1224 }
1225
1226 LayoutRect FrameSelection::localCaretRect()
1227 {
1228     if (shouldUpdateCaretRect()) {
1229         if (!isCaret() || m_selection.start().isOrphan() || m_selection.end().isOrphan())
1230             clearCaretRect();
1231         else if (updateCaretRect(m_frame->document(), VisiblePosition(m_selection.start(), m_selection.affinity())))
1232             m_absCaretBoundsDirty = true;
1233     }
1234
1235     return localCaretRectWithoutUpdate();
1236 }
1237
1238 LayoutRect CaretBase::absoluteBoundsForLocalRect(Node* node, const LayoutRect& rect) const
1239 {
1240     RenderObject* caretPainter = caretRenderer(node);
1241     if (!caretPainter)
1242         return LayoutRect();
1243     
1244     LayoutRect localRect(rect);
1245     if (caretPainter->isBox())
1246         toRenderBox(caretPainter)->flipForWritingMode(localRect);
1247     return caretPainter->localToAbsoluteQuad(FloatRect(localRect)).enclosingBoundingBox();
1248 }
1249
1250 LayoutRect FrameSelection::absoluteCaretBounds()
1251 {
1252     recomputeCaretRect();
1253     return m_absCaretBounds;
1254 }
1255
1256 static LayoutRect repaintRectForCaret(LayoutRect caret)
1257 {
1258     if (caret.isEmpty())
1259         return LayoutRect();
1260     // Ensure that the dirty rect intersects the block that paints the caret even in the case where
1261     // the caret itself is just outside the block. See <https://bugs.webkit.org/show_bug.cgi?id=19086>.
1262     caret.inflateX(1);
1263     return caret;
1264 }
1265
1266 LayoutRect CaretBase::caretRepaintRect(Node* node) const
1267 {
1268     return absoluteBoundsForLocalRect(node, repaintRectForCaret(localCaretRectWithoutUpdate()));
1269 }
1270
1271 bool FrameSelection::recomputeCaretRect()
1272 {
1273     if (!shouldUpdateCaretRect())
1274         return false;
1275
1276     if (!m_frame)
1277         return false;
1278
1279     FrameView* v = m_frame->document()->view();
1280     if (!v)
1281         return false;
1282
1283     LayoutRect oldRect = localCaretRectWithoutUpdate();
1284     LayoutRect newRect = localCaretRect();
1285     if (oldRect == newRect && !m_absCaretBoundsDirty)
1286         return false;
1287
1288     LayoutRect oldAbsCaretBounds = m_absCaretBounds;
1289     // FIXME: Rename m_caretRect to m_localCaretRect.
1290     m_absCaretBounds = absoluteBoundsForLocalRect(m_selection.start().deprecatedNode(), localCaretRectWithoutUpdate());
1291     m_absCaretBoundsDirty = false;
1292     
1293     if (oldAbsCaretBounds == m_absCaretBounds)
1294         return false;
1295         
1296     LayoutRect oldAbsoluteCaretRepaintBounds = m_absoluteCaretRepaintBounds;
1297     // We believe that we need to inflate the local rect before transforming it to obtain the repaint bounds.
1298     m_absoluteCaretRepaintBounds = caretRepaintRect(m_selection.start().deprecatedNode());
1299
1300 #if ENABLE(TEXT_CARET)    
1301     if (RenderView* view = toRenderView(m_frame->document()->renderer())) {
1302         // FIXME: make caret repainting container-aware.
1303         view->repaintRectangleInViewAndCompositedLayers(oldAbsoluteCaretRepaintBounds, false);
1304         if (shouldRepaintCaret(view, isContentEditable()))
1305             view->repaintRectangleInViewAndCompositedLayers(m_absoluteCaretRepaintBounds, false);
1306     }
1307 #endif
1308     return true;
1309 }
1310
1311 bool CaretBase::shouldRepaintCaret(const RenderView* view, bool isContentEditable) const
1312 {
1313     ASSERT(view);
1314     Frame* frame = view->frameView() ? view->frameView()->frame() : 0; // The frame where the selection started.
1315     bool caretBrowsing = frame && frame->settings() && frame->settings()->caretBrowsingEnabled();
1316     return (caretBrowsing || isContentEditable);
1317 }
1318
1319 void FrameSelection::invalidateCaretRect()
1320 {
1321     if (!isCaret())
1322         return;
1323
1324     CaretBase::invalidateCaretRect(m_selection.start().deprecatedNode(), recomputeCaretRect());
1325 }
1326
1327 void CaretBase::invalidateCaretRect(Node* node, bool caretRectChanged)
1328 {
1329     // EDIT FIXME: This is an unfortunate hack.
1330     // Basically, we can't trust this layout position since we 
1331     // can't guarantee that the check to see if we are in unrendered 
1332     // content will work at this point. We may have to wait for
1333     // a layout and re-render of the document to happen. So, resetting this
1334     // flag will cause another caret layout to happen the first time
1335     // that we try to paint the caret after this call. That one will work since
1336     // it happens after the document has accounted for any editing
1337     // changes which may have been done.
1338     // And, we need to leave this layout here so the caret moves right 
1339     // away after clicking.
1340     m_caretRectNeedsUpdate = true;
1341
1342     if (!caretRectChanged) {
1343         RenderView* view = toRenderView(node->document()->renderer());
1344         if (view && shouldRepaintCaret(view, node->isContentEditable()))
1345             view->repaintRectangleInViewAndCompositedLayers(caretRepaintRect(node), false);
1346     }
1347 }
1348
1349 void FrameSelection::paintCaret(GraphicsContext* context, const LayoutPoint& paintOffset, const LayoutRect& clipRect)
1350 {
1351     if (m_selection.isCaret() && m_caretPaint)
1352         CaretBase::paintCaret(m_selection.start().deprecatedNode(), context, paintOffset, clipRect);
1353 }
1354
1355 void CaretBase::paintCaret(Node* node, GraphicsContext* context, const LayoutPoint& paintOffset, const LayoutRect& clipRect) const
1356 {
1357 #if ENABLE(TEXT_CARET)
1358     if (m_caretVisibility == Hidden)
1359         return;
1360
1361     LayoutRect drawingRect = localCaretRectWithoutUpdate();
1362     RenderObject* renderer = caretRenderer(node);
1363     if (renderer && renderer->isBox())
1364         toRenderBox(renderer)->flipForWritingMode(drawingRect);
1365     drawingRect.moveBy(paintOffset);
1366     LayoutRect caret = intersection(drawingRect, clipRect);
1367     if (caret.isEmpty())
1368         return;
1369
1370     Color caretColor = Color::black;
1371     ColorSpace colorSpace = ColorSpaceDeviceRGB;
1372     Element* element = node->rootEditableElement();
1373     if (element && element->renderer()) {
1374         caretColor = element->renderer()->style()->visitedDependentColor(CSSPropertyColor);
1375         colorSpace = element->renderer()->style()->colorSpace();
1376     }
1377
1378     context->fillRect(caret, caretColor, colorSpace);
1379 #else
1380     UNUSED_PARAM(node);
1381     UNUSED_PARAM(context);
1382     UNUSED_PARAM(paintOffset);
1383     UNUSED_PARAM(clipRect);
1384 #endif
1385 }
1386
1387 void FrameSelection::debugRenderer(RenderObject *r, bool selected) const
1388 {
1389     if (r->node()->isElementNode()) {
1390         Element* element = static_cast<Element *>(r->node());
1391         fprintf(stderr, "%s%s\n", selected ? "==> " : "    ", element->localName().string().utf8().data());
1392     } else if (r->isText()) {
1393         RenderText* textRenderer = toRenderText(r);
1394         if (!textRenderer->textLength() || !textRenderer->firstTextBox()) {
1395             fprintf(stderr, "%s#text (empty)\n", selected ? "==> " : "    ");
1396             return;
1397         }
1398         
1399         static const int max = 36;
1400         String text = textRenderer->text();
1401         int textLength = text.length();
1402         if (selected) {
1403             int offset = 0;
1404             if (r->node() == m_selection.start().containerNode())
1405                 offset = m_selection.start().computeOffsetInContainerNode();
1406             else if (r->node() == m_selection.end().containerNode())
1407                 offset = m_selection.end().computeOffsetInContainerNode();
1408
1409             int pos;
1410             InlineTextBox* box = textRenderer->findNextInlineTextBox(offset, pos);
1411             text = text.substring(box->start(), box->len());
1412             
1413             String show;
1414             int mid = max / 2;
1415             int caret = 0;
1416             
1417             // text is shorter than max
1418             if (textLength < max) {
1419                 show = text;
1420                 caret = pos;
1421             } else if (pos - mid < 0) {
1422                 // too few characters to left
1423                 show = text.left(max - 3) + "...";
1424                 caret = pos;
1425             } else if (pos - mid >= 0 && pos + mid <= textLength) {
1426                 // enough characters on each side
1427                 show = "..." + text.substring(pos - mid + 3, max - 6) + "...";
1428                 caret = mid;
1429             } else {
1430                 // too few characters on right
1431                 show = "..." + text.right(max - 3);
1432                 caret = pos - (textLength - show.length());
1433             }
1434             
1435             show.replace('\n', ' ');
1436             show.replace('\r', ' ');
1437             fprintf(stderr, "==> #text : \"%s\" at offset %d\n", show.utf8().data(), pos);
1438             fprintf(stderr, "           ");
1439             for (int i = 0; i < caret; i++)
1440                 fprintf(stderr, " ");
1441             fprintf(stderr, "^\n");
1442         } else {
1443             if ((int)text.length() > max)
1444                 text = text.left(max - 3) + "...";
1445             else
1446                 text = text.left(max);
1447             fprintf(stderr, "    #text : \"%s\"\n", text.utf8().data());
1448         }
1449     }
1450 }
1451
1452 bool FrameSelection::contains(const LayoutPoint& point)
1453 {
1454     Document* document = m_frame->document();
1455     
1456     // Treat a collapsed selection like no selection.
1457     if (!isRange())
1458         return false;
1459     if (!document->renderer()) 
1460         return false;
1461     
1462     HitTestRequest request(HitTestRequest::ReadOnly |
1463                            HitTestRequest::Active);
1464     HitTestResult result(point);
1465     document->renderView()->layer()->hitTest(request, result);
1466     Node* innerNode = result.innerNode();
1467     if (!innerNode || !innerNode->renderer())
1468         return false;
1469     
1470     VisiblePosition visiblePos(innerNode->renderer()->positionForPoint(result.localPoint()));
1471     if (visiblePos.isNull())
1472         return false;
1473         
1474     if (m_selection.visibleStart().isNull() || m_selection.visibleEnd().isNull())
1475         return false;
1476         
1477     Position start(m_selection.visibleStart().deepEquivalent());
1478     Position end(m_selection.visibleEnd().deepEquivalent());
1479     Position p(visiblePos.deepEquivalent());
1480
1481     return comparePositions(start, p) <= 0 && comparePositions(p, end) <= 0;
1482 }
1483
1484 // Workaround for the fact that it's hard to delete a frame.
1485 // Call this after doing user-triggered selections to make it easy to delete the frame you entirely selected.
1486 // Can't do this implicitly as part of every setSelection call because in some contexts it might not be good
1487 // for the focus to move to another frame. So instead we call it from places where we are selecting with the
1488 // mouse or the keyboard after setting the selection.
1489 void FrameSelection::selectFrameElementInParentIfFullySelected()
1490 {
1491     // Find the parent frame; if there is none, then we have nothing to do.
1492     Frame* parent = m_frame->tree()->parent();
1493     if (!parent)
1494         return;
1495     Page* page = m_frame->page();
1496     if (!page)
1497         return;
1498
1499     // Check if the selection contains the entire frame contents; if not, then there is nothing to do.
1500     if (!isRange())
1501         return;
1502     if (!isStartOfDocument(selection().visibleStart()))
1503         return;
1504     if (!isEndOfDocument(selection().visibleEnd()))
1505         return;
1506
1507     // Get to the <iframe> or <frame> (or even <object>) element in the parent frame.
1508     Element* ownerElement = m_frame->ownerElement();
1509     if (!ownerElement)
1510         return;
1511     ContainerNode* ownerElementParent = ownerElement->parentNode();
1512     if (!ownerElementParent)
1513         return;
1514         
1515     // This method's purpose is it to make it easier to select iframes (in order to delete them).  Don't do anything if the iframe isn't deletable.
1516     if (!ownerElementParent->rendererIsEditable())
1517         return;
1518
1519     // Create compute positions before and after the element.
1520     unsigned ownerElementNodeIndex = ownerElement->nodeIndex();
1521     VisiblePosition beforeOwnerElement(VisiblePosition(Position(ownerElementParent, ownerElementNodeIndex, Position::PositionIsOffsetInAnchor)));
1522     VisiblePosition afterOwnerElement(VisiblePosition(Position(ownerElementParent, ownerElementNodeIndex + 1, Position::PositionIsOffsetInAnchor), VP_UPSTREAM_IF_POSSIBLE));
1523
1524     // Focus on the parent frame, and then select from before this element to after.
1525     VisibleSelection newSelection(beforeOwnerElement, afterOwnerElement);
1526     if (parent->selection()->shouldChangeSelection(newSelection)) {
1527         page->focusController()->setFocusedFrame(parent);
1528         parent->selection()->setSelection(newSelection);
1529     }
1530 }
1531
1532 void FrameSelection::selectAll()
1533 {
1534     Document* document = m_frame->document();
1535
1536     if (document->focusedNode() && document->focusedNode()->hasTagName(selectTag)) {
1537         HTMLSelectElement* selectElement = toHTMLSelectElement(document->focusedNode());
1538         if (selectElement->canSelectAll()) {
1539             selectElement->selectAll();
1540             return;
1541         }
1542     }
1543
1544     RefPtr<Node> root = 0;
1545     Node* selectStartTarget = 0;
1546     if (isContentEditable()) {
1547         root = highestEditableRoot(m_selection.start());
1548         if (Node* shadowRoot = m_selection.nonBoundaryShadowTreeRootNode())
1549             selectStartTarget = shadowRoot->shadowAncestorNode();
1550         else
1551             selectStartTarget = root.get();
1552     } else {
1553         root = m_selection.nonBoundaryShadowTreeRootNode();
1554         if (root)
1555             selectStartTarget = root->shadowAncestorNode();
1556         else {
1557             root = document->documentElement();
1558             selectStartTarget = document->body();
1559         }
1560     }
1561     if (!root)
1562         return;
1563
1564     if (selectStartTarget && !selectStartTarget->dispatchEvent(Event::create(eventNames().selectstartEvent, true, true)))
1565         return;
1566
1567     VisibleSelection newSelection(VisibleSelection::selectionFromContentsOfNode(root.get()));
1568
1569     if (shouldChangeSelection(newSelection))
1570         setSelection(newSelection);
1571
1572     selectFrameElementInParentIfFullySelected();
1573     notifyRendererOfSelectionChange(UserTriggered);
1574 }
1575
1576 bool FrameSelection::setSelectedRange(Range* range, EAffinity affinity, bool closeTyping)
1577 {
1578     if (!range || !range->startContainer() || !range->endContainer())
1579         return false;
1580     ASSERT(range->startContainer()->document() == range->endContainer()->document());
1581
1582     m_frame->document()->updateLayoutIgnorePendingStylesheets();
1583
1584     // Non-collapsed ranges are not allowed to start at the end of a line that is wrapped,
1585     // they start at the beginning of the next line instead
1586     ExceptionCode ec = 0;
1587     bool collapsed = range->collapsed(ec);
1588     if (ec)
1589         return false;
1590
1591     // FIXME: Can we provide extentAffinity?
1592     VisiblePosition visibleStart(range->startPosition(), collapsed ? affinity : DOWNSTREAM);
1593     VisiblePosition visibleEnd(range->endPosition(), SEL_DEFAULT_AFFINITY);
1594     setSelection(VisibleSelection(visibleStart, visibleEnd), ClearTypingStyle | (closeTyping ? CloseTyping : 0));
1595     return true;
1596 }
1597
1598 bool FrameSelection::isInPasswordField() const
1599 {
1600     HTMLTextFormControlElement* textControl = enclosingTextFormControl(start());
1601     return textControl && textControl->hasTagName(inputTag) && static_cast<HTMLInputElement*>(textControl)->isPasswordField();
1602 }
1603
1604 void FrameSelection::focusedOrActiveStateChanged()
1605 {
1606     bool activeAndFocused = isFocusedAndActive();
1607
1608     // Because RenderObject::selectionBackgroundColor() and
1609     // RenderObject::selectionForegroundColor() check if the frame is active,
1610     // we have to update places those colors were painted.
1611     if (RenderView* view = toRenderView(m_frame->document()->renderer()))
1612         view->repaintRectangleInViewAndCompositedLayers(enclosingIntRect(bounds()));
1613
1614     // Caret appears in the active frame.
1615     if (activeAndFocused)
1616         setSelectionFromNone();
1617     setCaretVisibility(activeAndFocused ? Visible : Hidden);
1618
1619     // Update for caps lock state
1620     m_frame->eventHandler()->capsLockStateMayHaveChanged();
1621
1622     // Because CSSStyleSelector::checkOneSelector() and
1623     // RenderTheme::isFocused() check if the frame is active, we have to
1624     // update style and theme state that depended on those.
1625     if (Node* node = m_frame->document()->focusedNode()) {
1626         node->setNeedsStyleRecalc();
1627         if (RenderObject* renderer = node->renderer())
1628             if (renderer && renderer->style()->hasAppearance())
1629                 renderer->theme()->stateChanged(renderer, FocusState);
1630     }
1631
1632     // Secure keyboard entry is set by the active frame.
1633     if (m_frame->document()->useSecureKeyboardEntryWhenActive())
1634         setUseSecureKeyboardEntry(activeAndFocused);
1635 }
1636
1637 void FrameSelection::pageActivationChanged()
1638 {
1639     focusedOrActiveStateChanged();
1640 }
1641
1642 void FrameSelection::updateSecureKeyboardEntryIfActive()
1643 {
1644     if (m_frame->document() && isFocusedAndActive())
1645         setUseSecureKeyboardEntry(m_frame->document()->useSecureKeyboardEntryWhenActive());
1646 }
1647
1648 void FrameSelection::setUseSecureKeyboardEntry(bool enable)
1649 {
1650     if (enable)
1651         enableSecureTextInput();
1652     else
1653         disableSecureTextInput();
1654 }
1655
1656 void FrameSelection::setFocused(bool flag)
1657 {
1658     if (m_focused == flag)
1659         return;
1660     m_focused = flag;
1661
1662     focusedOrActiveStateChanged();
1663 }
1664
1665 bool FrameSelection::isFocusedAndActive() const
1666 {
1667     return m_focused && m_frame->page() && m_frame->page()->focusController()->isActive();
1668 }
1669
1670 inline static bool shouldStopBlinkingDueToTypingCommand(Frame* frame)
1671 {
1672     return frame->editor()->lastEditCommand() && frame->editor()->lastEditCommand()->shouldStopCaretBlinking();
1673 }
1674
1675 void FrameSelection::updateAppearance()
1676 {
1677 #if ENABLE(TEXT_CARET)
1678     bool caretRectChanged = recomputeCaretRect();
1679
1680     bool caretBrowsing = m_frame->settings() && m_frame->settings()->caretBrowsingEnabled();
1681     bool shouldBlink = caretIsVisible() && isCaret() && (isContentEditable() || caretBrowsing);
1682
1683     // If the caret moved, stop the blink timer so we can restart with a
1684     // black caret in the new location.
1685     if (caretRectChanged || !shouldBlink || shouldStopBlinkingDueToTypingCommand(m_frame))
1686         m_caretBlinkTimer.stop();
1687
1688     // Start blinking with a black caret. Be sure not to restart if we're
1689     // already blinking in the right location.
1690     if (shouldBlink && !m_caretBlinkTimer.isActive()) {
1691         if (double blinkInterval = m_frame->page()->theme()->caretBlinkInterval())
1692             m_caretBlinkTimer.startRepeating(blinkInterval);
1693
1694         if (!m_caretPaint) {
1695             m_caretPaint = true;
1696             invalidateCaretRect();
1697         }
1698     }
1699 #endif
1700
1701     // We need to update style in case the node containing the selection is made display:none.
1702     m_frame->document()->updateStyleIfNeeded();
1703
1704     RenderView* view = m_frame->contentRenderer();
1705     if (!view)
1706         return;
1707
1708     // Construct a new VisibleSolution, since m_selection is not necessarily valid, and the following steps
1709     // assume a valid selection. See <https://bugs.webkit.org/show_bug.cgi?id=69563> and <rdar://problem/10232866>.
1710     VisibleSelection selection(m_selection.visibleStart(), m_selection.visibleEnd());
1711
1712     if (!selection.isRange()) {
1713         view->clearSelection();
1714         return;
1715     }
1716
1717     // Use the rightmost candidate for the start of the selection, and the leftmost candidate for the end of the selection.
1718     // Example: foo <a>bar</a>.  Imagine that a line wrap occurs after 'foo', and that 'bar' is selected.   If we pass [foo, 3]
1719     // as the start of the selection, the selection painting code will think that content on the line containing 'foo' is selected
1720     // and will fill the gap before 'bar'.
1721     Position startPos = selection.start();
1722     Position candidate = startPos.downstream();
1723     if (candidate.isCandidate())
1724         startPos = candidate;
1725     Position endPos = selection.end();
1726     candidate = endPos.upstream();
1727     if (candidate.isCandidate())
1728         endPos = candidate;
1729
1730     // We can get into a state where the selection endpoints map to the same VisiblePosition when a selection is deleted
1731     // because we don't yet notify the FrameSelection of text removal.
1732     if (startPos.isNotNull() && endPos.isNotNull() && selection.visibleStart() != selection.visibleEnd()) {
1733         RenderObject* startRenderer = startPos.deprecatedNode()->renderer();
1734         RenderObject* endRenderer = endPos.deprecatedNode()->renderer();
1735         view->setSelection(startRenderer, startPos.deprecatedEditingOffset(), endRenderer, endPos.deprecatedEditingOffset());
1736     }
1737 }
1738
1739 void FrameSelection::setCaretVisibility(CaretVisibility visibility)
1740 {
1741     if (caretVisibility() == visibility)
1742         return;
1743     clearCaretRectIfNeeded();
1744     CaretBase::setCaretVisibility(visibility);
1745     updateAppearance();
1746 }
1747
1748 void FrameSelection::clearCaretRectIfNeeded()
1749 {
1750 #if ENABLE(TEXT_CARET)
1751     if (!m_caretPaint)
1752         return;
1753     m_caretPaint = false;
1754     invalidateCaretRect();
1755 #endif
1756 }
1757
1758 void FrameSelection::caretBlinkTimerFired(Timer<FrameSelection>*)
1759 {
1760 #if ENABLE(TEXT_CARET)
1761     ASSERT(caretIsVisible());
1762     ASSERT(isCaret());
1763     bool caretPaint = m_caretPaint;
1764     if (isCaretBlinkingSuspended() && caretPaint)
1765         return;
1766     m_caretPaint = !caretPaint;
1767     invalidateCaretRect();
1768 #endif
1769 }
1770
1771 void FrameSelection::notifyRendererOfSelectionChange(EUserTriggered userTriggered)
1772 {
1773     m_frame->document()->updateStyleIfNeeded();
1774
1775     if (!rootEditableElement())
1776         return;
1777
1778     if (HTMLTextFormControlElement* textControl = enclosingTextFormControl(start()))
1779         textControl->selectionChanged(userTriggered == UserTriggered);
1780 }
1781
1782 // Helper function that tells whether a particular node is an element that has an entire
1783 // Frame and FrameView, a <frame>, <iframe>, or <object>.
1784 static bool isFrameElement(const Node* n)
1785 {
1786     if (!n)
1787         return false;
1788     RenderObject* renderer = n->renderer();
1789     if (!renderer || !renderer->isWidget())
1790         return false;
1791     Widget* widget = toRenderWidget(renderer)->widget();
1792     return widget && widget->isFrameView();
1793 }
1794
1795 void FrameSelection::setFocusedNodeIfNeeded()
1796 {
1797     if (isNone() || !isFocused())
1798         return;
1799
1800     bool caretBrowsing = m_frame->settings() && m_frame->settings()->caretBrowsingEnabled();
1801     if (caretBrowsing) {
1802         if (Node* anchor = enclosingAnchorElement(base())) {
1803             m_frame->page()->focusController()->setFocusedNode(anchor, m_frame);
1804             return;
1805         }
1806     }
1807
1808     if (Node* target = rootEditableElement()) {
1809         // Walk up the DOM tree to search for a node to focus. 
1810         while (target) {
1811             // We don't want to set focus on a subframe when selecting in a parent frame,
1812             // so add the !isFrameElement check here. There's probably a better way to make this
1813             // work in the long term, but this is the safest fix at this time.
1814             if (target && target->isMouseFocusable() && !isFrameElement(target)) {
1815                 m_frame->page()->focusController()->setFocusedNode(target, m_frame);
1816                 return;
1817             }
1818             target = target->parentOrHostNode(); 
1819         }
1820         m_frame->document()->setFocusedNode(0);
1821     }
1822
1823     if (caretBrowsing)
1824         m_frame->page()->focusController()->setFocusedNode(0, m_frame);
1825 }
1826
1827 void DragCaretController::paintDragCaret(Frame* frame, GraphicsContext* p, const LayoutPoint& paintOffset, const LayoutRect& clipRect) const
1828 {
1829 #if ENABLE(TEXT_CARET)
1830     if (m_position.deepEquivalent().deprecatedNode()->document()->frame() == frame)
1831         paintCaret(m_position.deepEquivalent().deprecatedNode(), p, paintOffset, clipRect);
1832 #else
1833     UNUSED_PARAM(frame);
1834     UNUSED_PARAM(p);
1835     UNUSED_PARAM(paintOffset);
1836     UNUSED_PARAM(clipRect);
1837 #endif
1838 }
1839
1840 PassRefPtr<CSSMutableStyleDeclaration> FrameSelection::copyTypingStyle() const
1841 {
1842     if (!m_typingStyle || !m_typingStyle->style())
1843         return 0;
1844     return m_typingStyle->style()->copy();
1845 }
1846
1847 bool FrameSelection::shouldDeleteSelection(const VisibleSelection& selection) const
1848 {
1849     return m_frame->editor()->client()->shouldDeleteRange(selection.toNormalizedRange().get());
1850 }
1851
1852 FloatRect FrameSelection::bounds(bool clipToVisibleContent) const
1853 {
1854     RenderView* root = m_frame->contentRenderer();
1855     FrameView* view = m_frame->view();
1856     if (!root || !view)
1857         return LayoutRect();
1858
1859     LayoutRect selectionRect = root->selectionBounds(clipToVisibleContent);
1860     return clipToVisibleContent ? intersection(selectionRect, view->visibleContentRect()) : selectionRect;
1861 }
1862
1863 void FrameSelection::getClippedVisibleTextRectangles(Vector<FloatRect>& rectangles) const
1864 {
1865     RenderView* root = m_frame->contentRenderer();
1866     if (!root)
1867         return;
1868
1869     FloatRect visibleContentRect = m_frame->view()->visibleContentRect();
1870
1871     Vector<FloatQuad> quads;
1872     toNormalizedRange()->textQuads(quads, true);
1873
1874     size_t size = quads.size();
1875     for (size_t i = 0; i < size; ++i) {
1876         FloatRect intersectionRect = intersection(quads[i].enclosingBoundingBox(), visibleContentRect);
1877         if (!intersectionRect.isEmpty())
1878             rectangles.append(intersectionRect);
1879     }
1880 }
1881
1882 // Scans logically forward from "start", including any child frames.
1883 static HTMLFormElement* scanForForm(Node* start)
1884 {
1885     for (Node* node = start; node; node = node->traverseNextNode()) {
1886         if (node->hasTagName(formTag))
1887             return static_cast<HTMLFormElement*>(node);
1888         if (node->isHTMLElement() && toHTMLElement(node)->isFormControlElement())
1889             return static_cast<HTMLFormControlElement*>(node)->form();
1890         if (node->hasTagName(frameTag) || node->hasTagName(iframeTag)) {
1891             Node* childDocument = static_cast<HTMLFrameElementBase*>(node)->contentDocument();
1892             if (HTMLFormElement* frameResult = scanForForm(childDocument))
1893                 return frameResult;
1894         }
1895     }
1896     return 0;
1897 }
1898
1899 // We look for either the form containing the current focus, or for one immediately after it
1900 HTMLFormElement* FrameSelection::currentForm() const
1901 {
1902     // Start looking either at the active (first responder) node, or where the selection is.
1903     Node* start = m_frame->document()->focusedNode();
1904     if (!start)
1905         start = this->start().deprecatedNode();
1906
1907     // Try walking up the node tree to find a form element.
1908     Node* node;
1909     for (node = start; node; node = node->parentNode()) {
1910         if (node->hasTagName(formTag))
1911             return static_cast<HTMLFormElement*>(node);
1912         if (node->isHTMLElement() && toHTMLElement(node)->isFormControlElement())
1913             return static_cast<HTMLFormControlElement*>(node)->form();
1914     }
1915
1916     // Try walking forward in the node tree to find a form element.
1917     return scanForForm(start);
1918 }
1919
1920 void FrameSelection::revealSelection(const ScrollAlignment& alignment, bool revealExtent)
1921 {
1922     LayoutRect rect;
1923
1924     switch (selectionType()) {
1925     case VisibleSelection::NoSelection:
1926         return;
1927     case VisibleSelection::CaretSelection:
1928         rect = absoluteCaretBounds();
1929         break;
1930     case VisibleSelection::RangeSelection:
1931         rect = revealExtent ? VisiblePosition(extent()).absoluteCaretBounds() : enclosingIntRect(bounds(false));
1932         break;
1933     }
1934
1935     Position start = this->start();
1936     ASSERT(start.deprecatedNode());
1937     if (start.deprecatedNode() && start.deprecatedNode()->renderer()) {
1938         // FIXME: This code only handles scrolling the startContainer's layer, but
1939         // the selection rect could intersect more than just that.
1940         // See <rdar://problem/4799899>.
1941         if (RenderLayer* layer = start.deprecatedNode()->renderer()->enclosingLayer()) {
1942             layer->scrollRectToVisible(rect, alignment, alignment);
1943             updateAppearance();
1944         }
1945     }
1946 }
1947
1948 void FrameSelection::setSelectionFromNone()
1949 {
1950     // Put a caret inside the body if the entire frame is editable (either the
1951     // entire WebView is editable or designMode is on for this document).
1952
1953     Document* document = m_frame->document();
1954     bool caretBrowsing = m_frame->settings() && m_frame->settings()->caretBrowsingEnabled();
1955     if (!isNone() || !(document->rendererIsEditable() || caretBrowsing))
1956         return;
1957
1958     Node* node = document->documentElement();
1959     while (node && !node->hasTagName(bodyTag))
1960         node = node->traverseNextNode();
1961     if (node)
1962         setSelection(VisibleSelection(firstPositionInOrBeforeNode(node), DOWNSTREAM));
1963 }
1964
1965 bool FrameSelection::shouldChangeSelection(const VisibleSelection& newSelection) const
1966 {
1967     return m_frame->editor()->shouldChangeSelection(selection(), newSelection, newSelection.affinity(), false);
1968 }
1969
1970 bool FrameSelection::dispatchSelectStart()
1971 {
1972     Node* selectStartTarget = m_selection.extent().containerNode();
1973     if (!selectStartTarget)
1974         return true;
1975
1976     return selectStartTarget->dispatchEvent(Event::create(eventNames().selectstartEvent, true, true));
1977 }
1978
1979 inline bool FrameSelection::visualWordMovementEnabled() const
1980 {
1981     Settings* settings = m_frame ? m_frame->settings() : 0;
1982     return settings && settings->visualWordMovementEnabled();
1983 }
1984
1985 #ifndef NDEBUG
1986
1987 void FrameSelection::formatForDebugger(char* buffer, unsigned length) const
1988 {
1989     m_selection.formatForDebugger(buffer, length);
1990 }
1991
1992 void FrameSelection::showTreeForThis() const
1993 {
1994     m_selection.showTreeForThis();
1995 }
1996
1997 #endif
1998
1999 }
2000
2001 #ifndef NDEBUG
2002
2003 void showTree(const WebCore::FrameSelection& sel)
2004 {
2005     sel.showTreeForThis();
2006 }
2007
2008 void showTree(const WebCore::FrameSelection* sel)
2009 {
2010     if (sel)
2011         sel->showTreeForThis();
2012 }
2013
2014 #endif