2009-01-23 David Hyatt <hyatt@apple.com>
[WebKit-https.git] / WebCore / editing / SelectionController.cpp
1 /*
2  * Copyright (C) 2004, 2008 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 "SelectionController.h"
28
29 #include "CString.h"
30 #include "DeleteSelectionCommand.h"
31 #include "Document.h"
32 #include "Editor.h"
33 #include "Element.h"
34 #include "EventHandler.h"
35 #include "EventNames.h"
36 #include "ExceptionCode.h"
37 #include "FocusController.h"
38 #include "Frame.h"
39 #include "FrameTree.h"
40 #include "FrameView.h"
41 #include "GraphicsContext.h"
42 #include "HTMLInputElement.h"
43 #include "HTMLNames.h"
44 #include "HitTestRequest.h"
45 #include "HitTestResult.h"
46 #include "Page.h"
47 #include "Range.h"
48 #include "RenderTheme.h"
49 #include "RenderView.h"
50 #include "TextIterator.h"
51 #include "TypingCommand.h"
52 #include "htmlediting.h"
53 #include "visible_units.h"
54 #include <stdio.h>
55
56 #define EDIT_DEBUG 0
57
58 namespace WebCore {
59
60 using namespace HTMLNames;
61
62 const int NoXPosForVerticalArrowNavigation = INT_MIN;
63
64 SelectionController::SelectionController(Frame* frame, bool isDragCaretController)
65     : m_frame(frame)
66     , m_xPosForVerticalArrowNavigation(NoXPosForVerticalArrowNavigation)
67     , m_needsLayout(true)
68     , m_absCaretBoundsDirty(true)
69     , m_lastChangeWasHorizontalExtension(false)
70     , m_isDragCaretController(isDragCaretController)
71     , m_isCaretBlinkingSuspended(false)
72     , m_focused(false)
73 {
74 }
75
76 void SelectionController::moveTo(const VisiblePosition &pos, bool userTriggered)
77 {
78     setSelection(Selection(pos.deepEquivalent(), pos.deepEquivalent(), pos.affinity()), true, true, userTriggered);
79 }
80
81 void SelectionController::moveTo(const VisiblePosition &base, const VisiblePosition &extent, bool userTriggered)
82 {
83     setSelection(Selection(base.deepEquivalent(), extent.deepEquivalent(), base.affinity()), true, true, userTriggered);
84 }
85
86 void SelectionController::moveTo(const Position &pos, EAffinity affinity, bool userTriggered)
87 {
88     setSelection(Selection(pos, affinity), true, true, userTriggered);
89 }
90
91 void SelectionController::moveTo(const Range *r, EAffinity affinity, bool userTriggered)
92 {
93     setSelection(Selection(startPosition(r), endPosition(r), affinity), true, true, userTriggered);
94 }
95
96 void SelectionController::moveTo(const Position &base, const Position &extent, EAffinity affinity, bool userTriggered)
97 {
98     setSelection(Selection(base, extent, affinity), true, true, userTriggered);
99 }
100
101 void SelectionController::setSelection(const Selection& s, bool closeTyping, bool clearTypingStyle, bool userTriggered)
102 {
103     if (m_isDragCaretController) {
104         invalidateCaretRect();
105         m_sel = s;
106         m_needsLayout = true;
107         invalidateCaretRect();
108         return;
109     }
110     if (!m_frame) {
111         m_sel = s;
112         return;
113     }
114
115     Node* baseNode = s.base().node();
116     Document* document = 0;
117     if (baseNode)
118         document = baseNode->document();
119     
120     // <http://bugs.webkit.org/show_bug.cgi?id=23464>: Infinite recursion at SelectionController::setSelection
121     // if document->frame() == m_frame we can get into an infinite loop
122     if (document && document->frame() != m_frame && document != m_frame->document()) {
123         document->frame()->selection()->setSelection(s, closeTyping, clearTypingStyle, userTriggered);
124         return;
125     }
126     
127     if (closeTyping)
128         TypingCommand::closeTyping(m_frame->editor()->lastEditCommand());
129
130     if (clearTypingStyle)
131         m_frame->clearTypingStyle();
132         
133     if (m_sel == s)
134         return;
135     
136     Selection oldSelection = m_sel;
137
138     m_sel = s;
139     
140     m_needsLayout = true;
141     
142     if (!s.isNone())
143         m_frame->setFocusedNodeIfNeeded();
144     
145     m_frame->selectionLayoutChanged();
146     // Always clear the x position used for vertical arrow navigation.
147     // It will be restored by the vertical arrow navigation code if necessary.
148     m_xPosForVerticalArrowNavigation = NoXPosForVerticalArrowNavigation;
149     selectFrameElementInParentIfFullySelected();
150     m_frame->notifyRendererOfSelectionChange(userTriggered);
151     m_frame->respondToChangedSelection(oldSelection, closeTyping);
152     if (userTriggered)
153         m_frame->revealCaret(RenderLayer::gAlignToEdgeIfNeeded);
154
155     notifyAccessibilityForSelectionChange();
156 }
157
158 static bool removingNodeRemovesPosition(Node* node, const Position& position)
159 {
160     if (!position.node())
161         return false;
162         
163     if (position.node() == node)
164         return true;
165     
166     if (!node->isElementNode())
167         return false;
168     
169     Element* element = static_cast<Element*>(node);
170     return element->contains(position.node()) || element->contains(position.node()->shadowAncestorNode());
171 }
172
173 void SelectionController::nodeWillBeRemoved(Node *node)
174 {
175     if (isNone())
176         return;
177         
178     // There can't be a selection inside a fragment, so if a fragment's node is being removed,
179     // the selection in the document that created the fragment needs no adjustment.
180     if (node && highestAncestor(node)->nodeType() == Node::DOCUMENT_FRAGMENT_NODE)
181         return;
182     
183     bool baseRemoved = removingNodeRemovesPosition(node, m_sel.base());
184     bool extentRemoved = removingNodeRemovesPosition(node, m_sel.extent());
185     bool startRemoved = removingNodeRemovesPosition(node, m_sel.start());
186     bool endRemoved = removingNodeRemovesPosition(node, m_sel.end());
187     
188     bool clearRenderTreeSelection = false;
189     bool clearDOMTreeSelection = false;
190
191     if (startRemoved || endRemoved) {
192         // FIXME: When endpoints are removed, we should just alter the selection, instead of blowing it away.
193         clearRenderTreeSelection = true;
194         clearDOMTreeSelection = true;
195     } else if (baseRemoved || extentRemoved) {
196         // The base and/or extent are about to be removed, but the start and end aren't.
197         // Change the base and extent to the start and end, but don't re-validate the
198         // selection, since doing so could move the start and end into the node
199         // that is about to be removed.
200         if (m_sel.isBaseFirst())
201             m_sel.setWithoutValidation(m_sel.start(), m_sel.end());
202         else
203             m_sel.setWithoutValidation(m_sel.end(), m_sel.start());
204     // FIXME: This could be more efficient if we had an isNodeInRange function on Ranges.
205     } else if (Range::compareBoundaryPoints(m_sel.start(), Position(node, 0)) == -1 &&
206                Range::compareBoundaryPoints(m_sel.end(), Position(node, 0)) == 1) {
207         // If we did nothing here, when this node's renderer was destroyed, the rect that it 
208         // occupied would be invalidated, but, selection gaps that change as a result of 
209         // the removal wouldn't be invalidated.
210         // FIXME: Don't do so much unnecessary invalidation.
211         clearRenderTreeSelection = true;
212     }
213
214     if (clearRenderTreeSelection) {
215         RefPtr<Document> document = m_sel.start().node()->document();
216         document->updateRendering();
217         if (RenderView* view = static_cast<RenderView*>(document->renderer()))
218             view->clearSelection();
219     }
220
221     if (clearDOMTreeSelection)
222         setSelection(Selection(), false, false);
223 }
224
225 void SelectionController::willBeModified(EAlteration alter, EDirection direction)
226 {
227     switch (alter) {
228         case MOVE:
229             m_lastChangeWasHorizontalExtension = false;
230             break;
231         case EXTEND:
232             if (!m_lastChangeWasHorizontalExtension) {
233                 m_lastChangeWasHorizontalExtension = true;
234                 Position start = m_sel.start();
235                 Position end = m_sel.end();
236                 switch (direction) {
237                     // FIXME: right for bidi?
238                     case RIGHT:
239                     case FORWARD:
240                         m_sel.setBase(start);
241                         m_sel.setExtent(end);
242                         break;
243                     case LEFT:
244                     case BACKWARD:
245                         m_sel.setBase(end);
246                         m_sel.setExtent(start);
247                         break;
248                 }
249             }
250             break;
251     }
252 }
253
254 VisiblePosition SelectionController::modifyExtendingRightForward(TextGranularity granularity)
255 {
256     VisiblePosition pos(m_sel.extent(), m_sel.affinity());
257     switch (granularity) {
258         case CharacterGranularity:
259             pos = pos.next(true);
260             break;
261         case WordGranularity:
262             pos = nextWordPosition(pos);
263             break;
264         case SentenceGranularity:
265             pos = nextSentencePosition(pos);
266             break;
267         case LineGranularity:
268             pos = nextLinePosition(pos, xPosForVerticalArrowNavigation(EXTENT));
269             break;
270         case ParagraphGranularity:
271             pos = nextParagraphPosition(pos, xPosForVerticalArrowNavigation(EXTENT));
272             break;
273         case SentenceBoundary:
274             pos = endOfSentence(VisiblePosition(m_sel.end(), m_sel.affinity()));
275             break;
276         case LineBoundary:
277             pos = endOfLine(VisiblePosition(m_sel.end(), m_sel.affinity()));
278             break;
279         case ParagraphBoundary:
280             pos = endOfParagraph(VisiblePosition(m_sel.end(), m_sel.affinity()));
281             break;
282         case DocumentBoundary:
283             pos = VisiblePosition(m_sel.end(), m_sel.affinity());
284             if (isEditablePosition(pos.deepEquivalent()))
285                 pos = endOfEditableContent(pos);
286             else
287                 pos = endOfDocument(pos);
288             break;
289     }
290     
291     return pos;
292 }
293
294 VisiblePosition SelectionController::modifyMovingRight(TextGranularity granularity)
295 {
296     VisiblePosition pos;
297     switch (granularity) {
298         case CharacterGranularity:
299             if (isRange()) 
300                 pos = VisiblePosition(m_sel.end(), m_sel.affinity());
301             else
302                 pos = VisiblePosition(m_sel.extent(), m_sel.affinity()).right(true);
303             break;
304         case WordGranularity:
305         case SentenceGranularity:
306         case LineGranularity:
307         case ParagraphGranularity:
308         case SentenceBoundary:
309         case LineBoundary:
310         case ParagraphBoundary:
311         case DocumentBoundary:
312             // FIXME: Implement all of the above.
313             pos = modifyMovingForward(granularity);
314             break;
315     }
316     return pos;
317 }
318
319 VisiblePosition SelectionController::modifyMovingForward(TextGranularity granularity)
320 {
321     VisiblePosition pos;
322     // FIXME: Stay in editable content for the less common granularities.
323     switch (granularity) {
324         case CharacterGranularity:
325             if (isRange()) 
326                 pos = VisiblePosition(m_sel.end(), m_sel.affinity());
327             else
328                 pos = VisiblePosition(m_sel.extent(), m_sel.affinity()).next(true);
329             break;
330         case WordGranularity:
331             pos = nextWordPosition(VisiblePosition(m_sel.extent(), m_sel.affinity()));
332             break;
333         case SentenceGranularity:
334             pos = nextSentencePosition(VisiblePosition(m_sel.extent(), m_sel.affinity()));
335             break;
336         case LineGranularity: {
337             // down-arrowing from a range selection that ends at the start of a line needs
338             // to leave the selection at that line start (no need to call nextLinePosition!)
339             pos = VisiblePosition(m_sel.end(), m_sel.affinity());
340             if (!isRange() || !isStartOfLine(pos))
341                 pos = nextLinePosition(pos, xPosForVerticalArrowNavigation(START));
342             break;
343         }
344         case ParagraphGranularity:
345             pos = nextParagraphPosition(VisiblePosition(m_sel.end(), m_sel.affinity()), xPosForVerticalArrowNavigation(START));
346             break;
347         case SentenceBoundary:
348             pos = endOfSentence(VisiblePosition(m_sel.end(), m_sel.affinity()));
349             break;
350         case LineBoundary:
351             pos = endOfLine(VisiblePosition(m_sel.end(), m_sel.affinity()));
352             break;
353         case ParagraphBoundary:
354             pos = endOfParagraph(VisiblePosition(m_sel.end(), m_sel.affinity()));
355             break;
356         case DocumentBoundary:
357             pos = VisiblePosition(m_sel.end(), m_sel.affinity());
358             if (isEditablePosition(pos.deepEquivalent()))
359                 pos = endOfEditableContent(pos);
360             else
361                 pos = endOfDocument(pos);
362             break;
363             
364     }
365     return pos;
366 }
367
368 VisiblePosition SelectionController::modifyExtendingLeftBackward(TextGranularity granularity)
369 {
370     VisiblePosition pos(m_sel.extent(), m_sel.affinity());
371         
372     // Extending a selection backward by word or character from just after a table selects
373     // the table.  This "makes sense" from the user perspective, esp. when deleting.
374     // It was done here instead of in VisiblePosition because we want VPs to iterate
375     // over everything.
376     switch (granularity) {
377         case CharacterGranularity:
378             pos = pos.previous(true);
379             break;
380         case WordGranularity:
381             pos = previousWordPosition(pos);
382             break;
383         case SentenceGranularity:
384             pos = previousSentencePosition(pos);
385             break;
386         case LineGranularity:
387             pos = previousLinePosition(pos, xPosForVerticalArrowNavigation(EXTENT));
388             break;
389         case ParagraphGranularity:
390             pos = previousParagraphPosition(pos, xPosForVerticalArrowNavigation(EXTENT));
391             break;
392         case SentenceBoundary:
393             pos = startOfSentence(VisiblePosition(m_sel.start(), m_sel.affinity()));
394             break;
395         case LineBoundary:
396             pos = startOfLine(VisiblePosition(m_sel.start(), m_sel.affinity()));
397             break;
398         case ParagraphBoundary:
399             pos = startOfParagraph(VisiblePosition(m_sel.start(), m_sel.affinity()));
400             break;
401         case DocumentBoundary:
402             pos = VisiblePosition(m_sel.start(), m_sel.affinity());
403             if (isEditablePosition(pos.deepEquivalent()))
404                 pos = startOfEditableContent(pos);
405             else 
406                 pos = startOfDocument(pos);
407             break;
408     }
409     return pos;
410 }
411
412 VisiblePosition SelectionController::modifyMovingLeft(TextGranularity granularity)
413 {
414     VisiblePosition pos;
415     switch (granularity) {
416         case CharacterGranularity:
417             if (isRange()) 
418                 pos = VisiblePosition(m_sel.start(), m_sel.affinity());
419             else
420                 pos = VisiblePosition(m_sel.extent(), m_sel.affinity()).left(true);
421             break;
422         case WordGranularity:
423         case SentenceGranularity:
424         case LineGranularity:
425         case ParagraphGranularity:
426         case SentenceBoundary:
427         case LineBoundary:
428         case ParagraphBoundary:
429         case DocumentBoundary:
430             // FIXME: Implement all of the above.
431             pos = modifyMovingBackward(granularity);
432             break;
433     }
434     return pos;
435 }
436
437 VisiblePosition SelectionController::modifyMovingBackward(TextGranularity granularity)
438 {
439     VisiblePosition pos;
440     switch (granularity) {
441         case CharacterGranularity:
442             if (isRange()) 
443                 pos = VisiblePosition(m_sel.start(), m_sel.affinity());
444             else
445                 pos = VisiblePosition(m_sel.extent(), m_sel.affinity()).previous(true);
446             break;
447         case WordGranularity:
448             pos = previousWordPosition(VisiblePosition(m_sel.extent(), m_sel.affinity()));
449             break;
450         case SentenceGranularity:
451             pos = previousSentencePosition(VisiblePosition(m_sel.extent(), m_sel.affinity()));
452             break;
453         case LineGranularity:
454             pos = previousLinePosition(VisiblePosition(m_sel.start(), m_sel.affinity()), xPosForVerticalArrowNavigation(START));
455             break;
456         case ParagraphGranularity:
457             pos = previousParagraphPosition(VisiblePosition(m_sel.start(), m_sel.affinity()), xPosForVerticalArrowNavigation(START));
458             break;
459         case SentenceBoundary:
460             pos = startOfSentence(VisiblePosition(m_sel.start(), m_sel.affinity()));
461             break;
462         case LineBoundary:
463             pos = startOfLine(VisiblePosition(m_sel.start(), m_sel.affinity()));
464             break;
465         case ParagraphBoundary:
466             pos = startOfParagraph(VisiblePosition(m_sel.start(), m_sel.affinity()));
467             break;
468         case DocumentBoundary:
469             pos = VisiblePosition(m_sel.start(), m_sel.affinity());
470             if (isEditablePosition(pos.deepEquivalent()))
471                 pos = startOfEditableContent(pos);
472             else 
473                 pos = startOfDocument(pos);
474             break;
475     }
476     return pos;
477 }
478
479 bool SelectionController::modify(EAlteration alter, EDirection dir, TextGranularity granularity, bool userTriggered)
480 {
481     if (userTriggered) {
482         SelectionController trialSelectionController;
483         trialSelectionController.setLastChangeWasHorizontalExtension(m_lastChangeWasHorizontalExtension);
484         trialSelectionController.setSelection(m_sel);
485         trialSelectionController.modify(alter, dir, granularity, false);
486
487         bool change = m_frame->shouldChangeSelection(trialSelectionController.selection());
488         if (!change)
489             return false;
490     }
491
492     if (m_frame)
493         m_frame->setSelectionGranularity(granularity);
494     
495     willBeModified(alter, dir);
496
497     VisiblePosition pos;
498     switch (dir) {
499         case RIGHT:
500             if (alter == MOVE)
501                 pos = modifyMovingRight(granularity);
502             else
503                 pos = modifyExtendingRightForward(granularity);
504             break;
505         case FORWARD:
506             if (alter == EXTEND)
507                 pos = modifyExtendingRightForward(granularity);
508             else
509                 pos = modifyMovingForward(granularity);
510             break;
511         case LEFT:
512             if (alter == MOVE)
513                 pos = modifyMovingLeft(granularity);
514             else
515                 pos = modifyExtendingLeftBackward(granularity);
516             break;
517         case BACKWARD:
518             if (alter == EXTEND)
519                 pos = modifyExtendingLeftBackward(granularity);
520             else
521                 pos = modifyMovingBackward(granularity);
522             break;
523     }
524
525     if (pos.isNull())
526         return false;
527     
528     // Some of the above operations set an xPosForVerticalArrowNavigation.
529     // Setting a selection will clear it, so save it to possibly restore later.
530     // Note: the START position type is arbitrary because it is unused, it would be
531     // the requested position type if there were no xPosForVerticalArrowNavigation set.
532     int x = xPosForVerticalArrowNavigation(START);
533
534     switch (alter) {
535         case MOVE:
536             moveTo(pos, userTriggered);
537             break;
538         case EXTEND:
539             setExtent(pos, userTriggered);
540             break;
541     }
542     
543     if (granularity == LineGranularity || granularity == ParagraphGranularity)
544         m_xPosForVerticalArrowNavigation = x;
545
546     if (userTriggered) {
547         // User modified selection change also sets the granularity back to character.
548         // NOTE: The one exception is that we need to keep word granularity to
549         // preserve smart delete behavior when extending by word (e.g. double-click),
550         // then shift-option-right arrow, then delete needs to smart delete, per TextEdit.
551         if (!(alter == EXTEND && granularity == WordGranularity && m_frame->selectionGranularity() == WordGranularity))
552             m_frame->setSelectionGranularity(CharacterGranularity);
553     }
554
555     setNeedsLayout();
556
557     return true;
558 }
559
560 // FIXME: Maybe baseline would be better?
561 static bool absoluteCaretY(const VisiblePosition &c, int &y)
562 {
563     IntRect rect = c.absoluteCaretBounds();
564     if (rect.isEmpty())
565         return false;
566     y = rect.y() + rect.height() / 2;
567     return true;
568 }
569
570 bool SelectionController::modify(EAlteration alter, int verticalDistance, bool userTriggered)
571 {
572     if (verticalDistance == 0)
573         return false;
574
575     if (userTriggered) {
576         SelectionController trialSelectionController;
577         trialSelectionController.setSelection(m_sel);
578         trialSelectionController.modify(alter, verticalDistance, false);
579
580         bool change = m_frame->shouldChangeSelection(trialSelectionController.selection());
581         if (!change)
582             return false;
583     }
584
585     bool up = verticalDistance < 0;
586     if (up)
587         verticalDistance = -verticalDistance;
588
589     willBeModified(alter, up ? BACKWARD : FORWARD);
590
591     VisiblePosition pos;
592     int xPos = 0;
593     switch (alter) {
594         case MOVE:
595             pos = VisiblePosition(up ? m_sel.start() : m_sel.end(), m_sel.affinity());
596             xPos = xPosForVerticalArrowNavigation(up ? START : END);
597             m_sel.setAffinity(up ? UPSTREAM : DOWNSTREAM);
598             break;
599         case EXTEND:
600             pos = VisiblePosition(m_sel.extent(), m_sel.affinity());
601             xPos = xPosForVerticalArrowNavigation(EXTENT);
602             m_sel.setAffinity(DOWNSTREAM);
603             break;
604     }
605
606     int startY;
607     if (!absoluteCaretY(pos, startY))
608         return false;
609     if (up)
610         startY = -startY;
611     int lastY = startY;
612
613     VisiblePosition result;
614     VisiblePosition next;
615     for (VisiblePosition p = pos; ; p = next) {
616         next = (up ? previousLinePosition : nextLinePosition)(p, xPos);
617         if (next.isNull() || next == p)
618             break;
619         int nextY;
620         if (!absoluteCaretY(next, nextY))
621             break;
622         if (up)
623             nextY = -nextY;
624         if (nextY - startY > verticalDistance)
625             break;
626         if (nextY >= lastY) {
627             lastY = nextY;
628             result = next;
629         }
630     }
631
632     if (result.isNull())
633         return false;
634
635     switch (alter) {
636         case MOVE:
637             moveTo(result, userTriggered);
638             break;
639         case EXTEND:
640             setExtent(result, userTriggered);
641             break;
642     }
643
644     if (userTriggered)
645         m_frame->setSelectionGranularity(CharacterGranularity);
646
647     return true;
648 }
649
650 bool SelectionController::expandUsingGranularity(TextGranularity granularity)
651 {
652     if (isNone())
653         return false;
654
655     m_sel.expandUsingGranularity(granularity);
656     m_needsLayout = true;
657     return true;
658 }
659
660 int SelectionController::xPosForVerticalArrowNavigation(EPositionType type)
661 {
662     int x = 0;
663
664     if (isNone())
665         return x;
666
667     Position pos;
668     switch (type) {
669         case START:
670             pos = m_sel.start();
671             break;
672         case END:
673             pos = m_sel.end();
674             break;
675         case BASE:
676             pos = m_sel.base();
677             break;
678         case EXTENT:
679             pos = m_sel.extent();
680             break;
681     }
682
683     Frame *frame = pos.node()->document()->frame();
684     if (!frame)
685         return x;
686         
687     if (m_xPosForVerticalArrowNavigation == NoXPosForVerticalArrowNavigation) {
688         VisiblePosition visiblePosition(pos, m_sel.affinity());
689         // VisiblePosition creation can fail here if a node containing the selection becomes visibility:hidden
690         // after the selection is created and before this function is called.
691         x = visiblePosition.isNotNull() ? visiblePosition.xOffsetForVerticalNavigation() : 0;
692         m_xPosForVerticalArrowNavigation = x;
693     }
694     else
695         x = m_xPosForVerticalArrowNavigation;
696         
697     return x;
698 }
699
700 void SelectionController::clear()
701 {
702     setSelection(Selection());
703 }
704
705 void SelectionController::setBase(const VisiblePosition &pos, bool userTriggered)
706 {
707     setSelection(Selection(pos.deepEquivalent(), m_sel.extent(), pos.affinity()), true, true, userTriggered);
708 }
709
710 void SelectionController::setExtent(const VisiblePosition &pos, bool userTriggered)
711 {
712     setSelection(Selection(m_sel.base(), pos.deepEquivalent(), pos.affinity()), true, true, userTriggered);
713 }
714
715 void SelectionController::setBase(const Position &pos, EAffinity affinity, bool userTriggered)
716 {
717     setSelection(Selection(pos, m_sel.extent(), affinity), true, true, userTriggered);
718 }
719
720 void SelectionController::setExtent(const Position &pos, EAffinity affinity, bool userTriggered)
721 {
722     setSelection(Selection(m_sel.base(), pos, affinity), true, true, userTriggered);
723 }
724
725 void SelectionController::setNeedsLayout(bool flag)
726 {
727     m_needsLayout = flag;
728 }
729
730 void SelectionController::layout()
731 {
732     if (isNone() || !m_sel.start().node()->inDocument() || !m_sel.end().node()->inDocument()) {
733         m_caretRect = IntRect();
734         return;
735     }
736
737     m_sel.start().node()->document()->updateRendering();
738     
739     m_caretRect = IntRect();
740         
741     if (isCaret()) {
742         VisiblePosition pos(m_sel.start(), m_sel.affinity());
743         if (pos.isNotNull()) {
744             ASSERT(pos.deepEquivalent().node()->renderer());
745             
746             // First compute a rect local to the renderer at the selection start
747             RenderObject* renderer;
748             IntRect localRect = pos.localCaretRect(renderer);
749
750             // Get the renderer that will be responsible for painting the caret (which
751             // is either the renderer we just found, or one of its containers)
752             RenderObject* caretPainter = caretRenderer();
753
754             // Compute an offset between the renderer and the caretPainter
755             IntSize offsetFromPainter;
756             bool unrooted = false;
757             while (renderer != caretPainter) {
758                 RenderObject* containerObject = renderer->container();
759                 if (!containerObject) {
760                     unrooted = true;
761                     break;
762                 }
763                 offsetFromPainter += renderer->offsetFromContainer(containerObject);
764                 renderer = containerObject;
765             }
766             
767             if (!unrooted) {
768                 // Move the caret rect to the coords of the painter
769                 localRect.move(offsetFromPainter);
770                 m_caretRect = localRect;
771             }
772             
773             m_absCaretBoundsDirty = true;
774         }
775     }
776
777     m_needsLayout = false;
778 }
779
780 RenderObject* SelectionController::caretRenderer() const
781 {
782     Node* node = m_sel.start().node();
783     if (!node)
784         return 0;
785
786     RenderObject* renderer = node->renderer();
787     if (!renderer)
788         return 0;
789
790     // if caretNode is a block and caret is inside it then caret should be painted by that block
791     bool paintedByBlock = renderer->isBlockFlow() && caretRendersInsideNode(node);
792     return paintedByBlock ? renderer : renderer->containingBlock();
793 }
794
795 IntRect SelectionController::localCaretRect() const
796 {
797     if (m_needsLayout)
798         const_cast<SelectionController *>(this)->layout();
799     
800     return m_caretRect;
801 }
802
803 IntRect SelectionController::absoluteCaretBounds()
804 {
805     recomputeCaretRect();
806     return m_absCaretBounds;
807 }
808
809 static IntRect repaintRectForCaret(IntRect caret)
810 {
811     if (caret.isEmpty())
812         return IntRect();
813     // Ensure that the dirty rect intersects the block that paints the caret even in the case where
814     // the caret itself is just outside the block. See <https://bugs.webkit.org/show_bug.cgi?id=19086>.
815     caret.inflateX(1);
816     return caret;
817 }
818
819 IntRect SelectionController::caretRepaintRect() const
820 {
821     IntRect localRect = repaintRectForCaret(localCaretRect());
822     
823     RenderObject* caretPainter = caretRenderer();
824     if (caretPainter)
825         return caretPainter->localToAbsoluteQuad(FloatRect(localRect)).enclosingBoundingBox();
826
827     return IntRect();
828 }
829
830 bool SelectionController::recomputeCaretRect()
831 {
832     if (!m_frame || !m_frame->document())
833         return false;
834         
835     FrameView* v = m_frame->document()->view();
836     if (!v)
837         return false;
838
839     if (!m_needsLayout)
840         return false;
841
842     IntRect oldRect = m_caretRect;
843     m_needsLayout = true;
844     IntRect newRect = localCaretRect();
845     if (oldRect == newRect && !m_absCaretBoundsDirty)
846         return false;
847
848     IntRect oldAbsRepaintRect = m_absCaretBounds;
849     m_absCaretBounds = caretRepaintRect();
850     m_absCaretBoundsDirty = false;
851     
852     if (oldAbsRepaintRect == m_absCaretBounds)
853         return false;
854     
855     if (RenderView* view = static_cast<RenderView*>(m_frame->document()->renderer())) {
856         view->repaintViewRectangle(oldAbsRepaintRect, false);
857         view->repaintViewRectangle(m_absCaretBounds, false);
858     }
859
860     return true;
861 }
862
863 void SelectionController::invalidateCaretRect()
864 {
865     if (!isCaret())
866         return;
867
868     Document* d = m_sel.start().node()->document();
869
870     // recomputeCaretRect will always return false for the drag caret,
871     // because its m_frame is always 0.
872     bool caretRectChanged = recomputeCaretRect();
873
874     // EDIT FIXME: This is an unfortunate hack.
875     // Basically, we can't trust this layout position since we 
876     // can't guarantee that the check to see if we are in unrendered 
877     // content will work at this point. We may have to wait for
878     // a layout and re-render of the document to happen. So, resetting this
879     // flag will cause another caret layout to happen the first time
880     // that we try to paint the caret after this call. That one will work since
881     // it happens after the document has accounted for any editing
882     // changes which may have been done.
883     // And, we need to leave this layout here so the caret moves right 
884     // away after clicking.
885     m_needsLayout = true;
886
887     if (!caretRectChanged) {
888         if (RenderView* view = static_cast<RenderView*>(d->renderer()))
889             view->repaintViewRectangle(caretRepaintRect(), false);
890     }
891 }
892
893 void SelectionController::paintCaret(GraphicsContext* p, int tx, int ty, const IntRect& clipRect)
894 {
895     if (! m_sel.isCaret())
896         return;
897
898     if (m_needsLayout)
899         layout();
900
901     IntRect drawingRect = localCaretRect();
902     drawingRect.move(tx, ty);
903     IntRect caret = intersection(drawingRect, clipRect);
904     if (!caret.isEmpty()) {
905         Color caretColor = Color::black;
906         Element* element = rootEditableElement();
907         if (element && element->renderer())
908             caretColor = element->renderer()->style()->color();
909
910         p->fillRect(caret, caretColor);
911     }
912 }
913
914 void SelectionController::debugRenderer(RenderObject *r, bool selected) const
915 {
916     if (r->node()->isElementNode()) {
917         Element *element = static_cast<Element *>(r->node());
918         fprintf(stderr, "%s%s\n", selected ? "==> " : "    ", element->localName().string().utf8().data());
919     }
920     else if (r->isText()) {
921         RenderText* textRenderer = static_cast<RenderText*>(r);
922         if (textRenderer->textLength() == 0 || !textRenderer->firstTextBox()) {
923             fprintf(stderr, "%s#text (empty)\n", selected ? "==> " : "    ");
924             return;
925         }
926         
927         static const int max = 36;
928         String text = textRenderer->text();
929         int textLength = text.length();
930         if (selected) {
931             int offset = 0;
932             if (r->node() == m_sel.start().node())
933                 offset = m_sel.start().offset();
934             else if (r->node() == m_sel.end().node())
935                 offset = m_sel.end().offset();
936                 
937             int pos;
938             InlineTextBox *box = textRenderer->findNextInlineTextBox(offset, pos);
939             text = text.substring(box->m_start, box->m_len);
940             
941             String show;
942             int mid = max / 2;
943             int caret = 0;
944             
945             // text is shorter than max
946             if (textLength < max) {
947                 show = text;
948                 caret = pos;
949             }
950             
951             // too few characters to left
952             else if (pos - mid < 0) {
953                 show = text.left(max - 3) + "...";
954                 caret = pos;
955             }
956             
957             // enough characters on each side
958             else if (pos - mid >= 0 && pos + mid <= textLength) {
959                 show = "..." + text.substring(pos - mid + 3, max - 6) + "...";
960                 caret = mid;
961             }
962             
963             // too few characters on right
964             else {
965                 show = "..." + text.right(max - 3);
966                 caret = pos - (textLength - show.length());
967             }
968             
969             show.replace('\n', ' ');
970             show.replace('\r', ' ');
971             fprintf(stderr, "==> #text : \"%s\" at offset %d\n", show.utf8().data(), pos);
972             fprintf(stderr, "           ");
973             for (int i = 0; i < caret; i++)
974                 fprintf(stderr, " ");
975             fprintf(stderr, "^\n");
976         }
977         else {
978             if ((int)text.length() > max)
979                 text = text.left(max - 3) + "...";
980             else
981                 text = text.left(max);
982             fprintf(stderr, "    #text : \"%s\"\n", text.utf8().data());
983         }
984     }
985 }
986
987 bool SelectionController::contains(const IntPoint& point)
988 {
989     Document* document = m_frame->document();
990     
991     // Treat a collapsed selection like no selection.
992     if (!isRange())
993         return false;
994     if (!document->renderer()) 
995         return false;
996     
997     HitTestRequest request(true, true);
998     HitTestResult result(point);
999     document->renderView()->layer()->hitTest(request, result);
1000     Node* innerNode = result.innerNode();
1001     if (!innerNode || !innerNode->renderer())
1002         return false;
1003     
1004     VisiblePosition visiblePos(innerNode->renderer()->positionForPoint(result.localPoint()));
1005     if (visiblePos.isNull())
1006         return false;
1007         
1008     if (m_sel.visibleStart().isNull() || m_sel.visibleEnd().isNull())
1009         return false;
1010         
1011     Position start(m_sel.visibleStart().deepEquivalent());
1012     Position end(m_sel.visibleEnd().deepEquivalent());
1013     Position p(visiblePos.deepEquivalent());
1014
1015     return comparePositions(start, p) <= 0 && comparePositions(p, end) <= 0;
1016 }
1017
1018 // Workaround for the fact that it's hard to delete a frame.
1019 // Call this after doing user-triggered selections to make it easy to delete the frame you entirely selected.
1020 // Can't do this implicitly as part of every setSelection call because in some contexts it might not be good
1021 // for the focus to move to another frame. So instead we call it from places where we are selecting with the
1022 // mouse or the keyboard after setting the selection.
1023 void SelectionController::selectFrameElementInParentIfFullySelected()
1024 {
1025     // Find the parent frame; if there is none, then we have nothing to do.
1026     Frame* parent = m_frame->tree()->parent();
1027     if (!parent)
1028         return;
1029     Page* page = m_frame->page();
1030     if (!page)
1031         return;
1032
1033     // Check if the selection contains the entire frame contents; if not, then there is nothing to do.
1034     if (!isRange())
1035         return;
1036     if (!isStartOfDocument(selection().visibleStart()))
1037         return;
1038     if (!isEndOfDocument(selection().visibleEnd()))
1039         return;
1040
1041     // Get to the <iframe> or <frame> (or even <object>) element in the parent frame.
1042     Document* doc = m_frame->document();
1043     if (!doc)
1044         return;
1045     Element* ownerElement = doc->ownerElement();
1046     if (!ownerElement)
1047         return;
1048     Node* ownerElementParent = ownerElement->parentNode();
1049     if (!ownerElementParent)
1050         return;
1051         
1052     // 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.
1053     if (!ownerElementParent->isContentEditable())
1054         return;
1055
1056     // Create compute positions before and after the element.
1057     unsigned ownerElementNodeIndex = ownerElement->nodeIndex();
1058     VisiblePosition beforeOwnerElement(VisiblePosition(ownerElementParent, ownerElementNodeIndex, SEL_DEFAULT_AFFINITY));
1059     VisiblePosition afterOwnerElement(VisiblePosition(ownerElementParent, ownerElementNodeIndex + 1, VP_UPSTREAM_IF_POSSIBLE));
1060
1061     // Focus on the parent frame, and then select from before this element to after.
1062     Selection newSelection(beforeOwnerElement, afterOwnerElement);
1063     if (parent->shouldChangeSelection(newSelection)) {
1064         page->focusController()->setFocusedFrame(parent);
1065         parent->selection()->setSelection(newSelection);
1066     }
1067 }
1068
1069 void SelectionController::selectAll()
1070 {
1071     Document* document = m_frame->document();
1072     if (!document)
1073         return;
1074     
1075     if (document->focusedNode() && document->focusedNode()->canSelectAll()) {
1076         document->focusedNode()->selectAll();
1077         return;
1078     }
1079     
1080     Node* root = 0;
1081     if (isContentEditable())
1082         root = highestEditableRoot(m_sel.start());
1083     else {
1084         root = shadowTreeRootNode();
1085         if (!root)
1086             root = document->documentElement();
1087     }
1088     if (!root)
1089         return;
1090     Selection newSelection(Selection::selectionFromContentsOfNode(root));
1091     if (m_frame->shouldChangeSelection(newSelection))
1092         setSelection(newSelection);
1093     selectFrameElementInParentIfFullySelected();
1094     m_frame->notifyRendererOfSelectionChange(true);
1095 }
1096
1097 bool SelectionController::setSelectedRange(Range* range, EAffinity affinity, bool closeTyping)
1098 {
1099     if (!range)
1100         return false;
1101
1102     ExceptionCode ec = 0;
1103     Node* startContainer = range->startContainer(ec);
1104     if (ec)
1105         return false;
1106
1107     Node* endContainer = range->endContainer(ec);
1108     if (ec)
1109         return false;
1110     
1111     ASSERT(startContainer);
1112     ASSERT(endContainer);
1113     ASSERT(startContainer->document() == endContainer->document());
1114     
1115     m_frame->document()->updateLayoutIgnorePendingStylesheets();
1116
1117     // Non-collapsed ranges are not allowed to start at the end of a line that is wrapped,
1118     // they start at the beginning of the next line instead
1119     bool collapsed = range->collapsed(ec);
1120     if (ec)
1121         return false;
1122     
1123     int startOffset = range->startOffset(ec);
1124     if (ec)
1125         return false;
1126
1127     int endOffset = range->endOffset(ec);
1128     if (ec)
1129         return false;
1130     
1131     // FIXME: Can we provide extentAffinity?
1132     VisiblePosition visibleStart(startContainer, startOffset, collapsed ? affinity : DOWNSTREAM);
1133     VisiblePosition visibleEnd(endContainer, endOffset, SEL_DEFAULT_AFFINITY);
1134     setSelection(Selection(visibleStart, visibleEnd), closeTyping);
1135     return true;
1136 }
1137
1138 bool SelectionController::isInPasswordField() const
1139 {
1140     Node* startNode = start().node();
1141     if (!startNode)
1142         return false;
1143
1144     startNode = startNode->shadowAncestorNode();
1145     if (!startNode)
1146         return false;
1147
1148     if (!startNode->hasTagName(inputTag))
1149         return false;
1150     
1151     return static_cast<HTMLInputElement*>(startNode)->inputType() == HTMLInputElement::PASSWORD;
1152 }
1153
1154 bool SelectionController::caretRendersInsideNode(Node* node) const
1155 {
1156     if (!node)
1157         return false;
1158     return !isTableElement(node) && !editingIgnoresContent(node);
1159 }
1160
1161 void SelectionController::focusedOrActiveStateChanged()
1162 {
1163     bool activeAndFocused = isFocusedAndActive();
1164
1165     // Because RenderObject::selectionBackgroundColor() and
1166     // RenderObject::selectionForegroundColor() check if the frame is active,
1167     // we have to update places those colors were painted.
1168     if (RenderView* view = static_cast<RenderView*>(m_frame->document()->renderer()))
1169         view->repaintViewRectangle(enclosingIntRect(m_frame->selectionBounds()));
1170
1171     // Caret appears in the active frame.
1172     if (activeAndFocused)
1173         m_frame->setSelectionFromNone();
1174     m_frame->setCaretVisible(activeAndFocused);
1175
1176     // Update for caps lock state
1177     m_frame->eventHandler()->capsLockStateMayHaveChanged();
1178
1179     // Because CSSStyleSelector::checkOneSelector() and
1180     // RenderTheme::isFocused() check if the frame is active, we have to
1181     // update style and theme state that depended on those.
1182     if (Node* node = m_frame->document()->focusedNode()) {
1183         node->setChanged();
1184         if (RenderObject* renderer = node->renderer())
1185             if (renderer && renderer->style()->hasAppearance())
1186                 theme()->stateChanged(renderer, FocusState);
1187     }
1188
1189     // Secure keyboard entry is set by the active frame.
1190     if (m_frame->document()->useSecureKeyboardEntryWhenActive())
1191         m_frame->setUseSecureKeyboardEntry(activeAndFocused);
1192 }
1193
1194 void SelectionController::pageActivationChanged()
1195 {
1196     focusedOrActiveStateChanged();
1197 }
1198
1199 void SelectionController::setFocused(bool flag)
1200 {
1201     if (m_focused == flag)
1202         return;
1203     m_focused = flag;
1204
1205     focusedOrActiveStateChanged();
1206
1207     if (Document* doc = m_frame->document())
1208         doc->dispatchWindowEvent(flag ? eventNames().focusEvent : eventNames().blurEvent, false, false);
1209 }
1210
1211 bool SelectionController::isFocusedAndActive() const
1212 {
1213     return m_focused && m_frame->page() && m_frame->page()->focusController()->isActive();
1214 }
1215
1216 #ifndef NDEBUG
1217
1218 void SelectionController::formatForDebugger(char* buffer, unsigned length) const
1219 {
1220     m_sel.formatForDebugger(buffer, length);
1221 }
1222
1223 void SelectionController::showTreeForThis() const
1224 {
1225     m_sel.showTreeForThis();
1226 }
1227
1228 #endif
1229
1230 }
1231
1232 #ifndef NDEBUG
1233
1234 void showTree(const WebCore::SelectionController& sel)
1235 {
1236     sel.showTreeForThis();
1237 }
1238
1239 void showTree(const WebCore::SelectionController* sel)
1240 {
1241     if (sel)
1242         sel->showTreeForThis();
1243 }
1244
1245 #endif