d8b071cdf667e27f3be3d6d27433a9915bf5ce4d
[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 CSSMutableStyleDeclaration *Frame::typingStyle() const
849 {
850     return d->m_typingStyle.get();
851 }
852
853 void Frame::setTypingStyle(CSSMutableStyleDeclaration *style)
854 {
855     d->m_typingStyle = style;
856 }
857
858 void Frame::clearTypingStyle()
859 {
860     d->m_typingStyle = 0;
861 }
862
863 bool Frame::tabsToLinks(KeyboardEvent*) const
864 {
865     return true;
866 }
867
868 bool Frame::tabsToAllControls(KeyboardEvent*) const
869 {
870     return true;
871 }
872
873 void Frame::copyToPasteboard()
874 {
875     issueCopyCommand();
876 }
877
878 void Frame::cutToPasteboard()
879 {
880     issueCutCommand();
881 }
882
883 void Frame::pasteFromPasteboard()
884 {
885     issuePasteCommand();
886 }
887
888 void Frame::pasteAndMatchStyle()
889 {
890     issuePasteAndMatchStyleCommand();
891 }
892
893 void Frame::transpose()
894 {
895     issueTransposeCommand();
896 }
897
898 void Frame::redo()
899 {
900     issueRedoCommand();
901 }
902
903 void Frame::undo()
904 {
905     issueUndoCommand();
906 }
907
908
909 void Frame::computeAndSetTypingStyle(CSSStyleDeclaration *style, EditAction editingAction)
910 {
911     if (!style || style->length() == 0) {
912         clearTypingStyle();
913         return;
914     }
915
916     // Calculate the current typing style.
917     RefPtr<CSSMutableStyleDeclaration> mutableStyle = style->makeMutable();
918     if (typingStyle()) {
919         typingStyle()->merge(mutableStyle.get());
920         mutableStyle = typingStyle();
921     }
922
923     Node *node = selectionController()->selection().visibleStart().deepEquivalent().node();
924     CSSComputedStyleDeclaration computedStyle(node);
925     computedStyle.diff(mutableStyle.get());
926     
927     // Handle block styles, substracting these from the typing style.
928     RefPtr<CSSMutableStyleDeclaration> blockStyle = mutableStyle->copyBlockProperties();
929     blockStyle->diff(mutableStyle.get());
930     if (document() && blockStyle->length() > 0)
931         applyCommand(new ApplyStyleCommand(document(), blockStyle.get(), editingAction));
932     
933     // Set the remaining style as the typing style.
934     d->m_typingStyle = mutableStyle.release();
935 }
936
937 static void updateState(CSSMutableStyleDeclaration *desiredStyle, CSSComputedStyleDeclaration *computedStyle, bool& atStart, Frame::TriState& state)
938 {
939     DeprecatedValueListConstIterator<CSSProperty> end;
940     for (DeprecatedValueListConstIterator<CSSProperty> it = desiredStyle->valuesIterator(); it != end; ++it) {
941         int propertyID = (*it).id();
942         String desiredProperty = desiredStyle->getPropertyValue(propertyID);
943         String computedProperty = computedStyle->getPropertyValue(propertyID);
944         Frame::TriState propertyState = equalIgnoringCase(desiredProperty, computedProperty)
945             ? Frame::trueTriState : Frame::falseTriState;
946         if (atStart) {
947             state = propertyState;
948             atStart = false;
949         } else if (state != propertyState) {
950             state = Frame::mixedTriState;
951             break;
952         }
953     }
954 }
955
956 Frame::TriState Frame::selectionHasStyle(CSSStyleDeclaration *style) const
957 {
958     bool atStart = true;
959     TriState state = falseTriState;
960
961     RefPtr<CSSMutableStyleDeclaration> mutableStyle = style->makeMutable();
962
963     if (!selectionController()->isRange()) {
964         Node* nodeToRemove;
965         RefPtr<CSSComputedStyleDeclaration> selectionStyle = selectionComputedStyle(nodeToRemove);
966         if (!selectionStyle)
967             return falseTriState;
968         updateState(mutableStyle.get(), selectionStyle.get(), atStart, state);
969         if (nodeToRemove) {
970             ExceptionCode ec = 0;
971             nodeToRemove->remove(ec);
972             assert(ec == 0);
973         }
974     } else {
975         for (Node* node = selectionController()->start().node(); node; node = node->traverseNextNode()) {
976             RefPtr<CSSComputedStyleDeclaration> computedStyle = new CSSComputedStyleDeclaration(node);
977             if (computedStyle)
978                 updateState(mutableStyle.get(), computedStyle.get(), atStart, state);
979             if (state == mixedTriState)
980                 break;
981             if (node == selectionController()->end().node())
982                 break;
983         }
984     }
985
986     return state;
987 }
988
989 String Frame::selectionStartStylePropertyValue(int stylePropertyID) const
990 {
991     Node *nodeToRemove;
992     RefPtr<CSSStyleDeclaration> selectionStyle = selectionComputedStyle(nodeToRemove);
993     if (!selectionStyle)
994         return String();
995
996     String value = selectionStyle->getPropertyValue(stylePropertyID);
997
998     if (nodeToRemove) {
999         ExceptionCode ec = 0;
1000         nodeToRemove->remove(ec);
1001         assert(ec == 0);
1002     }
1003
1004     return value;
1005 }
1006
1007 CSSComputedStyleDeclaration *Frame::selectionComputedStyle(Node *&nodeToRemove) const
1008 {
1009     nodeToRemove = 0;
1010
1011     if (!document())
1012         return 0;
1013
1014     if (selectionController()->isNone())
1015         return 0;
1016
1017     RefPtr<Range> range(selectionController()->toRange());
1018     Position pos = range->editingStartPosition();
1019
1020     Element *elem = pos.element();
1021     if (!elem)
1022         return 0;
1023     
1024     RefPtr<Element> styleElement = elem;
1025     ExceptionCode ec = 0;
1026
1027     if (d->m_typingStyle) {
1028         styleElement = document()->createElementNS(xhtmlNamespaceURI, "span", ec);
1029         assert(ec == 0);
1030
1031         styleElement->setAttribute(styleAttr, d->m_typingStyle->cssText().impl(), ec);
1032         assert(ec == 0);
1033         
1034         styleElement->appendChild(document()->createEditingTextNode(""), ec);
1035         assert(ec == 0);
1036
1037         if (elem->renderer() && elem->renderer()->canHaveChildren()) {
1038             elem->appendChild(styleElement, ec);
1039         } else {
1040             Node *parent = elem->parent();
1041             Node *next = elem->nextSibling();
1042
1043             if (next) {
1044                 parent->insertBefore(styleElement, next, ec);
1045             } else {
1046                 parent->appendChild(styleElement, ec);
1047             }
1048         }
1049         assert(ec == 0);
1050
1051         nodeToRemove = styleElement.get();
1052     }
1053
1054     return new CSSComputedStyleDeclaration(styleElement);
1055 }
1056
1057 void Frame::applyEditingStyleToBodyElement() const
1058 {
1059     if (!d->m_doc)
1060         return;
1061         
1062     RefPtr<NodeList> list = d->m_doc->getElementsByTagName("body");
1063     unsigned len = list->length();
1064     for (unsigned i = 0; i < len; i++) {
1065         applyEditingStyleToElement(static_cast<Element*>(list->item(i)));    
1066     }
1067 }
1068
1069 void Frame::removeEditingStyleFromBodyElement() const
1070 {
1071     if (!d->m_doc)
1072         return;
1073         
1074     RefPtr<NodeList> list = d->m_doc->getElementsByTagName("body");
1075     unsigned len = list->length();
1076     for (unsigned i = 0; i < len; i++) {
1077         removeEditingStyleFromElement(static_cast<Element*>(list->item(i)));    
1078     }
1079 }
1080
1081 void Frame::applyEditingStyleToElement(Element* element) const
1082 {
1083     if (!element)
1084         return;
1085
1086     CSSStyleDeclaration* style = element->style();
1087     ASSERT(style);
1088
1089     ExceptionCode ec = 0;
1090     style->setProperty(CSS_PROP_WORD_WRAP, "break-word", false, ec);
1091     ASSERT(ec == 0);
1092     style->setProperty(CSS_PROP__WEBKIT_NBSP_MODE, "space", false, ec);
1093     ASSERT(ec == 0);
1094     style->setProperty(CSS_PROP__WEBKIT_LINE_BREAK, "after-white-space", false, ec);
1095     ASSERT(ec == 0);
1096 }
1097
1098 void Frame::removeEditingStyleFromElement(Element*) const
1099 {
1100 }
1101
1102 bool Frame::isCharacterSmartReplaceExempt(UChar, bool)
1103 {
1104     // no smart replace
1105     return true;
1106 }
1107
1108 #ifndef NDEBUG
1109 static HashSet<Frame*> lifeSupportSet;
1110 #endif
1111
1112 void Frame::endAllLifeSupport()
1113 {
1114 #ifndef NDEBUG
1115     HashSet<Frame*> lifeSupportCopy = lifeSupportSet;
1116     HashSet<Frame*>::iterator end = lifeSupportCopy.end();
1117     for (HashSet<Frame*>::iterator it = lifeSupportCopy.begin(); it != end; ++it)
1118         (*it)->endLifeSupport();
1119 #endif
1120 }
1121
1122 void Frame::keepAlive()
1123 {
1124     if (d->m_lifeSupportTimer.isActive())
1125         return;
1126     ref();
1127 #ifndef NDEBUG
1128     lifeSupportSet.add(this);
1129 #endif
1130     d->m_lifeSupportTimer.startOneShot(0);
1131 }
1132
1133 void Frame::endLifeSupport()
1134 {
1135     if (!d->m_lifeSupportTimer.isActive())
1136         return;
1137     d->m_lifeSupportTimer.stop();
1138 #ifndef NDEBUG
1139     lifeSupportSet.remove(this);
1140 #endif
1141     deref();
1142 }
1143
1144 void Frame::lifeSupportTimerFired(Timer<Frame>*)
1145 {
1146 #ifndef NDEBUG
1147     lifeSupportSet.remove(this);
1148 #endif
1149     deref();
1150 }
1151
1152 bool Frame::mouseDownMayStartAutoscroll() const
1153 {
1154     return d->m_mouseDownMayStartAutoscroll;
1155 }
1156
1157 void Frame::setMouseDownMayStartAutoscroll(bool b)
1158 {
1159     d->m_mouseDownMayStartAutoscroll = b;
1160 }
1161
1162 bool Frame::mouseDownMayStartDrag() const
1163 {
1164     return d->m_mouseDownMayStartDrag;
1165 }
1166
1167 void Frame::setMouseDownMayStartDrag(bool b)
1168 {
1169     d->m_mouseDownMayStartDrag = b;
1170 }
1171
1172 void Frame::setSettings(Settings *settings)
1173 {
1174     d->m_settings = settings;
1175 }
1176
1177 RenderObject *Frame::renderer() const
1178 {
1179     Document *doc = document();
1180     return doc ? doc->renderer() : 0;
1181 }
1182
1183 Element* Frame::ownerElement()
1184 {
1185     return d->m_ownerElement;
1186 }
1187
1188 RenderPart* Frame::ownerRenderer()
1189 {
1190     Element* ownerElement = d->m_ownerElement;
1191     if (!ownerElement)
1192         return 0;
1193     return static_cast<RenderPart*>(ownerElement->renderer());
1194 }
1195
1196 IntRect Frame::selectionRect() const
1197 {
1198     RenderView *root = static_cast<RenderView*>(renderer());
1199     if (!root)
1200         return IntRect();
1201
1202     return root->selectionRect();
1203 }
1204
1205 // returns FloatRect because going through IntRect would truncate any floats
1206 FloatRect Frame::visibleSelectionRect() const
1207 {
1208     if (!d->m_view)
1209         return FloatRect();
1210     
1211     return intersection(selectionRect(), d->m_view->visibleContentRect());
1212 }
1213
1214 bool Frame::isFrameSet() const
1215 {
1216     Document* document = d->m_doc.get();
1217     if (!document || !document->isHTMLDocument())
1218         return false;
1219     Node *body = static_cast<HTMLDocument*>(document)->body();
1220     return body && body->renderer() && body->hasTagName(framesetTag);
1221 }
1222
1223 // Scans logically forward from "start", including any child frames
1224 static HTMLFormElement *scanForForm(Node *start)
1225 {
1226     Node *n;
1227     for (n = start; n; n = n->traverseNextNode()) {
1228         if (n->hasTagName(formTag))
1229             return static_cast<HTMLFormElement*>(n);
1230         else if (n->isHTMLElement() && static_cast<HTMLElement*>(n)->isGenericFormElement())
1231             return static_cast<HTMLGenericFormElement*>(n)->form();
1232         else if (n->hasTagName(frameTag) || n->hasTagName(iframeTag)) {
1233             Node *childDoc = static_cast<HTMLFrameElementBase*>(n)->contentDocument();
1234             if (HTMLFormElement *frameResult = scanForForm(childDoc))
1235                 return frameResult;
1236         }
1237     }
1238     return 0;
1239 }
1240
1241 // We look for either the form containing the current focus, or for one immediately after it
1242 HTMLFormElement *Frame::currentForm() const
1243 {
1244     // start looking either at the active (first responder) node, or where the selection is
1245     Node *start = d->m_doc ? d->m_doc->focusNode() : 0;
1246     if (!start)
1247         start = selectionController()->start().node();
1248     
1249     // try walking up the node tree to find a form element
1250     Node *n;
1251     for (n = start; n; n = n->parentNode()) {
1252         if (n->hasTagName(formTag))
1253             return static_cast<HTMLFormElement*>(n);
1254         else if (n->isHTMLElement()
1255                    && static_cast<HTMLElement*>(n)->isGenericFormElement())
1256             return static_cast<HTMLGenericFormElement*>(n)->form();
1257     }
1258     
1259     // try walking forward in the node tree to find a form element
1260     return start ? scanForForm(start) : 0;
1261 }
1262
1263 // FIXME: should this go in SelectionController?
1264 void Frame::revealSelection(const RenderLayer::ScrollAlignment& alignment) const
1265 {
1266     IntRect rect;
1267     
1268     switch (selectionController()->state()) {
1269         case Selection::NONE:
1270             return;
1271             
1272         case Selection::CARET:
1273             rect = selectionController()->caretRect();
1274             break;
1275             
1276         case Selection::RANGE:
1277             rect = selectionRect();
1278             break;
1279     }
1280
1281     Position start = selectionController()->start();
1282     Position end = selectionController()->end();
1283
1284     ASSERT(start.node());
1285     if (start.node() && start.node()->renderer()) {
1286         RenderLayer *layer = start.node()->renderer()->enclosingLayer();
1287         if (layer) {
1288             ASSERT(!end.node() || !end.node()->renderer() 
1289                    || (end.node()->renderer()->enclosingLayer() == layer));
1290             layer->scrollRectToVisible(rect, alignment, alignment);
1291         }
1292     }
1293 }
1294
1295 void Frame::revealCaret(const RenderLayer::ScrollAlignment& alignment) const
1296 {
1297     if (selectionController()->isNone())
1298         return;
1299
1300     Position extent = selectionController()->extent();
1301     if (extent.node() && extent.node()->renderer()) {
1302         IntRect extentRect = VisiblePosition(extent).caretRect();
1303         RenderLayer* layer = extent.node()->renderer()->enclosingLayer();
1304         if (layer)
1305             layer->scrollRectToVisible(extentRect, alignment, alignment);
1306     }
1307 }
1308
1309 // FIXME: should this be here?
1310 bool Frame::scrollOverflow(ScrollDirection direction, ScrollGranularity granularity)
1311 {
1312     if (!document()) {
1313         return false;
1314     }
1315     
1316     Node *node = document()->focusNode();
1317     if (node == 0) {
1318         node = d->m_mousePressNode.get();
1319     }
1320     
1321     if (node != 0) {
1322         RenderObject *r = node->renderer();
1323         if (r != 0 && !r->isListBox()) {
1324             return r->scroll(direction, granularity);
1325         }
1326     }
1327     
1328     return false;
1329 }
1330
1331 void Frame::handleAutoscroll(RenderObject* renderer)
1332 {
1333     if (d->m_autoscrollTimer.isActive())
1334         return;
1335     setAutoscrollRenderer(renderer);
1336     startAutoscrollTimer();
1337 }
1338
1339 void Frame::autoscrollTimerFired(Timer<Frame>*)
1340 {
1341     if (!d->m_bMousePressed){
1342         stopAutoscrollTimer();
1343         return;
1344     }
1345     if (RenderObject* r = autoscrollRenderer())
1346         r->autoscroll();
1347 }
1348
1349 RenderObject* Frame::autoscrollRenderer() const
1350 {
1351     return d->m_autoscrollRenderer;
1352 }
1353
1354 void Frame::setAutoscrollRenderer(RenderObject* renderer)
1355 {
1356     d->m_autoscrollRenderer = renderer;
1357 }
1358
1359 HitTestResult Frame::hitTestResultAtPoint(const IntPoint& point, bool allowShadowContent)
1360 {
1361     HitTestResult result(point);
1362     if (!renderer())
1363         return result;
1364     renderer()->layer()->hitTest(HitTestRequest(true, true), result);
1365
1366     IntPoint widgetPoint(point);
1367     while (true) {
1368         Node* n = result.innerNode();
1369         if (!n || !n->renderer() || !n->renderer()->isWidget())
1370             break;
1371         Widget* widget = static_cast<RenderWidget*>(n->renderer())->widget();
1372         if (!widget || !widget->isFrameView())
1373             break;
1374         Frame* frame = static_cast<HTMLFrameElementBase*>(n)->contentFrame();
1375         if (!frame || !frame->renderer())
1376             break;
1377         int absX, absY;
1378         n->renderer()->absolutePosition(absX, absY, true);
1379         FrameView* view = static_cast<FrameView*>(widget);
1380         widgetPoint.move(view->contentsX() - absX, view->contentsY() - absY);
1381         HitTestResult widgetHitTestResult(widgetPoint);
1382         frame->renderer()->layer()->hitTest(HitTestRequest(true, true), widgetHitTestResult);
1383         result = widgetHitTestResult;
1384     }
1385
1386     if (!allowShadowContent) {
1387         Node* node = result.innerNode();
1388         if (node)
1389             node = node->shadowAncestorNode();
1390         result.setInnerNode(node);
1391         node = result.innerNonSharedNode();
1392         if (node)
1393             node = node->shadowAncestorNode();
1394         result.setInnerNonSharedNode(node); 
1395     }
1396
1397     return result;
1398 }
1399
1400
1401 void Frame::startAutoscrollTimer()
1402 {
1403     d->m_autoscrollTimer.startRepeating(autoscrollInterval);
1404 }
1405
1406 void Frame::stopAutoscrollTimer(bool rendererIsBeingDestroyed)
1407 {
1408     if (!rendererIsBeingDestroyed && autoscrollRenderer())
1409         autoscrollRenderer()->stopAutoscroll();
1410     setAutoscrollRenderer(0);
1411     d->m_autoscrollTimer.stop();
1412 }
1413
1414 // FIXME: why is this here instead of on the FrameView?
1415 void Frame::paint(GraphicsContext* p, const IntRect& rect)
1416 {
1417 #ifndef NDEBUG
1418     bool fillWithRed;
1419     if (!document() || document()->printing())
1420         fillWithRed = false; // Printing, don't fill with red (can't remember why).
1421     else if (document()->ownerElement())
1422         fillWithRed = false; // Subframe, don't fill with red.
1423     else if (view() && view()->isTransparent())
1424         fillWithRed = false; // Transparent, don't fill with red.
1425     else if (d->m_paintRestriction == PaintRestrictionSelectionOnly || d->m_paintRestriction == PaintRestrictionSelectionOnlyWhiteText)
1426         fillWithRed = false; // Selections are transparent, don't fill with red.
1427     else if (d->m_elementToDraw)
1428         fillWithRed = false; // Element images are transparent, don't fill with red.
1429     else
1430         fillWithRed = true;
1431     
1432     if (fillWithRed)
1433         p->fillRect(rect, Color(0xFF, 0, 0));
1434 #endif
1435     
1436     if (renderer()) {
1437         // d->m_elementToDraw is used to draw only one element
1438         RenderObject *eltRenderer = d->m_elementToDraw ? d->m_elementToDraw->renderer() : 0;
1439         if (d->m_paintRestriction == PaintRestrictionNone)
1440             renderer()->document()->invalidateRenderedRectsForMarkersInRect(rect);
1441         renderer()->layer()->paint(p, rect, d->m_paintRestriction, eltRenderer);
1442
1443 #if PLATFORM(MAC)
1444         // Regions may have changed as a result of the visibility/z-index of element changing.
1445         if (renderer()->document()->dashboardRegionsDirty())
1446             renderer()->view()->frameView()->updateDashboardRegions();
1447 #endif
1448     } else
1449         LOG_ERROR("called Frame::paint with nil renderer");
1450 }
1451
1452 #if PLATFORM(CG)
1453
1454 void Frame::adjustPageHeight(float *newBottom, float oldTop, float oldBottom, float bottomLimit)
1455 {
1456     RenderView *root = static_cast<RenderView*>(document()->renderer());
1457     if (root) {
1458         // Use a context with painting disabled.
1459         GraphicsContext context((PlatformGraphicsContext*)0);
1460         root->setTruncatedAt((int)floorf(oldBottom));
1461         IntRect dirtyRect(0, (int)floorf(oldTop), root->docWidth(), (int)ceilf(oldBottom - oldTop));
1462         root->layer()->paint(&context, dirtyRect);
1463         *newBottom = root->bestTruncatedAt();
1464         if (*newBottom == 0)
1465             *newBottom = oldBottom;
1466     } else
1467         *newBottom = oldBottom;
1468 }
1469
1470 #endif
1471
1472 Frame *Frame::frameForWidget(const Widget *widget)
1473 {
1474     ASSERT_ARG(widget, widget);
1475     
1476     Node *node = nodeForWidget(widget);
1477     if (node)
1478         return frameForNode(node);
1479     
1480     // Assume all widgets are either form controls, or FrameViews.
1481     ASSERT(widget->isFrameView());
1482     return static_cast<const FrameView*>(widget)->frame();
1483 }
1484
1485 Frame *Frame::frameForNode(Node *node)
1486 {
1487     ASSERT_ARG(node, node);
1488     return node->document()->frame();
1489 }
1490
1491 Node* Frame::nodeForWidget(const Widget* widget)
1492 {
1493     ASSERT_ARG(widget, widget);
1494     WidgetClient* client = widget->client();
1495     if (!client)
1496         return 0;
1497     return client->element(const_cast<Widget*>(widget));
1498 }
1499
1500 void Frame::clearDocumentFocus(Widget *widget)
1501 {
1502     Node *node = nodeForWidget(widget);
1503     ASSERT(node);
1504     node->document()->setFocusNode(0);
1505 }
1506
1507 void Frame::forceLayout()
1508 {
1509     FrameView *v = d->m_view.get();
1510     if (v) {
1511         v->layout(false);
1512         // We cannot unschedule a pending relayout, since the force can be called with
1513         // a tiny rectangle from a drawRect update.  By unscheduling we in effect
1514         // "validate" and stop the necessary full repaint from occurring.  Basically any basic
1515         // append/remove DHTML is broken by this call.  For now, I have removed the optimization
1516         // until we have a better invalidation stategy. -dwh
1517         //v->unscheduleRelayout();
1518     }
1519 }
1520
1521 void Frame::forceLayoutWithPageWidthRange(float minPageWidth, float maxPageWidth)
1522 {
1523     // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
1524     // the state of things before and after the layout
1525     RenderView *root = static_cast<RenderView*>(document()->renderer());
1526     if (root) {
1527         // This magic is basically copied from khtmlview::print
1528         int pageW = (int)ceilf(minPageWidth);
1529         root->setWidth(pageW);
1530         root->setNeedsLayoutAndMinMaxRecalc();
1531         forceLayout();
1532         
1533         // If we don't fit in the minimum page width, we'll lay out again. If we don't fit in the
1534         // maximum page width, we will lay out to the maximum page width and clip extra content.
1535         // FIXME: We are assuming a shrink-to-fit printing implementation.  A cropping
1536         // implementation should not do this!
1537         int rightmostPos = root->rightmostPosition();
1538         if (rightmostPos > minPageWidth) {
1539             pageW = min(rightmostPos, (int)ceilf(maxPageWidth));
1540             root->setWidth(pageW);
1541             root->setNeedsLayoutAndMinMaxRecalc();
1542             forceLayout();
1543         }
1544     }
1545 }
1546
1547 void Frame::sendResizeEvent()
1548 {
1549     if (Document* doc = document())
1550         doc->dispatchWindowEvent(EventNames::resizeEvent, false, false);
1551 }
1552
1553 void Frame::sendScrollEvent()
1554 {
1555     FrameView *v = d->m_view.get();
1556     if (v) {
1557         Document *doc = document();
1558         if (!doc)
1559             return;
1560         doc->dispatchHTMLEvent(scrollEvent, true, false);
1561     }
1562 }
1563
1564 bool Frame::canMouseDownStartSelect(Node* node)
1565 {
1566     if (!node || !node->renderer())
1567         return true;
1568     
1569     // Check to see if -webkit-user-select has been set to none
1570     if (!node->renderer()->canSelect())
1571         return false;
1572     
1573     // Some controls and images can't start a select on a mouse down.
1574     for (RenderObject* curr = node->renderer(); curr; curr = curr->parent()) {
1575         if (curr->style()->userSelect() == SELECT_IGNORE)
1576             return false;
1577     }
1578     
1579     return true;
1580 }
1581
1582 void Frame::clearTimers(FrameView *view)
1583 {
1584     if (view) {
1585         view->unscheduleRelayout();
1586         if (view->frame()) {
1587             Document* document = view->frame()->document();
1588             if (document && document->renderer() && document->renderer()->layer())
1589                 document->renderer()->layer()->suspendMarquees();
1590         }
1591     }
1592 }
1593
1594 void Frame::clearTimers()
1595 {
1596     clearTimers(d->m_view.get());
1597 }
1598
1599 RenderStyle *Frame::styleForSelectionStart(Node *&nodeToRemove) const
1600 {
1601     nodeToRemove = 0;
1602     
1603     if (!document())
1604         return 0;
1605     if (selectionController()->isNone())
1606         return 0;
1607     
1608     Position pos = selectionController()->selection().visibleStart().deepEquivalent();
1609     if (!pos.inRenderedContent())
1610         return 0;
1611     Node *node = pos.node();
1612     if (!node)
1613         return 0;
1614     
1615     if (!d->m_typingStyle)
1616         return node->renderer()->style();
1617     
1618     ExceptionCode ec = 0;
1619     RefPtr<Element> styleElement = document()->createElementNS(xhtmlNamespaceURI, "span", ec);
1620     ASSERT(ec == 0);
1621     
1622     styleElement->setAttribute(styleAttr, d->m_typingStyle->cssText().impl(), ec);
1623     ASSERT(ec == 0);
1624     
1625     styleElement->appendChild(document()->createEditingTextNode(""), ec);
1626     ASSERT(ec == 0);
1627     
1628     node->parentNode()->appendChild(styleElement, ec);
1629     ASSERT(ec == 0);
1630     
1631     nodeToRemove = styleElement.get();    
1632     return styleElement->renderer()->style();
1633 }
1634
1635 void Frame::setSelectionFromNone()
1636 {
1637     // Put a caret inside the body if the entire frame is editable (either the 
1638     // entire WebView is editable or designMode is on for this document).
1639     Document *doc = document();
1640     if (!doc || !selectionController()->isNone() || !isContentEditable())
1641         return;
1642         
1643     Node* node = doc->documentElement();
1644     while (node && !node->hasTagName(bodyTag))
1645         node = node->traverseNextNode();
1646     if (node)
1647         selectionController()->setSelection(Selection(Position(node, 0), DOWNSTREAM));
1648 }
1649
1650 bool Frame::isActive() const
1651 {
1652     return d->m_isActive;
1653 }
1654
1655 void Frame::setIsActive(bool flag)
1656 {
1657     if (d->m_isActive == flag)
1658         return;
1659     
1660     d->m_isActive = flag;
1661
1662     // This method does the job of updating the view based on whether the view is "active".
1663     // This involves three kinds of drawing updates:
1664
1665     // 1. The background color used to draw behind selected content (active | inactive color)
1666     if (d->m_view)
1667         d->m_view->updateContents(enclosingIntRect(visibleSelectionRect()));
1668
1669     // 2. Caret blinking (blinks | does not blink)
1670     if (flag)
1671         setSelectionFromNone();
1672     setCaretVisible(flag);
1673     
1674     // 3. The drawing of a focus ring around links in web pages.
1675     Document *doc = document();
1676     if (doc) {
1677         Node *node = doc->focusNode();
1678         if (node) {
1679             node->setChanged();
1680             if (node->renderer() && node->renderer()->style()->hasAppearance())
1681                 theme()->stateChanged(node->renderer(), FocusState);
1682         }
1683     }
1684     
1685     // 4. Changing the tint of controls from clear to aqua/graphite and vice versa.  We
1686     // do a "fake" paint.  When the theme gets a paint call, it can then do an invalidate.  This is only
1687     // done if the theme supports control tinting.
1688     if (doc && d->m_view && theme()->supportsControlTints() && renderer()) {
1689         doc->updateLayout(); // Ensure layout is up to date.
1690         IntRect visibleRect(enclosingIntRect(d->m_view->visibleContentRect()));
1691         GraphicsContext context((PlatformGraphicsContext*)0);
1692         context.setUpdatingControlTints(true);
1693         paint(&context, visibleRect);
1694     }
1695    
1696     // 5. Enable or disable secure keyboard entry
1697     if ((flag && !isSecureKeyboardEntry() && doc && doc->focusNode() && doc->focusNode()->hasTagName(inputTag) && 
1698             static_cast<HTMLInputElement*>(doc->focusNode())->inputType() == HTMLInputElement::PASSWORD) ||
1699         (!flag && isSecureKeyboardEntry()))
1700             setSecureKeyboardEntry(flag);
1701 }
1702
1703 void Frame::setWindowHasFocus(bool flag)
1704 {
1705     if (d->m_windowHasFocus == flag)
1706         return;
1707     d->m_windowHasFocus = flag;
1708     
1709     if (Document *doc = document())
1710         doc->dispatchWindowEvent(flag ? focusEvent : blurEvent, false, false);
1711 }
1712
1713 bool Frame::inViewSourceMode() const
1714 {
1715     return d->m_inViewSourceMode;
1716 }
1717
1718 void Frame::setInViewSourceMode(bool mode) const
1719 {
1720     d->m_inViewSourceMode = mode;
1721 }
1722   
1723 UChar Frame::backslashAsCurrencySymbol() const
1724 {
1725     Document *doc = document();
1726     if (!doc)
1727         return '\\';
1728     TextResourceDecoder *decoder = doc->decoder();
1729     if (!decoder)
1730         return '\\';
1731
1732     return decoder->encoding().backslashAsCurrencySymbol();
1733 }
1734
1735 bool Frame::markedTextUsesUnderlines() const
1736 {
1737     return d->m_markedTextUsesUnderlines;
1738 }
1739
1740 const Vector<MarkedTextUnderline>& Frame::markedTextUnderlines() const
1741 {
1742     return d->m_markedTextUnderlines;
1743 }
1744
1745 // Searches from the beginning of the document if nothing is selected.
1746 bool Frame::findString(const String& target, bool forward, bool caseFlag, bool wrapFlag)
1747 {
1748     if (target.isEmpty())
1749         return false;
1750     
1751     // Initially search from the start (if forward) or end (if backward) of the selection, and search to edge of document.
1752     RefPtr<Range> searchRange(rangeOfContents(document()));
1753     Selection selection(selectionController()->selection());
1754     if (!selection.isNone()) {
1755         if (forward)
1756             setStart(searchRange.get(), selection.visibleStart());
1757         else
1758             setEnd(searchRange.get(), selection.visibleEnd());
1759     }
1760     RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, forward, caseFlag));
1761     // If the found range is already selected, find again.
1762     // Build a selection with the found range to remove collapsed whitespace.
1763     // Compare ranges instead of selection objects to ignore the way that the current selection was made.
1764     if (!selection.isNone() && *Selection(resultRange.get()).toRange() == *selection.toRange()) {
1765         searchRange = rangeOfContents(document());
1766         if (forward)
1767             setStart(searchRange.get(), selection.visibleEnd());
1768         else
1769             setEnd(searchRange.get(), selection.visibleStart());
1770         resultRange = findPlainText(searchRange.get(), target, forward, caseFlag);
1771     }
1772     
1773     int exception = 0;
1774     
1775     // If we didn't find anything and we're wrapping, search again in the entire document (this will
1776     // redundantly re-search the area already searched in some cases).
1777     if (resultRange->collapsed(exception) && wrapFlag) {
1778         searchRange = rangeOfContents(document());
1779         resultRange = findPlainText(searchRange.get(), target, forward, caseFlag);
1780         // We used to return false here if we ended up with the same range that we started with
1781         // (e.g., the selection was already the only instance of this text). But we decided that
1782         // this should be a success case instead, so we'll just fall through in that case.
1783     }
1784
1785     if (resultRange->collapsed(exception))
1786         return false;
1787
1788     selectionController()->setSelection(Selection(resultRange.get(), DOWNSTREAM));
1789     revealSelection();
1790     return true;
1791 }
1792
1793 unsigned Frame::markAllMatchesForText(const String& target, bool caseFlag, unsigned limit)
1794 {
1795     if (target.isEmpty())
1796         return 0;
1797     
1798     RefPtr<Range> searchRange(rangeOfContents(document()));
1799     
1800     int exception = 0;
1801     unsigned matchCount = 0;
1802     do {
1803         RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, true, caseFlag));
1804         if (resultRange->collapsed(exception))
1805             break;
1806         
1807         // A non-collapsed result range can in some funky whitespace cases still not
1808         // advance the range's start position (4509328). Break to avoid infinite loop.
1809         VisiblePosition newStart = endVisiblePosition(resultRange.get(), DOWNSTREAM);
1810         if (newStart == startVisiblePosition(searchRange.get(), DOWNSTREAM))
1811             break;
1812
1813         ++matchCount;
1814         
1815         document()->addMarker(resultRange.get(), DocumentMarker::TextMatch);        
1816         
1817         // Stop looking if we hit the specified limit. A limit of 0 means no limit.
1818         if (limit > 0 && matchCount >= limit)
1819             break;
1820         
1821         setStart(searchRange.get(), newStart);
1822     } while (true);
1823     
1824     // Do a "fake" paint in order to execute the code that computes the rendered rect for 
1825     // each text match.
1826     Document* doc = document();
1827     if (doc && d->m_view && renderer()) {
1828         doc->updateLayout(); // Ensure layout is up to date.
1829         IntRect visibleRect(enclosingIntRect(d->m_view->visibleContentRect()));
1830         GraphicsContext context((PlatformGraphicsContext*)0);
1831         context.setPaintingDisabled(true);
1832         paint(&context, visibleRect);
1833     }
1834     
1835     return matchCount;
1836 }
1837
1838 bool Frame::markedTextMatchesAreHighlighted() const
1839 {
1840     return d->m_highlightTextMatches;
1841 }
1842
1843 void Frame::setMarkedTextMatchesAreHighlighted(bool flag)
1844 {
1845     if (flag == d->m_highlightTextMatches)
1846         return;
1847     
1848     d->m_highlightTextMatches = flag;
1849     document()->repaintMarkers(DocumentMarker::TextMatch);
1850 }
1851
1852 Node *Frame::mousePressNode()
1853 {
1854     return d->m_mousePressNode.get();
1855 }
1856
1857 FrameTree* Frame::tree() const
1858 {
1859     return &d->m_treeNode;
1860 }
1861
1862 DOMWindow* Frame::domWindow() const
1863 {
1864     if (!d->m_domWindow)
1865         d->m_domWindow = new DOMWindow(const_cast<Frame*>(this));
1866
1867     return d->m_domWindow.get();
1868 }
1869
1870 Page* Frame::page() const
1871 {
1872     return d->m_page;
1873 }
1874
1875 void Frame::pageDestroyed()
1876 {
1877     d->m_page = 0;
1878
1879     // This will stop any JS timers
1880     if (d->m_jscript && d->m_jscript->haveInterpreter())
1881         if (Window* w = Window::retrieveWindow(this))
1882             w->disconnectFrame();
1883 }
1884
1885 void Frame::setStatusBarText(const String&)
1886 {
1887 }
1888
1889 void Frame::disconnectOwnerElement()
1890 {
1891     if (d->m_ownerElement && d->m_page)
1892         d->m_page->decrementFrameCount();
1893         
1894     d->m_ownerElement = 0;
1895 }
1896
1897 String Frame::documentTypeString() const
1898 {
1899     if (Document *doc = document())
1900         if (DocumentType *doctype = doc->realDocType())
1901             return doctype->toString();
1902
1903     return String();
1904 }
1905
1906 bool Frame::prohibitsScrolling() const
1907 {
1908     return d->m_prohibitsScrolling;
1909 }
1910
1911 void Frame::setProhibitsScrolling(const bool prohibit)
1912 {
1913     d->m_prohibitsScrolling = prohibit;
1914 }
1915
1916 FramePrivate::FramePrivate(Page* page, Frame* parent, Frame* thisFrame, Element* ownerElement, PassRefPtr<EditorClient> client)
1917     : m_page(page)
1918     , m_treeNode(thisFrame, parent)
1919     , m_ownerElement(ownerElement)
1920     , m_jscript(0)
1921     , m_bJScriptEnabled(true)
1922     , m_bJavaEnabled(true)
1923     , m_bPluginsEnabled(true)
1924     , m_settings(0)
1925     , m_zoomFactor(parent ? parent->d->m_zoomFactor : 100)
1926     , m_bMousePressed(false)
1927     , m_beganSelectingText(false)
1928     , m_selectionController(thisFrame)
1929     , m_caretBlinkTimer(thisFrame, &Frame::caretBlinkTimerFired)
1930     , m_editor(thisFrame, client)
1931     , m_command(thisFrame)
1932     , m_caretVisible(false)
1933     , m_caretPaint(true)
1934     , m_isActive(false)
1935     , m_lifeSupportTimer(thisFrame, &Frame::lifeSupportTimerFired)
1936     , m_loader(new FrameLoader(thisFrame))
1937     , m_userStyleSheetLoader(0)
1938     , m_autoscrollTimer(thisFrame, &Frame::autoscrollTimerFired)
1939     , m_autoscrollRenderer(0)
1940     , m_mouseDownMayStartAutoscroll(false)
1941     , m_mouseDownMayStartDrag(false)
1942     , m_paintRestriction(PaintRestrictionNone)
1943     , m_markedTextUsesUnderlines(false)
1944     , m_highlightTextMatches(false)
1945     , m_windowHasFocus(false)
1946     , m_inViewSourceMode(false)
1947     , frameCount(0)
1948     , m_prohibitsScrolling(false)
1949 {
1950 }
1951
1952 FramePrivate::~FramePrivate()
1953 {
1954     delete m_jscript;
1955     delete m_loader;
1956 }
1957
1958 } // namespace WebCore