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