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