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