WebCore:
[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 TextGranularity Frame::selectionGranularity() const
339 {
340     return d->m_selectionGranularity;
341 }
342
343 void Frame::setSelectionGranularity(TextGranularity granularity) const
344 {
345     d->m_selectionGranularity = granularity;
346 }
347
348 SelectionController* Frame::dragCaretController() const
349 {
350     return d->m_page->dragCaretController();
351 }
352
353 const Selection& Frame::mark() const
354 {
355     return d->m_mark;
356 }
357
358 void Frame::setMark(const Selection& s)
359 {
360     ASSERT(!s.base().node() || s.base().node()->document() == document());
361     ASSERT(!s.extent().node() || s.extent().node()->document() == document());
362     ASSERT(!s.start().node() || s.start().node()->document() == document());
363     ASSERT(!s.end().node() || s.end().node()->document() == document());
364
365     d->m_mark = s;
366 }
367
368 void Frame::notifyRendererOfSelectionChange(bool userTriggered)
369 {
370     RenderObject* renderer = 0;
371     if (selectionController()->rootEditableElement())
372         renderer = selectionController()->rootEditableElement()->shadowAncestorNode()->renderer();
373
374     // If the current selection is in a textfield or textarea, notify the renderer that the selection has changed
375     if (renderer && (renderer->isTextArea() || renderer->isTextField()))
376         static_cast<RenderTextControl*>(renderer)->selectionChanged(userTriggered);
377 }
378
379 void Frame::invalidateSelection()
380 {
381     selectionController()->setNeedsLayout();
382     selectionLayoutChanged();
383 }
384
385 void Frame::setCaretVisible(bool flag)
386 {
387     if (d->m_caretVisible == flag)
388         return;
389     clearCaretRectIfNeeded();
390     if (flag)
391         setFocusNodeIfNeeded();
392     d->m_caretVisible = flag;
393     selectionLayoutChanged();
394 }
395
396
397 void Frame::clearCaretRectIfNeeded()
398 {
399     if (d->m_caretPaint) {
400         d->m_caretPaint = false;
401         selectionController()->invalidateCaretRect();
402     }        
403 }
404
405 // Helper function that tells whether a particular node is an element that has an entire
406 // Frame and FrameView, a <frame>, <iframe>, or <object>.
407 static bool isFrameElement(const Node *n)
408 {
409     if (!n)
410         return false;
411     RenderObject *renderer = n->renderer();
412     if (!renderer || !renderer->isWidget())
413         return false;
414     Widget* widget = static_cast<RenderWidget*>(renderer)->widget();
415     return widget && widget->isFrameView();
416 }
417
418 void Frame::setFocusNodeIfNeeded()
419 {
420     if (!document() || selectionController()->isNone() || !d->m_isActive)
421         return;
422
423     Node* target = selectionController()->rootEditableElement();
424     if (target) {
425         RenderObject* renderer = target->renderer();
426
427         // Walk up the render tree to search for a node to focus.
428         // Walking up the DOM tree wouldn't work for shadow trees, like those behind the engine-based text fields.
429         while (renderer) {
430             // We don't want to set focus on a subframe when selecting in a parent frame,
431             // so add the !isFrameElement check here. There's probably a better way to make this
432             // work in the long term, but this is the safest fix at this time.
433             if (target && target->isMouseFocusable() && !isFrameElement(target)) {
434                 document()->setFocusNode(target);
435                 return;
436             }
437             renderer = renderer->parent();
438             if (renderer)
439                 target = renderer->element();
440         }
441         document()->setFocusNode(0);
442     }
443 }
444
445 void Frame::selectionLayoutChanged()
446 {
447     bool caretRectChanged = selectionController()->recomputeCaretRect();
448
449     bool shouldBlink = d->m_caretVisible
450         && selectionController()->isCaret() && selectionController()->isContentEditable();
451
452     // If the caret moved, stop the blink timer so we can restart with a
453     // black caret in the new location.
454     if (caretRectChanged || !shouldBlink)
455         d->m_caretBlinkTimer.stop();
456
457     // Start blinking with a black caret. Be sure not to restart if we're
458     // already blinking in the right location.
459     if (shouldBlink && !d->m_caretBlinkTimer.isActive()) {
460         d->m_caretBlinkTimer.startRepeating(caretBlinkFrequency);
461         d->m_caretPaint = true;
462     }
463
464     if (d->m_doc)
465         d->m_doc->updateSelection();
466 }
467
468 void Frame::setXPosForVerticalArrowNavigation(int x)
469 {
470     d->m_xPosForVerticalArrowNavigation = x;
471 }
472
473 int Frame::xPosForVerticalArrowNavigation() const
474 {
475     return d->m_xPosForVerticalArrowNavigation;
476 }
477
478 void Frame::caretBlinkTimerFired(Timer<Frame>*)
479 {
480     ASSERT(d->m_caretVisible);
481     ASSERT(selectionController()->isCaret());
482     bool caretPaint = d->m_caretPaint;
483     if (d->m_bMousePressed && caretPaint)
484         return;
485     d->m_caretPaint = !caretPaint;
486     selectionController()->invalidateCaretRect();
487 }
488
489 void Frame::paintCaret(GraphicsContext* p, const IntRect& rect) const
490 {
491     if (d->m_caretPaint && d->m_caretVisible)
492         selectionController()->paintCaret(p, rect);
493 }
494
495 void Frame::paintDragCaret(GraphicsContext* p, const IntRect& rect) const
496 {
497     SelectionController* dragCaretController = d->m_page->dragCaretController();
498     assert(dragCaretController->selection().isCaret());
499     if (dragCaretController->selection().start().node()->document()->frame() == this)
500         dragCaretController->paintCaret(p, rect);
501 }
502
503 int Frame::zoomFactor() const
504 {
505   return d->m_zoomFactor;
506 }
507
508 void Frame::setZoomFactor(int percent)
509 {  
510   if (d->m_zoomFactor == percent)
511       return;
512
513   d->m_zoomFactor = percent;
514
515   if (d->m_doc)
516       d->m_doc->recalcStyle(Node::Force);
517
518   for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
519       child->setZoomFactor(d->m_zoomFactor);
520
521   if (d->m_doc && d->m_doc->renderer() && d->m_doc->renderer()->needsLayout())
522       view()->layout();
523 }
524
525 void Frame::setJSStatusBarText(const String& text)
526 {
527     d->m_kjsStatusBarText = text;
528     setStatusBarText(d->m_kjsStatusBarText);
529 }
530
531 void Frame::setJSDefaultStatusBarText(const String& text)
532 {
533     d->m_kjsDefaultStatusBarText = text;
534     setStatusBarText(d->m_kjsDefaultStatusBarText);
535 }
536
537 String Frame::jsStatusBarText() const
538 {
539     return d->m_kjsStatusBarText;
540 }
541
542 String Frame::jsDefaultStatusBarText() const
543 {
544    return d->m_kjsDefaultStatusBarText;
545 }
546
547 void Frame::reparseConfiguration()
548 {
549     if (d->m_doc)
550         d->m_doc->docLoader()->setAutoLoadImages(d->m_settings->autoLoadImages());
551         
552     d->m_bJScriptEnabled = d->m_settings->isJavaScriptEnabled();
553     d->m_bJavaEnabled = d->m_settings->isJavaEnabled();
554     d->m_bPluginsEnabled = d->m_settings->isPluginsEnabled();
555
556     const KURL& userStyleSheetLocation = d->m_settings->userStyleSheetLocation();
557     if (!userStyleSheetLocation.isEmpty())
558         setUserStyleSheetLocation(userStyleSheetLocation);
559     else
560         setUserStyleSheet(String());
561
562     // FIXME: It's not entirely clear why the following is needed.
563     // The document automatically does this as required when you set the style sheet.
564     // But we had problems when this code was removed. Details are in
565     // <http://bugs.webkit.org/show_bug.cgi?id=8079>.
566     if (d->m_doc)
567         d->m_doc->updateStyleSelector();
568 }
569
570 bool Frame::shouldDragAutoNode(Node *node, const IntPoint& point) const
571 {
572     return false;
573 }
574
575 void Frame::selectClosestWordFromMouseEvent(const PlatformMouseEvent& mouse, Node *innerNode)
576 {
577     Selection newSelection;
578
579     if (innerNode && innerNode->renderer() && mouseDownMayStartSelect() && innerNode->renderer()->shouldSelect()) {
580         IntPoint vPoint = view()->windowToContents(mouse.pos());
581         VisiblePosition pos(innerNode->renderer()->positionForPoint(vPoint));
582         if (pos.isNotNull()) {
583             newSelection = Selection(pos);
584             newSelection.expandUsingGranularity(WordGranularity);
585         }
586     }
587     
588     if (newSelection.isRange()) {
589         d->m_selectionGranularity = WordGranularity;
590         d->m_beganSelectingText = true;
591     }
592     
593     if (shouldChangeSelection(newSelection))
594         selectionController()->setSelection(newSelection);
595 }
596
597 void Frame::handleMousePressEventDoubleClick(const MouseEventWithHitTestResults& event)
598 {
599     if (event.event().button() == LeftButton) {
600         if (selectionController()->isRange())
601             // A double-click when range is already selected
602             // should not change the selection.  So, do not call
603             // selectClosestWordFromMouseEvent, but do set
604             // m_beganSelectingText to prevent handleMouseReleaseEvent
605             // from setting caret selection.
606             d->m_beganSelectingText = true;
607         else
608             selectClosestWordFromMouseEvent(event.event(), event.targetNode());
609     }
610 }
611
612 void Frame::handleMousePressEventTripleClick(const MouseEventWithHitTestResults& event)
613 {
614     Node *innerNode = event.targetNode();
615     
616     if (event.event().button() == LeftButton && innerNode && innerNode->renderer() &&
617         mouseDownMayStartSelect() && innerNode->renderer()->shouldSelect()) {
618         Selection newSelection;
619         IntPoint vPoint = view()->windowToContents(event.event().pos());
620         VisiblePosition pos(innerNode->renderer()->positionForPoint(vPoint));
621         if (pos.isNotNull()) {
622             newSelection = Selection(pos);
623             newSelection.expandUsingGranularity(ParagraphGranularity);
624         }
625         if (newSelection.isRange()) {
626             d->m_selectionGranularity = ParagraphGranularity;
627             d->m_beganSelectingText = true;
628         }
629         
630         if (shouldChangeSelection(newSelection))
631             selectionController()->setSelection(newSelection);
632     }
633 }
634
635 void Frame::handleMousePressEventSingleClick(const MouseEventWithHitTestResults& event)
636 {
637     Node *innerNode = event.targetNode();
638     
639     if (event.event().button() == LeftButton) {
640         if (innerNode && innerNode->renderer() &&
641             mouseDownMayStartSelect() && innerNode->renderer()->shouldSelect()) {
642             
643             // Extend the selection if the Shift key is down, unless the click is in a link.
644             bool extendSelection = event.event().shiftKey() && !event.isOverLink();
645
646             // Don't restart the selection when the mouse is pressed on an
647             // existing selection so we can allow for text dragging.
648             IntPoint vPoint = view()->windowToContents(event.event().pos());
649             if (!extendSelection && selectionController()->contains(vPoint))
650                 return;
651
652             VisiblePosition visiblePos(innerNode->renderer()->positionForPoint(vPoint));
653             if (visiblePos.isNull())
654                 visiblePos = VisiblePosition(innerNode, innerNode->caretMinOffset(), DOWNSTREAM);
655             Position pos = visiblePos.deepEquivalent();
656             
657             Selection newSelection = selectionController()->selection();
658             if (extendSelection && newSelection.isCaretOrRange()) {
659                 selectionController()->clearModifyBias();
660                 
661                 // See <rdar://problem/3668157> REGRESSION (Mail): shift-click deselects when selection 
662                 // was created right-to-left
663                 Position start = newSelection.start();
664                 Position end = newSelection.end();
665                 short before = Range::compareBoundaryPoints(pos.node(), pos.offset(), start.node(), start.offset());
666                 if (before <= 0)
667                     newSelection = Selection(pos, end);
668                 else
669                     newSelection = Selection(start, pos);
670
671                 if (d->m_selectionGranularity != CharacterGranularity)
672                     newSelection.expandUsingGranularity(d->m_selectionGranularity);
673                 d->m_beganSelectingText = true;
674             } else {
675                 newSelection = Selection(visiblePos);
676                 d->m_selectionGranularity = CharacterGranularity;
677             }
678             
679             if (shouldChangeSelection(newSelection))
680                 selectionController()->setSelection(newSelection);
681         }
682     }
683 }
684
685 void Frame::handleMousePressEvent(const MouseEventWithHitTestResults& event)
686 {
687     Node *innerNode = event.targetNode();
688
689     d->m_mousePressNode = innerNode;
690     d->m_dragStartPos = event.event().pos();
691
692     if (event.event().button() == LeftButton || event.event().button() == MiddleButton) {
693         d->m_bMousePressed = true;
694         d->m_beganSelectingText = false;
695
696         if (event.event().clickCount() == 2) {
697             handleMousePressEventDoubleClick(event);
698             return;
699         }
700         if (event.event().clickCount() >= 3) {
701             handleMousePressEventTripleClick(event);
702             return;
703         }
704         handleMousePressEventSingleClick(event);
705     }
706     
707    setMouseDownMayStartAutoscroll(mouseDownMayStartSelect() || 
708         (d->m_mousePressNode && d->m_mousePressNode->renderer() && d->m_mousePressNode->renderer()->shouldAutoscroll()));
709 }
710
711 void Frame::handleMouseMoveEvent(const MouseEventWithHitTestResults& event)
712 {
713     // Mouse not pressed. Do nothing.
714     if (!d->m_bMousePressed)
715         return;
716
717     Node *innerNode = event.targetNode();
718
719     if (event.event().button() != 0 || !innerNode || !innerNode->renderer())
720         return;
721
722     ASSERT(mouseDownMayStartSelect() || mouseDownMayStartAutoscroll());
723
724     setMouseDownMayStartDrag(false);
725     view()->invalidateClick();
726
727      if (mouseDownMayStartAutoscroll()) {            
728         // If the selection is contained in a layer that can scroll, that layer should handle the autoscroll
729         // Otherwise, let the bridge handle it so the view can scroll itself.
730         RenderObject* renderer = innerNode->renderer();
731         while (renderer && !renderer->shouldAutoscroll())
732             renderer = renderer->parent();
733         if (renderer)
734             handleAutoscroll(renderer);
735     }
736     
737     if (mouseDownMayStartSelect() && innerNode->renderer()->shouldSelect()) {
738         // handle making selection
739         IntPoint vPoint = view()->windowToContents(event.event().pos());        
740         VisiblePosition pos(innerNode->renderer()->positionForPoint(vPoint));
741
742         updateSelectionForMouseDragOverPosition(pos);
743     }
744
745 }
746
747 void Frame::updateSelectionForMouseDragOverPosition(const VisiblePosition& pos)
748 {
749     // Don't modify the selection if we're not on a node.
750     if (pos.isNull())
751         return;
752
753     // Restart the selection if this is the first mouse move. This work is usually
754     // done in handleMousePressEvent, but not if the mouse press was on an existing selection.
755     Selection newSelection = selectionController()->selection();
756     selectionController()->clearModifyBias();
757     
758     if (!d->m_beganSelectingText) {
759         d->m_beganSelectingText = true;
760         newSelection = Selection(pos);
761     }
762
763     newSelection.setExtent(pos);
764     if (d->m_selectionGranularity != CharacterGranularity)
765         newSelection.expandUsingGranularity(d->m_selectionGranularity);
766
767     if (shouldChangeSelection(newSelection))
768         selectionController()->setSelection(newSelection);
769 }
770
771 void Frame::handleMouseReleaseEvent(const MouseEventWithHitTestResults& event)
772 {
773     stopAutoscrollTimer();
774     
775     // Used to prevent mouseMoveEvent from initiating a drag before
776     // the mouse is pressed again.
777     d->m_bMousePressed = false;
778   
779     // Clear the selection if the mouse didn't move after the last mouse press.
780     // We do this so when clicking on the selection, the selection goes away.
781     // However, if we are editing, place the caret.
782     if (mouseDownMayStartSelect() && !d->m_beganSelectingText
783             && d->m_dragStartPos == event.event().pos()
784             && selectionController()->isRange()) {
785         Selection newSelection;
786         Node *node = event.targetNode();
787         if (node && node->isContentEditable() && node->renderer()) {
788             IntPoint vPoint = view()->windowToContents(event.event().pos());
789             VisiblePosition pos = node->renderer()->positionForPoint(vPoint);
790             newSelection = Selection(pos);
791         }
792         if (shouldChangeSelection(newSelection))
793             selectionController()->setSelection(newSelection);
794     }
795
796     notifyRendererOfSelectionChange(true);
797
798     selectionController()->selectFrameElementInParentIfFullySelected();
799 }
800
801 bool Frame::shouldChangeSelection(const Selection& newSelection) const
802 {
803     return shouldChangeSelection(selectionController()->selection(), newSelection, newSelection.affinity(), false);
804 }
805
806 bool Frame::shouldDeleteSelection(const Selection& newSelection) const
807 {
808     return true;
809 }
810
811 bool Frame::isContentEditable() const 
812 {
813     if (!d->m_doc)
814         return false;
815     return d->m_doc->inDesignMode();
816 }
817
818 void Frame::textFieldDidBeginEditing(Element* input)
819 {
820 }
821
822 void Frame::textFieldDidEndEditing(Element* input)
823 {
824 }
825
826 void Frame::textDidChangeInTextField(Element* input)
827 {
828 }
829
830 bool Frame::doTextFieldCommandFromEvent(Element*, KeyboardEvent*)
831 {
832     return false;
833 }
834
835 void Frame::textWillBeDeletedInTextField(Element* input)
836 {
837 }
838
839 void Frame::textDidChangeInTextArea(Element* input)
840 {
841 }
842
843 CSSMutableStyleDeclaration *Frame::typingStyle() const
844 {
845     return d->m_typingStyle.get();
846 }
847
848 void Frame::setTypingStyle(CSSMutableStyleDeclaration *style)
849 {
850     d->m_typingStyle = style;
851 }
852
853 void Frame::clearTypingStyle()
854 {
855     d->m_typingStyle = 0;
856 }
857
858 bool Frame::tabsToLinks(KeyboardEvent*) const
859 {
860     return true;
861 }
862
863 bool Frame::tabsToAllControls(KeyboardEvent*) const
864 {
865     return true;
866 }
867
868 void Frame::copyToPasteboard()
869 {
870     issueCopyCommand();
871 }
872
873 void Frame::cutToPasteboard()
874 {
875     issueCutCommand();
876 }
877
878 void Frame::pasteFromPasteboard()
879 {
880     issuePasteCommand();
881 }
882
883 void Frame::pasteAndMatchStyle()
884 {
885     issuePasteAndMatchStyleCommand();
886 }
887
888 void Frame::transpose()
889 {
890     issueTransposeCommand();
891 }
892
893 void Frame::redo()
894 {
895     issueRedoCommand();
896 }
897
898 void Frame::undo()
899 {
900     issueUndoCommand();
901 }
902
903
904 void Frame::computeAndSetTypingStyle(CSSStyleDeclaration *style, EditAction editingAction)
905 {
906     if (!style || style->length() == 0) {
907         clearTypingStyle();
908         return;
909     }
910
911     // Calculate the current typing style.
912     RefPtr<CSSMutableStyleDeclaration> mutableStyle = style->makeMutable();
913     if (typingStyle()) {
914         typingStyle()->merge(mutableStyle.get());
915         mutableStyle = typingStyle();
916     }
917
918     Node *node = selectionController()->selection().visibleStart().deepEquivalent().node();
919     CSSComputedStyleDeclaration computedStyle(node);
920     computedStyle.diff(mutableStyle.get());
921     
922     // Handle block styles, substracting these from the typing style.
923     RefPtr<CSSMutableStyleDeclaration> blockStyle = mutableStyle->copyBlockProperties();
924     blockStyle->diff(mutableStyle.get());
925     if (document() && blockStyle->length() > 0)
926         applyCommand(new ApplyStyleCommand(document(), blockStyle.get(), editingAction));
927     
928     // Set the remaining style as the typing style.
929     d->m_typingStyle = mutableStyle.release();
930 }
931
932 static void updateState(CSSMutableStyleDeclaration *desiredStyle, CSSComputedStyleDeclaration *computedStyle, bool& atStart, Frame::TriState& state)
933 {
934     DeprecatedValueListConstIterator<CSSProperty> end;
935     for (DeprecatedValueListConstIterator<CSSProperty> it = desiredStyle->valuesIterator(); it != end; ++it) {
936         int propertyID = (*it).id();
937         String desiredProperty = desiredStyle->getPropertyValue(propertyID);
938         String computedProperty = computedStyle->getPropertyValue(propertyID);
939         Frame::TriState propertyState = equalIgnoringCase(desiredProperty, computedProperty)
940             ? Frame::trueTriState : Frame::falseTriState;
941         if (atStart) {
942             state = propertyState;
943             atStart = false;
944         } else if (state != propertyState) {
945             state = Frame::mixedTriState;
946             break;
947         }
948     }
949 }
950
951 Frame::TriState Frame::selectionHasStyle(CSSStyleDeclaration *style) const
952 {
953     bool atStart = true;
954     TriState state = falseTriState;
955
956     RefPtr<CSSMutableStyleDeclaration> mutableStyle = style->makeMutable();
957
958     if (!selectionController()->isRange()) {
959         Node* nodeToRemove;
960         RefPtr<CSSComputedStyleDeclaration> selectionStyle = selectionComputedStyle(nodeToRemove);
961         if (!selectionStyle)
962             return falseTriState;
963         updateState(mutableStyle.get(), selectionStyle.get(), atStart, state);
964         if (nodeToRemove) {
965             ExceptionCode ec = 0;
966             nodeToRemove->remove(ec);
967             assert(ec == 0);
968         }
969     } else {
970         for (Node* node = selectionController()->start().node(); node; node = node->traverseNextNode()) {
971             RefPtr<CSSComputedStyleDeclaration> computedStyle = new CSSComputedStyleDeclaration(node);
972             if (computedStyle)
973                 updateState(mutableStyle.get(), computedStyle.get(), atStart, state);
974             if (state == mixedTriState)
975                 break;
976             if (node == selectionController()->end().node())
977                 break;
978         }
979     }
980
981     return state;
982 }
983
984 String Frame::selectionStartStylePropertyValue(int stylePropertyID) const
985 {
986     Node *nodeToRemove;
987     RefPtr<CSSStyleDeclaration> selectionStyle = selectionComputedStyle(nodeToRemove);
988     if (!selectionStyle)
989         return String();
990
991     String value = selectionStyle->getPropertyValue(stylePropertyID);
992
993     if (nodeToRemove) {
994         ExceptionCode ec = 0;
995         nodeToRemove->remove(ec);
996         assert(ec == 0);
997     }
998
999     return value;
1000 }
1001
1002 CSSComputedStyleDeclaration *Frame::selectionComputedStyle(Node *&nodeToRemove) const
1003 {
1004     nodeToRemove = 0;
1005
1006     if (!document())
1007         return 0;
1008
1009     if (selectionController()->isNone())
1010         return 0;
1011
1012     RefPtr<Range> range(selectionController()->toRange());
1013     Position pos = range->editingStartPosition();
1014
1015     Element *elem = pos.element();
1016     if (!elem)
1017         return 0;
1018     
1019     RefPtr<Element> styleElement = elem;
1020     ExceptionCode ec = 0;
1021
1022     if (d->m_typingStyle) {
1023         styleElement = document()->createElementNS(xhtmlNamespaceURI, "span", ec);
1024         assert(ec == 0);
1025
1026         styleElement->setAttribute(styleAttr, d->m_typingStyle->cssText().impl(), ec);
1027         assert(ec == 0);
1028         
1029         styleElement->appendChild(document()->createEditingTextNode(""), ec);
1030         assert(ec == 0);
1031
1032         if (elem->renderer() && elem->renderer()->canHaveChildren()) {
1033             elem->appendChild(styleElement, ec);
1034         } else {
1035             Node *parent = elem->parent();
1036             Node *next = elem->nextSibling();
1037
1038             if (next) {
1039                 parent->insertBefore(styleElement, next, ec);
1040             } else {
1041                 parent->appendChild(styleElement, ec);
1042             }
1043         }
1044         assert(ec == 0);
1045
1046         nodeToRemove = styleElement.get();
1047     }
1048
1049     return new CSSComputedStyleDeclaration(styleElement);
1050 }
1051
1052 void Frame::applyEditingStyleToBodyElement() const
1053 {
1054     if (!d->m_doc)
1055         return;
1056         
1057     RefPtr<NodeList> list = d->m_doc->getElementsByTagName("body");
1058     unsigned len = list->length();
1059     for (unsigned i = 0; i < len; i++) {
1060         applyEditingStyleToElement(static_cast<Element*>(list->item(i)));    
1061     }
1062 }
1063
1064 void Frame::removeEditingStyleFromBodyElement() const
1065 {
1066     if (!d->m_doc)
1067         return;
1068         
1069     RefPtr<NodeList> list = d->m_doc->getElementsByTagName("body");
1070     unsigned len = list->length();
1071     for (unsigned i = 0; i < len; i++) {
1072         removeEditingStyleFromElement(static_cast<Element*>(list->item(i)));    
1073     }
1074 }
1075
1076 void Frame::applyEditingStyleToElement(Element* element) const
1077 {
1078     if (!element)
1079         return;
1080
1081     CSSStyleDeclaration* style = element->style();
1082     ASSERT(style);
1083
1084     ExceptionCode ec = 0;
1085     style->setProperty(CSS_PROP_WORD_WRAP, "break-word", false, ec);
1086     ASSERT(ec == 0);
1087     style->setProperty(CSS_PROP__WEBKIT_NBSP_MODE, "space", false, ec);
1088     ASSERT(ec == 0);
1089     style->setProperty(CSS_PROP__WEBKIT_LINE_BREAK, "after-white-space", false, ec);
1090     ASSERT(ec == 0);
1091 }
1092
1093 void Frame::removeEditingStyleFromElement(Element*) const
1094 {
1095 }
1096
1097 bool Frame::isCharacterSmartReplaceExempt(UChar, bool)
1098 {
1099     // no smart replace
1100     return true;
1101 }
1102
1103 #ifndef NDEBUG
1104 static HashSet<Frame*> lifeSupportSet;
1105 #endif
1106
1107 void Frame::endAllLifeSupport()
1108 {
1109 #ifndef NDEBUG
1110     HashSet<Frame*> lifeSupportCopy = lifeSupportSet;
1111     HashSet<Frame*>::iterator end = lifeSupportCopy.end();
1112     for (HashSet<Frame*>::iterator it = lifeSupportCopy.begin(); it != end; ++it)
1113         (*it)->endLifeSupport();
1114 #endif
1115 }
1116
1117 void Frame::keepAlive()
1118 {
1119     if (d->m_lifeSupportTimer.isActive())
1120         return;
1121     ref();
1122 #ifndef NDEBUG
1123     lifeSupportSet.add(this);
1124 #endif
1125     d->m_lifeSupportTimer.startOneShot(0);
1126 }
1127
1128 void Frame::endLifeSupport()
1129 {
1130     if (!d->m_lifeSupportTimer.isActive())
1131         return;
1132     d->m_lifeSupportTimer.stop();
1133 #ifndef NDEBUG
1134     lifeSupportSet.remove(this);
1135 #endif
1136     deref();
1137 }
1138
1139 void Frame::lifeSupportTimerFired(Timer<Frame>*)
1140 {
1141 #ifndef NDEBUG
1142     lifeSupportSet.remove(this);
1143 #endif
1144     deref();
1145 }
1146
1147 bool Frame::mouseDownMayStartAutoscroll() const
1148 {
1149     return d->m_mouseDownMayStartAutoscroll;
1150 }
1151
1152 void Frame::setMouseDownMayStartAutoscroll(bool b)
1153 {
1154     d->m_mouseDownMayStartAutoscroll = b;
1155 }
1156
1157 bool Frame::mouseDownMayStartDrag() const
1158 {
1159     return d->m_mouseDownMayStartDrag;
1160 }
1161
1162 void Frame::setMouseDownMayStartDrag(bool b)
1163 {
1164     d->m_mouseDownMayStartDrag = b;
1165 }
1166
1167 void Frame::setSettings(Settings *settings)
1168 {
1169     d->m_settings = settings;
1170 }
1171
1172 RenderObject *Frame::renderer() const
1173 {
1174     Document *doc = document();
1175     return doc ? doc->renderer() : 0;
1176 }
1177
1178 Element* Frame::ownerElement()
1179 {
1180     return d->m_ownerElement;
1181 }
1182
1183 RenderPart* Frame::ownerRenderer()
1184 {
1185     Element* ownerElement = d->m_ownerElement;
1186     if (!ownerElement)
1187         return 0;
1188     return static_cast<RenderPart*>(ownerElement->renderer());
1189 }
1190
1191 IntRect Frame::selectionRect() const
1192 {
1193     RenderView *root = static_cast<RenderView*>(renderer());
1194     if (!root)
1195         return IntRect();
1196
1197     return root->selectionRect();
1198 }
1199
1200 // returns FloatRect because going through IntRect would truncate any floats
1201 FloatRect Frame::visibleSelectionRect() const
1202 {
1203     if (!d->m_view)
1204         return FloatRect();
1205     
1206     return intersection(selectionRect(), d->m_view->visibleContentRect());
1207 }
1208
1209 bool Frame::isFrameSet() const
1210 {
1211     Document* document = d->m_doc.get();
1212     if (!document || !document->isHTMLDocument())
1213         return false;
1214     Node *body = static_cast<HTMLDocument*>(document)->body();
1215     return body && body->renderer() && body->hasTagName(framesetTag);
1216 }
1217
1218 // Scans logically forward from "start", including any child frames
1219 static HTMLFormElement *scanForForm(Node *start)
1220 {
1221     Node *n;
1222     for (n = start; n; n = n->traverseNextNode()) {
1223         if (n->hasTagName(formTag))
1224             return static_cast<HTMLFormElement*>(n);
1225         else if (n->isHTMLElement() && static_cast<HTMLElement*>(n)->isGenericFormElement())
1226             return static_cast<HTMLGenericFormElement*>(n)->form();
1227         else if (n->hasTagName(frameTag) || n->hasTagName(iframeTag)) {
1228             Node *childDoc = static_cast<HTMLFrameElementBase*>(n)->contentDocument();
1229             if (HTMLFormElement *frameResult = scanForForm(childDoc))
1230                 return frameResult;
1231         }
1232     }
1233     return 0;
1234 }
1235
1236 // We look for either the form containing the current focus, or for one immediately after it
1237 HTMLFormElement *Frame::currentForm() const
1238 {
1239     // start looking either at the active (first responder) node, or where the selection is
1240     Node *start = d->m_doc ? d->m_doc->focusNode() : 0;
1241     if (!start)
1242         start = selectionController()->start().node();
1243     
1244     // try walking up the node tree to find a form element
1245     Node *n;
1246     for (n = start; n; n = n->parentNode()) {
1247         if (n->hasTagName(formTag))
1248             return static_cast<HTMLFormElement*>(n);
1249         else if (n->isHTMLElement()
1250                    && static_cast<HTMLElement*>(n)->isGenericFormElement())
1251             return static_cast<HTMLGenericFormElement*>(n)->form();
1252     }
1253     
1254     // try walking forward in the node tree to find a form element
1255     return start ? scanForForm(start) : 0;
1256 }
1257
1258 // FIXME: should this go in SelectionController?
1259 void Frame::revealSelection(const RenderLayer::ScrollAlignment& alignment) const
1260 {
1261     IntRect rect;
1262     
1263     switch (selectionController()->state()) {
1264         case Selection::NONE:
1265             return;
1266             
1267         case Selection::CARET:
1268             rect = selectionController()->caretRect();
1269             break;
1270             
1271         case Selection::RANGE:
1272             rect = selectionRect();
1273             break;
1274     }
1275
1276     Position start = selectionController()->start();
1277     Position end = selectionController()->end();
1278
1279     ASSERT(start.node());
1280     if (start.node() && start.node()->renderer()) {
1281         RenderLayer *layer = start.node()->renderer()->enclosingLayer();
1282         if (layer) {
1283             ASSERT(!end.node() || !end.node()->renderer() 
1284                    || (end.node()->renderer()->enclosingLayer() == layer));
1285             layer->scrollRectToVisible(rect, alignment, alignment);
1286         }
1287     }
1288 }
1289
1290 void Frame::revealCaret(const RenderLayer::ScrollAlignment& alignment) const
1291 {
1292     if (selectionController()->isNone())
1293         return;
1294
1295     Position extent = selectionController()->extent();
1296     if (extent.node() && extent.node()->renderer()) {
1297         IntRect extentRect = VisiblePosition(extent).caretRect();
1298         RenderLayer* layer = extent.node()->renderer()->enclosingLayer();
1299         if (layer)
1300             layer->scrollRectToVisible(extentRect, alignment, alignment);
1301     }
1302 }
1303
1304 // FIXME: should this be here?
1305 bool Frame::scrollOverflow(ScrollDirection direction, ScrollGranularity granularity)
1306 {
1307     if (!document()) {
1308         return false;
1309     }
1310     
1311     Node *node = document()->focusNode();
1312     if (node == 0) {
1313         node = d->m_mousePressNode.get();
1314     }
1315     
1316     if (node != 0) {
1317         RenderObject *r = node->renderer();
1318         if (r != 0 && !r->isListBox()) {
1319             return r->scroll(direction, granularity);
1320         }
1321     }
1322     
1323     return false;
1324 }
1325
1326 void Frame::handleAutoscroll(RenderObject* renderer)
1327 {
1328     if (d->m_autoscrollTimer.isActive())
1329         return;
1330     setAutoscrollRenderer(renderer);
1331     startAutoscrollTimer();
1332 }
1333
1334 void Frame::autoscrollTimerFired(Timer<Frame>*)
1335 {
1336     if (!d->m_bMousePressed){
1337         stopAutoscrollTimer();
1338         return;
1339     }
1340     if (RenderObject* r = autoscrollRenderer())
1341         r->autoscroll();
1342 }
1343
1344 RenderObject* Frame::autoscrollRenderer() const
1345 {
1346     return d->m_autoscrollRenderer;
1347 }
1348
1349 void Frame::setAutoscrollRenderer(RenderObject* renderer)
1350 {
1351     d->m_autoscrollRenderer = renderer;
1352 }
1353
1354 HitTestResult Frame::hitTestResultAtPoint(const IntPoint& point, bool allowShadowContent)
1355 {
1356     HitTestResult result(point);
1357     if (!renderer())
1358         return result;
1359     renderer()->layer()->hitTest(HitTestRequest(true, true), result);
1360
1361     IntPoint widgetPoint(point);
1362     while (true) {
1363         Node* n = result.innerNode();
1364         if (!n || !n->renderer() || !n->renderer()->isWidget())
1365             break;
1366         Widget* widget = static_cast<RenderWidget*>(n->renderer())->widget();
1367         if (!widget || !widget->isFrameView())
1368             break;
1369         Frame* frame = static_cast<HTMLFrameElementBase*>(n)->contentFrame();
1370         if (!frame || !frame->renderer())
1371             break;
1372         int absX, absY;
1373         n->renderer()->absolutePosition(absX, absY, true);
1374         FrameView* view = static_cast<FrameView*>(widget);
1375         widgetPoint.move(view->contentsX() - absX, view->contentsY() - absY);
1376         HitTestResult widgetHitTestResult(widgetPoint);
1377         frame->renderer()->layer()->hitTest(HitTestRequest(true, true), widgetHitTestResult);
1378         result = widgetHitTestResult;
1379     }
1380
1381     if (!allowShadowContent) {
1382         Node* node = result.innerNode();
1383         if (node)
1384             node = node->shadowAncestorNode();
1385         result.setInnerNode(node);
1386         node = result.innerNonSharedNode();
1387         if (node)
1388             node = node->shadowAncestorNode();
1389         result.setInnerNonSharedNode(node); 
1390     }
1391
1392     return result;
1393 }
1394
1395
1396 void Frame::startAutoscrollTimer()
1397 {
1398     d->m_autoscrollTimer.startRepeating(autoscrollInterval);
1399 }
1400
1401 void Frame::stopAutoscrollTimer(bool rendererIsBeingDestroyed)
1402 {
1403     if (!rendererIsBeingDestroyed && autoscrollRenderer())
1404         autoscrollRenderer()->stopAutoscroll();
1405     setAutoscrollRenderer(0);
1406     d->m_autoscrollTimer.stop();
1407 }
1408
1409 // FIXME: why is this here instead of on the FrameView?
1410 void Frame::paint(GraphicsContext* p, const IntRect& rect)
1411 {
1412 #ifndef NDEBUG
1413     bool fillWithRed;
1414     if (!document() || document()->printing())
1415         fillWithRed = false; // Printing, don't fill with red (can't remember why).
1416     else if (document()->ownerElement())
1417         fillWithRed = false; // Subframe, don't fill with red.
1418     else if (view() && view()->isTransparent())
1419         fillWithRed = false; // Transparent, don't fill with red.
1420     else if (d->m_paintRestriction == PaintRestrictionSelectionOnly || d->m_paintRestriction == PaintRestrictionSelectionOnlyWhiteText)
1421         fillWithRed = false; // Selections are transparent, don't fill with red.
1422     else if (d->m_elementToDraw)
1423         fillWithRed = false; // Element images are transparent, don't fill with red.
1424     else
1425         fillWithRed = true;
1426     
1427     if (fillWithRed)
1428         p->fillRect(rect, Color(0xFF, 0, 0));
1429 #endif
1430     
1431     if (renderer()) {
1432         // d->m_elementToDraw is used to draw only one element
1433         RenderObject *eltRenderer = d->m_elementToDraw ? d->m_elementToDraw->renderer() : 0;
1434         if (d->m_paintRestriction == PaintRestrictionNone)
1435             renderer()->document()->invalidateRenderedRectsForMarkersInRect(rect);
1436         renderer()->layer()->paint(p, rect, d->m_paintRestriction, eltRenderer);
1437
1438 #if PLATFORM(MAC)
1439         // Regions may have changed as a result of the visibility/z-index of element changing.
1440         if (renderer()->document()->dashboardRegionsDirty())
1441             renderer()->view()->frameView()->updateDashboardRegions();
1442 #endif
1443     } else
1444         LOG_ERROR("called Frame::paint with nil renderer");
1445 }
1446
1447 #if PLATFORM(CG)
1448
1449 void Frame::adjustPageHeight(float *newBottom, float oldTop, float oldBottom, float bottomLimit)
1450 {
1451     RenderView *root = static_cast<RenderView*>(document()->renderer());
1452     if (root) {
1453         // Use a context with painting disabled.
1454         GraphicsContext context((PlatformGraphicsContext*)0);
1455         root->setTruncatedAt((int)floorf(oldBottom));
1456         IntRect dirtyRect(0, (int)floorf(oldTop), root->docWidth(), (int)ceilf(oldBottom - oldTop));
1457         root->layer()->paint(&context, dirtyRect);
1458         *newBottom = root->bestTruncatedAt();
1459         if (*newBottom == 0)
1460             *newBottom = oldBottom;
1461     } else
1462         *newBottom = oldBottom;
1463 }
1464
1465 #endif
1466
1467 Frame *Frame::frameForWidget(const Widget *widget)
1468 {
1469     ASSERT_ARG(widget, widget);
1470     
1471     Node *node = nodeForWidget(widget);
1472     if (node)
1473         return frameForNode(node);
1474     
1475     // Assume all widgets are either form controls, or FrameViews.
1476     ASSERT(widget->isFrameView());
1477     return static_cast<const FrameView*>(widget)->frame();
1478 }
1479
1480 Frame *Frame::frameForNode(Node *node)
1481 {
1482     ASSERT_ARG(node, node);
1483     return node->document()->frame();
1484 }
1485
1486 Node* Frame::nodeForWidget(const Widget* widget)
1487 {
1488     ASSERT_ARG(widget, widget);
1489     WidgetClient* client = widget->client();
1490     if (!client)
1491         return 0;
1492     return client->element(const_cast<Widget*>(widget));
1493 }
1494
1495 void Frame::clearDocumentFocus(Widget *widget)
1496 {
1497     Node *node = nodeForWidget(widget);
1498     ASSERT(node);
1499     node->document()->setFocusNode(0);
1500 }
1501
1502 void Frame::forceLayout()
1503 {
1504     FrameView *v = d->m_view.get();
1505     if (v) {
1506         v->layout(false);
1507         // We cannot unschedule a pending relayout, since the force can be called with
1508         // a tiny rectangle from a drawRect update.  By unscheduling we in effect
1509         // "validate" and stop the necessary full repaint from occurring.  Basically any basic
1510         // append/remove DHTML is broken by this call.  For now, I have removed the optimization
1511         // until we have a better invalidation stategy. -dwh
1512         //v->unscheduleRelayout();
1513     }
1514 }
1515
1516 void Frame::forceLayoutWithPageWidthRange(float minPageWidth, float maxPageWidth)
1517 {
1518     // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
1519     // the state of things before and after the layout
1520     RenderView *root = static_cast<RenderView*>(document()->renderer());
1521     if (root) {
1522         // This magic is basically copied from khtmlview::print
1523         int pageW = (int)ceilf(minPageWidth);
1524         root->setWidth(pageW);
1525         root->setNeedsLayoutAndMinMaxRecalc();
1526         forceLayout();
1527         
1528         // If we don't fit in the minimum page width, we'll lay out again. If we don't fit in the
1529         // maximum page width, we will lay out to the maximum page width and clip extra content.
1530         // FIXME: We are assuming a shrink-to-fit printing implementation.  A cropping
1531         // implementation should not do this!
1532         int rightmostPos = root->rightmostPosition();
1533         if (rightmostPos > minPageWidth) {
1534             pageW = min(rightmostPos, (int)ceilf(maxPageWidth));
1535             root->setWidth(pageW);
1536             root->setNeedsLayoutAndMinMaxRecalc();
1537             forceLayout();
1538         }
1539     }
1540 }
1541
1542 void Frame::sendResizeEvent()
1543 {
1544     if (Document* doc = document())
1545         doc->dispatchWindowEvent(EventNames::resizeEvent, false, false);
1546 }
1547
1548 void Frame::sendScrollEvent()
1549 {
1550     FrameView *v = d->m_view.get();
1551     if (v) {
1552         Document *doc = document();
1553         if (!doc)
1554             return;
1555         doc->dispatchHTMLEvent(scrollEvent, true, false);
1556     }
1557 }
1558
1559 bool Frame::canMouseDownStartSelect(Node* node)
1560 {
1561     if (!node || !node->renderer())
1562         return true;
1563     
1564     // Check to see if -webkit-user-select has been set to none
1565     if (!node->renderer()->canSelect())
1566         return false;
1567     
1568     // Some controls and images can't start a select on a mouse down.
1569     for (RenderObject* curr = node->renderer(); curr; curr = curr->parent()) {
1570         if (curr->style()->userSelect() == SELECT_IGNORE)
1571             return false;
1572     }
1573     
1574     return true;
1575 }
1576
1577 void Frame::clearTimers(FrameView *view)
1578 {
1579     if (view) {
1580         view->unscheduleRelayout();
1581         if (view->frame()) {
1582             Document* document = view->frame()->document();
1583             if (document && document->renderer() && document->renderer()->layer())
1584                 document->renderer()->layer()->suspendMarquees();
1585         }
1586     }
1587 }
1588
1589 void Frame::clearTimers()
1590 {
1591     clearTimers(d->m_view.get());
1592 }
1593
1594 RenderStyle *Frame::styleForSelectionStart(Node *&nodeToRemove) const
1595 {
1596     nodeToRemove = 0;
1597     
1598     if (!document())
1599         return 0;
1600     if (selectionController()->isNone())
1601         return 0;
1602     
1603     Position pos = selectionController()->selection().visibleStart().deepEquivalent();
1604     if (!pos.inRenderedContent())
1605         return 0;
1606     Node *node = pos.node();
1607     if (!node)
1608         return 0;
1609     
1610     if (!d->m_typingStyle)
1611         return node->renderer()->style();
1612     
1613     ExceptionCode ec = 0;
1614     RefPtr<Element> styleElement = document()->createElementNS(xhtmlNamespaceURI, "span", ec);
1615     ASSERT(ec == 0);
1616     
1617     styleElement->setAttribute(styleAttr, d->m_typingStyle->cssText().impl(), ec);
1618     ASSERT(ec == 0);
1619     
1620     styleElement->appendChild(document()->createEditingTextNode(""), ec);
1621     ASSERT(ec == 0);
1622     
1623     node->parentNode()->appendChild(styleElement, ec);
1624     ASSERT(ec == 0);
1625     
1626     nodeToRemove = styleElement.get();    
1627     return styleElement->renderer()->style();
1628 }
1629
1630 void Frame::setSelectionFromNone()
1631 {
1632     // Put a caret inside the body if the entire frame is editable (either the 
1633     // entire WebView is editable or designMode is on for this document).
1634     Document *doc = document();
1635     if (!doc || !selectionController()->isNone() || !isContentEditable())
1636         return;
1637         
1638     Node* node = doc->documentElement();
1639     while (node && !node->hasTagName(bodyTag))
1640         node = node->traverseNextNode();
1641     if (node)
1642         selectionController()->setSelection(Selection(Position(node, 0), DOWNSTREAM));
1643 }
1644
1645 bool Frame::isActive() const
1646 {
1647     return d->m_isActive;
1648 }
1649
1650 void Frame::setIsActive(bool flag)
1651 {
1652     if (d->m_isActive == flag)
1653         return;
1654     
1655     d->m_isActive = flag;
1656
1657     // This method does the job of updating the view based on whether the view is "active".
1658     // This involves three kinds of drawing updates:
1659
1660     // 1. The background color used to draw behind selected content (active | inactive color)
1661     if (d->m_view)
1662         d->m_view->updateContents(enclosingIntRect(visibleSelectionRect()));
1663
1664     // 2. Caret blinking (blinks | does not blink)
1665     if (flag)
1666         setSelectionFromNone();
1667     setCaretVisible(flag);
1668     
1669     // 3. The drawing of a focus ring around links in web pages.
1670     Document *doc = document();
1671     if (doc) {
1672         Node *node = doc->focusNode();
1673         if (node) {
1674             node->setChanged();
1675             if (node->renderer() && node->renderer()->style()->hasAppearance())
1676                 theme()->stateChanged(node->renderer(), FocusState);
1677         }
1678     }
1679     
1680     // 4. Changing the tint of controls from clear to aqua/graphite and vice versa.  We
1681     // do a "fake" paint.  When the theme gets a paint call, it can then do an invalidate.  This is only
1682     // done if the theme supports control tinting.
1683     if (doc && d->m_view && theme()->supportsControlTints() && renderer()) {
1684         doc->updateLayout(); // Ensure layout is up to date.
1685         IntRect visibleRect(enclosingIntRect(d->m_view->visibleContentRect()));
1686         GraphicsContext context((PlatformGraphicsContext*)0);
1687         context.setUpdatingControlTints(true);
1688         paint(&context, visibleRect);
1689     }
1690    
1691     // 5. Enable or disable secure keyboard entry
1692     if ((flag && !isSecureKeyboardEntry() && doc && doc->focusNode() && doc->focusNode()->hasTagName(inputTag) && 
1693             static_cast<HTMLInputElement*>(doc->focusNode())->inputType() == HTMLInputElement::PASSWORD) ||
1694         (!flag && isSecureKeyboardEntry()))
1695             setSecureKeyboardEntry(flag);
1696 }
1697
1698 void Frame::setWindowHasFocus(bool flag)
1699 {
1700     if (d->m_windowHasFocus == flag)
1701         return;
1702     d->m_windowHasFocus = flag;
1703     
1704     if (Document *doc = document())
1705         doc->dispatchWindowEvent(flag ? focusEvent : blurEvent, false, false);
1706 }
1707
1708 bool Frame::inViewSourceMode() const
1709 {
1710     return d->m_inViewSourceMode;
1711 }
1712
1713 void Frame::setInViewSourceMode(bool mode) const
1714 {
1715     d->m_inViewSourceMode = mode;
1716 }
1717   
1718 UChar Frame::backslashAsCurrencySymbol() const
1719 {
1720     Document *doc = document();
1721     if (!doc)
1722         return '\\';
1723     TextResourceDecoder *decoder = doc->decoder();
1724     if (!decoder)
1725         return '\\';
1726
1727     return decoder->encoding().backslashAsCurrencySymbol();
1728 }
1729
1730 bool Frame::markedTextUsesUnderlines() const
1731 {
1732     return d->m_markedTextUsesUnderlines;
1733 }
1734
1735 const Vector<MarkedTextUnderline>& Frame::markedTextUnderlines() const
1736 {
1737     return d->m_markedTextUnderlines;
1738 }
1739
1740 // Searches from the beginning of the document if nothing is selected.
1741 bool Frame::findString(const String& target, bool forward, bool caseFlag, bool wrapFlag)
1742 {
1743     if (target.isEmpty())
1744         return false;
1745     
1746     // Initially search from the start (if forward) or end (if backward) of the selection, and search to edge of document.
1747     RefPtr<Range> searchRange(rangeOfContents(document()));
1748     Selection selection(selectionController()->selection());
1749     if (!selection.isNone()) {
1750         if (forward)
1751             setStart(searchRange.get(), selection.visibleStart());
1752         else
1753             setEnd(searchRange.get(), selection.visibleEnd());
1754     }
1755     RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, forward, caseFlag));
1756     // If the found range is already selected, find again.
1757     // Build a selection with the found range to remove collapsed whitespace.
1758     // Compare ranges instead of selection objects to ignore the way that the current selection was made.
1759     if (!selection.isNone() && *Selection(resultRange.get()).toRange() == *selection.toRange()) {
1760         searchRange = rangeOfContents(document());
1761         if (forward)
1762             setStart(searchRange.get(), selection.visibleEnd());
1763         else
1764             setEnd(searchRange.get(), selection.visibleStart());
1765         resultRange = findPlainText(searchRange.get(), target, forward, caseFlag);
1766     }
1767     
1768     int exception = 0;
1769     
1770     // If we didn't find anything and we're wrapping, search again in the entire document (this will
1771     // redundantly re-search the area already searched in some cases).
1772     if (resultRange->collapsed(exception) && wrapFlag) {
1773         searchRange = rangeOfContents(document());
1774         resultRange = findPlainText(searchRange.get(), target, forward, caseFlag);
1775         // We used to return false here if we ended up with the same range that we started with
1776         // (e.g., the selection was already the only instance of this text). But we decided that
1777         // this should be a success case instead, so we'll just fall through in that case.
1778     }
1779
1780     if (resultRange->collapsed(exception))
1781         return false;
1782
1783     selectionController()->setSelection(Selection(resultRange.get(), DOWNSTREAM));
1784     revealSelection();
1785     return true;
1786 }
1787
1788 unsigned Frame::markAllMatchesForText(const String& target, bool caseFlag, unsigned limit)
1789 {
1790     if (target.isEmpty())
1791         return 0;
1792     
1793     RefPtr<Range> searchRange(rangeOfContents(document()));
1794     
1795     int exception = 0;
1796     unsigned matchCount = 0;
1797     do {
1798         RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, true, caseFlag));
1799         if (resultRange->collapsed(exception))
1800             break;
1801         
1802         // A non-collapsed result range can in some funky whitespace cases still not
1803         // advance the range's start position (4509328). Break to avoid infinite loop.
1804         VisiblePosition newStart = endVisiblePosition(resultRange.get(), DOWNSTREAM);
1805         if (newStart == startVisiblePosition(searchRange.get(), DOWNSTREAM))
1806             break;
1807
1808         ++matchCount;
1809         
1810         document()->addMarker(resultRange.get(), DocumentMarker::TextMatch);        
1811         
1812         // Stop looking if we hit the specified limit. A limit of 0 means no limit.
1813         if (limit > 0 && matchCount >= limit)
1814             break;
1815         
1816         setStart(searchRange.get(), newStart);
1817     } while (true);
1818     
1819     // Do a "fake" paint in order to execute the code that computes the rendered rect for 
1820     // each text match.
1821     Document* doc = document();
1822     if (doc && d->m_view && renderer()) {
1823         doc->updateLayout(); // Ensure layout is up to date.
1824         IntRect visibleRect(enclosingIntRect(d->m_view->visibleContentRect()));
1825         GraphicsContext context((PlatformGraphicsContext*)0);
1826         context.setPaintingDisabled(true);
1827         paint(&context, visibleRect);
1828     }
1829     
1830     return matchCount;
1831 }
1832
1833 bool Frame::markedTextMatchesAreHighlighted() const
1834 {
1835     return d->m_highlightTextMatches;
1836 }
1837
1838 void Frame::setMarkedTextMatchesAreHighlighted(bool flag)
1839 {
1840     if (flag == d->m_highlightTextMatches)
1841         return;
1842     
1843     d->m_highlightTextMatches = flag;
1844     document()->repaintMarkers(DocumentMarker::TextMatch);
1845 }
1846
1847 Node *Frame::mousePressNode()
1848 {
1849     return d->m_mousePressNode.get();
1850 }
1851
1852 FrameTree* Frame::tree() const
1853 {
1854     return &d->m_treeNode;
1855 }
1856
1857 DOMWindow* Frame::domWindow() const
1858 {
1859     if (!d->m_domWindow)
1860         d->m_domWindow = new DOMWindow(const_cast<Frame*>(this));
1861
1862     return d->m_domWindow.get();
1863 }
1864
1865 Page* Frame::page() const
1866 {
1867     return d->m_page;
1868 }
1869
1870 void Frame::pageDestroyed()
1871 {
1872     d->m_page = 0;
1873
1874     // This will stop any JS timers
1875     if (d->m_jscript && d->m_jscript->haveInterpreter())
1876         if (Window* w = Window::retrieveWindow(this))
1877             w->disconnectFrame();
1878 }
1879
1880 void Frame::setStatusBarText(const String&)
1881 {
1882 }
1883
1884 void Frame::disconnectOwnerElement()
1885 {
1886     if (d->m_ownerElement && d->m_page)
1887         d->m_page->decrementFrameCount();
1888         
1889     d->m_ownerElement = 0;
1890 }
1891
1892 String Frame::documentTypeString() const
1893 {
1894     if (Document *doc = document())
1895         if (DocumentType *doctype = doc->realDocType())
1896             return doctype->toString();
1897
1898     return String();
1899 }
1900
1901 bool Frame::prohibitsScrolling() const
1902 {
1903     return d->m_prohibitsScrolling;
1904 }
1905
1906 void Frame::setProhibitsScrolling(const bool prohibit)
1907 {
1908     d->m_prohibitsScrolling = prohibit;
1909 }
1910
1911 FramePrivate::FramePrivate(Page* page, Frame* parent, Frame* thisFrame, Element* ownerElement, PassRefPtr<EditorClient> client)
1912     : m_page(page)
1913     , m_treeNode(thisFrame, parent)
1914     , m_ownerElement(ownerElement)
1915     , m_jscript(0)
1916     , m_bJScriptEnabled(true)
1917     , m_bJavaEnabled(true)
1918     , m_bPluginsEnabled(true)
1919     , m_settings(0)
1920     , m_zoomFactor(parent ? parent->d->m_zoomFactor : 100)
1921     , m_bMousePressed(false)
1922     , m_beganSelectingText(false)
1923     , m_selectionController(thisFrame)
1924     , m_caretBlinkTimer(thisFrame, &Frame::caretBlinkTimerFired)
1925     , m_editor(thisFrame, client)
1926     , m_caretVisible(false)
1927     , m_caretPaint(true)
1928     , m_isActive(false)
1929     , m_lifeSupportTimer(thisFrame, &Frame::lifeSupportTimerFired)
1930     , m_loader(new FrameLoader(thisFrame))
1931     , m_userStyleSheetLoader(0)
1932     , m_autoscrollTimer(thisFrame, &Frame::autoscrollTimerFired)
1933     , m_autoscrollRenderer(0)
1934     , m_mouseDownMayStartAutoscroll(false)
1935     , m_mouseDownMayStartDrag(false)
1936     , m_paintRestriction(PaintRestrictionNone)
1937     , m_markedTextUsesUnderlines(false)
1938     , m_highlightTextMatches(false)
1939     , m_windowHasFocus(false)
1940     , m_inViewSourceMode(false)
1941     , frameCount(0)
1942     , m_prohibitsScrolling(false)
1943 {
1944 }
1945
1946 FramePrivate::~FramePrivate()
1947 {
1948     delete m_jscript;
1949     delete m_loader;
1950 }
1951
1952 } // namespace WebCore