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