8427e78f4d6d44a23996f407a0c094eb9ef1c446
[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 "ElementIterator.h"
36 #include "EventHandler.h"
37 #include "ExceptionCode.h"
38 #include "FloatQuad.h"
39 #include "FocusController.h"
40 #include "Frame.h"
41 #include "FrameTree.h"
42 #include "FrameView.h"
43 #include "GraphicsContext.h"
44 #include "HTMLFormElement.h"
45 #include "HTMLFrameElementBase.h"
46 #include "HTMLInputElement.h"
47 #include "HTMLSelectElement.h"
48 #include "HTMLNames.h"
49 #include "HitTestRequest.h"
50 #include "HitTestResult.h"
51 #include "InlineTextBox.h"
52 #include "Page.h"
53 #include "RenderText.h"
54 #include "RenderTextControl.h"
55 #include "RenderTheme.h"
56 #include "RenderView.h"
57 #include "RenderWidget.h"
58 #include "RenderedPosition.h"
59 #include "Settings.h"
60 #include "SpatialNavigation.h"
61 #include "StyleProperties.h"
62 #include "TypingCommand.h"
63 #include "VisibleUnits.h"
64 #include "htmlediting.h"
65 #include <stdio.h>
66 #include <wtf/text/CString.h>
67
68 #if PLATFORM(IOS)
69 #include "Chrome.h"
70 #include "ChromeClient.h"
71 #include "Color.h"
72 #include "RenderLayer.h"
73 #include "RenderObject.h"
74 #include "RenderStyle.h"
75 #endif
76
77 #define EDIT_DEBUG 0
78
79 namespace WebCore {
80
81 using namespace HTMLNames;
82
83 static inline LayoutUnit NoXPosForVerticalArrowNavigation()
84 {
85     return LayoutUnit::min();
86 }
87
88 CaretBase::CaretBase(CaretVisibility visibility)
89     : m_caretRectNeedsUpdate(true)
90     , m_caretVisibility(visibility)
91 {
92 }
93
94 DragCaretController::DragCaretController()
95     : CaretBase(Visible)
96 {
97 }
98
99 bool DragCaretController::isContentRichlyEditable() const
100 {
101     return isRichlyEditablePosition(m_position.deepEquivalent());
102 }
103
104 static inline bool shouldAlwaysUseDirectionalSelection(Frame* frame)
105 {
106     return !frame || frame->editor().behavior().shouldConsiderSelectionAsDirectional();
107 }
108
109 FrameSelection::FrameSelection(Frame* frame)
110     : m_frame(frame)
111     , m_xPosForVerticalArrowNavigation(NoXPosForVerticalArrowNavigation())
112     , m_granularity(CharacterGranularity)
113     , m_caretBlinkTimer(this, &FrameSelection::caretBlinkTimerFired)
114     , m_absCaretBoundsDirty(true)
115     , m_caretPaint(true)
116     , m_isCaretBlinkingSuspended(false)
117     , m_focused(frame && frame->page() && frame->page()->focusController().focusedFrame() == frame)
118     , m_shouldShowBlockCursor(false)
119 #if PLATFORM(IOS)
120     , m_updateAppearanceEnabled(false)
121     , m_caretBlinks(true)
122     , m_closeTypingSuppressions(0)
123     , m_scrollingSuppressCount(0)
124 #endif
125 {
126     if (shouldAlwaysUseDirectionalSelection(m_frame))
127         m_selection.setIsDirectional(true);
128 }
129
130 Element* FrameSelection::rootEditableElementOrDocumentElement() const
131 {
132     Element* selectionRoot = m_selection.rootEditableElement();
133     return selectionRoot ? selectionRoot : m_frame->document()->documentElement();
134 }
135
136 void FrameSelection::moveTo(const VisiblePosition &pos, EUserTriggered userTriggered, CursorAlignOnScroll align)
137 {
138     SetSelectionOptions options = CloseTyping | ClearTypingStyle | userTriggered;
139     setSelection(VisibleSelection(pos.deepEquivalent(), pos.deepEquivalent(), pos.affinity(), m_selection.isDirectional()), options, align);
140 }
141
142 void FrameSelection::moveTo(const VisiblePosition &base, const VisiblePosition &extent, EUserTriggered userTriggered)
143 {
144     const bool selectionHasDirection = true;
145     SetSelectionOptions options = CloseTyping | ClearTypingStyle | userTriggered;
146     setSelection(VisibleSelection(base.deepEquivalent(), extent.deepEquivalent(), base.affinity(), selectionHasDirection), options);
147 }
148
149 void FrameSelection::moveTo(const Position &pos, EAffinity affinity, EUserTriggered userTriggered)
150 {
151     SetSelectionOptions options = CloseTyping | ClearTypingStyle | userTriggered;
152     setSelection(VisibleSelection(pos, affinity, m_selection.isDirectional()), options);
153 }
154
155 void FrameSelection::moveTo(const Range *r, EAffinity affinity, EUserTriggered userTriggered)
156 {
157     SetSelectionOptions options = CloseTyping | ClearTypingStyle | userTriggered;
158     VisibleSelection selection = r ? VisibleSelection(r->startPosition(), r->endPosition(), affinity) : VisibleSelection(Position(), Position(), affinity);
159     setSelection(selection, options);
160 }
161
162 void FrameSelection::moveTo(const Position &base, const Position &extent, EAffinity affinity, EUserTriggered userTriggered)
163 {
164     const bool selectionHasDirection = true;
165     SetSelectionOptions options = CloseTyping | ClearTypingStyle | userTriggered;
166     setSelection(VisibleSelection(base, extent, affinity, selectionHasDirection), options);
167 }
168
169 void DragCaretController::setCaretPosition(const VisiblePosition& position)
170 {
171     if (Node* node = m_position.deepEquivalent().deprecatedNode())
172         invalidateCaretRect(node);
173     m_position = position;
174     setCaretRectNeedsUpdate();
175     Document* document = 0;
176     if (Node* node = m_position.deepEquivalent().deprecatedNode()) {
177         invalidateCaretRect(node);
178         document = &node->document();
179     }
180     if (m_position.isNull() || m_position.isOrphan())
181         clearCaretRect();
182     else
183         updateCaretRect(document, m_position);
184 }
185
186 static void adjustEndpointsAtBidiBoundary(VisiblePosition& visibleBase, VisiblePosition& visibleExtent)
187 {
188     RenderedPosition base(visibleBase);
189     RenderedPosition extent(visibleExtent);
190
191     if (base.isNull() || extent.isNull() || base.isEquivalent(extent))
192         return;
193
194     if (base.atLeftBoundaryOfBidiRun()) {
195         if (!extent.atRightBoundaryOfBidiRun(base.bidiLevelOnRight())
196             && base.isEquivalent(extent.leftBoundaryOfBidiRun(base.bidiLevelOnRight()))) {
197             visibleBase = base.positionAtLeftBoundaryOfBiDiRun();
198             return;
199         }
200         return;
201     }
202
203     if (base.atRightBoundaryOfBidiRun()) {
204         if (!extent.atLeftBoundaryOfBidiRun(base.bidiLevelOnLeft())
205             && base.isEquivalent(extent.rightBoundaryOfBidiRun(base.bidiLevelOnLeft()))) {
206             visibleBase = base.positionAtRightBoundaryOfBiDiRun();
207             return;
208         }
209         return;
210     }
211
212     if (extent.atLeftBoundaryOfBidiRun() && extent.isEquivalent(base.leftBoundaryOfBidiRun(extent.bidiLevelOnRight()))) {
213         visibleExtent = extent.positionAtLeftBoundaryOfBiDiRun();
214         return;
215     }
216
217     if (extent.atRightBoundaryOfBidiRun() && extent.isEquivalent(base.rightBoundaryOfBidiRun(extent.bidiLevelOnLeft()))) {
218         visibleExtent = extent.positionAtRightBoundaryOfBiDiRun();
219         return;
220     }
221 }
222
223 void FrameSelection::setSelectionByMouseIfDifferent(const VisibleSelection& passedNewSelection, TextGranularity granularity,
224     EndPointsAdjustmentMode endpointsAdjustmentMode)
225 {
226     VisibleSelection newSelection = passedNewSelection;
227     bool isDirectional = shouldAlwaysUseDirectionalSelection(m_frame) || newSelection.isDirectional();
228
229     VisiblePosition base = m_originalBase.isNotNull() ? m_originalBase : newSelection.visibleBase();
230     VisiblePosition newBase = base;
231     VisiblePosition extent = newSelection.visibleExtent();
232     VisiblePosition newExtent = extent;
233     if (endpointsAdjustmentMode == AdjustEndpointsAtBidiBoundary)
234         adjustEndpointsAtBidiBoundary(newBase, newExtent);
235
236     if (newBase != base || newExtent != extent) {
237         m_originalBase = base;
238         newSelection.setBase(newBase);
239         newSelection.setExtent(newExtent);
240     } else if (m_originalBase.isNotNull()) {
241         if (m_selection.base() == newSelection.base())
242             newSelection.setBase(m_originalBase);
243         m_originalBase.clear();
244     }
245
246     newSelection.setIsDirectional(isDirectional); // Adjusting base and extent will make newSelection always directional
247     if (m_selection == newSelection || !shouldChangeSelection(newSelection))
248         return;
249
250     setSelection(newSelection, UserTriggered | DoNotRevealSelection | CloseTyping | ClearTypingStyle, AlignCursorOnScrollIfNeeded, granularity);
251 }
252
253 bool FrameSelection::setSelectionWithoutUpdatingAppearance(const VisibleSelection& newSelection, SetSelectionOptions options, CursorAlignOnScroll align, TextGranularity granularity, EUserTriggered userTriggered)
254 {
255     bool closeTyping = options & CloseTyping;
256     bool shouldClearTypingStyle = options & ClearTypingStyle;
257
258     VisibleSelection s = newSelection;
259     if (shouldAlwaysUseDirectionalSelection(m_frame))
260         s.setIsDirectional(true);
261
262     if (!m_frame) {
263         m_selection = s;
264         return false;
265     }
266
267     // <http://bugs.webkit.org/show_bug.cgi?id=23464>: Infinite recursion at FrameSelection::setSelection
268     // if document->frame() == m_frame we can get into an infinite loop
269     if (s.base().anchorNode()) {
270         Document& document = s.base().anchorNode()->document();
271         if (document.frame() && document.frame() != m_frame && &document != m_frame->document()) {
272             RefPtr<Frame> guard = document.frame();
273             document.frame()->selection().setSelection(s, options, align, granularity);
274             // It's possible that during the above set selection, this FrameSelection has been modified by
275             // selectFrameElementInParentIfFullySelected, but that the selection is no longer valid since
276             // the frame is about to be destroyed. If this is the case, clear our selection.
277             if (guard->hasOneRef() && !m_selection.isNonOrphanedCaretOrRange())
278                 clear();
279             return false;
280         }
281     }
282
283     m_granularity = granularity;
284
285 #if PLATFORM(IOS)
286     if (closeTyping && m_closeTypingSuppressions == 0)
287 #else
288     if (closeTyping)
289 #endif
290         TypingCommand::closeTyping(m_frame);
291
292     if (shouldClearTypingStyle)
293         clearTypingStyle();
294
295     if (m_selection == s) {
296         // Even if selection was not changed, selection offsets may have been changed.
297         updateSelectionCachesIfSelectionIsInsideTextFormControl(userTriggered);
298         return false;
299     }
300
301     VisibleSelection oldSelection = m_selection;
302
303     m_selection = s;
304     setCaretRectNeedsUpdate();
305     
306     if (!s.isNone() && !(options & DoNotSetFocus))
307         setFocusedElementIfNeeded();
308
309     // Always clear the x position used for vertical arrow navigation.
310     // It will be restored by the vertical arrow navigation code if necessary.
311     m_xPosForVerticalArrowNavigation = NoXPosForVerticalArrowNavigation();
312     selectFrameElementInParentIfFullySelected();
313     updateSelectionCachesIfSelectionIsInsideTextFormControl(userTriggered);
314     m_frame->editor().respondToChangedSelection(oldSelection, options);
315     m_frame->document()->enqueueDocumentEvent(Event::create(eventNames().selectionchangeEvent, false, false));
316
317     return true;
318 }
319
320 void FrameSelection::setSelection(const VisibleSelection& selection, SetSelectionOptions options, CursorAlignOnScroll align, TextGranularity granularity)
321 {
322     EUserTriggered userTriggered = selectionOptionsToUserTriggered(options);
323     if (!setSelectionWithoutUpdatingAppearance(selection, options, align, granularity, userTriggered))
324         return;
325
326 #if ENABLE(TEXT_CARET)
327     m_frame->document()->updateLayoutIgnorePendingStylesheets();
328 #else
329     m_frame->document()->updateStyleIfNeeded();
330 #endif
331     updateAppearance();
332
333     if (userTriggered == UserTriggered && !(options & DoNotRevealSelection)) {
334         ScrollAlignment alignment;
335
336         if (m_frame->editor().behavior().shouldCenterAlignWhenSelectionIsRevealed())
337             alignment = (align == AlignCursorOnScrollAlways) ? ScrollAlignment::alignCenterAlways : ScrollAlignment::alignCenterIfNeeded;
338         else
339             alignment = (align == AlignCursorOnScrollAlways) ? ScrollAlignment::alignTopAlways : ScrollAlignment::alignToEdgeIfNeeded;
340
341         revealSelection(alignment, RevealExtent);
342     }
343
344     notifyAccessibilityForSelectionChange();
345 }
346
347 static bool removingNodeRemovesPosition(Node* node, const Position& position)
348 {
349     if (!position.anchorNode())
350         return false;
351
352     if (position.anchorNode() == node)
353         return true;
354
355     if (!node->isElementNode())
356         return false;
357
358     Element* element = toElement(node);
359     return element->containsIncludingShadowDOM(position.anchorNode());
360 }
361
362 static void clearRenderViewSelection(const Position& position)
363 {
364     Ref<Document> document(position.anchorNode()->document());
365     document->updateStyleIfNeeded();
366     if (RenderView* view = document->renderView())
367         view->clearSelection();
368 }
369
370 void DragCaretController::nodeWillBeRemoved(Node* node)
371 {
372     if (!hasCaret() || (node && !node->inDocument()))
373         return;
374
375     if (!removingNodeRemovesPosition(node, m_position.deepEquivalent()))
376         return;
377
378     clearRenderViewSelection(m_position.deepEquivalent());
379     clear();
380 }
381
382 void FrameSelection::nodeWillBeRemoved(Node* node)
383 {
384     // There can't be a selection inside a fragment, so if a fragment's node is being removed,
385     // the selection in the document that created the fragment needs no adjustment.
386     if (isNone() || (node && !node->inDocument()))
387         return;
388
389     respondToNodeModification(node, removingNodeRemovesPosition(node, m_selection.base()), removingNodeRemovesPosition(node, m_selection.extent()),
390         removingNodeRemovesPosition(node, m_selection.start()), removingNodeRemovesPosition(node, m_selection.end()));
391 }
392
393 void FrameSelection::respondToNodeModification(Node* node, bool baseRemoved, bool extentRemoved, bool startRemoved, bool endRemoved)
394 {
395     bool clearRenderTreeSelection = false;
396     bool clearDOMTreeSelection = false;
397
398     if (startRemoved || endRemoved) {
399         Position start = m_selection.start();
400         Position end = m_selection.end();
401         if (startRemoved)
402             updatePositionForNodeRemoval(start, node);
403         if (endRemoved)
404             updatePositionForNodeRemoval(end, node);
405
406         if (start.isNotNull() && end.isNotNull()) {
407             if (m_selection.isBaseFirst())
408                 m_selection.setWithoutValidation(start, end);
409             else
410                 m_selection.setWithoutValidation(end, start);
411         } else
412             clearDOMTreeSelection = true;
413
414         clearRenderTreeSelection = true;
415     } else if (baseRemoved || extentRemoved) {
416         // The base and/or extent are about to be removed, but the start and end aren't.
417         // Change the base and extent to the start and end, but don't re-validate the
418         // selection, since doing so could move the start and end into the node
419         // that is about to be removed.
420         if (m_selection.isBaseFirst())
421             m_selection.setWithoutValidation(m_selection.start(), m_selection.end());
422         else
423             m_selection.setWithoutValidation(m_selection.end(), m_selection.start());
424     } else if (RefPtr<Range> range = m_selection.firstRange()) {
425         ExceptionCode ec = 0;
426         Range::CompareResults compareResult = range->compareNode(node, ec);
427         if (!ec && (compareResult == Range::NODE_BEFORE_AND_AFTER || compareResult == Range::NODE_INSIDE)) {
428             // If we did nothing here, when this node's renderer was destroyed, the rect that it 
429             // occupied would be invalidated, but, selection gaps that change as a result of 
430             // the removal wouldn't be invalidated.
431             // FIXME: Don't do so much unnecessary invalidation.
432             clearRenderTreeSelection = true;
433         }
434     }
435
436     if (clearRenderTreeSelection)
437         clearRenderViewSelection(m_selection.start());
438
439     if (clearDOMTreeSelection)
440         setSelection(VisibleSelection(), DoNotSetFocus);
441 }
442
443 static void updatePositionAfterAdoptingTextReplacement(Position& position, CharacterData* node, unsigned offset, unsigned oldLength, unsigned newLength)
444 {
445     if (!position.anchorNode() || position.anchorNode() != node || position.anchorType() != Position::PositionIsOffsetInAnchor)
446         return;
447
448     // See: http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Mutation
449     ASSERT(position.offsetInContainerNode() >= 0);
450     unsigned positionOffset = static_cast<unsigned>(position.offsetInContainerNode());
451     // Replacing text can be viewed as a deletion followed by insertion.
452     if (positionOffset >= offset && positionOffset <= offset + oldLength)
453         position.moveToOffset(offset);
454
455     // Adjust the offset if the position is after the end of the deleted contents
456     // (positionOffset > offset + oldLength) to avoid having a stale offset.
457     if (positionOffset > offset + oldLength)
458         position.moveToOffset(positionOffset - oldLength + newLength);
459
460     ASSERT(static_cast<unsigned>(position.offsetInContainerNode()) <= node->length());
461 }
462
463 void FrameSelection::textWasReplaced(CharacterData* node, unsigned offset, unsigned oldLength, unsigned newLength)
464 {
465     // The fragment check is a performance optimization. See http://trac.webkit.org/changeset/30062.
466     if (isNone() || !node || !node->inDocument())
467         return;
468
469     Position base = m_selection.base();
470     Position extent = m_selection.extent();
471     Position start = m_selection.start();
472     Position end = m_selection.end();
473     updatePositionAfterAdoptingTextReplacement(base, node, offset, oldLength, newLength);
474     updatePositionAfterAdoptingTextReplacement(extent, node, offset, oldLength, newLength);
475     updatePositionAfterAdoptingTextReplacement(start, node, offset, oldLength, newLength);
476     updatePositionAfterAdoptingTextReplacement(end, node, offset, oldLength, newLength);
477
478     if (base != m_selection.base() || extent != m_selection.extent() || start != m_selection.start() || end != m_selection.end()) {
479         VisibleSelection newSelection;
480         if (base != extent)
481             newSelection.setWithoutValidation(base, extent);
482         else if (m_selection.isDirectional() && !m_selection.isBaseFirst())
483             newSelection.setWithoutValidation(end, start);
484         else
485             newSelection.setWithoutValidation(start, end);
486
487         m_frame->document()->updateLayout();
488         setSelection(newSelection, DoNotSetFocus);
489     }
490 }
491
492 TextDirection FrameSelection::directionOfEnclosingBlock()
493 {
494     return WebCore::directionOfEnclosingBlock(m_selection.extent());
495 }
496
497 TextDirection FrameSelection::directionOfSelection()
498 {
499     InlineBox* startBox = 0;
500     InlineBox* endBox = 0;
501     int unusedOffset;
502     if (m_selection.start().isNotNull())
503         m_selection.visibleStart().getInlineBoxAndOffset(startBox, unusedOffset);
504     if (m_selection.end().isNotNull())
505         m_selection.visibleEnd().getInlineBoxAndOffset(endBox, unusedOffset);
506     if (startBox && endBox && startBox->direction() == endBox->direction())
507         return startBox->direction();
508
509     return directionOfEnclosingBlock();
510 }
511
512 void FrameSelection::willBeModified(EAlteration alter, SelectionDirection direction)
513 {
514     if (alter != AlterationExtend)
515         return;
516
517     Position start = m_selection.start();
518     Position end = m_selection.end();
519
520     bool baseIsStart = true;
521
522     if (m_selection.isDirectional()) {
523         // Make base and extent match start and end so we extend the user-visible selection.
524         // This only matters for cases where base and extend point to different positions than
525         // start and end (e.g. after a double-click to select a word).
526         if (m_selection.isBaseFirst())
527             baseIsStart = true;
528         else
529             baseIsStart = false;
530     } else {
531         switch (direction) {
532         case DirectionRight:
533             if (directionOfSelection() == LTR)
534                 baseIsStart = true;
535             else
536                 baseIsStart = false;
537             break;
538         case DirectionForward:
539             baseIsStart = true;
540             break;
541         case DirectionLeft:
542             if (directionOfSelection() == LTR)
543                 baseIsStart = false;
544             else
545                 baseIsStart = true;
546             break;
547         case DirectionBackward:
548             baseIsStart = false;
549             break;
550         }
551     }
552     if (baseIsStart) {
553         m_selection.setBase(start);
554         m_selection.setExtent(end);
555     } else {
556         m_selection.setBase(end);
557         m_selection.setExtent(start);
558     }
559 }
560
561 VisiblePosition FrameSelection::positionForPlatform(bool isGetStart) const
562 {
563     if (m_frame && m_frame->settings().editingBehaviorType() == EditingMacBehavior)
564         return isGetStart ? m_selection.visibleStart() : m_selection.visibleEnd();
565     // Linux and Windows always extend selections from the extent endpoint.
566     // FIXME: VisibleSelection should be fixed to ensure as an invariant that
567     // base/extent always point to the same nodes as start/end, but which points
568     // to which depends on the value of isBaseFirst. Then this can be changed
569     // to just return m_sel.extent().
570     return m_selection.isBaseFirst() ? m_selection.visibleEnd() : m_selection.visibleStart();
571 }
572
573 VisiblePosition FrameSelection::startForPlatform() const
574 {
575     return positionForPlatform(true);
576 }
577
578 VisiblePosition FrameSelection::endForPlatform() const
579 {
580     return positionForPlatform(false);
581 }
582
583 VisiblePosition FrameSelection::nextWordPositionForPlatform(const VisiblePosition &originalPosition)
584 {
585     VisiblePosition positionAfterCurrentWord = nextWordPosition(originalPosition);
586
587     if (m_frame && m_frame->editor().behavior().shouldSkipSpaceWhenMovingRight()) {
588         // In order to skip spaces when moving right, we advance one
589         // word further and then move one word back. Given the
590         // semantics of previousWordPosition() this will put us at the
591         // beginning of the word following.
592         VisiblePosition positionAfterSpacingAndFollowingWord = nextWordPosition(positionAfterCurrentWord);
593         if (positionAfterSpacingAndFollowingWord != positionAfterCurrentWord)
594             positionAfterCurrentWord = previousWordPosition(positionAfterSpacingAndFollowingWord);
595
596         bool movingBackwardsMovedPositionToStartOfCurrentWord = positionAfterCurrentWord == previousWordPosition(nextWordPosition(originalPosition));
597         if (movingBackwardsMovedPositionToStartOfCurrentWord)
598             positionAfterCurrentWord = positionAfterSpacingAndFollowingWord;
599     }
600     return positionAfterCurrentWord;
601 }
602
603 #if ENABLE(USERSELECT_ALL)
604 static void adjustPositionForUserSelectAll(VisiblePosition& pos, bool isForward)
605 {
606     if (Node* rootUserSelectAll = Position::rootUserSelectAllForNode(pos.deepEquivalent().anchorNode()))
607         pos = isForward ? positionAfterNode(rootUserSelectAll).downstream(CanCrossEditingBoundary) : positionBeforeNode(rootUserSelectAll).upstream(CanCrossEditingBoundary);
608 }
609 #endif
610
611 VisiblePosition FrameSelection::modifyExtendingRight(TextGranularity granularity)
612 {
613     VisiblePosition pos(m_selection.extent(), m_selection.affinity());
614
615     // The difference between modifyExtendingRight and modifyExtendingForward is:
616     // modifyExtendingForward always extends forward logically.
617     // modifyExtendingRight behaves the same as modifyExtendingForward except for extending character or word,
618     // it extends forward logically if the enclosing block is LTR direction,
619     // but it extends backward logically if the enclosing block is RTL direction.
620     switch (granularity) {
621     case CharacterGranularity:
622         if (directionOfEnclosingBlock() == LTR)
623             pos = pos.next(CannotCrossEditingBoundary);
624         else
625             pos = pos.previous(CannotCrossEditingBoundary);
626         break;
627     case WordGranularity:
628         if (directionOfEnclosingBlock() == LTR)
629             pos = nextWordPositionForPlatform(pos);
630         else
631             pos = previousWordPosition(pos);
632         break;
633     case LineBoundary:
634         if (directionOfEnclosingBlock() == LTR)
635             pos = modifyExtendingForward(granularity);
636         else
637             pos = modifyExtendingBackward(granularity);
638         break;
639     case SentenceGranularity:
640     case LineGranularity:
641     case ParagraphGranularity:
642     case SentenceBoundary:
643     case ParagraphBoundary:
644     case DocumentBoundary:
645         // FIXME: implement all of the above?
646         pos = modifyExtendingForward(granularity);
647         break;
648 #if PLATFORM(IOS)
649     case DocumentGranularity:
650         ASSERT_NOT_REACHED();
651         break;
652 #endif
653     }
654 #if ENABLE(USERSELECT_ALL)
655     adjustPositionForUserSelectAll(pos, directionOfEnclosingBlock() == LTR);
656 #endif
657     return pos;
658 }
659
660 VisiblePosition FrameSelection::modifyExtendingForward(TextGranularity granularity)
661 {
662     VisiblePosition pos(m_selection.extent(), m_selection.affinity());
663     switch (granularity) {
664     case CharacterGranularity:
665         pos = pos.next(CannotCrossEditingBoundary);
666         break;
667     case WordGranularity:
668         pos = nextWordPositionForPlatform(pos);
669         break;
670     case SentenceGranularity:
671         pos = nextSentencePosition(pos);
672         break;
673     case LineGranularity:
674         pos = nextLinePosition(pos, lineDirectionPointForBlockDirectionNavigation(EXTENT));
675         break;
676     case ParagraphGranularity:
677         pos = nextParagraphPosition(pos, lineDirectionPointForBlockDirectionNavigation(EXTENT));
678         break;
679 #if PLATFORM(IOS)
680     case DocumentGranularity:
681         ASSERT_NOT_REACHED();
682         break;
683 #endif
684     case SentenceBoundary:
685         pos = endOfSentence(endForPlatform());
686         break;
687     case LineBoundary:
688         pos = logicalEndOfLine(endForPlatform());
689         break;
690     case ParagraphBoundary:
691         pos = endOfParagraph(endForPlatform());
692         break;
693     case DocumentBoundary:
694         pos = endForPlatform();
695         if (isEditablePosition(pos.deepEquivalent()))
696             pos = endOfEditableContent(pos);
697         else
698             pos = endOfDocument(pos);
699         break;
700     }
701 #if ENABLE(USERSELECT_ALL)
702      adjustPositionForUserSelectAll(pos, directionOfEnclosingBlock() == LTR);
703 #endif
704     return pos;
705 }
706
707 VisiblePosition FrameSelection::modifyMovingRight(TextGranularity granularity)
708 {
709     VisiblePosition pos;
710     switch (granularity) {
711     case CharacterGranularity:
712         if (isRange()) {
713             if (directionOfSelection() == LTR)
714                 pos = VisiblePosition(m_selection.end(), m_selection.affinity());
715             else
716                 pos = VisiblePosition(m_selection.start(), m_selection.affinity());
717         } else
718             pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).right(true);
719         break;
720     case WordGranularity: {
721         // Visual word movement relies on isWordTextBreak which is not implemented in WinCE and QT.
722         // https://bugs.webkit.org/show_bug.cgi?id=81136.
723         bool skipsSpaceWhenMovingRight = m_frame && m_frame->editor().behavior().shouldSkipSpaceWhenMovingRight();
724         pos = rightWordPosition(VisiblePosition(m_selection.extent(), m_selection.affinity()), skipsSpaceWhenMovingRight);
725         break;
726     }
727     case SentenceGranularity:
728     case LineGranularity:
729     case ParagraphGranularity:
730     case SentenceBoundary:
731     case ParagraphBoundary:
732     case DocumentBoundary:
733         // FIXME: Implement all of the above.
734         pos = modifyMovingForward(granularity);
735         break;
736     case LineBoundary:
737         pos = rightBoundaryOfLine(startForPlatform(), directionOfEnclosingBlock());
738         break;
739 #if PLATFORM(IOS)
740     case DocumentGranularity:
741         ASSERT_NOT_REACHED();
742         break;
743 #endif
744     }
745     return pos;
746 }
747
748 VisiblePosition FrameSelection::modifyMovingForward(TextGranularity granularity)
749 {
750     VisiblePosition pos;
751     // FIXME: Stay in editable content for the less common granularities.
752     switch (granularity) {
753     case CharacterGranularity:
754         if (isRange())
755             pos = VisiblePosition(m_selection.end(), m_selection.affinity());
756         else
757             pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).next(CannotCrossEditingBoundary);
758         break;
759     case WordGranularity:
760         pos = nextWordPositionForPlatform(VisiblePosition(m_selection.extent(), m_selection.affinity()));
761         break;
762     case SentenceGranularity:
763         pos = nextSentencePosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
764         break;
765     case LineGranularity: {
766         // down-arrowing from a range selection that ends at the start of a line needs
767         // to leave the selection at that line start (no need to call nextLinePosition!)
768         pos = endForPlatform();
769         if (!isRange() || !isStartOfLine(pos))
770             pos = nextLinePosition(pos, lineDirectionPointForBlockDirectionNavigation(START));
771         break;
772     }
773     case ParagraphGranularity:
774         pos = nextParagraphPosition(endForPlatform(), lineDirectionPointForBlockDirectionNavigation(START));
775         break;
776 #if PLATFORM(IOS)
777     case DocumentGranularity:
778         ASSERT_NOT_REACHED();
779         break;
780 #endif
781     case SentenceBoundary:
782         pos = endOfSentence(endForPlatform());
783         break;
784     case LineBoundary:
785         pos = logicalEndOfLine(endForPlatform());
786         break;
787     case ParagraphBoundary:
788         pos = endOfParagraph(endForPlatform());
789         break;
790     case DocumentBoundary:
791         pos = endForPlatform();
792         if (isEditablePosition(pos.deepEquivalent()))
793             pos = endOfEditableContent(pos);
794         else
795             pos = endOfDocument(pos);
796         break;
797     }
798     return pos;
799 }
800
801 VisiblePosition FrameSelection::modifyExtendingLeft(TextGranularity granularity)
802 {
803     VisiblePosition pos(m_selection.extent(), m_selection.affinity());
804
805     // The difference between modifyExtendingLeft and modifyExtendingBackward is:
806     // modifyExtendingBackward always extends backward logically.
807     // modifyExtendingLeft behaves the same as modifyExtendingBackward except for extending character or word,
808     // it extends backward logically if the enclosing block is LTR direction,
809     // but it extends forward logically if the enclosing block is RTL direction.
810     switch (granularity) {
811     case CharacterGranularity:
812         if (directionOfEnclosingBlock() == LTR)
813             pos = pos.previous(CannotCrossEditingBoundary);
814         else
815             pos = pos.next(CannotCrossEditingBoundary);
816         break;
817     case WordGranularity:
818         if (directionOfEnclosingBlock() == LTR)
819             pos = previousWordPosition(pos);
820         else
821             pos = nextWordPositionForPlatform(pos);
822         break;
823     case LineBoundary:
824         if (directionOfEnclosingBlock() == LTR)
825             pos = modifyExtendingBackward(granularity);
826         else
827             pos = modifyExtendingForward(granularity);
828         break;
829     case SentenceGranularity:
830     case LineGranularity:
831     case ParagraphGranularity:
832     case SentenceBoundary:
833     case ParagraphBoundary:
834     case DocumentBoundary:
835         pos = modifyExtendingBackward(granularity);
836         break;
837 #if PLATFORM(IOS)
838     case DocumentGranularity:
839         ASSERT_NOT_REACHED();
840         break;
841 #endif
842     }
843 #if ENABLE(USERSELECT_ALL)
844     adjustPositionForUserSelectAll(pos, !(directionOfEnclosingBlock() == LTR));
845 #endif
846     return pos;
847 }
848        
849 VisiblePosition FrameSelection::modifyExtendingBackward(TextGranularity granularity)
850 {
851     VisiblePosition pos(m_selection.extent(), m_selection.affinity());
852
853     // Extending a selection backward by word or character from just after a table selects
854     // the table.  This "makes sense" from the user perspective, esp. when deleting.
855     // It was done here instead of in VisiblePosition because we want VPs to iterate
856     // over everything.
857     switch (granularity) {
858     case CharacterGranularity:
859         pos = pos.previous(CannotCrossEditingBoundary);
860         break;
861     case WordGranularity:
862         pos = previousWordPosition(pos);
863         break;
864     case SentenceGranularity:
865         pos = previousSentencePosition(pos);
866         break;
867     case LineGranularity:
868         pos = previousLinePosition(pos, lineDirectionPointForBlockDirectionNavigation(EXTENT));
869         break;
870     case ParagraphGranularity:
871         pos = previousParagraphPosition(pos, lineDirectionPointForBlockDirectionNavigation(EXTENT));
872         break;
873     case SentenceBoundary:
874         pos = startOfSentence(startForPlatform());
875         break;
876     case LineBoundary:
877         pos = logicalStartOfLine(startForPlatform());
878         break;
879     case ParagraphBoundary:
880         pos = startOfParagraph(startForPlatform());
881         break;
882     case DocumentBoundary:
883         pos = startForPlatform();
884         if (isEditablePosition(pos.deepEquivalent()))
885             pos = startOfEditableContent(pos);
886         else
887             pos = startOfDocument(pos);
888         break;
889 #if PLATFORM(IOS)
890     case DocumentGranularity:
891         ASSERT_NOT_REACHED();
892         break;
893 #endif
894     }
895 #if ENABLE(USERSELECT_ALL)
896     adjustPositionForUserSelectAll(pos, !(directionOfEnclosingBlock() == LTR));
897 #endif
898     return pos;
899 }
900
901 VisiblePosition FrameSelection::modifyMovingLeft(TextGranularity granularity)
902 {
903     VisiblePosition pos;
904     switch (granularity) {
905     case CharacterGranularity:
906         if (isRange())
907             if (directionOfSelection() == LTR)
908                 pos = VisiblePosition(m_selection.start(), m_selection.affinity());
909             else
910                 pos = VisiblePosition(m_selection.end(), m_selection.affinity());
911         else
912             pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).left(true);
913         break;
914     case WordGranularity: {
915         bool skipsSpaceWhenMovingRight = m_frame && m_frame->editor().behavior().shouldSkipSpaceWhenMovingRight();
916         pos = leftWordPosition(VisiblePosition(m_selection.extent(), m_selection.affinity()), skipsSpaceWhenMovingRight);
917         break;
918     }
919     case SentenceGranularity:
920     case LineGranularity:
921     case ParagraphGranularity:
922     case SentenceBoundary:
923     case ParagraphBoundary:
924     case DocumentBoundary:
925         // FIXME: Implement all of the above.
926         pos = modifyMovingBackward(granularity);
927         break;
928     case LineBoundary:
929         pos = leftBoundaryOfLine(startForPlatform(), directionOfEnclosingBlock());
930         break;
931 #if PLATFORM(IOS)
932     case DocumentGranularity:
933         ASSERT_NOT_REACHED();
934         break;
935 #endif
936     }
937     return pos;
938 }
939
940 VisiblePosition FrameSelection::modifyMovingBackward(TextGranularity granularity)
941 {
942     VisiblePosition pos;
943     switch (granularity) {
944     case CharacterGranularity:
945         if (isRange())
946             pos = VisiblePosition(m_selection.start(), m_selection.affinity());
947         else
948             pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).previous(CannotCrossEditingBoundary);
949         break;
950     case WordGranularity:
951         pos = previousWordPosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
952         break;
953     case SentenceGranularity:
954         pos = previousSentencePosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
955         break;
956     case LineGranularity:
957         pos = previousLinePosition(startForPlatform(), lineDirectionPointForBlockDirectionNavigation(START));
958         break;
959     case ParagraphGranularity:
960         pos = previousParagraphPosition(startForPlatform(), lineDirectionPointForBlockDirectionNavigation(START));
961         break;
962     case SentenceBoundary:
963         pos = startOfSentence(startForPlatform());
964         break;
965     case LineBoundary:
966         pos = logicalStartOfLine(startForPlatform());
967         break;
968     case ParagraphBoundary:
969         pos = startOfParagraph(startForPlatform());
970         break;
971     case DocumentBoundary:
972         pos = startForPlatform();
973         if (isEditablePosition(pos.deepEquivalent()))
974             pos = startOfEditableContent(pos);
975         else
976             pos = startOfDocument(pos);
977         break;
978 #if PLATFORM(IOS)
979     case DocumentGranularity:
980         ASSERT_NOT_REACHED();
981         break;
982 #endif
983     }
984     return pos;
985 }
986
987 static bool isBoundary(TextGranularity granularity)
988 {
989     return granularity == LineBoundary || granularity == ParagraphBoundary || granularity == DocumentBoundary;
990 }    
991
992 bool FrameSelection::modify(EAlteration alter, SelectionDirection direction, TextGranularity granularity, EUserTriggered userTriggered)
993 {
994     if (userTriggered == UserTriggered) {
995         FrameSelection trialFrameSelection;
996         trialFrameSelection.setSelection(m_selection);
997         trialFrameSelection.modify(alter, direction, granularity, NotUserTriggered);
998
999         bool change = shouldChangeSelection(trialFrameSelection.selection());
1000         if (!change)
1001             return false;
1002
1003         if (trialFrameSelection.selection().isRange() && m_selection.isCaret() && !dispatchSelectStart())
1004             return false;
1005     }
1006
1007     willBeModified(alter, direction);
1008
1009     bool wasRange = m_selection.isRange();
1010     Position originalStartPosition = m_selection.start();
1011     VisiblePosition position;
1012     switch (direction) {
1013     case DirectionRight:
1014         if (alter == AlterationMove)
1015             position = modifyMovingRight(granularity);
1016         else
1017             position = modifyExtendingRight(granularity);
1018         break;
1019     case DirectionForward:
1020         if (alter == AlterationExtend)
1021             position = modifyExtendingForward(granularity);
1022         else
1023             position = modifyMovingForward(granularity);
1024         break;
1025     case DirectionLeft:
1026         if (alter == AlterationMove)
1027             position = modifyMovingLeft(granularity);
1028         else
1029             position = modifyExtendingLeft(granularity);
1030         break;
1031     case DirectionBackward:
1032         if (alter == AlterationExtend)
1033             position = modifyExtendingBackward(granularity);
1034         else
1035             position = modifyMovingBackward(granularity);
1036         break;
1037     }
1038
1039     if (position.isNull())
1040         return false;
1041
1042     if (isSpatialNavigationEnabled(m_frame))
1043         if (!wasRange && alter == AlterationMove && position == originalStartPosition)
1044             return false;
1045
1046     // Some of the above operations set an xPosForVerticalArrowNavigation.
1047     // Setting a selection will clear it, so save it to possibly restore later.
1048     // Note: the START position type is arbitrary because it is unused, it would be
1049     // the requested position type if there were no xPosForVerticalArrowNavigation set.
1050     LayoutUnit x = lineDirectionPointForBlockDirectionNavigation(START);
1051     m_selection.setIsDirectional(shouldAlwaysUseDirectionalSelection(m_frame) || alter == AlterationExtend);
1052
1053     switch (alter) {
1054     case AlterationMove:
1055         moveTo(position, userTriggered);
1056         break;
1057     case AlterationExtend:
1058
1059         if (!m_selection.isCaret()
1060             && (granularity == WordGranularity || granularity == ParagraphGranularity || granularity == LineGranularity)
1061             && m_frame && !m_frame->editor().behavior().shouldExtendSelectionByWordOrLineAcrossCaret()) {
1062             // Don't let the selection go across the base position directly. Needed to match mac
1063             // behavior when, for instance, word-selecting backwards starting with the caret in
1064             // the middle of a word and then word-selecting forward, leaving the caret in the
1065             // same place where it was, instead of directly selecting to the end of the word.
1066             VisibleSelection newSelection = m_selection;
1067             newSelection.setExtent(position);
1068             if (m_selection.isBaseFirst() != newSelection.isBaseFirst())
1069                 position = m_selection.base();
1070         }
1071
1072         // Standard Mac behavior when extending to a boundary is grow the selection rather than leaving the
1073         // base in place and moving the extent. Matches NSTextView.
1074         if (!m_frame || !m_frame->editor().behavior().shouldAlwaysGrowSelectionWhenExtendingToBoundary() || m_selection.isCaret() || !isBoundary(granularity))
1075             setExtent(position, userTriggered);
1076         else {
1077             TextDirection textDirection = directionOfEnclosingBlock();
1078             if (direction == DirectionForward || (textDirection == LTR && direction == DirectionRight) || (textDirection == RTL && direction == DirectionLeft))
1079                 setEnd(position, userTriggered);
1080             else
1081                 setStart(position, userTriggered);
1082         }
1083         break;
1084     }
1085     
1086     if (granularity == LineGranularity || granularity == ParagraphGranularity)
1087         m_xPosForVerticalArrowNavigation = x;
1088
1089     if (userTriggered == UserTriggered)
1090         m_granularity = CharacterGranularity;
1091
1092     setCaretRectNeedsUpdate();
1093
1094     return true;
1095 }
1096
1097 // FIXME: Maybe baseline would be better?
1098 static bool absoluteCaretY(const VisiblePosition &c, int &y)
1099 {
1100     IntRect rect = c.absoluteCaretBounds();
1101     if (rect.isEmpty())
1102         return false;
1103     y = rect.y() + rect.height() / 2;
1104     return true;
1105 }
1106
1107 bool FrameSelection::modify(EAlteration alter, unsigned verticalDistance, VerticalDirection direction, EUserTriggered userTriggered, CursorAlignOnScroll align)
1108 {
1109     if (!verticalDistance)
1110         return false;
1111
1112     if (userTriggered == UserTriggered) {
1113         FrameSelection trialFrameSelection;
1114         trialFrameSelection.setSelection(m_selection);
1115         trialFrameSelection.modify(alter, verticalDistance, direction, NotUserTriggered);
1116
1117         bool change = shouldChangeSelection(trialFrameSelection.selection());
1118         if (!change)
1119             return false;
1120     }
1121
1122     willBeModified(alter, direction == DirectionUp ? DirectionBackward : DirectionForward);
1123
1124     VisiblePosition pos;
1125     LayoutUnit xPos = 0;
1126     switch (alter) {
1127     case AlterationMove:
1128         pos = VisiblePosition(direction == DirectionUp ? m_selection.start() : m_selection.end(), m_selection.affinity());
1129         xPos = lineDirectionPointForBlockDirectionNavigation(direction == DirectionUp ? START : END);
1130         m_selection.setAffinity(direction == DirectionUp ? UPSTREAM : DOWNSTREAM);
1131         break;
1132     case AlterationExtend:
1133         pos = VisiblePosition(m_selection.extent(), m_selection.affinity());
1134         xPos = lineDirectionPointForBlockDirectionNavigation(EXTENT);
1135         m_selection.setAffinity(DOWNSTREAM);
1136         break;
1137     }
1138
1139     int startY;
1140     if (!absoluteCaretY(pos, startY))
1141         return false;
1142     if (direction == DirectionUp)
1143         startY = -startY;
1144     int lastY = startY;
1145
1146     VisiblePosition result;
1147     VisiblePosition next;
1148     for (VisiblePosition p = pos; ; p = next) {
1149         if (direction == DirectionUp)
1150             next = previousLinePosition(p, xPos);
1151         else
1152             next = nextLinePosition(p, xPos);
1153
1154         if (next.isNull() || next == p)
1155             break;
1156         int nextY;
1157         if (!absoluteCaretY(next, nextY))
1158             break;
1159         if (direction == DirectionUp)
1160             nextY = -nextY;
1161         if (nextY - startY > static_cast<int>(verticalDistance))
1162             break;
1163         if (nextY >= lastY) {
1164             lastY = nextY;
1165             result = next;
1166         }
1167     }
1168
1169     if (result.isNull())
1170         return false;
1171
1172     switch (alter) {
1173     case AlterationMove:
1174         moveTo(result, userTriggered, align);
1175         break;
1176     case AlterationExtend:
1177         setExtent(result, userTriggered);
1178         break;
1179     }
1180
1181     if (userTriggered == UserTriggered)
1182         m_granularity = CharacterGranularity;
1183
1184     m_selection.setIsDirectional(shouldAlwaysUseDirectionalSelection(m_frame) || alter == AlterationExtend);
1185
1186     return true;
1187 }
1188
1189 LayoutUnit FrameSelection::lineDirectionPointForBlockDirectionNavigation(EPositionType type)
1190 {
1191     LayoutUnit x = 0;
1192
1193     if (isNone())
1194         return x;
1195
1196     Position pos;
1197     switch (type) {
1198     case START:
1199         pos = m_selection.start();
1200         break;
1201     case END:
1202         pos = m_selection.end();
1203         break;
1204     case BASE:
1205         pos = m_selection.base();
1206         break;
1207     case EXTENT:
1208         pos = m_selection.extent();
1209         break;
1210     }
1211
1212     Frame* frame = pos.anchorNode()->document().frame();
1213     if (!frame)
1214         return x;
1215         
1216     if (m_xPosForVerticalArrowNavigation == NoXPosForVerticalArrowNavigation()) {
1217         VisiblePosition visiblePosition(pos, m_selection.affinity());
1218         // VisiblePosition creation can fail here if a node containing the selection becomes visibility:hidden
1219         // after the selection is created and before this function is called.
1220         x = visiblePosition.isNotNull() ? visiblePosition.lineDirectionPointForBlockDirectionNavigation() : 0;
1221         m_xPosForVerticalArrowNavigation = x;
1222     } else
1223         x = m_xPosForVerticalArrowNavigation;
1224         
1225     return x;
1226 }
1227
1228 void FrameSelection::clear()
1229 {
1230     m_granularity = CharacterGranularity;
1231     setSelection(VisibleSelection());
1232 }
1233
1234 void FrameSelection::prepareForDestruction()
1235 {
1236     m_granularity = CharacterGranularity;
1237
1238 #if ENABLE(TEXT_CARET)
1239     m_caretBlinkTimer.stop();
1240 #endif
1241
1242     RenderView* view = m_frame->contentRenderer();
1243     if (view)
1244         view->clearSelection();
1245
1246     setSelectionWithoutUpdatingAppearance(VisibleSelection(), CloseTyping | ClearTypingStyle,
1247         AlignCursorOnScrollIfNeeded, CharacterGranularity, NotUserTriggered);
1248     m_previousCaretNode.clear();
1249 }
1250
1251 void FrameSelection::setStart(const VisiblePosition &pos, EUserTriggered trigger)
1252 {
1253     if (m_selection.isBaseFirst())
1254         setBase(pos, trigger);
1255     else
1256         setExtent(pos, trigger);
1257 }
1258
1259 void FrameSelection::setEnd(const VisiblePosition &pos, EUserTriggered trigger)
1260 {
1261     if (m_selection.isBaseFirst())
1262         setExtent(pos, trigger);
1263     else
1264         setBase(pos, trigger);
1265 }
1266
1267 void FrameSelection::setBase(const VisiblePosition &pos, EUserTriggered userTriggered)
1268 {
1269     const bool selectionHasDirection = true;
1270     setSelection(VisibleSelection(pos.deepEquivalent(), m_selection.extent(), pos.affinity(), selectionHasDirection), CloseTyping | ClearTypingStyle | userTriggered);
1271 }
1272
1273 void FrameSelection::setExtent(const VisiblePosition &pos, EUserTriggered userTriggered)
1274 {
1275     const bool selectionHasDirection = true;
1276     setSelection(VisibleSelection(m_selection.base(), pos.deepEquivalent(), pos.affinity(), selectionHasDirection), CloseTyping | ClearTypingStyle | userTriggered);
1277 }
1278
1279 void FrameSelection::setBase(const Position &pos, EAffinity affinity, EUserTriggered userTriggered)
1280 {
1281     const bool selectionHasDirection = true;
1282     setSelection(VisibleSelection(pos, m_selection.extent(), affinity, selectionHasDirection), CloseTyping | ClearTypingStyle | userTriggered);
1283 }
1284
1285 void FrameSelection::setExtent(const Position &pos, EAffinity affinity, EUserTriggered userTriggered)
1286 {
1287     const bool selectionHasDirection = true;
1288     setSelection(VisibleSelection(m_selection.base(), pos, affinity, selectionHasDirection), CloseTyping | ClearTypingStyle | userTriggered);
1289 }
1290
1291 void CaretBase::clearCaretRect()
1292 {
1293     m_caretLocalRect = LayoutRect();
1294 }
1295
1296 static inline bool caretRendersInsideNode(Node* node)
1297 {
1298     return node && !isRenderedTable(node) && !editingIgnoresContent(node);
1299 }
1300
1301 static RenderObject* caretRenderer(Node* node)
1302 {
1303     if (!node)
1304         return 0;
1305
1306     RenderObject* renderer = node->renderer();
1307     if (!renderer)
1308         return 0;
1309
1310     // if caretNode is a block and caret is inside it then caret should be painted by that block
1311     bool paintedByBlock = renderer->isRenderBlockFlow() && caretRendersInsideNode(node);
1312     return paintedByBlock ? renderer : renderer->containingBlock();
1313 }
1314
1315 bool CaretBase::updateCaretRect(Document* document, const VisiblePosition& caretPosition)
1316 {
1317     document->updateLayoutIgnorePendingStylesheets();
1318     m_caretLocalRect = LayoutRect();
1319
1320     m_caretRectNeedsUpdate = false;
1321
1322     if (caretPosition.isNull())
1323         return false;
1324
1325     ASSERT(caretPosition.deepEquivalent().deprecatedNode()->renderer());
1326
1327     // First compute a rect local to the renderer at the selection start.
1328     RenderObject* renderer;
1329     LayoutRect localRect = caretPosition.localCaretRect(renderer);
1330
1331     // Get the renderer that will be responsible for painting the caret
1332     // (which is either the renderer we just found, or one of its containers).
1333     RenderObject* caretPainter = caretRenderer(caretPosition.deepEquivalent().deprecatedNode());
1334
1335     // Compute an offset between the renderer and the caretPainter.
1336     bool unrooted = false;
1337     while (renderer != caretPainter) {
1338         RenderObject* containerObject = renderer->container();
1339         if (!containerObject) {
1340             unrooted = true;
1341             break;
1342         }
1343         localRect.move(renderer->offsetFromContainer(containerObject, localRect.location()));
1344         renderer = containerObject;
1345     }
1346
1347     if (!unrooted)
1348         m_caretLocalRect = localRect;
1349
1350     return true;
1351 }
1352
1353 RenderObject* FrameSelection::caretRenderer() const
1354 {
1355     return WebCore::caretRenderer(m_selection.start().deprecatedNode());
1356 }
1357
1358 RenderObject* DragCaretController::caretRenderer() const
1359 {
1360     return WebCore::caretRenderer(m_position.deepEquivalent().deprecatedNode());
1361 }
1362
1363 static bool isNonOrphanedCaret(const VisibleSelection& selection)
1364 {
1365     return selection.isCaret() && !selection.start().isOrphan() && !selection.end().isOrphan();
1366 }
1367
1368 LayoutRect FrameSelection::localCaretRect()
1369 {
1370     if (shouldUpdateCaretRect()) {
1371         if (!isNonOrphanedCaret(m_selection))
1372             clearCaretRect();
1373         else if (updateCaretRect(m_frame->document(), VisiblePosition(m_selection.start(), m_selection.affinity())))
1374             m_absCaretBoundsDirty = true;
1375     }
1376
1377     return localCaretRectWithoutUpdate();
1378 }
1379
1380 IntRect CaretBase::absoluteBoundsForLocalRect(Node* node, const LayoutRect& rect) const
1381 {
1382     RenderObject* caretPainter = caretRenderer(node);
1383     if (!caretPainter)
1384         return IntRect();
1385     
1386     LayoutRect localRect(rect);
1387     if (caretPainter->isBox())
1388         toRenderBox(caretPainter)->flipForWritingMode(localRect);
1389     return caretPainter->localToAbsoluteQuad(FloatRect(localRect)).enclosingBoundingBox();
1390 }
1391
1392 IntRect FrameSelection::absoluteCaretBounds()
1393 {
1394     recomputeCaretRect();
1395     return m_absCaretBounds;
1396 }
1397
1398 static void repaintCaretForLocalRect(Node* node, const LayoutRect& rect)
1399 {
1400     RenderObject* caretPainter = caretRenderer(node);
1401     if (!caretPainter)
1402         return;
1403
1404     caretPainter->repaintRectangle(rect);
1405 }
1406
1407 bool FrameSelection::recomputeCaretRect()
1408 {
1409     if (!shouldUpdateCaretRect())
1410         return false;
1411
1412     if (!m_frame)
1413         return false;
1414
1415     FrameView* v = m_frame->document()->view();
1416     if (!v)
1417         return false;
1418
1419     Node* caretNode = m_selection.start().deprecatedNode();
1420
1421     LayoutRect oldRect = localCaretRectWithoutUpdate();
1422     LayoutRect newRect = localCaretRect();
1423
1424     if (caretNode == m_previousCaretNode && oldRect == newRect && !m_absCaretBoundsDirty)
1425         return false;
1426
1427     IntRect oldAbsCaretBounds = m_absCaretBounds;
1428     m_absCaretBounds = absoluteBoundsForLocalRect(caretNode, localCaretRectWithoutUpdate());
1429     m_absCaretBoundsDirty = false;
1430
1431     if (caretNode == m_previousCaretNode && oldAbsCaretBounds == m_absCaretBounds)
1432         return false;
1433
1434 #if ENABLE(TEXT_CARET)
1435     if (RenderView* view = m_frame->document()->renderView()) {
1436         bool previousOrNewCaretNodeIsContentEditable = m_selection.isContentEditable() || (m_previousCaretNode && m_previousCaretNode->isContentEditable());
1437         if (shouldRepaintCaret(view, previousOrNewCaretNodeIsContentEditable)) {
1438             if (m_previousCaretNode)
1439                 repaintCaretForLocalRect(m_previousCaretNode.get(), oldRect);
1440             m_previousCaretNode = caretNode;
1441             repaintCaretForLocalRect(caretNode, newRect);
1442         }
1443     }
1444 #endif
1445     return true;
1446 }
1447
1448 bool CaretBase::shouldRepaintCaret(const RenderView* view, bool isContentEditable) const
1449 {
1450     ASSERT(view);
1451     Frame* frame = &view->frameView().frame(); // The frame where the selection started.
1452     bool caretBrowsing = frame && frame->settings().caretBrowsingEnabled();
1453     return (caretBrowsing || isContentEditable);
1454 }
1455
1456 void FrameSelection::invalidateCaretRect()
1457 {
1458     if (!isCaret())
1459         return;
1460
1461     CaretBase::invalidateCaretRect(m_selection.start().deprecatedNode(), recomputeCaretRect());
1462 }
1463
1464 void CaretBase::invalidateCaretRect(Node* node, bool caretRectChanged)
1465 {
1466     // EDIT FIXME: This is an unfortunate hack.
1467     // Basically, we can't trust this layout position since we 
1468     // can't guarantee that the check to see if we are in unrendered 
1469     // content will work at this point. We may have to wait for
1470     // a layout and re-render of the document to happen. So, resetting this
1471     // flag will cause another caret layout to happen the first time
1472     // that we try to paint the caret after this call. That one will work since
1473     // it happens after the document has accounted for any editing
1474     // changes which may have been done.
1475     // And, we need to leave this layout here so the caret moves right 
1476     // away after clicking.
1477     m_caretRectNeedsUpdate = true;
1478
1479     if (caretRectChanged)
1480         return;
1481
1482     if (RenderView* view = node->document().renderView()) {
1483         if (shouldRepaintCaret(view, node->isContentEditable(Node::UserSelectAllIsAlwaysNonEditable)))
1484             repaintCaretForLocalRect(node, localCaretRectWithoutUpdate());
1485     }
1486 }
1487
1488 void FrameSelection::paintCaret(GraphicsContext* context, const LayoutPoint& paintOffset, const LayoutRect& clipRect)
1489 {
1490     if (m_selection.isCaret() && m_caretPaint)
1491         CaretBase::paintCaret(m_selection.start().deprecatedNode(), context, paintOffset, clipRect);
1492 }
1493
1494 void CaretBase::paintCaret(Node* node, GraphicsContext* context, const LayoutPoint& paintOffset, const LayoutRect& clipRect) const
1495 {
1496 #if ENABLE(TEXT_CARET)
1497     if (m_caretVisibility == Hidden)
1498         return;
1499
1500     LayoutRect drawingRect = localCaretRectWithoutUpdate();
1501     RenderObject* renderer = caretRenderer(node);
1502     if (renderer && renderer->isBox())
1503         toRenderBox(renderer)->flipForWritingMode(drawingRect);
1504     drawingRect.moveBy(roundedIntPoint(paintOffset));
1505     LayoutRect caret = intersection(drawingRect, clipRect);
1506     if (caret.isEmpty())
1507         return;
1508
1509     Color caretColor = Color::black;
1510     ColorSpace colorSpace = ColorSpaceDeviceRGB;
1511     Element* element = node->isElementNode() ? toElement(node) : node->parentElement();
1512
1513     if (element && element->renderer()) {
1514         caretColor = element->renderer()->style().visitedDependentColor(CSSPropertyColor);
1515         colorSpace = element->renderer()->style().colorSpace();
1516     }
1517
1518     context->fillRect(caret, caretColor, colorSpace);
1519 #else
1520     UNUSED_PARAM(node);
1521     UNUSED_PARAM(context);
1522     UNUSED_PARAM(paintOffset);
1523     UNUSED_PARAM(clipRect);
1524 #endif
1525 }
1526
1527 void FrameSelection::debugRenderer(RenderObject* r, bool selected) const
1528 {
1529     if (r->node()->isElementNode()) {
1530         Element* element = toElement(r->node());
1531         fprintf(stderr, "%s%s\n", selected ? "==> " : "    ", element->localName().string().utf8().data());
1532     } else if (r->isText()) {
1533         RenderText* textRenderer = toRenderText(r);
1534         if (!textRenderer->textLength() || !textRenderer->firstTextBox()) {
1535             fprintf(stderr, "%s#text (empty)\n", selected ? "==> " : "    ");
1536             return;
1537         }
1538         
1539         static const int max = 36;
1540         String text = textRenderer->text();
1541         int textLength = text.length();
1542         if (selected) {
1543             int offset = 0;
1544             if (r->node() == m_selection.start().containerNode())
1545                 offset = m_selection.start().computeOffsetInContainerNode();
1546             else if (r->node() == m_selection.end().containerNode())
1547                 offset = m_selection.end().computeOffsetInContainerNode();
1548
1549             int pos;
1550             InlineTextBox* box = textRenderer->findNextInlineTextBox(offset, pos);
1551             text = text.substring(box->start(), box->len());
1552             
1553             String show;
1554             int mid = max / 2;
1555             int caret = 0;
1556             
1557             // text is shorter than max
1558             if (textLength < max) {
1559                 show = text;
1560                 caret = pos;
1561             } else if (pos - mid < 0) {
1562                 // too few characters to left
1563                 show = text.left(max - 3) + "...";
1564                 caret = pos;
1565             } else if (pos - mid >= 0 && pos + mid <= textLength) {
1566                 // enough characters on each side
1567                 show = "..." + text.substring(pos - mid + 3, max - 6) + "...";
1568                 caret = mid;
1569             } else {
1570                 // too few characters on right
1571                 show = "..." + text.right(max - 3);
1572                 caret = pos - (textLength - show.length());
1573             }
1574             
1575             show.replace('\n', ' ');
1576             show.replace('\r', ' ');
1577             fprintf(stderr, "==> #text : \"%s\" at offset %d\n", show.utf8().data(), pos);
1578             fprintf(stderr, "           ");
1579             for (int i = 0; i < caret; i++)
1580                 fprintf(stderr, " ");
1581             fprintf(stderr, "^\n");
1582         } else {
1583             if ((int)text.length() > max)
1584                 text = text.left(max - 3) + "...";
1585             else
1586                 text = text.left(max);
1587             fprintf(stderr, "    #text : \"%s\"\n", text.utf8().data());
1588         }
1589     }
1590 }
1591
1592 bool FrameSelection::contains(const LayoutPoint& point)
1593 {
1594     Document* document = m_frame->document();
1595     
1596     // Treat a collapsed selection like no selection.
1597     if (!isRange())
1598         return false;
1599     if (!document->renderView()) 
1600         return false;
1601     
1602     HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::DisallowShadowContent);
1603     HitTestResult result(point);
1604     document->renderView()->hitTest(request, result);
1605     Node* innerNode = result.innerNode();
1606     if (!innerNode || !innerNode->renderer())
1607         return false;
1608     
1609     VisiblePosition visiblePos(innerNode->renderer()->positionForPoint(result.localPoint()));
1610     if (visiblePos.isNull())
1611         return false;
1612         
1613     if (m_selection.visibleStart().isNull() || m_selection.visibleEnd().isNull())
1614         return false;
1615         
1616     Position start(m_selection.visibleStart().deepEquivalent());
1617     Position end(m_selection.visibleEnd().deepEquivalent());
1618     Position p(visiblePos.deepEquivalent());
1619
1620     return comparePositions(start, p) <= 0 && comparePositions(p, end) <= 0;
1621 }
1622
1623 // Workaround for the fact that it's hard to delete a frame.
1624 // Call this after doing user-triggered selections to make it easy to delete the frame you entirely selected.
1625 // Can't do this implicitly as part of every setSelection call because in some contexts it might not be good
1626 // for the focus to move to another frame. So instead we call it from places where we are selecting with the
1627 // mouse or the keyboard after setting the selection.
1628 void FrameSelection::selectFrameElementInParentIfFullySelected()
1629 {
1630     // Find the parent frame; if there is none, then we have nothing to do.
1631     Frame* parent = m_frame->tree().parent();
1632     if (!parent)
1633         return;
1634     Page* page = m_frame->page();
1635     if (!page)
1636         return;
1637
1638     // Check if the selection contains the entire frame contents; if not, then there is nothing to do.
1639     if (!isRange())
1640         return;
1641     if (!isStartOfDocument(selection().visibleStart()))
1642         return;
1643     if (!isEndOfDocument(selection().visibleEnd()))
1644         return;
1645
1646     // Get to the <iframe> or <frame> (or even <object>) element in the parent frame.
1647     Element* ownerElement = m_frame->ownerElement();
1648     if (!ownerElement)
1649         return;
1650     ContainerNode* ownerElementParent = ownerElement->parentNode();
1651     if (!ownerElementParent)
1652         return;
1653         
1654     // 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.
1655     if (!ownerElementParent->hasEditableStyle())
1656         return;
1657
1658     // Create compute positions before and after the element.
1659     unsigned ownerElementNodeIndex = ownerElement->nodeIndex();
1660     VisiblePosition beforeOwnerElement(VisiblePosition(Position(ownerElementParent, ownerElementNodeIndex, Position::PositionIsOffsetInAnchor)));
1661     VisiblePosition afterOwnerElement(VisiblePosition(Position(ownerElementParent, ownerElementNodeIndex + 1, Position::PositionIsOffsetInAnchor), VP_UPSTREAM_IF_POSSIBLE));
1662
1663     // Focus on the parent frame, and then select from before this element to after.
1664     VisibleSelection newSelection(beforeOwnerElement, afterOwnerElement);
1665     if (parent->selection().shouldChangeSelection(newSelection)) {
1666         page->focusController().setFocusedFrame(parent);
1667         parent->selection().setSelection(newSelection);
1668     }
1669 }
1670
1671 void FrameSelection::selectAll()
1672 {
1673     Document* document = m_frame->document();
1674
1675     if (document->focusedElement() && document->focusedElement()->hasTagName(selectTag)) {
1676         HTMLSelectElement* selectElement = toHTMLSelectElement(document->focusedElement());
1677         if (selectElement->canSelectAll()) {
1678             selectElement->selectAll();
1679             return;
1680         }
1681     }
1682
1683     RefPtr<Node> root = 0;
1684     Node* selectStartTarget = 0;
1685     if (m_selection.isContentEditable()) {
1686         root = highestEditableRoot(m_selection.start());
1687         if (Node* shadowRoot = m_selection.nonBoundaryShadowTreeRootNode())
1688             selectStartTarget = shadowRoot->shadowHost();
1689         else
1690             selectStartTarget = root.get();
1691     } else {
1692         root = m_selection.nonBoundaryShadowTreeRootNode();
1693         if (root)
1694             selectStartTarget = root->shadowHost();
1695         else {
1696             root = document->documentElement();
1697             selectStartTarget = document->body();
1698         }
1699     }
1700     if (!root)
1701         return;
1702
1703     if (selectStartTarget && !selectStartTarget->dispatchEvent(Event::create(eventNames().selectstartEvent, true, true)))
1704         return;
1705
1706     VisibleSelection newSelection(VisibleSelection::selectionFromContentsOfNode(root.get()));
1707
1708     if (shouldChangeSelection(newSelection))
1709         setSelection(newSelection);
1710
1711     selectFrameElementInParentIfFullySelected();
1712     updateSelectionCachesIfSelectionIsInsideTextFormControl(UserTriggered);
1713 }
1714
1715 bool FrameSelection::setSelectedRange(Range* range, EAffinity affinity, bool closeTyping)
1716 {
1717     if (!range || !range->startContainer() || !range->endContainer())
1718         return false;
1719     ASSERT(&range->startContainer()->document() == &range->endContainer()->document());
1720
1721     m_frame->document()->updateLayoutIgnorePendingStylesheets();
1722
1723     // Non-collapsed ranges are not allowed to start at the end of a line that is wrapped,
1724     // they start at the beginning of the next line instead
1725     ExceptionCode ec = 0;
1726     bool collapsed = range->collapsed(ec);
1727     if (ec)
1728         return false;
1729
1730     // FIXME: Can we provide extentAffinity?
1731     VisiblePosition visibleStart(range->startPosition(), collapsed ? affinity : DOWNSTREAM);
1732     VisiblePosition visibleEnd(range->endPosition(), SEL_DEFAULT_AFFINITY);
1733 #if PLATFORM(IOS)
1734     if (range->startContainer() && visibleStart.isNull())
1735         return false;
1736     if (range->endContainer() && visibleEnd.isNull())
1737         return false;
1738 #endif
1739     setSelection(VisibleSelection(visibleStart, visibleEnd), ClearTypingStyle | (closeTyping ? CloseTyping : 0));
1740     return true;
1741 }
1742
1743 void FrameSelection::focusedOrActiveStateChanged()
1744 {
1745     bool activeAndFocused = isFocusedAndActive();
1746     Ref<Document> document(*m_frame->document());
1747
1748     document->updateStyleIfNeeded();
1749
1750 #if USE(UIKIT_EDITING)
1751     // Caret blinking (blinks | does not blink)
1752     if (activeAndFocused)
1753         setSelectionFromNone();
1754     setCaretVisible(activeAndFocused);
1755 #else
1756     // Because RenderObject::selectionBackgroundColor() and
1757     // RenderObject::selectionForegroundColor() check if the frame is active,
1758     // we have to update places those colors were painted.
1759     if (RenderView* view = document->renderView())
1760         view->repaintSelection();
1761
1762     // Caret appears in the active frame.
1763     if (activeAndFocused)
1764         setSelectionFromNone();
1765     setCaretVisibility(activeAndFocused ? Visible : Hidden);
1766
1767     // Update for caps lock state
1768     m_frame->eventHandler().capsLockStateMayHaveChanged();
1769
1770     // Because StyleResolver::checkOneSelector() and
1771     // RenderTheme::isFocused() check if the frame is active, we have to
1772     // update style and theme state that depended on those.
1773     if (Element* element = document->focusedElement()) {
1774         element->setNeedsStyleRecalc();
1775         if (RenderObject* renderer = element->renderer())
1776             if (renderer && renderer->style().hasAppearance())
1777                 renderer->theme().stateChanged(renderer, FocusState);
1778     }
1779 #endif
1780 }
1781
1782 void FrameSelection::pageActivationChanged()
1783 {
1784     focusedOrActiveStateChanged();
1785 }
1786
1787 void FrameSelection::setFocused(bool flag)
1788 {
1789     if (m_focused == flag)
1790         return;
1791     m_focused = flag;
1792
1793     focusedOrActiveStateChanged();
1794 }
1795
1796 bool FrameSelection::isFocusedAndActive() const
1797 {
1798     return m_focused && m_frame->page() && m_frame->page()->focusController().isActive();
1799 }
1800
1801 #if ENABLE(TEXT_CARET)
1802 inline static bool shouldStopBlinkingDueToTypingCommand(Frame* frame)
1803 {
1804     return frame->editor().lastEditCommand() && frame->editor().lastEditCommand()->shouldStopCaretBlinking();
1805 }
1806 #endif
1807
1808 void FrameSelection::updateAppearance()
1809 {
1810 #if PLATFORM(IOS)
1811     if (!m_updateAppearanceEnabled)
1812         return;
1813 #endif
1814
1815     // Paint a block cursor instead of a caret in overtype mode unless the caret is at the end of a line (in this case
1816     // the FrameSelection will paint a blinking caret as usual).
1817     VisibleSelection oldSelection = selection();
1818     VisiblePosition forwardPosition;
1819     if (m_shouldShowBlockCursor && oldSelection.isCaret()) {
1820         forwardPosition = modifyExtendingForward(CharacterGranularity);
1821         m_caretPaint = forwardPosition.isNull();
1822     }
1823
1824 #if ENABLE(TEXT_CARET)
1825     bool caretRectChangedOrCleared = recomputeCaretRect();
1826
1827     bool caretBrowsing = m_frame->settings().caretBrowsingEnabled();
1828     bool shouldBlink = caretIsVisible() && isCaret() && (oldSelection.isContentEditable() || caretBrowsing) && forwardPosition.isNull();
1829
1830     // If the caret moved, stop the blink timer so we can restart with a
1831     // black caret in the new location.
1832     if (caretRectChangedOrCleared || !shouldBlink || shouldStopBlinkingDueToTypingCommand(m_frame))
1833         m_caretBlinkTimer.stop();
1834
1835     // Start blinking with a black caret. Be sure not to restart if we're
1836     // already blinking in the right location.
1837     if (shouldBlink && !m_caretBlinkTimer.isActive()) {
1838         if (double blinkInterval = m_frame->page()->theme().caretBlinkInterval())
1839             m_caretBlinkTimer.startRepeating(blinkInterval);
1840
1841         if (!m_caretPaint) {
1842             m_caretPaint = true;
1843             invalidateCaretRect();
1844         }
1845     }
1846 #endif
1847
1848     RenderView* view = m_frame->contentRenderer();
1849     if (!view)
1850         return;
1851
1852     // Construct a new VisibleSolution, since m_selection is not necessarily valid, and the following steps
1853     // assume a valid selection. See <https://bugs.webkit.org/show_bug.cgi?id=69563> and <rdar://problem/10232866>.
1854     VisibleSelection selection(oldSelection.visibleStart(), forwardPosition.isNotNull() ? forwardPosition : oldSelection.visibleEnd());
1855
1856     if (!selection.isRange()) {
1857         view->clearSelection();
1858         return;
1859     }
1860
1861     // Use the rightmost candidate for the start of the selection, and the leftmost candidate for the end of the selection.
1862     // Example: foo <a>bar</a>.  Imagine that a line wrap occurs after 'foo', and that 'bar' is selected.   If we pass [foo, 3]
1863     // as the start of the selection, the selection painting code will think that content on the line containing 'foo' is selected
1864     // and will fill the gap before 'bar'.
1865     Position startPos = selection.start();
1866     Position candidate = startPos.downstream();
1867     if (candidate.isCandidate())
1868         startPos = candidate;
1869     Position endPos = selection.end();
1870     candidate = endPos.upstream();
1871     if (candidate.isCandidate())
1872         endPos = candidate;
1873
1874     // We can get into a state where the selection endpoints map to the same VisiblePosition when a selection is deleted
1875     // because we don't yet notify the FrameSelection of text removal.
1876     if (startPos.isNotNull() && endPos.isNotNull() && selection.visibleStart() != selection.visibleEnd()) {
1877         RenderObject* startRenderer = startPos.deprecatedNode()->renderer();
1878         RenderObject* endRenderer = endPos.deprecatedNode()->renderer();
1879         view->setSelection(startRenderer, startPos.deprecatedEditingOffset(), endRenderer, endPos.deprecatedEditingOffset());
1880     }
1881 }
1882
1883 void FrameSelection::setCaretVisibility(CaretVisibility visibility)
1884 {
1885     if (caretVisibility() == visibility)
1886         return;
1887
1888 #if ENABLE(TEXT_CARET)
1889     m_frame->document()->updateLayoutIgnorePendingStylesheets();
1890     if (m_caretPaint) {
1891         m_caretPaint = false;
1892         invalidateCaretRect();
1893     }
1894     CaretBase::setCaretVisibility(visibility);
1895 #else
1896     m_frame->document()->updateStyleIfNeeded();
1897 #endif
1898
1899     updateAppearance();
1900 }
1901
1902 void FrameSelection::caretBlinkTimerFired(Timer<FrameSelection>&)
1903 {
1904 #if ENABLE(TEXT_CARET)
1905     ASSERT(caretIsVisible());
1906     ASSERT(isCaret());
1907     bool caretPaint = m_caretPaint;
1908     if (isCaretBlinkingSuspended() && caretPaint)
1909         return;
1910     m_caretPaint = !caretPaint;
1911     invalidateCaretRect();
1912 #endif
1913 }
1914
1915 void FrameSelection::updateSelectionCachesIfSelectionIsInsideTextFormControl(EUserTriggered userTriggered)
1916 {
1917     if (HTMLTextFormControlElement* textControl = enclosingTextFormControl(m_selection.start()))
1918         textControl->selectionChanged(userTriggered == UserTriggered);
1919 }
1920
1921 // Helper function that tells whether a particular node is an element that has an entire
1922 // Frame and FrameView, a <frame>, <iframe>, or <object>.
1923 static bool isFrameElement(const Node* n)
1924 {
1925     if (!n)
1926         return false;
1927     RenderObject* renderer = n->renderer();
1928     if (!renderer || !renderer->isWidget())
1929         return false;
1930     Widget* widget = toRenderWidget(renderer)->widget();
1931     return widget && widget->isFrameView();
1932 }
1933
1934 void FrameSelection::setFocusedElementIfNeeded()
1935 {
1936     if (isNone() || !isFocused())
1937         return;
1938
1939     bool caretBrowsing = m_frame->settings().caretBrowsingEnabled();
1940     if (caretBrowsing) {
1941         if (Element* anchor = enclosingAnchorElement(m_selection.base())) {
1942             m_frame->page()->focusController().setFocusedElement(anchor, m_frame);
1943             return;
1944         }
1945     }
1946
1947     if (Element* target = m_selection.rootEditableElement()) {
1948         // Walk up the DOM tree to search for an element to focus.
1949         while (target) {
1950             // We don't want to set focus on a subframe when selecting in a parent frame,
1951             // so add the !isFrameElement check here. There's probably a better way to make this
1952             // work in the long term, but this is the safest fix at this time.
1953             if (target->isMouseFocusable() && !isFrameElement(target)) {
1954                 m_frame->page()->focusController().setFocusedElement(target, m_frame);
1955                 return;
1956             }
1957             target = target->parentOrShadowHostElement();
1958         }
1959         m_frame->document()->setFocusedElement(0);
1960     }
1961
1962     if (caretBrowsing)
1963         m_frame->page()->focusController().setFocusedElement(0, m_frame);
1964 }
1965
1966 void DragCaretController::paintDragCaret(Frame* frame, GraphicsContext* p, const LayoutPoint& paintOffset, const LayoutRect& clipRect) const
1967 {
1968 #if ENABLE(TEXT_CARET)
1969     if (m_position.deepEquivalent().deprecatedNode()->document().frame() == frame)
1970         paintCaret(m_position.deepEquivalent().deprecatedNode(), p, paintOffset, clipRect);
1971 #else
1972     UNUSED_PARAM(frame);
1973     UNUSED_PARAM(p);
1974     UNUSED_PARAM(paintOffset);
1975     UNUSED_PARAM(clipRect);
1976 #endif
1977 }
1978
1979 PassRefPtr<MutableStyleProperties> FrameSelection::copyTypingStyle() const
1980 {
1981     if (!m_typingStyle || !m_typingStyle->style())
1982         return 0;
1983     return m_typingStyle->style()->mutableCopy();
1984 }
1985
1986 bool FrameSelection::shouldDeleteSelection(const VisibleSelection& selection) const
1987 {
1988 #if PLATFORM(IOS)
1989     if (m_frame->selectionChangeCallbacksDisabled())
1990         return true;
1991 #endif
1992     return m_frame->editor().client()->shouldDeleteRange(selection.toNormalizedRange().get());
1993 }
1994
1995 FloatRect FrameSelection::bounds(bool clipToVisibleContent) const
1996 {
1997     if (!m_frame->document())
1998         return LayoutRect();
1999
2000     m_frame->document()->updateStyleIfNeeded();
2001     RenderView* root = m_frame->contentRenderer();
2002     FrameView* view = m_frame->view();
2003     if (!root || !view)
2004         return LayoutRect();
2005
2006     LayoutRect selectionRect = root->selectionBounds(clipToVisibleContent);
2007     return clipToVisibleContent ? intersection(selectionRect, view->visibleContentRect(ScrollableArea::LegacyIOSDocumentVisibleRect)) : selectionRect;
2008 }
2009
2010 void FrameSelection::getClippedVisibleTextRectangles(Vector<FloatRect>& rectangles) const
2011 {
2012     RenderView* root = m_frame->contentRenderer();
2013     if (!root)
2014         return;
2015
2016     FloatRect visibleContentRect = m_frame->view()->visibleContentRect(ScrollableArea::LegacyIOSDocumentVisibleRect);
2017
2018     Vector<FloatQuad> quads;
2019     toNormalizedRange()->textQuads(quads, true);
2020
2021     size_t size = quads.size();
2022     for (size_t i = 0; i < size; ++i) {
2023         FloatRect intersectionRect = intersection(quads[i].enclosingBoundingBox(), visibleContentRect);
2024         if (!intersectionRect.isEmpty())
2025             rectangles.append(intersectionRect);
2026     }
2027 }
2028
2029 // Scans logically forward from "start", including any child frames.
2030 static HTMLFormElement* scanForForm(Element* start)
2031 {
2032     if (!start)
2033         return nullptr;
2034
2035     auto descendants = descendantsOfType<HTMLElement>(start->document());
2036     for (auto it = descendants.from(*start), end = descendants.end(); it != end; ++it) {
2037         HTMLElement& element = *it;
2038         if (isHTMLFormElement(&element))
2039             return toHTMLFormElement(&element);
2040         if (isHTMLFormControlElement(element))
2041             return toHTMLFormControlElement(element).form();
2042         if (isHTMLFrameElementBase(element)) {
2043             Document* contentDocument = toHTMLFrameElementBase(element).contentDocument();
2044             if (!contentDocument)
2045                 continue;
2046             if (HTMLFormElement* frameResult = scanForForm(contentDocument->documentElement()))
2047                 return frameResult;
2048         }
2049     }
2050     return nullptr;
2051 }
2052
2053 // We look for either the form containing the current focus, or for one immediately after it
2054 HTMLFormElement* FrameSelection::currentForm() const
2055 {
2056     // Start looking either at the active (first responder) node, or where the selection is.
2057     Element* start = m_frame->document()->focusedElement();
2058     if (!start)
2059         start = m_selection.start().element();
2060     if (!start)
2061         return nullptr;
2062
2063     if (auto form = lineageOfType<HTMLFormElement>(*start).first())
2064         return form;
2065     if (auto formControl = lineageOfType<HTMLFormControlElement>(*start).first())
2066         return formControl->form();
2067
2068     // Try walking forward in the node tree to find a form element.
2069     return scanForForm(start);
2070 }
2071
2072 void FrameSelection::revealSelection(const ScrollAlignment& alignment, RevealExtentOption revealExtentOption)
2073 {
2074     LayoutRect rect;
2075
2076     switch (m_selection.selectionType()) {
2077     case VisibleSelection::NoSelection:
2078         return;
2079     case VisibleSelection::CaretSelection:
2080         rect = absoluteCaretBounds();
2081         break;
2082     case VisibleSelection::RangeSelection:
2083         rect = revealExtentOption == RevealExtent ? VisiblePosition(m_selection.extent()).absoluteCaretBounds() : enclosingIntRect(bounds(false));
2084         break;
2085     }
2086
2087     Position start = m_selection.start();
2088     ASSERT(start.deprecatedNode());
2089     if (start.deprecatedNode() && start.deprecatedNode()->renderer()) {
2090 #if PLATFORM(IOS)
2091         if (RenderLayer* layer = start.deprecatedNode()->renderer()->enclosingLayer()) {
2092             if (!m_scrollingSuppressCount) {
2093                 layer->setAdjustForIOSCaretWhenScrolling(true);
2094                 layer->scrollRectToVisible(rect, alignment, alignment);
2095                 layer->setAdjustForIOSCaretWhenScrolling(false);
2096                 updateAppearance();
2097                 if (m_frame->page())
2098                     m_frame->page()->chrome().client().notifyRevealedSelectionByScrollingFrame(m_frame);
2099             }
2100         }
2101 #else
2102         // FIXME: This code only handles scrolling the startContainer's layer, but
2103         // the selection rect could intersect more than just that.
2104         // See <rdar://problem/4799899>.
2105         if (start.deprecatedNode()->renderer()->scrollRectToVisible(rect, alignment, alignment))
2106             updateAppearance();
2107 #endif
2108     }
2109 }
2110
2111 void FrameSelection::setSelectionFromNone()
2112 {
2113     // Put a caret inside the body if the entire frame is editable (either the
2114     // entire WebView is editable or designMode is on for this document).
2115
2116     Document* document = m_frame->document();
2117 #if !PLATFORM(IOS)
2118     bool caretBrowsing = m_frame->settings().caretBrowsingEnabled();
2119     if (!isNone() || !(document->hasEditableStyle() || caretBrowsing))
2120         return;
2121 #else
2122     if (!document || !(isNone() || isStartOfDocument(VisiblePosition(m_selection.start(), m_selection.affinity()))) || !document->hasEditableStyle())
2123         return;
2124 #endif
2125
2126     Node* node = document->documentElement();
2127     while (node && !node->hasTagName(bodyTag))
2128         node = NodeTraversal::next(node);
2129     if (node)
2130         setSelection(VisibleSelection(firstPositionInOrBeforeNode(node), DOWNSTREAM));
2131 }
2132
2133 bool FrameSelection::shouldChangeSelection(const VisibleSelection& newSelection) const
2134 {
2135 #if PLATFORM(IOS)
2136     if (m_frame->selectionChangeCallbacksDisabled())
2137         return true;
2138 #endif
2139     return m_frame->editor().shouldChangeSelection(selection(), newSelection, newSelection.affinity(), false);
2140 }
2141
2142 bool FrameSelection::dispatchSelectStart()
2143 {
2144     Node* selectStartTarget = m_selection.extent().containerNode();
2145     if (!selectStartTarget)
2146         return true;
2147
2148     return selectStartTarget->dispatchEvent(Event::create(eventNames().selectstartEvent, true, true));
2149 }
2150
2151 void FrameSelection::setShouldShowBlockCursor(bool shouldShowBlockCursor)
2152 {
2153     m_shouldShowBlockCursor = shouldShowBlockCursor;
2154
2155     m_frame->document()->updateLayoutIgnorePendingStylesheets();
2156
2157     updateAppearance();
2158 }
2159
2160 #ifndef NDEBUG
2161
2162 void FrameSelection::formatForDebugger(char* buffer, unsigned length) const
2163 {
2164     m_selection.formatForDebugger(buffer, length);
2165 }
2166
2167 void FrameSelection::showTreeForThis() const
2168 {
2169     m_selection.showTreeForThis();
2170 }
2171
2172 #endif
2173
2174 #if PLATFORM(IOS)
2175 void FrameSelection::expandSelectionToElementContainingCaretSelection()
2176 {
2177     RefPtr<Range> range = elementRangeContainingCaretSelection();
2178     if (!range)
2179         return;
2180     VisibleSelection selection(range.get(), DOWNSTREAM);
2181     setSelection(selection);
2182 }
2183
2184 PassRefPtr<Range> FrameSelection::elementRangeContainingCaretSelection() const
2185 {
2186     if (m_selection.isNone())
2187         return nullptr;
2188
2189     VisibleSelection selection = m_selection;
2190     if (selection.isNone())
2191         return nullptr;
2192
2193     VisiblePosition visiblePos(selection.start(), VP_DEFAULT_AFFINITY);
2194     if (visiblePos.isNull())
2195         return nullptr;
2196
2197     Node* node = visiblePos.deepEquivalent().deprecatedNode();
2198     Element* element = deprecatedEnclosingBlockFlowElement(node);
2199     if (!element)
2200         return nullptr;
2201
2202     Position startPos = createLegacyEditingPosition(element, 0);
2203     Position endPos = createLegacyEditingPosition(element, element->childNodeCount());
2204     
2205     VisiblePosition startVisiblePos(startPos, VP_DEFAULT_AFFINITY);
2206     VisiblePosition endVisiblePos(endPos, VP_DEFAULT_AFFINITY);
2207     if (startVisiblePos.isNull() || endVisiblePos.isNull())
2208         return nullptr;
2209
2210     selection.setBase(startVisiblePos);
2211     selection.setExtent(endVisiblePos);
2212
2213     return selection.toNormalizedRange();
2214 }
2215
2216 void FrameSelection::expandSelectionToWordContainingCaretSelection()
2217 {
2218     VisibleSelection selection(wordSelectionContainingCaretSelection(m_selection));        
2219     if (selection.isCaretOrRange())
2220         setSelection(selection);
2221 }
2222
2223 PassRefPtr<Range> FrameSelection::wordRangeContainingCaretSelection()
2224 {
2225     return wordSelectionContainingCaretSelection(m_selection).toNormalizedRange();
2226 }
2227
2228 void FrameSelection::expandSelectionToStartOfWordContainingCaretSelection()
2229 {
2230     if (m_selection.isNone() || isStartOfDocument(m_selection.start()))
2231         return;
2232
2233     VisiblePosition s1(m_selection.start());
2234     VisiblePosition e1(m_selection.end());
2235
2236     VisibleSelection expanded(wordSelectionContainingCaretSelection(m_selection));
2237     VisiblePosition s2(expanded.start());
2238
2239     // Don't allow the start to become greater after the expansion.
2240     if (s2.isNull() || s2 > s1)
2241         s2 = s1;
2242
2243     moveTo(s2, e1);
2244 }
2245
2246 UChar FrameSelection::characterInRelationToCaretSelection(int amount) const
2247 {
2248     if (m_selection.isNone())
2249         return 0;
2250
2251     VisibleSelection selection = m_selection;
2252     ASSERT(selection.isCaretOrRange());
2253
2254     VisiblePosition visiblePosition(selection.start(), VP_DEFAULT_AFFINITY);
2255
2256     if (amount < 0) {
2257         int count = abs(amount);
2258         for (int i = 0; i < count; i++)
2259             visiblePosition = visiblePosition.previous();    
2260         return visiblePosition.characterBefore();
2261     }
2262     for (int i = 0; i < amount; i++)
2263         visiblePosition = visiblePosition.next();    
2264     return visiblePosition.characterAfter();
2265 }
2266
2267 UChar FrameSelection::characterBeforeCaretSelection() const
2268 {
2269     if (m_selection.isNone())
2270         return 0;
2271
2272     VisibleSelection selection = m_selection;
2273     ASSERT(selection.isCaretOrRange());
2274
2275     VisiblePosition visiblePosition(selection.start(), VP_DEFAULT_AFFINITY);
2276     return visiblePosition.characterBefore();
2277 }
2278
2279 UChar FrameSelection::characterAfterCaretSelection() const
2280 {
2281     if (m_selection.isNone())
2282         return 0;
2283
2284     VisibleSelection selection = m_selection;
2285     ASSERT(selection.isCaretOrRange());
2286
2287     VisiblePosition visiblePosition(selection.end(), VP_DEFAULT_AFFINITY);
2288     return visiblePosition.characterAfter();
2289 }
2290
2291 int FrameSelection::wordOffsetInRange(const Range *range) const
2292 {
2293     if (!range)
2294         return -1;
2295
2296     VisibleSelection selection = m_selection;
2297     if (!selection.isCaret())
2298         return -1;
2299
2300     // FIXME: This will only work in cases where the selection remains in
2301     // the same node after it is expanded. Improve to handle more complicated
2302     // cases.
2303     ExceptionCode ec = 0;
2304     int result = selection.start().deprecatedEditingOffset() - range->startOffset(ec);
2305     ASSERT(!ec);
2306     if (result < 0)
2307         result = 0;
2308     return result;
2309 }
2310
2311 bool FrameSelection::spaceFollowsWordInRange(const Range *range) const
2312 {
2313     if (!range)
2314         return false;
2315     ExceptionCode ec = 0;
2316     Node* node = range->endContainer(ec);
2317     ASSERT(!ec);
2318     int endOffset = range->endOffset(ec);
2319     ASSERT(!ec);
2320     VisiblePosition pos(createLegacyEditingPosition(node, endOffset), VP_DEFAULT_AFFINITY);
2321     return isSpaceOrNewline(pos.characterAfter());
2322 }
2323
2324 bool FrameSelection::selectionAtDocumentStart() const
2325 {
2326     VisibleSelection selection = m_selection;
2327     if (selection.isNone())
2328         return false;
2329
2330     Position startPos(selection.start());
2331     VisiblePosition pos(createLegacyEditingPosition(startPos.deprecatedNode(), startPos.deprecatedEditingOffset()), VP_DEFAULT_AFFINITY);
2332     if (pos.isNull())
2333         return false;
2334
2335     return isStartOfDocument(pos);
2336 }
2337
2338 bool FrameSelection::selectionAtSentenceStart() const
2339 {
2340     VisibleSelection selection = m_selection;
2341     if (selection.isNone())
2342         return false;
2343
2344     return actualSelectionAtSentenceStart(selection);
2345 }
2346
2347 bool FrameSelection::selectionAtWordStart() const
2348 {
2349     VisibleSelection selection = m_selection;
2350     if (selection.isNone())
2351         return false;
2352
2353     Position startPos(selection.start());
2354     VisiblePosition pos(createLegacyEditingPosition(startPos.deprecatedNode(), startPos.deprecatedEditingOffset()), VP_DEFAULT_AFFINITY);
2355     if (pos.isNull())
2356         return false;
2357
2358     if (isStartOfParagraph(pos))
2359         return true;
2360         
2361     bool result = true;
2362     unsigned previousCount = 0;
2363     for (pos = pos.previous(); !pos.isNull(); pos = pos.previous()) {
2364         previousCount++;
2365         if (isStartOfParagraph(pos)) {
2366             if (previousCount == 1)
2367                 result = false;
2368             break;
2369         }
2370         UChar c(pos.characterAfter());
2371         if (c) {
2372             result = isSpaceOrNewline(c) || c == 0xA0 || (u_ispunct(c) && c != ',' && c != '-' && c != '\'');
2373             break;
2374         }
2375     }
2376
2377     return result;
2378 }
2379
2380 PassRefPtr<Range> FrameSelection::rangeByMovingCurrentSelection(int amount) const
2381 {
2382     return rangeByAlteringCurrentSelection(AlterationMove, amount);
2383 }
2384
2385 PassRefPtr<Range> FrameSelection::rangeByExtendingCurrentSelection(int amount) const
2386 {
2387     return rangeByAlteringCurrentSelection(AlterationExtend, amount);
2388 }
2389
2390 void FrameSelection::selectRangeOnElement(unsigned location, unsigned length, Node* node)
2391 {
2392     RefPtr<Range> resultRange = m_frame->document()->createRange();
2393     ExceptionCode ec = 0;
2394     resultRange->setStart(node, location, ec);
2395     ASSERT(!ec);
2396     resultRange->setEnd(node, location + length, ec);
2397     ASSERT(!ec);
2398     VisibleSelection selection = VisibleSelection(resultRange.get(), SEL_DEFAULT_AFFINITY);
2399     setSelection(selection, true);
2400 }
2401
2402 VisibleSelection FrameSelection::wordSelectionContainingCaretSelection(const VisibleSelection& selection)
2403 {
2404     if (selection.isNone())
2405         return VisibleSelection();
2406
2407     ASSERT(selection.isCaretOrRange());
2408     FrameSelection frameSelection;
2409     frameSelection.setSelection(selection);
2410
2411     Position startPosBeforeExpansion(selection.start());
2412     Position endPosBeforeExpansion(selection.end());
2413     VisiblePosition startVisiblePosBeforeExpansion(startPosBeforeExpansion, VP_DEFAULT_AFFINITY);
2414     VisiblePosition endVisiblePosBeforeExpansion(endPosBeforeExpansion, VP_DEFAULT_AFFINITY);
2415     if (endVisiblePosBeforeExpansion.isNull())
2416         return VisibleSelection();
2417
2418     if (isEndOfParagraph(endVisiblePosBeforeExpansion)) {
2419         UChar c(endVisiblePosBeforeExpansion.characterBefore());
2420         if (isSpaceOrNewline(c) || c == 0xA0) {
2421             // End of paragraph with space.
2422             return VisibleSelection();
2423         }
2424     }
2425
2426     // If at end of paragraph, move backwards one character.
2427     // This has the effect of selecting the word on the line (which is
2428     // what we want, rather than selecting past the end of the line).
2429     if (isEndOfParagraph(endVisiblePosBeforeExpansion) && !isStartOfParagraph(endVisiblePosBeforeExpansion))
2430         frameSelection.modify(FrameSelection::AlterationMove, DirectionBackward, CharacterGranularity);
2431
2432     VisibleSelection newSelection = frameSelection.selection();
2433     newSelection.expandUsingGranularity(WordGranularity);
2434     frameSelection.setSelection(newSelection, CloseTyping | ClearTypingStyle, AlignCursorOnScrollIfNeeded, frameSelection.granularity());
2435
2436     Position startPos(frameSelection.selection().start());
2437     Position endPos(frameSelection.selection().end());
2438
2439     // Expansion cannot be allowed to change selection so that it is no longer
2440     // touches (or contains) the original, unexpanded selection.
2441     // Enforce this on the way into these additional calculations to give them
2442     // the best chance to yield a suitable answer.
2443     if (startPos > startPosBeforeExpansion)
2444         startPos = startPosBeforeExpansion;
2445     if (endPos < endPosBeforeExpansion)
2446         endPos = endPosBeforeExpansion;
2447
2448     VisiblePosition startVisiblePos(startPos, VP_DEFAULT_AFFINITY);
2449     VisiblePosition endVisiblePos(endPos, VP_DEFAULT_AFFINITY);
2450
2451     if (startVisiblePos.isNull() || endVisiblePos.isNull()) {
2452         // Start or end is nil
2453         return VisibleSelection();
2454     }
2455
2456     if (isEndOfLine(endVisiblePosBeforeExpansion)) {
2457         VisiblePosition previous(endVisiblePos.previous());
2458         if (previous == endVisiblePos) {
2459             // Empty document
2460             return VisibleSelection();
2461         }
2462         UChar c(previous.characterAfter());
2463         if (isSpaceOrNewline(c) || c == 0xA0) {
2464             // Space at end of line
2465             return VisibleSelection();
2466         }
2467     }
2468
2469     // Expansion has selected past end of line.
2470     // Try repositioning backwards.
2471     if (isEndOfLine(startVisiblePos) && isStartOfLine(endVisiblePos)) {
2472         VisiblePosition previous(startVisiblePos.previous());
2473         if (isEndOfLine(previous)) {
2474             // On empty line
2475             return VisibleSelection();
2476         }
2477         UChar c(previous.characterAfter());
2478         if (isSpaceOrNewline(c) || c == 0xA0) {
2479             // Space at end of line
2480             return VisibleSelection();
2481         }
2482         frameSelection.moveTo(startVisiblePos);
2483         frameSelection.modify(FrameSelection::AlterationExtend, DirectionBackward, WordGranularity);
2484         startPos = frameSelection.selection().start();
2485         endPos = frameSelection.selection().end();
2486         startVisiblePos = VisiblePosition(startPos, VP_DEFAULT_AFFINITY);
2487         endVisiblePos = VisiblePosition(endPos, VP_DEFAULT_AFFINITY);
2488         if (startVisiblePos.isNull() || endVisiblePos.isNull()) {
2489             // Start or end is nil
2490             return VisibleSelection();
2491         }
2492     }
2493
2494     // Now loop backwards until we find a non-space.
2495     while (endVisiblePos != startVisiblePos) {
2496         VisiblePosition previous(endVisiblePos.previous());
2497         UChar c(previous.characterAfter());
2498         if (!isSpaceOrNewline(c) && c != 0xA0)
2499             break;
2500         endVisiblePos = previous;
2501     }
2502
2503     // Expansion cannot be allowed to change selection so that it is no longer
2504     // touches (or contains) the original, unexpanded selection.
2505     // Enforce this on the way out of the function to preserve the invariant.
2506     if (startVisiblePos > startVisiblePosBeforeExpansion)
2507         startVisiblePos = startVisiblePosBeforeExpansion;
2508     if (endVisiblePos < endVisiblePosBeforeExpansion)
2509         endVisiblePos = endVisiblePosBeforeExpansion;
2510
2511     return VisibleSelection(startVisiblePos, endVisiblePos);    
2512 }
2513
2514 bool FrameSelection::actualSelectionAtSentenceStart(const VisibleSelection& sel) const
2515 {
2516     Position startPos(sel.start());
2517     VisiblePosition pos(createLegacyEditingPosition(startPos.deprecatedNode(), startPos.deprecatedEditingOffset()), VP_DEFAULT_AFFINITY);
2518     if (pos.isNull())
2519         return false;
2520
2521     if (isStartOfParagraph(pos))
2522         return true;
2523  
2524     bool result = true;
2525     bool sawSpace = false;
2526     unsigned previousCount = 0;
2527     for (pos = pos.previous(); !pos.isNull(); pos = pos.previous()) {
2528         previousCount++;
2529         if (isStartOfParagraph(pos)) {
2530             if (previousCount == 1 || (previousCount == 2 && sawSpace))
2531                 result = false;
2532             break;
2533         }
2534         UChar c(pos.characterAfter());
2535         if (c) {
2536             if (isSpaceOrNewline(c) || c == 0xA0) {
2537                 sawSpace = true;
2538             }
2539             else {
2540                 result = (c == '.' || c == '!' || c == '?');
2541                 break;
2542             }
2543         }
2544     }
2545     
2546     return result;
2547 }
2548
2549 PassRefPtr<Range> FrameSelection::rangeByAlteringCurrentSelection(EAlteration alteration, int amount) const
2550 {
2551     if (m_selection.isNone())
2552         return nullptr;
2553
2554     if (!amount)
2555         return toNormalizedRange();
2556
2557     FrameSelection frameSelection;
2558     frameSelection.setSelection(m_selection);
2559     SelectionDirection direction = amount > 0 ? DirectionForward : DirectionBackward;
2560     for (int i = 0; i < abs(amount); i++)
2561         frameSelection.modify(alteration, direction, CharacterGranularity);
2562     return frameSelection.toNormalizedRange();
2563 }
2564
2565 void FrameSelection::clearCurrentSelection()
2566 {
2567     setSelection(VisibleSelection());
2568 }
2569
2570 void FrameSelection::setCaretBlinks(bool caretBlinks)
2571 {
2572     if (m_caretBlinks == caretBlinks)
2573         return;
2574 #if ENABLE(TEXT_CARET)
2575     m_frame->document()->updateLayoutIgnorePendingStylesheets(); 
2576     if (m_caretPaint) {
2577         m_caretPaint = false; 
2578         invalidateCaretRect(); 
2579     }
2580 #endif
2581     if (caretBlinks)
2582         setFocusedElementIfNeeded();
2583     m_caretBlinks = caretBlinks;
2584     updateAppearance();
2585 }
2586
2587 void FrameSelection::setCaretColor(const Color& caretColor)
2588 {
2589     if (m_caretColor != caretColor) {
2590         m_caretColor = caretColor;
2591         if (caretIsVisible() && m_caretBlinks && isCaret())
2592             invalidateCaretRect();
2593     }
2594 }
2595 #endif // PLATFORM(IOS)
2596
2597 }
2598
2599 #ifndef NDEBUG
2600
2601 void showTree(const WebCore::FrameSelection& sel)
2602 {
2603     sel.showTreeForThis();
2604 }
2605
2606 void showTree(const WebCore::FrameSelection* sel)
2607 {
2608     if (sel)
2609         sel->showTreeForThis();
2610 }
2611
2612 #endif