LayoutTests:
[WebKit-https.git] / WebCore / page / Frame.cpp
1 /* This file is part of the KDE project
2  *
3  * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
4  *                     1999 Lars Knoll <knoll@kde.org>
5  *                     1999 Antti Koivisto <koivisto@kde.org>
6  *                     2000 Simon Hausmann <hausmann@kde.org>
7  *                     2000 Stefan Schimanski <1Stein@gmx.de>
8  *                     2001 George Staikos <staikos@kde.org>
9  * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
10  * Copyright (C) 2005 Alexey Proskuryakov <ap@nypop.com>
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Library General Public
14  * License as published by the Free Software Foundation; either
15  * version 2 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public License
23  * along with this library; see the file COPYING.LIB.  If not, write to
24  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25  * Boston, MA 02111-1307, USA.
26  */
27
28 #include "config.h"
29 #include "Frame.h"
30 #include "FramePrivate.h"
31
32 #include "ApplyStyleCommand.h"
33 #include "CSSComputedStyleDeclaration.h"
34 #include "CSSProperty.h"
35 #include "CSSPropertyNames.h"
36 #include "Cache.h"
37 #include "CachedCSSStyleSheet.h"
38 #include "DOMWindow.h"
39 #include "DocLoader.h"
40 #include "DocumentType.h"
41 #include "EditingText.h"
42 #include "EditorClient.h"
43 #include "Event.h"
44 #include "EventNames.h"
45 #include "FloatRect.h"
46 #include "Frame.h"
47 #include "FrameLoader.h"
48 #include "FrameLoadRequest.h"
49 #include "FrameView.h"
50 #include "GraphicsContext.h"
51 #include "HTMLFormElement.h"
52 #include "HTMLFrameElementBase.h"
53 #include "HTMLGenericFormElement.h"
54 #include "HTMLInputElement.h"
55 #include "HTMLNames.h"
56 #include "HTMLObjectElement.h"
57 #include "HitTestRequest.h"
58 #include "HitTestResult.h"
59 #include "IconDatabase.h"
60 #include "IconLoader.h"
61 #include "ImageDocument.h"
62 #include "IndentOutdentCommand.h"
63 #include "MediaFeatureNames.h"
64 #include "MouseEventWithHitTestResults.h"
65 #include "NodeList.h"
66 #include "Page.h"
67 #include "PlatformScrollBar.h"
68 #include "RenderListBox.h"
69 #include "RenderObject.h"
70 #include "RenderPart.h"
71 #include "RenderTextControl.h"
72 #include "RenderTheme.h"
73 #include "RenderView.h"
74 #include "SegmentedString.h"
75 #include "TextIterator.h"
76 #include "TextResourceDecoder.h"
77 #include "TypingCommand.h"
78 #include "XMLTokenizer.h"
79 #include "cssstyleselector.h"
80 #include "htmlediting.h"
81 #include "kjs_proxy.h"
82 #include "kjs_window.h"
83 #include "markup.h"
84 #include "visible_units.h"
85 #include "xmlhttprequest.h"
86 #include <math.h>
87 #include <sys/types.h>
88 #include <wtf/Platform.h>
89
90 #if PLATFORM(MAC)
91 #include "FrameMac.h"
92 #endif
93
94 #if !PLATFORM(WIN_OS)
95 #include <unistd.h>
96 #endif
97
98 #ifdef SVG_SUPPORT
99 #include "SVGNames.h"
100 #include "XLinkNames.h"
101 #include "XMLNames.h"
102 #include "SVGDocument.h"
103 #include "SVGDocumentExtensions.h"
104 #endif
105
106 using namespace std;
107
108 using KJS::JSLock;
109 using KJS::JSValue;
110 using KJS::Location;
111 using KJS::PausedTimeouts;
112 using KJS::SavedProperties;
113 using KJS::SavedBuiltins;
114 using KJS::UString;
115 using KJS::Window;
116
117 namespace WebCore {
118
119 using namespace EventNames;
120 using namespace HTMLNames;
121
122 const double caretBlinkFrequency = 0.5;
123 const double autoscrollInterval = 0.1;
124
125 class UserStyleSheetLoader : public CachedResourceClient {
126 public:
127     UserStyleSheetLoader(Frame* frame, const String& url, DocLoader* docLoader)
128         : m_frame(frame)
129         , m_cachedSheet(docLoader->requestCSSStyleSheet(url, ""))
130     {
131         m_cachedSheet->ref(this);
132     }
133     ~UserStyleSheetLoader()
134     {
135         m_cachedSheet->deref(this);
136     }
137 private:
138     virtual void setCSSStyleSheet(const String& /*URL*/, const String& /*charset*/, const String& sheet)
139     {
140         m_frame->setUserStyleSheet(sheet);
141     }
142     Frame* m_frame;
143     CachedCSSStyleSheet* m_cachedSheet;
144 };
145
146 #ifndef NDEBUG
147 struct FrameCounter { 
148     static int count; 
149     ~FrameCounter() { if (count != 0) fprintf(stderr, "LEAK: %d Frame\n", count); }
150 };
151 int FrameCounter::count = 0;
152 static FrameCounter frameCounter;
153 #endif
154
155 static inline Frame* parentFromOwnerElement(Element* ownerElement)
156 {
157     if (!ownerElement)
158         return 0;
159     return ownerElement->document()->frame();
160 }
161
162 Frame::Frame(Page* page, Element* ownerElement, PassRefPtr<EditorClient> client) 
163     : d(new FramePrivate(page, parentFromOwnerElement(ownerElement), this, ownerElement, client))
164 {
165     AtomicString::init();
166     EventNames::init();
167     HTMLNames::init();
168     QualifiedName::init();
169     MediaFeatureNames::init();
170
171 #ifdef SVG_SUPPORT
172     SVGNames::init();
173     XLinkNames::init();
174     XMLNames::init();
175 #endif
176
177     if (!ownerElement)
178         page->setMainFrame(this);
179     else {
180         // FIXME: Frames were originally created with a refcount of 1.
181         // Leave this ref call here until we can straighten that out.
182         ref();
183         page->incrementFrameCount();
184     }
185
186 #ifndef NDEBUG
187     ++FrameCounter::count;
188 #endif
189 }
190
191 Frame::~Frame()
192 {
193     // FIXME: We should not be doing all this work inside the destructor
194
195     ASSERT(!d->m_lifeSupportTimer.isActive());
196
197 #ifndef NDEBUG
198     --FrameCounter::count;
199 #endif
200
201     if (d->m_jscript && d->m_jscript->haveInterpreter())
202         if (Window* w = Window::retrieveWindow(this)) {
203             w->disconnectFrame();
204             // Must clear the window pointer, otherwise we will not
205             // garbage-collect collect the window (inside the call to
206             // delete d below).
207             w = 0;
208         }
209
210     disconnectOwnerElement();
211     
212     if (d->m_domWindow)
213         d->m_domWindow->disconnectFrame();
214             
215     if (d->m_view) {
216         d->m_view->hide();
217         d->m_view->m_frame = 0;
218     }
219   
220     ASSERT(!d->m_lifeSupportTimer.isActive());
221
222     delete d->m_userStyleSheetLoader;
223     delete d;
224     d = 0;
225 }
226
227 FrameLoader* Frame::loader() const
228 {
229     return d->m_loader;
230 }
231
232 FrameView* Frame::view() const
233 {
234     return d->m_view.get();
235 }
236
237 void Frame::setView(FrameView* view)
238 {
239     // Detach the document now, so any onUnload handlers get run - if
240     // we wait until the view is destroyed, then things won't be
241     // hooked up enough for some JavaScript calls to work.
242     if (d->m_doc && view == 0)
243         d->m_doc->detach();
244
245     d->m_view = view;
246 }
247
248 bool Frame::javaScriptEnabled() const
249 {
250     return d->m_bJScriptEnabled;
251 }
252
253 KJSProxy *Frame::scriptProxy()
254 {
255     if (!d->m_bJScriptEnabled)
256         return 0;
257
258     if (!d->m_jscript)
259         d->m_jscript = new KJSProxy(this);
260
261     return d->m_jscript;
262 }
263
264 bool Frame::javaEnabled() const
265 {
266     return d->m_settings->isJavaEnabled();
267 }
268
269 bool Frame::pluginsEnabled() const
270 {
271     return d->m_bPluginsEnabled;
272 }
273
274 Document *Frame::document() const
275 {
276     if (d)
277         return d->m_doc.get();
278     return 0;
279 }
280
281 void Frame::setDocument(Document* newDoc)
282 {
283     if (d) {
284         if (d->m_doc)
285             d->m_doc->detach();
286         d->m_doc = newDoc;
287         if (newDoc)
288             newDoc->attach();
289     }
290 }
291
292 const Settings *Frame::settings() const
293 {
294   return d->m_settings;
295 }
296
297 void Frame::setUserStyleSheetLocation(const KURL& url)
298 {
299     delete d->m_userStyleSheetLoader;
300     d->m_userStyleSheetLoader = 0;
301     if (d->m_doc && d->m_doc->docLoader())
302         d->m_userStyleSheetLoader = new UserStyleSheetLoader(this, url.url(), d->m_doc->docLoader());
303 }
304
305 void Frame::setUserStyleSheet(const String& styleSheet)
306 {
307     delete d->m_userStyleSheetLoader;
308     d->m_userStyleSheetLoader = 0;
309     if (d->m_doc)
310         d->m_doc->setUserStyleSheet(styleSheet);
311 }
312
313 void Frame::setStandardFont(const String& name)
314 {
315     d->m_settings->setStdFontName(AtomicString(name));
316 }
317
318 void Frame::setFixedFont(const String& name)
319 {
320     d->m_settings->setFixedFontName(AtomicString(name));
321 }
322
323 String Frame::selectedText() const
324 {
325     return plainText(selectionController()->toRange().get());
326 }
327
328 SelectionController* Frame::selectionController() const
329 {
330     return &d->m_selectionController;
331 }
332
333 Editor* Frame::editor() const
334 {
335     return &d->m_editor;
336 }
337
338 CommandByName* Frame::command() const
339 {
340     return &d->m_command;
341 }
342
343 TextGranularity Frame::selectionGranularity() const
344 {
345     return d->m_selectionGranularity;
346 }
347
348 void Frame::setSelectionGranularity(TextGranularity granularity) const
349 {
350     d->m_selectionGranularity = granularity;
351 }
352
353 SelectionController* Frame::dragCaretController() const
354 {
355     return d->m_page->dragCaretController();
356 }
357
358 const Selection& Frame::mark() const
359 {
360     return d->m_mark;
361 }
362
363 void Frame::setMark(const Selection& s)
364 {
365     ASSERT(!s.base().node() || s.base().node()->document() == document());
366     ASSERT(!s.extent().node() || s.extent().node()->document() == document());
367     ASSERT(!s.start().node() || s.start().node()->document() == document());
368     ASSERT(!s.end().node() || s.end().node()->document() == document());
369
370     d->m_mark = s;
371 }
372
373 void Frame::notifyRendererOfSelectionChange(bool userTriggered)
374 {
375     RenderObject* renderer = 0;
376     if (selectionController()->rootEditableElement())
377         renderer = selectionController()->rootEditableElement()->shadowAncestorNode()->renderer();
378
379     // If the current selection is in a textfield or textarea, notify the renderer that the selection has changed
380     if (renderer && (renderer->isTextArea() || renderer->isTextField()))
381         static_cast<RenderTextControl*>(renderer)->selectionChanged(userTriggered);
382 }
383
384 void Frame::invalidateSelection()
385 {
386     selectionController()->setNeedsLayout();
387     selectionLayoutChanged();
388 }
389
390 void Frame::setCaretVisible(bool flag)
391 {
392     if (d->m_caretVisible == flag)
393         return;
394     clearCaretRectIfNeeded();
395     if (flag)
396         setFocusNodeIfNeeded();
397     d->m_caretVisible = flag;
398     selectionLayoutChanged();
399 }
400
401
402 void Frame::clearCaretRectIfNeeded()
403 {
404     if (d->m_caretPaint) {
405         d->m_caretPaint = false;
406         selectionController()->invalidateCaretRect();
407     }        
408 }
409
410 // Helper function that tells whether a particular node is an element that has an entire
411 // Frame and FrameView, a <frame>, <iframe>, or <object>.
412 static bool isFrameElement(const Node *n)
413 {
414     if (!n)
415         return false;
416     RenderObject *renderer = n->renderer();
417     if (!renderer || !renderer->isWidget())
418         return false;
419     Widget* widget = static_cast<RenderWidget*>(renderer)->widget();
420     return widget && widget->isFrameView();
421 }
422
423 void Frame::setFocusNodeIfNeeded()
424 {
425     if (!document() || selectionController()->isNone() || !d->m_isActive)
426         return;
427
428     Node* target = selectionController()->rootEditableElement();
429     if (target) {
430         RenderObject* renderer = target->renderer();
431
432         // Walk up the render tree to search for a node to focus.
433         // Walking up the DOM tree wouldn't work for shadow trees, like those behind the engine-based text fields.
434         while (renderer) {
435             // We don't want to set focus on a subframe when selecting in a parent frame,
436             // so add the !isFrameElement check here. There's probably a better way to make this
437             // work in the long term, but this is the safest fix at this time.
438             if (target && target->isMouseFocusable() && !isFrameElement(target)) {
439                 document()->setFocusNode(target);
440                 return;
441             }
442             renderer = renderer->parent();
443             if (renderer)
444                 target = renderer->element();
445         }
446         document()->setFocusNode(0);
447     }
448 }
449
450 void Frame::selectionLayoutChanged()
451 {
452     bool caretRectChanged = selectionController()->recomputeCaretRect();
453
454     bool shouldBlink = d->m_caretVisible
455         && selectionController()->isCaret() && selectionController()->isContentEditable();
456
457     // If the caret moved, stop the blink timer so we can restart with a
458     // black caret in the new location.
459     if (caretRectChanged || !shouldBlink)
460         d->m_caretBlinkTimer.stop();
461
462     // Start blinking with a black caret. Be sure not to restart if we're
463     // already blinking in the right location.
464     if (shouldBlink && !d->m_caretBlinkTimer.isActive()) {
465         d->m_caretBlinkTimer.startRepeating(caretBlinkFrequency);
466         d->m_caretPaint = true;
467     }
468
469     if (d->m_doc)
470         d->m_doc->updateSelection();
471 }
472
473 void Frame::setXPosForVerticalArrowNavigation(int x)
474 {
475     d->m_xPosForVerticalArrowNavigation = x;
476 }
477
478 int Frame::xPosForVerticalArrowNavigation() const
479 {
480     return d->m_xPosForVerticalArrowNavigation;
481 }
482
483 void Frame::caretBlinkTimerFired(Timer<Frame>*)
484 {
485     ASSERT(d->m_caretVisible);
486     ASSERT(selectionController()->isCaret());
487     bool caretPaint = d->m_caretPaint;
488     if (d->m_bMousePressed && caretPaint)
489         return;
490     d->m_caretPaint = !caretPaint;
491     selectionController()->invalidateCaretRect();
492 }
493
494 void Frame::paintCaret(GraphicsContext* p, const IntRect& rect) const
495 {
496     if (d->m_caretPaint && d->m_caretVisible)
497         selectionController()->paintCaret(p, rect);
498 }
499
500 void Frame::paintDragCaret(GraphicsContext* p, const IntRect& rect) const
501 {
502     SelectionController* dragCaretController = d->m_page->dragCaretController();
503     assert(dragCaretController->selection().isCaret());
504     if (dragCaretController->selection().start().node()->document()->frame() == this)
505         dragCaretController->paintCaret(p, rect);
506 }
507
508 int Frame::zoomFactor() const
509 {
510   return d->m_zoomFactor;
511 }
512
513 void Frame::setZoomFactor(int percent)
514 {  
515   if (d->m_zoomFactor == percent)
516       return;
517
518   d->m_zoomFactor = percent;
519
520   if (d->m_doc)
521       d->m_doc->recalcStyle(Node::Force);
522
523   for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
524       child->setZoomFactor(d->m_zoomFactor);
525
526   if (d->m_doc && d->m_doc->renderer() && d->m_doc->renderer()->needsLayout())
527       view()->layout();
528 }
529
530 void Frame::setJSStatusBarText(const String& text)
531 {
532     d->m_kjsStatusBarText = text;
533     setStatusBarText(d->m_kjsStatusBarText);
534 }
535
536 void Frame::setJSDefaultStatusBarText(const String& text)
537 {
538     d->m_kjsDefaultStatusBarText = text;
539     setStatusBarText(d->m_kjsDefaultStatusBarText);
540 }
541
542 String Frame::jsStatusBarText() const
543 {
544     return d->m_kjsStatusBarText;
545 }
546
547 String Frame::jsDefaultStatusBarText() const
548 {
549    return d->m_kjsDefaultStatusBarText;
550 }
551
552 void Frame::reparseConfiguration()
553 {
554     if (d->m_doc)
555         d->m_doc->docLoader()->setAutoLoadImages(d->m_settings->autoLoadImages());
556         
557     d->m_bJScriptEnabled = d->m_settings->isJavaScriptEnabled();
558     d->m_bJavaEnabled = d->m_settings->isJavaEnabled();
559     d->m_bPluginsEnabled = d->m_settings->isPluginsEnabled();
560
561     const KURL& userStyleSheetLocation = d->m_settings->userStyleSheetLocation();
562     if (!userStyleSheetLocation.isEmpty())
563         setUserStyleSheetLocation(userStyleSheetLocation);
564     else
565         setUserStyleSheet(String());
566
567     // FIXME: It's not entirely clear why the following is needed.
568     // The document automatically does this as required when you set the style sheet.
569     // But we had problems when this code was removed. Details are in
570     // <http://bugs.webkit.org/show_bug.cgi?id=8079>.
571     if (d->m_doc)
572         d->m_doc->updateStyleSelector();
573 }
574
575 bool Frame::shouldDragAutoNode(Node *node, const IntPoint& point) const
576 {
577     return false;
578 }
579
580 void Frame::selectClosestWordFromMouseEvent(const PlatformMouseEvent& mouse, Node *innerNode)
581 {
582     Selection newSelection;
583
584     if (innerNode && innerNode->renderer() && mouseDownMayStartSelect() && innerNode->renderer()->shouldSelect()) {
585         IntPoint vPoint = view()->windowToContents(mouse.pos());
586         VisiblePosition pos(innerNode->renderer()->positionForPoint(vPoint));
587         if (pos.isNotNull()) {
588             newSelection = Selection(pos);
589             newSelection.expandUsingGranularity(WordGranularity);
590         }
591     }
592     
593     if (newSelection.isRange()) {
594         d->m_selectionGranularity = WordGranularity;
595         d->m_beganSelectingText = true;
596     }
597     
598     if (shouldChangeSelection(newSelection))
599         selectionController()->setSelection(newSelection);
600 }
601
602 void Frame::handleMousePressEventDoubleClick(const MouseEventWithHitTestResults& event)
603 {
604     if (event.event().button() == LeftButton) {
605         if (selectionController()->isRange())
606             // A double-click when range is already selected
607             // should not change the selection.  So, do not call
608             // selectClosestWordFromMouseEvent, but do set
609             // m_beganSelectingText to prevent handleMouseReleaseEvent
610             // from setting caret selection.
611             d->m_beganSelectingText = true;
612         else
613             selectClosestWordFromMouseEvent(event.event(), event.targetNode());
614     }
615 }
616
617 void Frame::handleMousePressEventTripleClick(const MouseEventWithHitTestResults& event)
618 {
619     Node *innerNode = event.targetNode();
620     
621     if (event.event().button() == LeftButton && innerNode && innerNode->renderer() &&
622         mouseDownMayStartSelect() && innerNode->renderer()->shouldSelect()) {
623         Selection newSelection;
624         IntPoint vPoint = view()->windowToContents(event.event().pos());
625         VisiblePosition pos(innerNode->renderer()->positionForPoint(vPoint));
626         if (pos.isNotNull()) {
627             newSelection = Selection(pos);
628             newSelection.expandUsingGranularity(ParagraphGranularity);
629         }
630         if (newSelection.isRange()) {
631             d->m_selectionGranularity = ParagraphGranularity;
632             d->m_beganSelectingText = true;
633         }
634         
635         if (shouldChangeSelection(newSelection))
636             selectionController()->setSelection(newSelection);
637     }
638 }
639
640 void Frame::handleMousePressEventSingleClick(const MouseEventWithHitTestResults& event)
641 {
642     Node *innerNode = event.targetNode();
643     
644     if (event.event().button() == LeftButton) {
645         if (innerNode && innerNode->renderer() &&
646             mouseDownMayStartSelect() && innerNode->renderer()->shouldSelect()) {
647             
648             // Extend the selection if the Shift key is down, unless the click is in a link.
649             bool extendSelection = event.event().shiftKey() && !event.isOverLink();
650
651             // Don't restart the selection when the mouse is pressed on an
652             // existing selection so we can allow for text dragging.
653             IntPoint vPoint = view()->windowToContents(event.event().pos());
654             if (!extendSelection && selectionController()->contains(vPoint))
655                 return;
656
657             VisiblePosition visiblePos(innerNode->renderer()->positionForPoint(vPoint));
658             if (visiblePos.isNull())
659                 visiblePos = VisiblePosition(innerNode, innerNode->caretMinOffset(), DOWNSTREAM);
660             Position pos = visiblePos.deepEquivalent();
661             
662             Selection newSelection = selectionController()->selection();
663             if (extendSelection && newSelection.isCaretOrRange()) {
664                 selectionController()->clearModifyBias();
665                 
666                 // See <rdar://problem/3668157> REGRESSION (Mail): shift-click deselects when selection 
667                 // was created right-to-left
668                 Position start = newSelection.start();
669                 Position end = newSelection.end();
670                 short before = Range::compareBoundaryPoints(pos.node(), pos.offset(), start.node(), start.offset());
671                 if (before <= 0)
672                     newSelection = Selection(pos, end);
673                 else
674                     newSelection = Selection(start, pos);
675
676                 if (d->m_selectionGranularity != CharacterGranularity)
677                     newSelection.expandUsingGranularity(d->m_selectionGranularity);
678                 d->m_beganSelectingText = true;
679             } else {
680                 newSelection = Selection(visiblePos);
681                 d->m_selectionGranularity = CharacterGranularity;
682             }
683             
684             if (shouldChangeSelection(newSelection))
685                 selectionController()->setSelection(newSelection);
686         }
687     }
688 }
689
690 void Frame::handleMousePressEvent(const MouseEventWithHitTestResults& event)
691 {
692     Node *innerNode = event.targetNode();
693
694     d->m_mousePressNode = innerNode;
695     d->m_dragStartPos = event.event().pos();
696
697     if (event.event().button() == LeftButton || event.event().button() == MiddleButton) {
698         d->m_bMousePressed = true;
699         d->m_beganSelectingText = false;
700
701         if (event.event().clickCount() == 2) {
702             handleMousePressEventDoubleClick(event);
703             return;
704         }
705         if (event.event().clickCount() >= 3) {
706             handleMousePressEventTripleClick(event);
707             return;
708         }
709         handleMousePressEventSingleClick(event);
710     }
711     
712    setMouseDownMayStartAutoscroll(mouseDownMayStartSelect() || 
713         (d->m_mousePressNode && d->m_mousePressNode->renderer() && d->m_mousePressNode->renderer()->shouldAutoscroll()));
714 }
715
716 void Frame::handleMouseMoveEvent(const MouseEventWithHitTestResults& event)
717 {
718     // Mouse not pressed. Do nothing.
719     if (!d->m_bMousePressed)
720         return;
721
722     Node *innerNode = event.targetNode();
723
724     if (event.event().button() != 0 || !innerNode || !innerNode->renderer())
725         return;
726
727     ASSERT(mouseDownMayStartSelect() || mouseDownMayStartAutoscroll());
728
729     setMouseDownMayStartDrag(false);
730     view()->invalidateClick();
731
732      if (mouseDownMayStartAutoscroll()) {            
733         // If the selection is contained in a layer that can scroll, that layer should handle the autoscroll
734         // Otherwise, let the bridge handle it so the view can scroll itself.
735         RenderObject* renderer = innerNode->renderer();
736         while (renderer && !renderer->shouldAutoscroll())
737             renderer = renderer->parent();
738         if (renderer)
739             handleAutoscroll(renderer);
740     }
741     
742     if (mouseDownMayStartSelect() && innerNode->renderer()->shouldSelect()) {
743         // handle making selection
744         IntPoint vPoint = view()->windowToContents(event.event().pos());        
745         VisiblePosition pos(innerNode->renderer()->positionForPoint(vPoint));
746
747         updateSelectionForMouseDragOverPosition(pos);
748     }
749
750 }
751
752 void Frame::updateSelectionForMouseDragOverPosition(const VisiblePosition& pos)
753 {
754     // Don't modify the selection if we're not on a node.
755     if (pos.isNull())
756         return;
757
758     // Restart the selection if this is the first mouse move. This work is usually
759     // done in handleMousePressEvent, but not if the mouse press was on an existing selection.
760     Selection newSelection = selectionController()->selection();
761     selectionController()->clearModifyBias();
762     
763     if (!d->m_beganSelectingText) {
764         d->m_beganSelectingText = true;
765         newSelection = Selection(pos);
766     }
767
768     newSelection.setExtent(pos);
769     if (d->m_selectionGranularity != CharacterGranularity)
770         newSelection.expandUsingGranularity(d->m_selectionGranularity);
771
772     if (shouldChangeSelection(newSelection))
773         selectionController()->setSelection(newSelection);
774 }
775
776 void Frame::handleMouseReleaseEvent(const MouseEventWithHitTestResults& event)
777 {
778     stopAutoscrollTimer();
779     
780     // Used to prevent mouseMoveEvent from initiating a drag before
781     // the mouse is pressed again.
782     d->m_bMousePressed = false;
783   
784     // Clear the selection if the mouse didn't move after the last mouse press.
785     // We do this so when clicking on the selection, the selection goes away.
786     // However, if we are editing, place the caret.
787     if (mouseDownMayStartSelect() && !d->m_beganSelectingText
788             && d->m_dragStartPos == event.event().pos()
789             && selectionController()->isRange()) {
790         Selection newSelection;
791         Node *node = event.targetNode();
792         if (node && node->isContentEditable() && node->renderer()) {
793             IntPoint vPoint = view()->windowToContents(event.event().pos());
794             VisiblePosition pos = node->renderer()->positionForPoint(vPoint);
795             newSelection = Selection(pos);
796         }
797         if (shouldChangeSelection(newSelection))
798             selectionController()->setSelection(newSelection);
799     }
800
801     notifyRendererOfSelectionChange(true);
802
803     selectionController()->selectFrameElementInParentIfFullySelected();
804 }
805
806 bool Frame::shouldChangeSelection(const Selection& newSelection) const
807 {
808     return shouldChangeSelection(selectionController()->selection(), newSelection, newSelection.affinity(), false);
809 }
810
811 bool Frame::shouldDeleteSelection(const Selection& newSelection) const
812 {
813     return true;
814 }
815
816 bool Frame::isContentEditable() const 
817 {
818     if (!d->m_doc)
819         return false;
820     return d->m_doc->inDesignMode();
821 }
822
823 void Frame::textFieldDidBeginEditing(Element* input)
824 {
825 }
826
827 void Frame::textFieldDidEndEditing(Element* input)
828 {
829 }
830
831 void Frame::textDidChangeInTextField(Element* input)
832 {
833 }
834
835 bool Frame::doTextFieldCommandFromEvent(Element*, KeyboardEvent*)
836 {
837     return false;
838 }
839
840 void Frame::textWillBeDeletedInTextField(Element* input)
841 {
842 }
843
844 void Frame::textDidChangeInTextArea(Element* input)
845 {
846 }
847
848 static void dispatchEditableContentChangedEvents(const EditCommand& command)
849 {
850      Element* startRoot = command.startingRootEditableElement();
851      Element* endRoot = command.endingRootEditableElement();
852      ExceptionCode ec;
853      if (startRoot)
854          startRoot->dispatchEvent(new Event(khtmlEditableContentChangedEvent, false, false), ec, true);
855      if (endRoot && endRoot != startRoot)
856          endRoot->dispatchEvent(new Event(khtmlEditableContentChangedEvent, false, false), ec, true);
857 }
858
859 void Frame::appliedEditing(PassRefPtr<EditCommand> cmd)
860 {
861     dispatchEditableContentChangedEvents(*cmd);
862  
863     Selection newSelection(cmd->endingSelection());
864     if (shouldChangeSelection(newSelection))
865         selectionController()->setSelection(newSelection, false);
866     
867     // Now set the typing style from the command. Clear it when done.
868     // This helps make the case work where you completely delete a piece
869     // of styled text and then type a character immediately after.
870     // That new character needs to take on the style of the just-deleted text.
871     // FIXME: Improve typing style.
872     // See this bug: <rdar://problem/3769899> Implementation of typing style needs improvement
873     if (cmd->typingStyle()) {
874         setTypingStyle(cmd->typingStyle());
875         cmd->setTypingStyle(0);
876     }
877
878     // Command will be equal to last edit command only in the case of typing
879     if (editor()->lastEditCommand() == cmd)
880         assert(cmd->isTypingCommand());
881     else {
882         // Only register a new undo command if the command passed in is
883         // different from the last command
884         editor()->setLastEditCommand(cmd.get());
885         registerCommandForUndo(cmd);
886     }
887     respondToChangedContents(newSelection);
888     editor()->respondToChangedContents();
889 }
890
891 void Frame::unappliedEditing(PassRefPtr<EditCommand> cmd)
892 {
893     dispatchEditableContentChangedEvents(*cmd);
894
895     Selection newSelection(cmd->startingSelection());
896     if (shouldChangeSelection(newSelection))
897         selectionController()->setSelection(newSelection, true);
898         
899     editor()->setLastEditCommand(0);
900     registerCommandForRedo(cmd);
901     respondToChangedContents(newSelection);
902     editor()->respondToChangedContents();
903 }
904
905 void Frame::reappliedEditing(PassRefPtr<EditCommand> cmd)
906 {
907     dispatchEditableContentChangedEvents(*cmd);
908
909     Selection newSelection(cmd->endingSelection());
910     if (shouldChangeSelection(newSelection))
911         selectionController()->setSelection(newSelection, true);
912         
913     editor()->setLastEditCommand(0);
914     registerCommandForUndo(cmd);
915     respondToChangedContents(newSelection);
916     editor()->respondToChangedContents();
917 }
918
919 CSSMutableStyleDeclaration *Frame::typingStyle() const
920 {
921     return d->m_typingStyle.get();
922 }
923
924 void Frame::setTypingStyle(CSSMutableStyleDeclaration *style)
925 {
926     d->m_typingStyle = style;
927 }
928
929 void Frame::clearTypingStyle()
930 {
931     d->m_typingStyle = 0;
932 }
933
934 bool Frame::tabsToLinks(KeyboardEvent*) const
935 {
936     return true;
937 }
938
939 bool Frame::tabsToAllControls(KeyboardEvent*) const
940 {
941     return true;
942 }
943
944 void Frame::copyToPasteboard()
945 {
946     issueCopyCommand();
947 }
948
949 void Frame::cutToPasteboard()
950 {
951     issueCutCommand();
952 }
953
954 void Frame::pasteFromPasteboard()
955 {
956     issuePasteCommand();
957 }
958
959 void Frame::pasteAndMatchStyle()
960 {
961     issuePasteAndMatchStyleCommand();
962 }
963
964 void Frame::transpose()
965 {
966     issueTransposeCommand();
967 }
968
969 void Frame::redo()
970 {
971     issueRedoCommand();
972 }
973
974 void Frame::undo()
975 {
976     issueUndoCommand();
977 }
978
979
980 void Frame::computeAndSetTypingStyle(CSSStyleDeclaration *style, EditAction editingAction)
981 {
982     if (!style || style->length() == 0) {
983         clearTypingStyle();
984         return;
985     }
986
987     // Calculate the current typing style.
988     RefPtr<CSSMutableStyleDeclaration> mutableStyle = style->makeMutable();
989     if (typingStyle()) {
990         typingStyle()->merge(mutableStyle.get());
991         mutableStyle = typingStyle();
992     }
993
994     Node *node = selectionController()->selection().visibleStart().deepEquivalent().node();
995     CSSComputedStyleDeclaration computedStyle(node);
996     computedStyle.diff(mutableStyle.get());
997     
998     // Handle block styles, substracting these from the typing style.
999     RefPtr<CSSMutableStyleDeclaration> blockStyle = mutableStyle->copyBlockProperties();
1000     blockStyle->diff(mutableStyle.get());
1001     if (document() && blockStyle->length() > 0)
1002         applyCommand(new ApplyStyleCommand(document(), blockStyle.get(), editingAction));
1003     
1004     // Set the remaining style as the typing style.
1005     d->m_typingStyle = mutableStyle.release();
1006 }
1007
1008 static void updateState(CSSMutableStyleDeclaration *desiredStyle, CSSComputedStyleDeclaration *computedStyle, bool& atStart, Frame::TriState& state)
1009 {
1010     DeprecatedValueListConstIterator<CSSProperty> end;
1011     for (DeprecatedValueListConstIterator<CSSProperty> it = desiredStyle->valuesIterator(); it != end; ++it) {
1012         int propertyID = (*it).id();
1013         String desiredProperty = desiredStyle->getPropertyValue(propertyID);
1014         String computedProperty = computedStyle->getPropertyValue(propertyID);
1015         Frame::TriState propertyState = equalIgnoringCase(desiredProperty, computedProperty)
1016             ? Frame::trueTriState : Frame::falseTriState;
1017         if (atStart) {
1018             state = propertyState;
1019             atStart = false;
1020         } else if (state != propertyState) {
1021             state = Frame::mixedTriState;
1022             break;
1023         }
1024     }
1025 }
1026
1027 Frame::TriState Frame::selectionHasStyle(CSSStyleDeclaration *style) const
1028 {
1029     bool atStart = true;
1030     TriState state = falseTriState;
1031
1032     RefPtr<CSSMutableStyleDeclaration> mutableStyle = style->makeMutable();
1033
1034     if (!selectionController()->isRange()) {
1035         Node* nodeToRemove;
1036         RefPtr<CSSComputedStyleDeclaration> selectionStyle = selectionComputedStyle(nodeToRemove);
1037         if (!selectionStyle)
1038             return falseTriState;
1039         updateState(mutableStyle.get(), selectionStyle.get(), atStart, state);
1040         if (nodeToRemove) {
1041             ExceptionCode ec = 0;
1042             nodeToRemove->remove(ec);
1043             assert(ec == 0);
1044         }
1045     } else {
1046         for (Node* node = selectionController()->start().node(); node; node = node->traverseNextNode()) {
1047             RefPtr<CSSComputedStyleDeclaration> computedStyle = new CSSComputedStyleDeclaration(node);
1048             if (computedStyle)
1049                 updateState(mutableStyle.get(), computedStyle.get(), atStart, state);
1050             if (state == mixedTriState)
1051                 break;
1052             if (node == selectionController()->end().node())
1053                 break;
1054         }
1055     }
1056
1057     return state;
1058 }
1059
1060 String Frame::selectionStartStylePropertyValue(int stylePropertyID) const
1061 {
1062     Node *nodeToRemove;
1063     RefPtr<CSSStyleDeclaration> selectionStyle = selectionComputedStyle(nodeToRemove);
1064     if (!selectionStyle)
1065         return String();
1066
1067     String value = selectionStyle->getPropertyValue(stylePropertyID);
1068
1069     if (nodeToRemove) {
1070         ExceptionCode ec = 0;
1071         nodeToRemove->remove(ec);
1072         assert(ec == 0);
1073     }
1074
1075     return value;
1076 }
1077
1078 CSSComputedStyleDeclaration *Frame::selectionComputedStyle(Node *&nodeToRemove) const
1079 {
1080     nodeToRemove = 0;
1081
1082     if (!document())
1083         return 0;
1084
1085     if (selectionController()->isNone())
1086         return 0;
1087
1088     RefPtr<Range> range(selectionController()->toRange());
1089     Position pos = range->editingStartPosition();
1090
1091     Element *elem = pos.element();
1092     if (!elem)
1093         return 0;
1094     
1095     RefPtr<Element> styleElement = elem;
1096     ExceptionCode ec = 0;
1097
1098     if (d->m_typingStyle) {
1099         styleElement = document()->createElementNS(xhtmlNamespaceURI, "span", ec);
1100         assert(ec == 0);
1101
1102         styleElement->setAttribute(styleAttr, d->m_typingStyle->cssText().impl(), ec);
1103         assert(ec == 0);
1104         
1105         styleElement->appendChild(document()->createEditingTextNode(""), ec);
1106         assert(ec == 0);
1107
1108         if (elem->renderer() && elem->renderer()->canHaveChildren()) {
1109             elem->appendChild(styleElement, ec);
1110         } else {
1111             Node *parent = elem->parent();
1112             Node *next = elem->nextSibling();
1113
1114             if (next) {
1115                 parent->insertBefore(styleElement, next, ec);
1116             } else {
1117                 parent->appendChild(styleElement, ec);
1118             }
1119         }
1120         assert(ec == 0);
1121
1122         nodeToRemove = styleElement.get();
1123     }
1124
1125     return new CSSComputedStyleDeclaration(styleElement);
1126 }
1127
1128 void Frame::applyEditingStyleToBodyElement() const
1129 {
1130     if (!d->m_doc)
1131         return;
1132         
1133     RefPtr<NodeList> list = d->m_doc->getElementsByTagName("body");
1134     unsigned len = list->length();
1135     for (unsigned i = 0; i < len; i++) {
1136         applyEditingStyleToElement(static_cast<Element*>(list->item(i)));    
1137     }
1138 }
1139
1140 void Frame::removeEditingStyleFromBodyElement() const
1141 {
1142     if (!d->m_doc)
1143         return;
1144         
1145     RefPtr<NodeList> list = d->m_doc->getElementsByTagName("body");
1146     unsigned len = list->length();
1147     for (unsigned i = 0; i < len; i++) {
1148         removeEditingStyleFromElement(static_cast<Element*>(list->item(i)));    
1149     }
1150 }
1151
1152 void Frame::applyEditingStyleToElement(Element* element) const
1153 {
1154     if (!element)
1155         return;
1156
1157     CSSStyleDeclaration* style = element->style();
1158     ASSERT(style);
1159
1160     ExceptionCode ec = 0;
1161     style->setProperty(CSS_PROP_WORD_WRAP, "break-word", false, ec);
1162     ASSERT(ec == 0);
1163     style->setProperty(CSS_PROP__WEBKIT_NBSP_MODE, "space", false, ec);
1164     ASSERT(ec == 0);
1165     style->setProperty(CSS_PROP__WEBKIT_LINE_BREAK, "after-white-space", false, ec);
1166     ASSERT(ec == 0);
1167 }
1168
1169 void Frame::removeEditingStyleFromElement(Element*) const
1170 {
1171 }
1172
1173 bool Frame::isCharacterSmartReplaceExempt(UChar, bool)
1174 {
1175     // no smart replace
1176     return true;
1177 }
1178
1179 #ifndef NDEBUG
1180 static HashSet<Frame*> lifeSupportSet;
1181 #endif
1182
1183 void Frame::endAllLifeSupport()
1184 {
1185 #ifndef NDEBUG
1186     HashSet<Frame*> lifeSupportCopy = lifeSupportSet;
1187     HashSet<Frame*>::iterator end = lifeSupportCopy.end();
1188     for (HashSet<Frame*>::iterator it = lifeSupportCopy.begin(); it != end; ++it)
1189         (*it)->endLifeSupport();
1190 #endif
1191 }
1192
1193 void Frame::keepAlive()
1194 {
1195     if (d->m_lifeSupportTimer.isActive())
1196         return;
1197     ref();
1198 #ifndef NDEBUG
1199     lifeSupportSet.add(this);
1200 #endif
1201     d->m_lifeSupportTimer.startOneShot(0);
1202 }
1203
1204 void Frame::endLifeSupport()
1205 {
1206     if (!d->m_lifeSupportTimer.isActive())
1207         return;
1208     d->m_lifeSupportTimer.stop();
1209 #ifndef NDEBUG
1210     lifeSupportSet.remove(this);
1211 #endif
1212     deref();
1213 }
1214
1215 void Frame::lifeSupportTimerFired(Timer<Frame>*)
1216 {
1217 #ifndef NDEBUG
1218     lifeSupportSet.remove(this);
1219 #endif
1220     deref();
1221 }
1222
1223 bool Frame::mouseDownMayStartAutoscroll() const
1224 {
1225     return d->m_mouseDownMayStartAutoscroll;
1226 }
1227
1228 void Frame::setMouseDownMayStartAutoscroll(bool b)
1229 {
1230     d->m_mouseDownMayStartAutoscroll = b;
1231 }
1232
1233 bool Frame::mouseDownMayStartDrag() const
1234 {
1235     return d->m_mouseDownMayStartDrag;
1236 }
1237
1238 void Frame::setMouseDownMayStartDrag(bool b)
1239 {
1240     d->m_mouseDownMayStartDrag = b;
1241 }
1242
1243 void Frame::setSettings(Settings *settings)
1244 {
1245     d->m_settings = settings;
1246 }
1247
1248 RenderObject *Frame::renderer() const
1249 {
1250     Document *doc = document();
1251     return doc ? doc->renderer() : 0;
1252 }
1253
1254 Element* Frame::ownerElement()
1255 {
1256     return d->m_ownerElement;
1257 }
1258
1259 RenderPart* Frame::ownerRenderer()
1260 {
1261     Element* ownerElement = d->m_ownerElement;
1262     if (!ownerElement)
1263         return 0;
1264     return static_cast<RenderPart*>(ownerElement->renderer());
1265 }
1266
1267 IntRect Frame::selectionRect() const
1268 {
1269     RenderView *root = static_cast<RenderView*>(renderer());
1270     if (!root)
1271         return IntRect();
1272
1273     return root->selectionRect();
1274 }
1275
1276 // returns FloatRect because going through IntRect would truncate any floats
1277 FloatRect Frame::visibleSelectionRect() const
1278 {
1279     if (!d->m_view)
1280         return FloatRect();
1281     
1282     return intersection(selectionRect(), d->m_view->visibleContentRect());
1283 }
1284
1285 bool Frame::isFrameSet() const
1286 {
1287     Document* document = d->m_doc.get();
1288     if (!document || !document->isHTMLDocument())
1289         return false;
1290     Node *body = static_cast<HTMLDocument*>(document)->body();
1291     return body && body->renderer() && body->hasTagName(framesetTag);
1292 }
1293
1294 // Scans logically forward from "start", including any child frames
1295 static HTMLFormElement *scanForForm(Node *start)
1296 {
1297     Node *n;
1298     for (n = start; n; n = n->traverseNextNode()) {
1299         if (n->hasTagName(formTag))
1300             return static_cast<HTMLFormElement*>(n);
1301         else if (n->isHTMLElement() && static_cast<HTMLElement*>(n)->isGenericFormElement())
1302             return static_cast<HTMLGenericFormElement*>(n)->form();
1303         else if (n->hasTagName(frameTag) || n->hasTagName(iframeTag)) {
1304             Node *childDoc = static_cast<HTMLFrameElementBase*>(n)->contentDocument();
1305             if (HTMLFormElement *frameResult = scanForForm(childDoc))
1306                 return frameResult;
1307         }
1308     }
1309     return 0;
1310 }
1311
1312 // We look for either the form containing the current focus, or for one immediately after it
1313 HTMLFormElement *Frame::currentForm() const
1314 {
1315     // start looking either at the active (first responder) node, or where the selection is
1316     Node *start = d->m_doc ? d->m_doc->focusNode() : 0;
1317     if (!start)
1318         start = selectionController()->start().node();
1319     
1320     // try walking up the node tree to find a form element
1321     Node *n;
1322     for (n = start; n; n = n->parentNode()) {
1323         if (n->hasTagName(formTag))
1324             return static_cast<HTMLFormElement*>(n);
1325         else if (n->isHTMLElement()
1326                    && static_cast<HTMLElement*>(n)->isGenericFormElement())
1327             return static_cast<HTMLGenericFormElement*>(n)->form();
1328     }
1329     
1330     // try walking forward in the node tree to find a form element
1331     return start ? scanForForm(start) : 0;
1332 }
1333
1334 // FIXME: should this go in SelectionController?
1335 void Frame::revealSelection(const RenderLayer::ScrollAlignment& alignment) const
1336 {
1337     IntRect rect;
1338     
1339     switch (selectionController()->state()) {
1340         case Selection::NONE:
1341             return;
1342             
1343         case Selection::CARET:
1344             rect = selectionController()->caretRect();
1345             break;
1346             
1347         case Selection::RANGE:
1348             rect = selectionRect();
1349             break;
1350     }
1351
1352     Position start = selectionController()->start();
1353     Position end = selectionController()->end();
1354
1355     ASSERT(start.node());
1356     if (start.node() && start.node()->renderer()) {
1357         RenderLayer *layer = start.node()->renderer()->enclosingLayer();
1358         if (layer) {
1359             ASSERT(!end.node() || !end.node()->renderer() 
1360                    || (end.node()->renderer()->enclosingLayer() == layer));
1361             layer->scrollRectToVisible(rect, alignment, alignment);
1362         }
1363     }
1364 }
1365
1366 void Frame::revealCaret(const RenderLayer::ScrollAlignment& alignment) const
1367 {
1368     if (selectionController()->isNone())
1369         return;
1370
1371     Position extent = selectionController()->extent();
1372     if (extent.node() && extent.node()->renderer()) {
1373         IntRect extentRect = VisiblePosition(extent).caretRect();
1374         RenderLayer* layer = extent.node()->renderer()->enclosingLayer();
1375         if (layer)
1376             layer->scrollRectToVisible(extentRect, alignment, alignment);
1377     }
1378 }
1379
1380 // FIXME: should this be here?
1381 bool Frame::scrollOverflow(ScrollDirection direction, ScrollGranularity granularity)
1382 {
1383     if (!document()) {
1384         return false;
1385     }
1386     
1387     Node *node = document()->focusNode();
1388     if (node == 0) {
1389         node = d->m_mousePressNode.get();
1390     }
1391     
1392     if (node != 0) {
1393         RenderObject *r = node->renderer();
1394         if (r != 0 && !r->isListBox()) {
1395             return r->scroll(direction, granularity);
1396         }
1397     }
1398     
1399     return false;
1400 }
1401
1402 void Frame::handleAutoscroll(RenderObject* renderer)
1403 {
1404     if (d->m_autoscrollTimer.isActive())
1405         return;
1406     setAutoscrollRenderer(renderer);
1407     startAutoscrollTimer();
1408 }
1409
1410 void Frame::autoscrollTimerFired(Timer<Frame>*)
1411 {
1412     if (!d->m_bMousePressed){
1413         stopAutoscrollTimer();
1414         return;
1415     }
1416     if (RenderObject* r = autoscrollRenderer())
1417         r->autoscroll();
1418 }
1419
1420 RenderObject* Frame::autoscrollRenderer() const
1421 {
1422     return d->m_autoscrollRenderer;
1423 }
1424
1425 void Frame::setAutoscrollRenderer(RenderObject* renderer)
1426 {
1427     d->m_autoscrollRenderer = renderer;
1428 }
1429
1430 HitTestResult Frame::hitTestResultAtPoint(const IntPoint& point, bool allowShadowContent)
1431 {
1432     HitTestResult result(point);
1433     if (!renderer())
1434         return result;
1435     renderer()->layer()->hitTest(HitTestRequest(true, true), result);
1436
1437     IntPoint widgetPoint(point);
1438     while (true) {
1439         Node* n = result.innerNode();
1440         if (!n || !n->renderer() || !n->renderer()->isWidget())
1441             break;
1442         Widget* widget = static_cast<RenderWidget*>(n->renderer())->widget();
1443         if (!widget || !widget->isFrameView())
1444             break;
1445         Frame* frame = static_cast<HTMLFrameElementBase*>(n)->contentFrame();
1446         if (!frame || !frame->renderer())
1447             break;
1448         int absX, absY;
1449         n->renderer()->absolutePosition(absX, absY, true);
1450         FrameView* view = static_cast<FrameView*>(widget);
1451         widgetPoint.move(view->contentsX() - absX, view->contentsY() - absY);
1452         HitTestResult widgetHitTestResult(widgetPoint);
1453         frame->renderer()->layer()->hitTest(HitTestRequest(true, true), widgetHitTestResult);
1454         result = widgetHitTestResult;
1455     }
1456
1457     if (!allowShadowContent) {
1458         Node* node = result.innerNode();
1459         if (node)
1460             node = node->shadowAncestorNode();
1461         result.setInnerNode(node);
1462         node = result.innerNonSharedNode();
1463         if (node)
1464             node = node->shadowAncestorNode();
1465         result.setInnerNonSharedNode(node); 
1466     }
1467
1468     return result;
1469 }
1470
1471
1472 void Frame::startAutoscrollTimer()
1473 {
1474     d->m_autoscrollTimer.startRepeating(autoscrollInterval);
1475 }
1476
1477 void Frame::stopAutoscrollTimer(bool rendererIsBeingDestroyed)
1478 {
1479     if (!rendererIsBeingDestroyed && autoscrollRenderer())
1480         autoscrollRenderer()->stopAutoscroll();
1481     setAutoscrollRenderer(0);
1482     d->m_autoscrollTimer.stop();
1483 }
1484
1485 // FIXME: why is this here instead of on the FrameView?
1486 void Frame::paint(GraphicsContext* p, const IntRect& rect)
1487 {
1488 #ifndef NDEBUG
1489     bool fillWithRed;
1490     if (!document() || document()->printing())
1491         fillWithRed = false; // Printing, don't fill with red (can't remember why).
1492     else if (document()->ownerElement())
1493         fillWithRed = false; // Subframe, don't fill with red.
1494     else if (view() && view()->isTransparent())
1495         fillWithRed = false; // Transparent, don't fill with red.
1496     else if (d->m_paintRestriction == PaintRestrictionSelectionOnly || d->m_paintRestriction == PaintRestrictionSelectionOnlyWhiteText)
1497         fillWithRed = false; // Selections are transparent, don't fill with red.
1498     else if (d->m_elementToDraw)
1499         fillWithRed = false; // Element images are transparent, don't fill with red.
1500     else
1501         fillWithRed = true;
1502     
1503     if (fillWithRed)
1504         p->fillRect(rect, Color(0xFF, 0, 0));
1505 #endif
1506     
1507     if (renderer()) {
1508         // d->m_elementToDraw is used to draw only one element
1509         RenderObject *eltRenderer = d->m_elementToDraw ? d->m_elementToDraw->renderer() : 0;
1510         if (d->m_paintRestriction == PaintRestrictionNone)
1511             renderer()->document()->invalidateRenderedRectsForMarkersInRect(rect);
1512         renderer()->layer()->paint(p, rect, d->m_paintRestriction, eltRenderer);
1513
1514 #if PLATFORM(MAC)
1515         // Regions may have changed as a result of the visibility/z-index of element changing.
1516         if (renderer()->document()->dashboardRegionsDirty())
1517             renderer()->view()->frameView()->updateDashboardRegions();
1518 #endif
1519     } else
1520         LOG_ERROR("called Frame::paint with nil renderer");
1521 }
1522
1523 #if PLATFORM(CG)
1524
1525 void Frame::adjustPageHeight(float *newBottom, float oldTop, float oldBottom, float bottomLimit)
1526 {
1527     RenderView *root = static_cast<RenderView*>(document()->renderer());
1528     if (root) {
1529         // Use a context with painting disabled.
1530         GraphicsContext context((PlatformGraphicsContext*)0);
1531         root->setTruncatedAt((int)floorf(oldBottom));
1532         IntRect dirtyRect(0, (int)floorf(oldTop), root->docWidth(), (int)ceilf(oldBottom - oldTop));
1533         root->layer()->paint(&context, dirtyRect);
1534         *newBottom = root->bestTruncatedAt();
1535         if (*newBottom == 0)
1536             *newBottom = oldBottom;
1537     } else
1538         *newBottom = oldBottom;
1539 }
1540
1541 #endif
1542
1543 Frame *Frame::frameForWidget(const Widget *widget)
1544 {
1545     ASSERT_ARG(widget, widget);
1546     
1547     Node *node = nodeForWidget(widget);
1548     if (node)
1549         return frameForNode(node);
1550     
1551     // Assume all widgets are either form controls, or FrameViews.
1552     ASSERT(widget->isFrameView());
1553     return static_cast<const FrameView*>(widget)->frame();
1554 }
1555
1556 Frame *Frame::frameForNode(Node *node)
1557 {
1558     ASSERT_ARG(node, node);
1559     return node->document()->frame();
1560 }
1561
1562 Node* Frame::nodeForWidget(const Widget* widget)
1563 {
1564     ASSERT_ARG(widget, widget);
1565     WidgetClient* client = widget->client();
1566     if (!client)
1567         return 0;
1568     return client->element(const_cast<Widget*>(widget));
1569 }
1570
1571 void Frame::clearDocumentFocus(Widget *widget)
1572 {
1573     Node *node = nodeForWidget(widget);
1574     ASSERT(node);
1575     node->document()->setFocusNode(0);
1576 }
1577
1578 void Frame::forceLayout()
1579 {
1580     FrameView *v = d->m_view.get();
1581     if (v) {
1582         v->layout(false);
1583         // We cannot unschedule a pending relayout, since the force can be called with
1584         // a tiny rectangle from a drawRect update.  By unscheduling we in effect
1585         // "validate" and stop the necessary full repaint from occurring.  Basically any basic
1586         // append/remove DHTML is broken by this call.  For now, I have removed the optimization
1587         // until we have a better invalidation stategy. -dwh
1588         //v->unscheduleRelayout();
1589     }
1590 }
1591
1592 void Frame::forceLayoutWithPageWidthRange(float minPageWidth, float maxPageWidth)
1593 {
1594     // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
1595     // the state of things before and after the layout
1596     RenderView *root = static_cast<RenderView*>(document()->renderer());
1597     if (root) {
1598         // This magic is basically copied from khtmlview::print
1599         int pageW = (int)ceilf(minPageWidth);
1600         root->setWidth(pageW);
1601         root->setNeedsLayoutAndMinMaxRecalc();
1602         forceLayout();
1603         
1604         // If we don't fit in the minimum page width, we'll lay out again. If we don't fit in the
1605         // maximum page width, we will lay out to the maximum page width and clip extra content.
1606         // FIXME: We are assuming a shrink-to-fit printing implementation.  A cropping
1607         // implementation should not do this!
1608         int rightmostPos = root->rightmostPosition();
1609         if (rightmostPos > minPageWidth) {
1610             pageW = min(rightmostPos, (int)ceilf(maxPageWidth));
1611             root->setWidth(pageW);
1612             root->setNeedsLayoutAndMinMaxRecalc();
1613             forceLayout();
1614         }
1615     }
1616 }
1617
1618 void Frame::sendResizeEvent()
1619 {
1620     if (Document* doc = document())
1621         doc->dispatchWindowEvent(EventNames::resizeEvent, false, false);
1622 }
1623
1624 void Frame::sendScrollEvent()
1625 {
1626     FrameView *v = d->m_view.get();
1627     if (v) {
1628         Document *doc = document();
1629         if (!doc)
1630             return;
1631         doc->dispatchHTMLEvent(scrollEvent, true, false);
1632     }
1633 }
1634
1635 bool Frame::canMouseDownStartSelect(Node* node)
1636 {
1637     if (!node || !node->renderer())
1638         return true;
1639     
1640     // Check to see if -webkit-user-select has been set to none
1641     if (!node->renderer()->canSelect())
1642         return false;
1643     
1644     // Some controls and images can't start a select on a mouse down.
1645     for (RenderObject* curr = node->renderer(); curr; curr = curr->parent()) {
1646         if (curr->style()->userSelect() == SELECT_IGNORE)
1647             return false;
1648     }
1649     
1650     return true;
1651 }
1652
1653 void Frame::clearTimers(FrameView *view)
1654 {
1655     if (view) {
1656         view->unscheduleRelayout();
1657         if (view->frame()) {
1658             Document* document = view->frame()->document();
1659             if (document && document->renderer() && document->renderer()->layer())
1660                 document->renderer()->layer()->suspendMarquees();
1661         }
1662     }
1663 }
1664
1665 void Frame::clearTimers()
1666 {
1667     clearTimers(d->m_view.get());
1668 }
1669
1670 RenderStyle *Frame::styleForSelectionStart(Node *&nodeToRemove) const
1671 {
1672     nodeToRemove = 0;
1673     
1674     if (!document())
1675         return 0;
1676     if (selectionController()->isNone())
1677         return 0;
1678     
1679     Position pos = selectionController()->selection().visibleStart().deepEquivalent();
1680     if (!pos.inRenderedContent())
1681         return 0;
1682     Node *node = pos.node();
1683     if (!node)
1684         return 0;
1685     
1686     if (!d->m_typingStyle)
1687         return node->renderer()->style();
1688     
1689     ExceptionCode ec = 0;
1690     RefPtr<Element> styleElement = document()->createElementNS(xhtmlNamespaceURI, "span", ec);
1691     ASSERT(ec == 0);
1692     
1693     styleElement->setAttribute(styleAttr, d->m_typingStyle->cssText().impl(), ec);
1694     ASSERT(ec == 0);
1695     
1696     styleElement->appendChild(document()->createEditingTextNode(""), ec);
1697     ASSERT(ec == 0);
1698     
1699     node->parentNode()->appendChild(styleElement, ec);
1700     ASSERT(ec == 0);
1701     
1702     nodeToRemove = styleElement.get();    
1703     return styleElement->renderer()->style();
1704 }
1705
1706 void Frame::setSelectionFromNone()
1707 {
1708     // Put a caret inside the body if the entire frame is editable (either the 
1709     // entire WebView is editable or designMode is on for this document).
1710     Document *doc = document();
1711     if (!doc || !selectionController()->isNone() || !isContentEditable())
1712         return;
1713         
1714     Node* node = doc->documentElement();
1715     while (node && !node->hasTagName(bodyTag))
1716         node = node->traverseNextNode();
1717     if (node)
1718         selectionController()->setSelection(Selection(Position(node, 0), DOWNSTREAM));
1719 }
1720
1721 bool Frame::isActive() const
1722 {
1723     return d->m_isActive;
1724 }
1725
1726 void Frame::setIsActive(bool flag)
1727 {
1728     if (d->m_isActive == flag)
1729         return;
1730     
1731     d->m_isActive = flag;
1732
1733     // This method does the job of updating the view based on whether the view is "active".
1734     // This involves three kinds of drawing updates:
1735
1736     // 1. The background color used to draw behind selected content (active | inactive color)
1737     if (d->m_view)
1738         d->m_view->updateContents(enclosingIntRect(visibleSelectionRect()));
1739
1740     // 2. Caret blinking (blinks | does not blink)
1741     if (flag)
1742         setSelectionFromNone();
1743     setCaretVisible(flag);
1744     
1745     // 3. The drawing of a focus ring around links in web pages.
1746     Document *doc = document();
1747     if (doc) {
1748         Node *node = doc->focusNode();
1749         if (node) {
1750             node->setChanged();
1751             if (node->renderer() && node->renderer()->style()->hasAppearance())
1752                 theme()->stateChanged(node->renderer(), FocusState);
1753         }
1754     }
1755     
1756     // 4. Changing the tint of controls from clear to aqua/graphite and vice versa.  We
1757     // do a "fake" paint.  When the theme gets a paint call, it can then do an invalidate.  This is only
1758     // done if the theme supports control tinting.
1759     if (doc && d->m_view && theme()->supportsControlTints() && renderer()) {
1760         doc->updateLayout(); // Ensure layout is up to date.
1761         IntRect visibleRect(enclosingIntRect(d->m_view->visibleContentRect()));
1762         GraphicsContext context((PlatformGraphicsContext*)0);
1763         context.setUpdatingControlTints(true);
1764         paint(&context, visibleRect);
1765     }
1766    
1767     // 5. Enable or disable secure keyboard entry
1768     if ((flag && !isSecureKeyboardEntry() && doc && doc->focusNode() && doc->focusNode()->hasTagName(inputTag) && 
1769             static_cast<HTMLInputElement*>(doc->focusNode())->inputType() == HTMLInputElement::PASSWORD) ||
1770         (!flag && isSecureKeyboardEntry()))
1771             setSecureKeyboardEntry(flag);
1772 }
1773
1774 void Frame::setWindowHasFocus(bool flag)
1775 {
1776     if (d->m_windowHasFocus == flag)
1777         return;
1778     d->m_windowHasFocus = flag;
1779     
1780     if (Document *doc = document())
1781         doc->dispatchWindowEvent(flag ? focusEvent : blurEvent, false, false);
1782 }
1783
1784 bool Frame::inViewSourceMode() const
1785 {
1786     return d->m_inViewSourceMode;
1787 }
1788
1789 void Frame::setInViewSourceMode(bool mode) const
1790 {
1791     d->m_inViewSourceMode = mode;
1792 }
1793   
1794 UChar Frame::backslashAsCurrencySymbol() const
1795 {
1796     Document *doc = document();
1797     if (!doc)
1798         return '\\';
1799     TextResourceDecoder *decoder = doc->decoder();
1800     if (!decoder)
1801         return '\\';
1802
1803     return decoder->encoding().backslashAsCurrencySymbol();
1804 }
1805
1806 bool Frame::markedTextUsesUnderlines() const
1807 {
1808     return d->m_markedTextUsesUnderlines;
1809 }
1810
1811 const Vector<MarkedTextUnderline>& Frame::markedTextUnderlines() const
1812 {
1813     return d->m_markedTextUnderlines;
1814 }
1815
1816 // Searches from the beginning of the document if nothing is selected.
1817 bool Frame::findString(const String& target, bool forward, bool caseFlag, bool wrapFlag)
1818 {
1819     if (target.isEmpty())
1820         return false;
1821     
1822     // Initially search from the start (if forward) or end (if backward) of the selection, and search to edge of document.
1823     RefPtr<Range> searchRange(rangeOfContents(document()));
1824     Selection selection(selectionController()->selection());
1825     if (!selection.isNone()) {
1826         if (forward)
1827             setStart(searchRange.get(), selection.visibleStart());
1828         else
1829             setEnd(searchRange.get(), selection.visibleEnd());
1830     }
1831     RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, forward, caseFlag));
1832     // If the found range is already selected, find again.
1833     // Build a selection with the found range to remove collapsed whitespace.
1834     // Compare ranges instead of selection objects to ignore the way that the current selection was made.
1835     if (!selection.isNone() && *Selection(resultRange.get()).toRange() == *selection.toRange()) {
1836         searchRange = rangeOfContents(document());
1837         if (forward)
1838             setStart(searchRange.get(), selection.visibleEnd());
1839         else
1840             setEnd(searchRange.get(), selection.visibleStart());
1841         resultRange = findPlainText(searchRange.get(), target, forward, caseFlag);
1842     }
1843     
1844     int exception = 0;
1845     
1846     // If we didn't find anything and we're wrapping, search again in the entire document (this will
1847     // redundantly re-search the area already searched in some cases).
1848     if (resultRange->collapsed(exception) && wrapFlag) {
1849         searchRange = rangeOfContents(document());
1850         resultRange = findPlainText(searchRange.get(), target, forward, caseFlag);
1851         // We used to return false here if we ended up with the same range that we started with
1852         // (e.g., the selection was already the only instance of this text). But we decided that
1853         // this should be a success case instead, so we'll just fall through in that case.
1854     }
1855
1856     if (resultRange->collapsed(exception))
1857         return false;
1858
1859     selectionController()->setSelection(Selection(resultRange.get(), DOWNSTREAM));
1860     revealSelection();
1861     return true;
1862 }
1863
1864 unsigned Frame::markAllMatchesForText(const String& target, bool caseFlag, unsigned limit)
1865 {
1866     if (target.isEmpty())
1867         return 0;
1868     
1869     RefPtr<Range> searchRange(rangeOfContents(document()));
1870     
1871     int exception = 0;
1872     unsigned matchCount = 0;
1873     do {
1874         RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, true, caseFlag));
1875         if (resultRange->collapsed(exception))
1876             break;
1877         
1878         // A non-collapsed result range can in some funky whitespace cases still not
1879         // advance the range's start position (4509328). Break to avoid infinite loop.
1880         VisiblePosition newStart = endVisiblePosition(resultRange.get(), DOWNSTREAM);
1881         if (newStart == startVisiblePosition(searchRange.get(), DOWNSTREAM))
1882             break;
1883
1884         ++matchCount;
1885         
1886         document()->addMarker(resultRange.get(), DocumentMarker::TextMatch);        
1887         
1888         // Stop looking if we hit the specified limit. A limit of 0 means no limit.
1889         if (limit > 0 && matchCount >= limit)
1890             break;
1891         
1892         setStart(searchRange.get(), newStart);
1893     } while (true);
1894     
1895     // Do a "fake" paint in order to execute the code that computes the rendered rect for 
1896     // each text match.
1897     Document* doc = document();
1898     if (doc && d->m_view && renderer()) {
1899         doc->updateLayout(); // Ensure layout is up to date.
1900         IntRect visibleRect(enclosingIntRect(d->m_view->visibleContentRect()));
1901         GraphicsContext context((PlatformGraphicsContext*)0);
1902         context.setPaintingDisabled(true);
1903         paint(&context, visibleRect);
1904     }
1905     
1906     return matchCount;
1907 }
1908
1909 bool Frame::markedTextMatchesAreHighlighted() const
1910 {
1911     return d->m_highlightTextMatches;
1912 }
1913
1914 void Frame::setMarkedTextMatchesAreHighlighted(bool flag)
1915 {
1916     if (flag == d->m_highlightTextMatches)
1917         return;
1918     
1919     d->m_highlightTextMatches = flag;
1920     document()->repaintMarkers(DocumentMarker::TextMatch);
1921 }
1922
1923 Node *Frame::mousePressNode()
1924 {
1925     return d->m_mousePressNode.get();
1926 }
1927
1928 FrameTree* Frame::tree() const
1929 {
1930     return &d->m_treeNode;
1931 }
1932
1933 DOMWindow* Frame::domWindow() const
1934 {
1935     if (!d->m_domWindow)
1936         d->m_domWindow = new DOMWindow(const_cast<Frame*>(this));
1937
1938     return d->m_domWindow.get();
1939 }
1940
1941 Page* Frame::page() const
1942 {
1943     return d->m_page;
1944 }
1945
1946 void Frame::pageDestroyed()
1947 {
1948     d->m_page = 0;
1949
1950     // This will stop any JS timers
1951     if (d->m_jscript && d->m_jscript->haveInterpreter())
1952         if (Window* w = Window::retrieveWindow(this))
1953             w->disconnectFrame();
1954 }
1955
1956 void Frame::setStatusBarText(const String&)
1957 {
1958 }
1959
1960 void Frame::disconnectOwnerElement()
1961 {
1962     if (d->m_ownerElement && d->m_page)
1963         d->m_page->decrementFrameCount();
1964         
1965     d->m_ownerElement = 0;
1966 }
1967
1968 String Frame::documentTypeString() const
1969 {
1970     if (Document *doc = document())
1971         if (DocumentType *doctype = doc->realDocType())
1972             return doctype->toString();
1973
1974     return String();
1975 }
1976
1977 bool Frame::prohibitsScrolling() const
1978 {
1979     return d->m_prohibitsScrolling;
1980 }
1981
1982 void Frame::setProhibitsScrolling(const bool prohibit)
1983 {
1984     d->m_prohibitsScrolling = prohibit;
1985 }
1986
1987 FramePrivate::FramePrivate(Page* page, Frame* parent, Frame* thisFrame, Element* ownerElement, PassRefPtr<EditorClient> client)
1988     : m_page(page)
1989     , m_treeNode(thisFrame, parent)
1990     , m_ownerElement(ownerElement)
1991     , m_jscript(0)
1992     , m_bJScriptEnabled(true)
1993     , m_bJavaEnabled(true)
1994     , m_bPluginsEnabled(true)
1995     , m_settings(0)
1996     , m_zoomFactor(parent ? parent->d->m_zoomFactor : 100)
1997     , m_bMousePressed(false)
1998     , m_beganSelectingText(false)
1999     , m_selectionController(thisFrame)
2000     , m_caretBlinkTimer(thisFrame, &Frame::caretBlinkTimerFired)
2001     , m_editor(thisFrame, client)
2002     , m_command(thisFrame)
2003     , m_caretVisible(false)
2004     , m_caretPaint(true)
2005     , m_isActive(false)
2006     , m_lifeSupportTimer(thisFrame, &Frame::lifeSupportTimerFired)
2007     , m_loader(new FrameLoader(thisFrame))
2008     , m_userStyleSheetLoader(0)
2009     , m_autoscrollTimer(thisFrame, &Frame::autoscrollTimerFired)
2010     , m_autoscrollRenderer(0)
2011     , m_mouseDownMayStartAutoscroll(false)
2012     , m_mouseDownMayStartDrag(false)
2013     , m_paintRestriction(PaintRestrictionNone)
2014     , m_markedTextUsesUnderlines(false)
2015     , m_highlightTextMatches(false)
2016     , m_windowHasFocus(false)
2017     , m_inViewSourceMode(false)
2018     , frameCount(0)
2019     , m_prohibitsScrolling(false)
2020 {
2021 }
2022
2023 FramePrivate::~FramePrivate()
2024 {
2025     delete m_jscript;
2026     delete m_loader;
2027 }
2028
2029 } // namespace WebCore