2006-03-20 Eric Seidel <eseidel@apple.com>
[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 "Cache.h"
34 #include "CachedCSSStyleSheet.h"
35 #include "DOMImplementation.h"
36 #include "DocLoader.h"
37 #include "EditingText.h"
38 #include "EventNames.h"
39 #include "FloatRect.h"
40 #include "Frame.h"
41 #include "FrameView.h"
42 #include "GraphicsContext.h"
43 #include "HTMLCollection.h"
44 #include "HTMLFormElement.h"
45 #include "HTMLGenericFormElement.h"
46 #include "PlatformMouseEvent.h"
47 #include "MouseEventWithHitTestResults.h"
48 #include "NodeList.h"
49 #include "PlatformString.h"
50 #include "Plugin.h"
51 #include "RenderBlock.h"
52 #include "RenderText.h"
53 #include "SegmentedString.h"
54 #include "TypingCommand.h"
55 #include "VisiblePosition.h"
56 #include "CSSComputedStyleDeclaration.h"
57 #include "css_valueimpl.h"
58 #include "CSSPropertyNames.h"
59 #include "cssstyleselector.h"
60 #include "dom2_eventsimpl.h"
61 #include "Range.h"
62 #include "html_baseimpl.h"
63 #include "HTMLDocument.h"
64 #include "html_imageimpl.h"
65 #include "html_objectimpl.h"
66 #include "htmlediting.h"
67 #include "HTMLNames.h"
68 #include "khtml_settings.h"
69 #include "kjs_proxy.h"
70 #include "kjs_window.h"
71 #include "loader.h"
72 #include "markup.h"
73 #include "RenderCanvas.h"
74 #include "render_frames.h"
75 #include "RenderLayer.h"
76 #include "RenderTheme.h"
77 #include "TextIterator.h"
78 #include "visible_units.h"
79 #include "xml_tokenizer.h"
80 #include "xmlhttprequest.h"
81 #include <assert.h>
82 #include <kio/global.h>
83 #include "TransferJob.h"
84 #include <kxmlcore/Assertions.h>
85 #include <qptrlist.h>
86 #include "TextEncoding.h"
87 #include <sys/types.h>
88 #include <math.h>
89
90 #if !WIN32
91 #include <unistd.h>
92 #endif
93
94 #if SVG_SUPPORT
95 #include "SVGNames.h"
96 #include "XLinkNames.h"
97 #include "SVGDocumentExtensions.h"
98 #endif
99
100 using namespace KJS;
101
102 namespace WebCore {
103
104 using namespace EventNames;
105 using namespace HTMLNames;
106
107 const double caretBlinkFrequency = 0.5;
108 const double autoscrollInterval = 0.1;
109
110 class UserStyleSheetLoader : public CachedObjectClient {
111 public:
112     UserStyleSheetLoader(Frame* frame, const String& url, DocLoader* dl)
113         : m_frame(frame)
114         , m_cachedSheet(Cache::requestStyleSheet(dl, url))
115     {
116         m_cachedSheet->ref(this);
117     }
118     ~UserStyleSheetLoader()
119     {
120         m_cachedSheet->deref(this);
121     }
122 private:
123     virtual void setStyleSheet(const String&, const String& sheet)
124     {
125         m_frame->setUserStyleSheet(sheet);
126     }
127     Frame* m_frame;
128     CachedCSSStyleSheet* m_cachedSheet;
129 };
130
131 #if !NDEBUG
132 struct FrameCounter { 
133     static int count; 
134     ~FrameCounter() { if (count != 0) fprintf(stderr, "LEAK: %d Frame\n", count); }
135 };
136 int FrameCounter::count = 0;
137 static FrameCounter frameCounter;
138 #endif
139
140 static inline Frame* parentFromOwnerRenderer(RenderPart* ownerRenderer)
141 {
142     if (!ownerRenderer)
143         return 0;
144     return ownerRenderer->node()->getDocument()->frame();
145 }
146
147 Frame::Frame(Page* page, RenderPart* ownerRenderer) 
148     : d(new FramePrivate(page, parentFromOwnerRenderer(ownerRenderer), this, ownerRenderer))
149 {
150     AtomicString::init();
151     Cache::init();
152     EventNames::init();
153     HTMLNames::init();
154     QualifiedName::init();
155
156 #if SVG_SUPPORT
157     SVGNames::init();
158     XLinkNames::init();
159 #endif
160
161     // FIXME: Frames were originally created with a refcount of 1, leave this
162     // ref call here until we can straighten that out.
163     ref();
164 #if !NDEBUG
165     ++FrameCounter::count;
166 #endif
167
168     if (ownerRenderer)
169         ownerRenderer->setFrame(this);
170 }
171
172 Frame::~Frame()
173 {
174     ASSERT(!d->m_lifeSupportTimer.isActive());
175
176 #if !NDEBUG
177     --FrameCounter::count;
178 #endif
179
180     cancelRedirection();
181
182     if (!d->m_bComplete)
183         closeURL();
184
185     clear(false);
186
187     if (d->m_jscript && d->m_jscript->haveInterpreter())
188         if (Window* w = Window::retrieveWindow(this)) {
189             w->disconnectFrame();
190             // Must clear the window pointer, otherwise we will not
191             // garbage-collect collect the window (inside the call to
192             // delete d below).
193             w = 0;
194         }
195
196     setOpener(0);
197     HashSet<Frame*> openedBy = d->m_openedFrames;
198     HashSet<Frame*>::iterator end = openedBy.end();
199     for (HashSet<Frame*>::iterator it = openedBy.begin(); it != end; ++it)
200         (*it)->setOpener(0);
201
202     if (d->m_ownerRenderer)
203         d->m_ownerRenderer->setFrame(0);
204     ASSERT(!d->m_ownerRenderer);
205
206     if (d->m_view) {
207         d->m_view->hide();
208         d->m_view->m_frame = 0;
209     }
210   
211     ASSERT(!d->m_lifeSupportTimer.isActive());
212
213     delete d->m_userStyleSheetLoader;
214     delete d;
215     d = 0;
216 }
217
218 bool Frame::didOpenURL(const KURL& url)
219 {
220   if (d->m_scheduledRedirection == locationChangeScheduledDuringLoad) {
221     // A redirect was shceduled before the document was created. This can happen
222     // when one frame changes another frame's location.
223     return false;
224   }
225   
226   cancelRedirection();
227   
228   // clear last edit command
229   d->m_lastEditCommand = EditCommandPtr();
230   
231   closeURL();
232
233   if (d->m_request.reload)
234      d->m_cachePolicy = KIO::CC_Refresh;
235   else
236      d->m_cachePolicy = KIO::CC_Verify;
237
238   if (d->m_request.doPost() && url.protocol().startsWith("http")) {
239       d->m_job = new TransferJob(this, "POST", url, d->m_request.postData);
240       d->m_job->addMetaData("content-type", d->m_request.contentType());
241   } else
242       d->m_job = new TransferJob(this, "GET", url);
243
244   d->m_bComplete = false;
245   d->m_bLoadingMainResource = true;
246   d->m_bLoadEventEmitted = false;
247
248   d->m_kjsStatusBarText = String();
249   d->m_kjsDefaultStatusBarText = String();
250
251   d->m_bJScriptEnabled = d->m_settings->isJavaScriptEnabled();
252   d->m_bJavaEnabled = d->m_settings->isJavaEnabled();
253   d->m_bPluginsEnabled = d->m_settings->isPluginsEnabled();
254
255   // initializing d->m_url to the new url breaks relative links when opening such a link after this call and _before_ begin() is called (when the first
256   // data arrives) (Simon)
257   d->m_url = url;
258   if (d->m_url.protocol().startsWith("http") && !d->m_url.host().isEmpty() && d->m_url.path().isEmpty())
259     d->m_url.setPath("/");
260   d->m_workingURL = d->m_url;
261
262   started();
263
264   return true;
265 }
266
267 void Frame::didExplicitOpen()
268 {
269   d->m_bComplete = false;
270   d->m_bLoadEventEmitted = false;
271     
272   // Prevent window.open(url) -- eg window.open("about:blank") -- from blowing away results
273   // from a subsequent window.document.open / window.document.write call. 
274   // Cancelling redirection here works for all cases because document.open 
275   // implicitly precedes document.write.
276   cancelRedirection(); 
277 }
278
279 void Frame::stopLoading(bool sendUnload)
280 {
281   if (d->m_doc && d->m_doc->tokenizer())
282     d->m_doc->tokenizer()->stopParsing();
283     
284   if (d->m_job)
285   {
286     d->m_job->kill();
287     d->m_job = 0;
288   }
289
290   if (sendUnload) {
291     if (d->m_doc) {
292       if (d->m_bLoadEventEmitted && !d->m_bUnloadEventEmitted) {
293         d->m_doc->dispatchWindowEvent(unloadEvent, false, false);
294         if (d->m_doc)
295           d->m_doc->updateRendering();
296         d->m_bUnloadEventEmitted = true;
297       }
298     }
299     
300     if (d->m_doc && !d->m_doc->inPageCache())
301       d->m_doc->removeAllEventListenersFromAllNodes();
302   }
303
304   d->m_bComplete = true; // to avoid calling completed() in finishedParsing() (David)
305   d->m_bLoadingMainResource = false;
306   d->m_bLoadEventEmitted = true; // don't want that one either
307   d->m_cachePolicy = KIO::CC_Verify; // Why here?
308
309   if (d->m_doc && d->m_doc->parsing()) {
310     finishedParsing();
311     d->m_doc->setParsing(false);
312   }
313   
314   d->m_workingURL = KURL();
315
316   if (Document *doc = d->m_doc.get()) {
317     if (DocLoader *docLoader = doc->docLoader())
318       Cache::loader()->cancelRequests(docLoader);
319       XMLHttpRequest::cancelRequests(doc);
320   }
321
322   // tell all subframes to stop as well
323   for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
324       child->stopLoading(sendUnload);
325
326   d->m_bPendingChildRedirection = false;
327
328   cancelRedirection();
329 }
330
331 BrowserExtension *Frame::browserExtension() const
332 {
333   return d->m_extension;
334 }
335
336 FrameView* Frame::view() const
337 {
338     return d->m_view.get();
339 }
340
341 void Frame::setView(FrameView* view)
342 {
343     d->m_view = view;
344 }
345
346 bool Frame::jScriptEnabled() const
347 {
348   return d->m_bJScriptEnabled;
349 }
350
351 void Frame::setMetaRefreshEnabled(bool enable)
352 {
353   d->m_metaRefreshEnabled = enable;
354 }
355
356 bool Frame::metaRefreshEnabled() const
357 {
358   return d->m_metaRefreshEnabled;
359 }
360
361 KJSProxy *Frame::jScript()
362 {
363     if (!d->m_bJScriptEnabled)
364         return 0;
365
366     if (!d->m_jscript)
367         d->m_jscript = new KJSProxy(this);
368
369     return d->m_jscript;
370 }
371
372 static bool getString(JSValue* result, DeprecatedString& string)
373 {
374     if (!result)
375         return false;
376     JSLock lock;
377     UString ustring;
378     if (!result->getString(ustring))
379         return false;
380     string = ustring.deprecatedString();
381     return true;
382 }
383
384 void Frame::replaceContentsWithScriptResult(const KURL& url)
385 {
386     JSValue* ret = executeScript(0, KURL::decode_string(url.url().mid(strlen("javascript:"))));
387     DeprecatedString scriptResult;
388     if (getString(ret, scriptResult)) {
389         begin();
390         write(scriptResult);
391         end();
392     }
393 }
394
395 JSValue* Frame::executeScript(Node* n, const DeprecatedString& script, bool forceUserGesture)
396 {
397   KJSProxy *proxy = jScript();
398
399   if (!proxy)
400     return 0;
401
402   d->m_runningScripts++;
403   // If forceUserGesture is true, then make the script interpreter
404   // treat it as if triggered by a user gesture even if there is no
405   // current DOM event being processed.
406   JSValue* ret = proxy->evaluate(forceUserGesture ? DeprecatedString::null : d->m_url.url(), 0, script, n);
407   d->m_runningScripts--;
408
409   if (!d->m_runningScripts)
410       submitFormAgain();
411
412   Document::updateDocumentsRendering();
413
414   return ret;
415 }
416
417 bool Frame::javaEnabled() const
418 {
419 #ifndef Q_WS_QWS
420   return d->m_bJavaEnabled;
421 #else
422   return false;
423 #endif
424 }
425
426 bool Frame::pluginsEnabled() const
427 {
428   return d->m_bPluginsEnabled;
429 }
430
431 void Frame::setAutoloadImages(bool enable)
432 {
433   if (d->m_doc && d->m_doc->docLoader()->autoloadImages() == enable)
434     return;
435
436   if (d->m_doc)
437     d->m_doc->docLoader()->setAutoloadImages(enable);
438 }
439
440 bool Frame::autoloadImages() const
441 {
442   if (d->m_doc)
443     return d->m_doc->docLoader()->autoloadImages();
444
445   return true;
446 }
447
448 void Frame::clear(bool clearWindowProperties)
449 {
450   if (d->m_bCleared)
451     return;
452   d->m_bCleared = true;
453   d->m_mousePressNode = 0;
454
455   if (d->m_doc) {
456     d->m_doc->cancelParsing();
457     d->m_doc->detach();
458   }
459
460   // Moving past doc so that onUnload works.
461   if (clearWindowProperties && d->m_jscript)
462     d->m_jscript->clear();
463
464   if (d->m_view)
465     d->m_view->clear();
466
467   // do not drop the document before the jscript and view are cleared, as some destructors
468   // might still try to access the document.
469   d->m_doc = 0;
470   d->m_decoder = 0;
471
472   d->m_plugins.clear();
473
474   d->m_scheduledRedirection = noRedirectionScheduled;
475   d->m_delayRedirect = 0;
476   d->m_redirectURL = DeprecatedString::null;
477   d->m_redirectReferrer = DeprecatedString::null;
478   d->m_redirectLockHistory = true;
479   d->m_redirectUserGesture = false;
480   d->m_bHTTPRefresh = false;
481   d->m_bFirstData = true;
482
483   d->m_bMousePressed = false;
484
485   if (!d->m_haveEncoding)
486     d->m_encoding = DeprecatedString::null;
487 }
488
489 Document *Frame::document() const
490 {
491     if (d)
492         return d->m_doc.get();
493     return 0;
494 }
495
496 void Frame::setDocument(Document* newDoc)
497 {
498     if (d) {
499         if (d->m_doc)
500             d->m_doc->detach();
501         d->m_doc = newDoc;
502         if (newDoc)
503             newDoc->attach();
504     }
505 }
506
507 void Frame::receivedFirstData()
508 {
509     begin(d->m_workingURL);
510
511     d->m_doc->docLoader()->setCachePolicy(d->m_cachePolicy);
512     d->m_workingURL = KURL();
513
514     // When the first data arrives, the metadata has just been made available
515     DeprecatedString qData;
516
517     // Support for http-refresh
518     qData = d->m_job->queryMetaData("http-refresh").deprecatedString();
519     if (!qData.isEmpty() && d->m_metaRefreshEnabled) {
520       double delay;
521       int pos = qData.find(';');
522       if (pos == -1)
523         pos = qData.find(',');
524
525       if (pos == -1) {
526         delay = qData.stripWhiteSpace().toDouble();
527         // We want a new history item if the refresh timeout > 1 second
528         scheduleRedirection(delay, d->m_url.url(), delay <= 1);
529       } else {
530         int end_pos = qData.length();
531         delay = qData.left(pos).stripWhiteSpace().toDouble();
532         while (qData[++pos] == ' ');
533         if (qData.find("url", pos, false) == pos) {
534           pos += 3;
535           while (qData[pos] == ' ' || qData[pos] == '=')
536               pos++;
537           if (qData[pos] == '"') {
538               pos++;
539               int index = end_pos-1;
540               while (index > pos) {
541                 if (qData[index] == '"')
542                     break;
543                 index--;
544               }
545               if (index > pos)
546                 end_pos = index;
547           }
548         }
549         // We want a new history item if the refresh timeout > 1 second
550         scheduleRedirection(delay, d->m_doc->completeURL(qData.mid(pos, end_pos)), delay <= 1);
551       }
552       d->m_bHTTPRefresh = true;
553     }
554
555     // Support for http last-modified
556     d->m_lastModified = d->m_job->queryMetaData("modified");
557 }
558
559 void Frame::receivedAllData(TransferJob* job)
560 {
561     d->m_job = 0;
562
563     if (job->error()) {
564         checkCompleted();
565         return;
566     }
567
568     d->m_workingURL = KURL();
569
570     if (d->m_doc->parsing())
571         end(); // will call completed()
572 }
573
574 void Frame::childBegin()
575 {
576     // We need to do this when the child is created so as to avoid the parent thining the child
577     // is complete before it has even started loading.
578     // FIXME: do we really still need this?
579     d->m_bComplete = false;
580 }
581
582 void Frame::setResourceRequest(const ResourceRequest& request)
583 {
584     d->m_request = request;
585 }
586
587 const ResourceRequest& Frame::resourceRequest() const
588 {
589     return d->m_request;
590 }
591
592 void Frame::begin(const KURL& url)
593 {
594   if (d->m_workingURL.isEmpty())
595     createEmptyDocument(); // Creates an empty document if we don't have one already
596
597   clear();
598   partClearedInBegin();
599
600   d->m_bCleared = false;
601   d->m_bComplete = false;
602   d->m_bLoadEventEmitted = false;
603   d->m_bLoadingMainResource = true;
604
605   KURL ref(url);
606   ref.setUser(QSTRING_NULL);
607   ref.setPass(QSTRING_NULL);
608   ref.setRef(QSTRING_NULL);
609   d->m_referrer = ref.url();
610   d->m_url = url;
611   KURL baseurl;
612
613   // We don't need KDE chained URI handling or window caption setting
614   if (!d->m_url.isEmpty())
615     baseurl = d->m_url;
616
617   if (DOMImplementation::isXMLMIMEType(d->m_request.m_responseMIMEType))
618     d->m_doc = DOMImplementation::instance()->createDocument(d->m_view.get());
619   else
620     d->m_doc = DOMImplementation::instance()->createHTMLDocument(d->m_view.get());
621
622   if (!d->m_doc->attached())
623     d->m_doc->attach();
624   d->m_doc->setURL(d->m_url.url());
625   // We prefer m_baseURL over d->m_url because d->m_url changes when we are
626   // about to load a new page.
627   d->m_doc->setBaseURL(baseurl.url());
628   if (d->m_decoder)
629     d->m_doc->setDecoder(d->m_decoder.get());
630   d->m_doc->docLoader()->setShowAnimations(KHTMLSettings::KAnimationEnabled);
631
632   updatePolicyBaseURL();
633
634   setAutoloadImages(d->m_settings->autoLoadImages());
635   String userStyleSheet = d->m_settings->userStyleSheet();
636
637   if (!userStyleSheet.isEmpty())
638     setUserStyleSheet(KURL(userStyleSheet));
639
640   restoreDocumentState();
641
642   d->m_doc->implicitOpen();
643   // clear widget
644   if (d->m_view)
645     d->m_view->resizeContents(0, 0);
646 }
647
648 void Frame::write(const char* str, int len)
649 {
650     if (!d->m_decoder) {
651         d->m_decoder = new Decoder;
652         if (!d->m_encoding.isNull())
653             d->m_decoder->setEncodingName(d->m_encoding.latin1(),
654                 d->m_haveEncoding ? Decoder::UserChosenEncoding : Decoder::EncodingFromHTTPHeader);
655         else
656             d->m_decoder->setEncodingName(settings()->encoding().latin1(), Decoder::DefaultEncoding);
657
658         if (d->m_doc)
659             d->m_doc->setDecoder(d->m_decoder.get());
660     }
661   if (len == 0)
662     return;
663
664   if (len == -1)
665     len = strlen(str);
666
667   DeprecatedString decoded = d->m_decoder->decode(str, len);
668
669   if (decoded.isEmpty())
670     return;
671
672   if (d->m_bFirstData) {
673       // determine the parse mode
674       d->m_doc->determineParseMode(decoded);
675       d->m_bFirstData = false;
676
677       // ### this is still quite hacky, but should work a lot better than the old solution
678       if (d->m_decoder->visuallyOrdered()) d->m_doc->setVisuallyOrdered();
679       d->m_doc->recalcStyle(Node::Force);
680   }
681
682   if (Tokenizer* t = d->m_doc->tokenizer())
683       t->write(decoded, true);
684 }
685
686 void Frame::write(const DeprecatedString& str)
687 {
688   if (str.isNull())
689     return;
690
691   if (d->m_bFirstData) {
692       // determine the parse mode
693       d->m_doc->setParseMode(Document::Strict);
694       d->m_bFirstData = false;
695   }
696   Tokenizer* t = d->m_doc->tokenizer();
697   if (t)
698     t->write(str, true);
699 }
700
701 void Frame::end()
702 {
703     d->m_bLoadingMainResource = false;
704     endIfNotLoading();
705 }
706
707 void Frame::endIfNotLoading()
708 {
709     if (d->m_bLoadingMainResource)
710         return;
711
712     // make sure nothing's left in there...
713     if (d->m_decoder)
714         write(d->m_decoder->flush());
715     if (d->m_doc)
716         d->m_doc->finishParsing();
717     else
718         // WebKit partially uses WebCore when loading non-HTML docs.  In these cases doc==nil, but
719         // WebCore is enough involved that we need to checkCompleted() in order for m_bComplete to
720         // become true.  An example is when a subframe is a pure text doc, and that subframe is the
721         // last one to complete.
722         checkCompleted();
723 }
724
725 void Frame::stop()
726 {
727     if (d->m_doc) {
728         if (d->m_doc->tokenizer())
729             d->m_doc->tokenizer()->stopParsing();
730         d->m_doc->finishParsing();
731     } else
732         // WebKit partially uses WebCore when loading non-HTML docs.  In these cases doc==nil, but
733         // WebCore is enough involved that we need to checkCompleted() in order for m_bComplete to
734         // become true.  An example is when a subframe is a pure text doc, and that subframe is the
735         // last one to complete.
736         checkCompleted();
737 }
738
739 void Frame::stopAnimations()
740 {
741   if (d->m_doc)
742       d->m_doc->docLoader()->setShowAnimations(KHTMLSettings::KAnimationDisabled);
743
744   for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
745       child->stopAnimations();
746 }
747
748 void Frame::gotoAnchor()
749 {
750     // If our URL has no ref, then we have no place we need to jump to.
751     if (!d->m_url.hasRef())
752         return;
753
754     DeprecatedString ref = d->m_url.encodedHtmlRef();
755     if (!gotoAnchor(ref)) {
756         // Can't use htmlRef() here because it doesn't know which encoding to use to decode.
757         // Decoding here has to match encoding in completeURL, which means it has to use the
758         // page's encoding rather than UTF-8.
759         if (d->m_decoder)
760             gotoAnchor(KURL::decode_string(ref, d->m_decoder->encoding()));
761     }
762 }
763
764 void Frame::finishedParsing()
765 {
766   RefPtr<Frame> protector(this);
767   checkCompleted();
768
769   if (!d->m_view)
770     return; // We are being destroyed by something checkCompleted called.
771
772   // check if the scrollbars are really needed for the content
773   // if not, remove them, relayout, and repaint
774
775   d->m_view->restoreScrollBar();
776   gotoAnchor();
777 }
778
779 void Frame::loadDone()
780 {
781     if (d->m_doc)
782         checkCompleted();
783 }
784
785 void Frame::checkCompleted()
786 {
787   // Any frame that hasn't completed yet ?
788   for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
789       if (!child->d->m_bComplete)
790           return;
791
792   // Have we completed before?
793   if (d->m_bComplete)
794       return;
795
796   // Are we still parsing?
797   if (d->m_doc && d->m_doc->parsing())
798       return;
799
800   // Still waiting for images/scripts from the loader ?
801   int requests = 0;
802   if (d->m_doc && d->m_doc->docLoader())
803       requests = Cache::loader()->numRequests(d->m_doc->docLoader());
804
805   if (requests > 0)
806       return;
807
808   // OK, completed.
809   // Now do what should be done when we are really completed.
810   d->m_bComplete = true;
811
812   checkEmitLoadEvent(); // if we didn't do it before
813
814   if (d->m_scheduledRedirection != noRedirectionScheduled) {
815       // Do not start redirection for frames here! That action is
816       // deferred until the parent emits a completed signal.
817       if (!tree()->parent())
818           startRedirectionTimer();
819
820       completed(true);
821   } else {
822       completed(d->m_bPendingChildRedirection);
823   }
824 }
825
826 void Frame::checkEmitLoadEvent()
827 {
828     if (d->m_bLoadEventEmitted || !d->m_doc || d->m_doc->parsing())
829         return;
830
831     for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
832         if (!child->d->m_bComplete) // still got a frame running -> too early
833             return;
834
835     // All frames completed -> set their domain to the frameset's domain
836     // This must only be done when loading the frameset initially (#22039),
837     // not when following a link in a frame (#44162).
838     if (d->m_doc) {
839         String domain = d->m_doc->domain();
840         for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
841             if (child->d->m_doc)
842                 child->d->m_doc->setDomain(domain);
843     }
844
845     d->m_bLoadEventEmitted = true;
846     d->m_bUnloadEventEmitted = false;
847     if (d->m_doc)
848         d->m_doc->implicitClose();
849 }
850
851 const KHTMLSettings *Frame::settings() const
852 {
853   return d->m_settings;
854 }
855
856 KURL Frame::baseURL() const
857 {
858     if (!d->m_doc)
859         return KURL();
860     return d->m_doc->baseURL();
861 }
862
863 String Frame::baseTarget() const
864 {
865     if (!d->m_doc)
866         return DeprecatedString();
867     return d->m_doc->baseTarget();
868 }
869
870 KURL Frame::completeURL(const DeprecatedString& url)
871 {
872     if (!d->m_doc)
873         return url;
874
875     return KURL(d->m_doc->completeURL(url));
876 }
877
878 void Frame::scheduleRedirection(double delay, const DeprecatedString& url, bool doLockHistory)
879 {
880     if (delay < 0 || delay > INT_MAX / 1000)
881       return;
882     if (d->m_scheduledRedirection == noRedirectionScheduled || delay <= d->m_delayRedirect)
883     {
884        d->m_scheduledRedirection = redirectionScheduled;
885        d->m_delayRedirect = delay;
886        d->m_redirectURL = url;
887        d->m_redirectReferrer = DeprecatedString::null;
888        d->m_redirectLockHistory = doLockHistory;
889        d->m_redirectUserGesture = false;
890
891        stopRedirectionTimer();
892        if (d->m_bComplete)
893          startRedirectionTimer();
894     }
895 }
896
897 void Frame::scheduleLocationChange(const DeprecatedString& url, const DeprecatedString& referrer, bool lockHistory, bool userGesture)
898 {
899     // Handle a location change of a page with no document as a special case.
900     // This may happen when a frame changes the location of another frame.
901     d->m_scheduledRedirection = d->m_doc ? locationChangeScheduled : locationChangeScheduledDuringLoad;
902     
903     // If a redirect was scheduled during a load, then stop the current load.
904     // Otherwise when the current load transitions from a provisional to a 
905     // committed state, pending redirects may be cancelled. 
906     if (d->m_scheduledRedirection == locationChangeScheduledDuringLoad) {
907         stopLoading(true);   
908     }
909     
910     d->m_delayRedirect = 0;
911     d->m_redirectURL = url;
912     d->m_redirectReferrer = referrer;
913     d->m_redirectLockHistory = lockHistory;
914     d->m_redirectUserGesture = userGesture;
915     stopRedirectionTimer();
916     if (d->m_bComplete)
917         startRedirectionTimer();
918 }
919
920 bool Frame::isScheduledLocationChangePending() const
921 {
922     switch (d->m_scheduledRedirection) {
923         case noRedirectionScheduled:
924         case redirectionScheduled:
925             return false;
926         case historyNavigationScheduled:
927         case locationChangeScheduled:
928         case locationChangeScheduledDuringLoad:
929             return true;
930     }
931     return false;
932 }
933
934 void Frame::scheduleHistoryNavigation(int steps)
935 {
936     // navigation will always be allowed in the 0 steps case, which is OK because
937     // that's supposed to force a reload.
938     if (!canGoBackOrForward(steps)) {
939         cancelRedirection();
940         return;
941     }
942
943     d->m_scheduledRedirection = historyNavigationScheduled;
944     d->m_delayRedirect = 0;
945     d->m_redirectURL = DeprecatedString::null;
946     d->m_redirectReferrer = DeprecatedString::null;
947     d->m_scheduledHistoryNavigationSteps = steps;
948     stopRedirectionTimer();
949     if (d->m_bComplete)
950         startRedirectionTimer();
951 }
952
953 void Frame::cancelRedirection(bool cancelWithLoadInProgress)
954 {
955     if (d) {
956         d->m_cancelWithLoadInProgress = cancelWithLoadInProgress;
957         d->m_scheduledRedirection = noRedirectionScheduled;
958         stopRedirectionTimer();
959     }
960 }
961
962 void Frame::changeLocation(const DeprecatedString& URL, const DeprecatedString& referrer, bool lockHistory, bool userGesture)
963 {
964     if (URL.find("javascript:", 0, false) == 0) {
965         DeprecatedString script = KURL::decode_string(URL.mid(11));
966         JSValue* result = executeScript(0, script, userGesture);
967         DeprecatedString scriptResult;
968         if (getString(result, scriptResult)) {
969             begin(url());
970             write(scriptResult);
971             end();
972         }
973         return;
974     }
975
976     ResourceRequest request(completeURL(URL));
977     request.setLockHistory(lockHistory);
978     if (!referrer.isEmpty())
979         request.setReferrer(referrer);
980
981     urlSelected(request, "_self");
982 }
983
984 void Frame::redirectionTimerFired(Timer<Frame>*)
985 {
986     if (d->m_scheduledRedirection == historyNavigationScheduled) {
987         d->m_scheduledRedirection = noRedirectionScheduled;
988
989         // Special case for go(0) from a frame -> reload only the frame
990         // go(i!=0) from a frame navigates into the history of the frame only,
991         // in both IE and NS (but not in Mozilla).... we can't easily do that
992         // in Konqueror...
993         if (d->m_scheduledHistoryNavigationSteps == 0) // add && parent() to get only frames, but doesn't matter
994             openURL(url()); /// ## need args.reload=true?
995         else {
996             if (d->m_extension) {
997                 d->m_extension->goBackOrForward(d->m_scheduledHistoryNavigationSteps);
998             }
999         }
1000         return;
1001     }
1002
1003     DeprecatedString URL = d->m_redirectURL;
1004     DeprecatedString referrer = d->m_redirectReferrer;
1005     bool lockHistory = d->m_redirectLockHistory;
1006     bool userGesture = d->m_redirectUserGesture;
1007
1008     d->m_scheduledRedirection = noRedirectionScheduled;
1009     d->m_delayRedirect = 0;
1010     d->m_redirectURL = DeprecatedString::null;
1011     d->m_redirectReferrer = DeprecatedString::null;
1012
1013     changeLocation(URL, referrer, lockHistory, userGesture);
1014 }
1015
1016 void Frame::receivedRedirect(TransferJob*, const KURL& url)
1017 {
1018     d->m_workingURL = url;
1019 }
1020
1021 DeprecatedString Frame::encoding() const
1022 {
1023     if (d->m_haveEncoding && !d->m_encoding.isEmpty())
1024         return d->m_encoding;
1025
1026     if (d->m_decoder && d->m_decoder->encoding().isValid())
1027         return d->m_decoder->encodingName();
1028
1029     return settings()->encoding();
1030 }
1031
1032 void Frame::setUserStyleSheet(const KURL& url)
1033 {
1034     delete d->m_userStyleSheetLoader;
1035     d->m_userStyleSheetLoader = 0;
1036     if (d->m_doc && d->m_doc->docLoader())
1037         d->m_userStyleSheetLoader = new UserStyleSheetLoader(this, url.url(), d->m_doc->docLoader());
1038 }
1039
1040 void Frame::setUserStyleSheet(const DeprecatedString& styleSheet)
1041 {
1042     delete d->m_userStyleSheetLoader;
1043     d->m_userStyleSheetLoader = 0;
1044     if (d->m_doc)
1045         d->m_doc->setUserStyleSheet(styleSheet);
1046 }
1047
1048 bool Frame::gotoAnchor(const String& name)
1049 {
1050   if (!d->m_doc)
1051     return false;
1052
1053   Node *n = d->m_doc->getElementById(AtomicString(name));
1054   if (!n) {
1055     HTMLCollection *anchors =
1056         new HTMLCollection(d->m_doc.get(), HTMLCollection::DOC_ANCHORS);
1057     anchors->ref();
1058     n = anchors->namedItem(name, !d->m_doc->inCompatMode());
1059     anchors->deref();
1060   }
1061
1062   d->m_doc->setCSSTarget(n); // Setting to null will clear the current target.
1063   
1064   // Implement the rule that "" and "top" both mean top of page as in other browsers.
1065   if (!n && !(name.isEmpty() || name.lower() == "top"))
1066       return false;
1067
1068   // We need to update the layout before scrolling, otherwise we could
1069   // really mess things up if an anchor scroll comes at a bad moment.
1070   if (d->m_doc) {
1071     d->m_doc->updateRendering();
1072     // Only do a layout if changes have occurred that make it necessary.      
1073     if (d->m_view && d->m_doc->renderer() && d->m_doc->renderer()->needsLayout()) {
1074       d->m_view->layout();
1075     }
1076   }
1077   
1078   // Scroll nested layers and frames to reveal the anchor.
1079   RenderObject *renderer;
1080   IntRect rect;
1081   if (n) {
1082       renderer = n->renderer();
1083       rect = n->getRect();
1084   } else {
1085     // If there's no node, we should scroll to the top of the document.
1086       renderer = d->m_doc->renderer();
1087       rect = IntRect();
1088   }
1089
1090   if (renderer) {
1091     // Align to the top and to the closest side (this matches other browsers).
1092     renderer->enclosingLayer()->scrollRectToVisible(rect, RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignTopAlways);
1093   }
1094   
1095   return true;
1096 }
1097
1098 void Frame::setStandardFont(const String& name)
1099 {
1100     d->m_settings->setStdFontName(AtomicString(name));
1101 }
1102
1103 void Frame::setFixedFont(const String& name)
1104 {
1105     d->m_settings->setFixedFontName(AtomicString(name));
1106 }
1107
1108 String Frame::selectedText() const
1109 {
1110     return plainText(selection().toRange().get());
1111 }
1112
1113 bool Frame::hasSelection() const
1114 {
1115     return d->m_selection.isCaretOrRange();
1116 }
1117
1118 SelectionController& Frame::selection() const
1119 {
1120     return d->m_selection;
1121 }
1122
1123 TextGranularity Frame::selectionGranularity() const
1124 {
1125     return d->m_selectionGranularity;
1126 }
1127
1128 void Frame::setSelectionGranularity(TextGranularity granularity) const
1129 {
1130     d->m_selectionGranularity = granularity;
1131 }
1132
1133 const SelectionController& Frame::dragCaret() const
1134 {
1135     return d->m_dragCaret;
1136 }
1137
1138 const Selection& Frame::mark() const
1139 {
1140     return d->m_mark;
1141 }
1142
1143 void Frame::setMark(const Selection& s)
1144 {
1145     d->m_mark = s;
1146 }
1147
1148 void Frame::setSelection(const SelectionController& s, bool closeTyping, bool keepTypingStyle)
1149 {
1150     if (d->m_selection == s) {
1151         return;
1152     }
1153     
1154     clearCaretRectIfNeeded();
1155
1156     SelectionController oldSelection = d->m_selection;
1157
1158     d->m_selection = s;
1159     if (!s.isNone())
1160         setFocusNodeIfNeeded();
1161     
1162     selectionLayoutChanged();
1163
1164     // Always clear the x position used for vertical arrow navigation.
1165     // It will be restored by the vertical arrow navigation code if necessary.
1166     d->m_xPosForVerticalArrowNavigation = NoXPosForVerticalArrowNavigation;
1167
1168     if (closeTyping)
1169         TypingCommand::closeTyping(lastEditCommand());
1170
1171     if (!keepTypingStyle)
1172         clearTypingStyle();
1173     
1174     respondToChangedSelection(oldSelection, closeTyping);
1175 }
1176
1177 void Frame::setDragCaret(const SelectionController& dragCaret)
1178 {
1179     if (d->m_dragCaret != dragCaret) {
1180         d->m_dragCaret.needsCaretRepaint();
1181         d->m_dragCaret = dragCaret;
1182         d->m_dragCaret.needsCaretRepaint();
1183     }
1184 }
1185
1186 void Frame::invalidateSelection()
1187 {
1188     clearCaretRectIfNeeded();
1189     d->m_selection.setNeedsLayout();
1190     selectionLayoutChanged();
1191 }
1192
1193 void Frame::setCaretVisible(bool flag)
1194 {
1195     if (d->m_caretVisible == flag)
1196         return;
1197     clearCaretRectIfNeeded();
1198     if (flag)
1199         setFocusNodeIfNeeded();
1200     d->m_caretVisible = flag;
1201     selectionLayoutChanged();
1202 }
1203
1204
1205 void Frame::clearCaretRectIfNeeded()
1206 {
1207     if (d->m_caretPaint) {
1208         d->m_caretPaint = false;
1209         d->m_selection.needsCaretRepaint();
1210     }        
1211 }
1212
1213 // Helper function that tells whether a particular node is an element that has an entire
1214 // Frame and FrameView, a <frame>, <iframe>, or <object>.
1215 static bool isFrameElement(const Node *n)
1216 {
1217     if (!n)
1218         return false;
1219     RenderObject *renderer = n->renderer();
1220     if (!renderer || !renderer->isWidget())
1221         return false;
1222     Widget *widget = static_cast<RenderWidget *>(renderer)->widget();
1223     return widget && widget->isFrameView();
1224 }
1225
1226 void Frame::setFocusNodeIfNeeded()
1227 {
1228     if (!document() || d->m_selection.isNone() || !d->m_isFocused)
1229         return;
1230
1231     Node *startNode = d->m_selection.start().node();
1232     Node *target = startNode ? startNode->rootEditableElement() : 0;
1233     
1234     if (target) {
1235         RenderObject* renderer = target->renderer();
1236
1237         // Walk up the render tree to search for a node to focus.
1238         // Walking up the DOM tree wouldn't work for shadow trees, like those behind the engine-based text fields.
1239         while (renderer) {
1240             // We don't want to set focus on a subframe when selecting in a parent frame,
1241             // so add the !isFrameElement check here. There's probably a better way to make this
1242             // work in the long term, but this is the safest fix at this time.
1243             if (target && target->isMouseFocusable() && !isFrameElement(target)) {
1244                 document()->setFocusNode(target);
1245                 return;
1246             }
1247             renderer = renderer->parent();
1248             if (renderer)
1249                 target = renderer->element();
1250         }
1251         document()->setFocusNode(0);
1252     }
1253 }
1254
1255 void Frame::selectionLayoutChanged()
1256 {
1257     // kill any caret blink timer now running
1258     d->m_caretBlinkTimer.stop();
1259
1260     // see if a new caret blink timer needs to be started
1261     if (d->m_caretVisible && d->m_caretBlinks && 
1262         d->m_selection.isCaret() && d->m_selection.start().node()->isContentEditable()) {
1263         d->m_caretBlinkTimer.startRepeating(caretBlinkFrequency);
1264         d->m_caretPaint = true;
1265         d->m_selection.needsCaretRepaint();
1266     }
1267
1268     if (d->m_doc)
1269         d->m_doc->updateSelection();
1270 }
1271
1272 void Frame::setXPosForVerticalArrowNavigation(int x)
1273 {
1274     d->m_xPosForVerticalArrowNavigation = x;
1275 }
1276
1277 int Frame::xPosForVerticalArrowNavigation() const
1278 {
1279     return d->m_xPosForVerticalArrowNavigation;
1280 }
1281
1282 void Frame::caretBlinkTimerFired(Timer<Frame>*)
1283 {
1284     // Might be better to turn the timer off during some of these circumstances
1285     // and assert rather then letting the timer fire and do nothing here.
1286     // Could do that in selectionLayoutChanged.
1287
1288     if (!d->m_caretVisible)
1289         return;
1290     if (!d->m_caretBlinks)
1291         return;
1292     if (!d->m_selection.isCaret())
1293         return;
1294     bool caretPaint = d->m_caretPaint;
1295     if (d->m_bMousePressed && caretPaint)
1296         return;
1297     d->m_caretPaint = !caretPaint;
1298     d->m_selection.needsCaretRepaint();
1299 }
1300
1301 void Frame::paintCaret(GraphicsContext* p, const IntRect& rect) const
1302 {
1303     if (d->m_caretPaint)
1304         d->m_selection.paintCaret(p, rect);
1305 }
1306
1307 void Frame::paintDragCaret(GraphicsContext* p, const IntRect& rect) const
1308 {
1309     d->m_dragCaret.paintCaret(p, rect);
1310 }
1311
1312 void Frame::urlSelected(const DeprecatedString& url, const String& target)
1313 {
1314     urlSelected(ResourceRequest(completeURL(url)), target);
1315 }
1316
1317 void Frame::urlSelected(const ResourceRequest& request, const String& _target)
1318 {
1319   String target = _target;
1320   if (target.isEmpty() && d->m_doc)
1321     target = d->m_doc->baseTarget();
1322
1323   const KURL& url = request.url();
1324
1325   if (url.url().startsWith("javascript:", false)) {
1326     executeScript(0, KURL::decode_string(url.url().mid(11)), true);
1327     return;
1328   }
1329
1330   if (!url.isValid())
1331     // ### ERROR HANDLING
1332     return;
1333
1334   ResourceRequest requestCopy = request;
1335   requestCopy.frameName = target;
1336
1337   if (d->m_bHTTPRefresh)
1338     d->m_bHTTPRefresh = false;
1339
1340   if (!d->m_referrer.isEmpty())
1341     requestCopy.setReferrer(d->m_referrer);
1342
1343   urlSelected(requestCopy);
1344 }
1345
1346 bool Frame::requestFrame(RenderPart* renderer, const String& urlParam, const AtomicString& frameName)
1347 {
1348     DeprecatedString _url = urlParam.deprecatedString();
1349     // Support for <frame src="javascript:string">
1350     KURL scriptURL;
1351     KURL url;
1352     if (_url.startsWith("javascript:", false)) {
1353         scriptURL = _url;
1354         url = "about:blank";
1355     } else
1356         url = completeURL(_url);
1357
1358     Frame* frame = tree()->child(frameName);
1359     if (frame) {
1360         ResourceRequest request(url);
1361         request.setReferrer(d->m_referrer);
1362         request.reload = (d->m_cachePolicy == KIO::CC_Reload) || (d->m_cachePolicy == KIO::CC_Refresh);
1363         frame->openURLRequest(request);
1364     } else
1365         frame = loadSubframe(renderer, url, frameName, d->m_referrer);
1366     
1367     if (!frame)
1368         return false;
1369
1370     if (!scriptURL.isEmpty())
1371         frame->replaceContentsWithScriptResult(scriptURL);
1372
1373     return true;
1374 }
1375
1376 bool Frame::requestObject(RenderPart* renderer, const String& url, const AtomicString& frameName,
1377                           const String& mimeType, const DeprecatedStringList& paramNames, const DeprecatedStringList& paramValues)
1378 {
1379     KURL completedURL;
1380     if (!url.isEmpty())
1381         completedURL = completeURL(url.deprecatedString());
1382     
1383     if (url.isEmpty() && mimeType.isEmpty())
1384         return true;
1385     
1386     bool useFallback;
1387     if (shouldUsePlugin(renderer->element(), completedURL, mimeType, renderer->hasFallbackContent(), useFallback))
1388         return loadPlugin(renderer, completedURL, mimeType, paramNames, paramValues, useFallback);
1389
1390     // FIXME: ok to always make a new one? when does the old frame get removed?
1391     return loadSubframe(renderer, completedURL, frameName, d->m_referrer);
1392 }
1393
1394 bool Frame::shouldUsePlugin(Node* element, const KURL& url, const String& mimeType, bool hasFallback, bool& useFallback)
1395 {
1396     useFallback = false;
1397     ObjectContentType objectType = objectContentType(url, mimeType);
1398
1399     // if an object's content can't be handled and it has no fallback, let
1400     // it be handled as a plugin to show the broken plugin icon
1401     if (objectType == ObjectContentNone && hasFallback)
1402         useFallback = true;
1403
1404     return objectType == ObjectContentNone || objectType == ObjectContentPlugin;
1405 }
1406
1407
1408 bool Frame::loadPlugin(RenderPart *renderer, const KURL& url, const String& mimeType, 
1409                        const DeprecatedStringList& paramNames, const DeprecatedStringList& paramValues, bool useFallback)
1410 {
1411     if (useFallback) {
1412         checkEmitLoadEvent();
1413         return false;
1414     }
1415
1416     Plugin* plugin = createPlugin(url, paramNames, paramValues, mimeType);
1417     if (!plugin) {
1418         checkEmitLoadEvent();
1419         return false;
1420     }
1421     d->m_plugins.append(plugin);
1422     
1423     if (renderer && plugin->view())
1424         renderer->setWidget(plugin->view());
1425     
1426     checkEmitLoadEvent();
1427     
1428     return true;
1429 }
1430
1431 Frame* Frame::loadSubframe(RenderPart* renderer, const KURL& url, const String& name, const String& referrer)
1432 {
1433     Frame* frame = createFrame(url, name, renderer, referrer);
1434     if (!frame)  {
1435         checkEmitLoadEvent();
1436         return 0;
1437     }
1438     
1439     frame->childBegin();
1440     
1441     if (renderer && frame->view())
1442         renderer->setWidget(frame->view());
1443     
1444     checkEmitLoadEvent();
1445     
1446     // In these cases, the synchronous load would have finished
1447     // before we could connect the signals, so make sure to send the 
1448     // completed() signal for the child by hand
1449     // FIXME: In this case the Frame will have finished loading before 
1450     // it's being added to the child list. It would be a good idea to
1451     // create the child first, then invoke the loader separately.
1452     if (url.isEmpty() || url == "about:blank") {
1453         frame->completed(false);
1454         frame->checkCompleted();
1455     }
1456
1457     return frame;
1458 }
1459
1460 void Frame::clearRecordedFormValues()
1461 {
1462     d->m_formAboutToBeSubmitted = 0;
1463     d->m_formValuesAboutToBeSubmitted.clear();
1464 }
1465
1466 void Frame::recordFormValue(const String& name, const String& value, PassRefPtr<HTMLFormElement> element)
1467 {
1468     d->m_formAboutToBeSubmitted = element;
1469     d->m_formValuesAboutToBeSubmitted.set(name, value);
1470 }
1471
1472 void Frame::submitFormAgain()
1473 {
1474     FramePrivate::SubmitForm* form = d->m_submitForm;
1475     d->m_submitForm = 0;
1476     if (d->m_doc && !d->m_doc->parsing() && form)
1477         submitForm(form->submitAction, form->submitUrl, form->submitFormData,
1478             form->target, form->submitContentType, form->submitBoundary);
1479     delete form;
1480 }
1481
1482 void Frame::submitForm(const char *action, const String& url, const FormData& formData, const String& _target, const String& contentType, const String& boundary)
1483 {
1484   KURL u = completeURL(url.deprecatedString());
1485
1486   if (!u.isValid())
1487     // ### ERROR HANDLING!
1488     return;
1489
1490   DeprecatedString urlstring = u.url();
1491   if (urlstring.startsWith("javascript:", false)) {
1492     urlstring = KURL::decode_string(urlstring);
1493     d->m_executingJavaScriptFormAction = true;
1494     executeScript(0, urlstring.mid(11));
1495     d->m_executingJavaScriptFormAction = false;
1496     return;
1497   }
1498
1499   ResourceRequest request;
1500
1501   if (!d->m_referrer.isEmpty())
1502      request.setReferrer(d->m_referrer);
1503
1504   request.frameName = _target.isEmpty() ? d->m_doc->baseTarget() : _target ;
1505
1506   // Handle mailto: forms
1507   if (u.protocol() == "mailto") {
1508       // 1)  Check for attach= and strip it
1509       DeprecatedString q = u.query().mid(1);
1510       DeprecatedStringList nvps = DeprecatedStringList::split("&", q);
1511       bool triedToAttach = false;
1512
1513       for (DeprecatedStringList::Iterator nvp = nvps.begin(); nvp != nvps.end(); ++nvp) {
1514          DeprecatedStringList pair = DeprecatedStringList::split("=", *nvp);
1515          if (pair.count() >= 2) {
1516             if (pair.first().lower() == "attach") {
1517                nvp = nvps.remove(nvp);
1518                triedToAttach = true;
1519             }
1520          }
1521       }
1522
1523
1524       // 2)  Append body=
1525       DeprecatedString bodyEnc;
1526       if (contentType.lower() == "multipart/form-data") {
1527          // FIXME: is this correct?  I suspect not
1528          bodyEnc = KURL::encode_string(formData.flattenToString());
1529       } else if (contentType.lower() == "text/plain") {
1530          // Convention seems to be to decode, and s/&/\n/
1531          DeprecatedString tmpbody = formData.flattenToString();
1532          tmpbody.replace('&', '\n');
1533          tmpbody.replace('+', ' ');
1534          tmpbody = KURL::decode_string(tmpbody);  // Decode the rest of it
1535          bodyEnc = KURL::encode_string(tmpbody);  // Recode for the URL
1536       } else {
1537          bodyEnc = KURL::encode_string(formData.flattenToString());
1538       }
1539
1540       nvps.append(DeprecatedString("body=%1").arg(bodyEnc));
1541       q = nvps.join("&");
1542       u.setQuery(q);
1543   } 
1544
1545   if (strcmp(action, "get") == 0) {
1546     if (u.protocol() != "mailto")
1547        u.setQuery(formData.flattenToString());
1548     request.setDoPost(false);
1549   }
1550   else {
1551     request.postData = formData;
1552     request.setDoPost(true);
1553
1554     // construct some user headers if necessary
1555     if (contentType.isNull() || contentType == "application/x-www-form-urlencoded")
1556       request.setContentType("Content-Type: application/x-www-form-urlencoded");
1557     else // contentType must be "multipart/form-data"
1558       request.setContentType("Content-Type: " + contentType + "; boundary=" + boundary);
1559   }
1560
1561   if (d->m_doc->parsing() || d->m_runningScripts > 0) {
1562     if (d->m_submitForm)
1563         return;
1564     d->m_submitForm = new FramePrivate::SubmitForm;
1565     d->m_submitForm->submitAction = action;
1566     d->m_submitForm->submitUrl = url;
1567     d->m_submitForm->submitFormData = formData;
1568     d->m_submitForm->target = _target;
1569     d->m_submitForm->submitContentType = contentType;
1570     d->m_submitForm->submitBoundary = boundary;
1571   } else {
1572       request.setURL(u);
1573       submitForm(request);
1574   }
1575 }
1576
1577 void Frame::parentCompleted()
1578 {
1579     if (d->m_scheduledRedirection != noRedirectionScheduled && !d->m_redirectionTimer.isActive())
1580         startRedirectionTimer();
1581 }
1582
1583 void Frame::childCompleted(bool complete)
1584 {
1585     if (complete && !tree()->parent())
1586         d->m_bPendingChildRedirection = true;
1587     checkCompleted();
1588 }
1589
1590 int Frame::zoomFactor() const
1591 {
1592   return d->m_zoomFactor;
1593 }
1594
1595 void Frame::setZoomFactor(int percent)
1596 {  
1597   if (d->m_zoomFactor == percent)
1598       return;
1599
1600   d->m_zoomFactor = percent;
1601
1602   if (d->m_doc)
1603       d->m_doc->recalcStyle(Node::Force);
1604
1605   for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
1606       child->setZoomFactor(d->m_zoomFactor);
1607
1608   if (d->m_doc && d->m_doc->renderer() && d->m_doc->renderer()->needsLayout())
1609       view()->layout();
1610 }
1611
1612 void Frame::setJSStatusBarText(const String& text)
1613 {
1614     d->m_kjsStatusBarText = text;
1615     setStatusBarText(d->m_kjsStatusBarText);
1616 }
1617
1618 void Frame::setJSDefaultStatusBarText(const String& text)
1619 {
1620     d->m_kjsDefaultStatusBarText = text;
1621     setStatusBarText(d->m_kjsDefaultStatusBarText);
1622 }
1623
1624 String Frame::jsStatusBarText() const
1625 {
1626     return d->m_kjsStatusBarText;
1627 }
1628
1629 String Frame::jsDefaultStatusBarText() const
1630 {
1631    return d->m_kjsDefaultStatusBarText;
1632 }
1633
1634 DeprecatedString Frame::referrer() const
1635 {
1636    return d->m_referrer;
1637 }
1638
1639 String Frame::lastModified() const
1640 {
1641   return d->m_lastModified;
1642 }
1643
1644 void Frame::reparseConfiguration()
1645 {
1646   setAutoloadImages(d->m_settings->autoLoadImages());
1647   if (d->m_doc)
1648      d->m_doc->docLoader()->setShowAnimations(KHTMLSettings::KAnimationEnabled);
1649
1650   d->m_bJScriptEnabled = d->m_settings->isJavaScriptEnabled();
1651   d->m_bJavaEnabled = d->m_settings->isJavaEnabled();
1652   d->m_bPluginsEnabled = d->m_settings->isPluginsEnabled();
1653
1654   DeprecatedString userStyleSheet = d->m_settings->userStyleSheet();
1655   if (!userStyleSheet.isEmpty())
1656     setUserStyleSheet(KURL(userStyleSheet));
1657   else
1658     setUserStyleSheet(DeprecatedString());
1659
1660   if (d->m_doc) d->m_doc->updateStyleSelector();
1661 }
1662
1663 bool Frame::shouldDragAutoNode(Node *node, int x, int y) const
1664 {
1665     // No KDE impl yet
1666     return false;
1667 }
1668
1669 bool Frame::isPointInsideSelection(int x, int y)
1670 {
1671     // Treat a collapsed selection like no selection.
1672     if (!d->m_selection.isRange())
1673         return false;
1674     if (!document()->renderer()) 
1675         return false;
1676     
1677     RenderObject::NodeInfo nodeInfo(true, true);
1678     document()->renderer()->layer()->hitTest(nodeInfo, x, y);
1679     Node *innerNode = nodeInfo.innerNode();
1680     if (!innerNode || !innerNode->renderer())
1681         return false;
1682     
1683     Position pos(innerNode->renderer()->positionForCoordinates(x, y).deepEquivalent());
1684     if (pos.isNull())
1685         return false;
1686
1687     Node *n = d->m_selection.start().node();
1688     while (n) {
1689         if (n == pos.node()) {
1690             if ((n == d->m_selection.start().node() && pos.offset() < d->m_selection.start().offset()) ||
1691                 (n == d->m_selection.end().node() && pos.offset() > d->m_selection.end().offset())) {
1692                 return false;
1693             }
1694             return true;
1695         }
1696         if (n == d->m_selection.end().node())
1697             break;
1698         n = n->traverseNextNode();
1699     }
1700
1701    return false;
1702 }
1703
1704 void Frame::selectClosestWordFromMouseEvent(const PlatformMouseEvent& mouse, Node *innerNode, int x, int y)
1705 {
1706     SelectionController selection;
1707
1708     if (innerNode && innerNode->renderer() && mouseDownMayStartSelect() && innerNode->renderer()->shouldSelect()) {
1709         VisiblePosition pos(innerNode->renderer()->positionForCoordinates(x, y));
1710         if (pos.isNotNull()) {
1711             selection.moveTo(pos);
1712             selection.expandUsingGranularity(WordGranularity);
1713         }
1714     }
1715     
1716     if (selection.isRange()) {
1717         d->m_selectionGranularity = WordGranularity;
1718         d->m_beganSelectingText = true;
1719     }
1720     
1721     if (shouldChangeSelection(selection))
1722         setSelection(selection);
1723 }
1724
1725 void Frame::handleMousePressEventDoubleClick(const MouseEventWithHitTestResults& event)
1726 {
1727     if (event.event().button() == LeftButton) {
1728         if (selection().isRange())
1729             // A double-click when range is already selected
1730             // should not change the selection.  So, do not call
1731             // selectClosestWordFromMouseEvent, but do set
1732             // m_beganSelectingText to prevent handleMouseReleaseEvent
1733             // from setting caret selection.
1734             d->m_beganSelectingText = true;
1735         else {
1736             int x, y;
1737             view()->viewportToContents(event.event().x(), event.event().y(), x, y);
1738             selectClosestWordFromMouseEvent(event.event(), event.innerNode(), x, y);
1739         }
1740     }
1741 }
1742
1743 void Frame::handleMousePressEventTripleClick(const MouseEventWithHitTestResults& event)
1744 {
1745     Node *innerNode = event.innerNode();
1746     
1747     if (event.event().button() == LeftButton && innerNode && innerNode->renderer() &&
1748         mouseDownMayStartSelect() && innerNode->renderer()->shouldSelect()) {
1749         SelectionController selection;
1750         int x, y;
1751         view()->viewportToContents(event.event().x(), event.event().y(), x, y);
1752         VisiblePosition pos(innerNode->renderer()->positionForCoordinates(x, y));
1753         if (pos.isNotNull()) {
1754             selection.moveTo(pos);
1755             selection.expandUsingGranularity(ParagraphGranularity);
1756         }
1757         if (selection.isRange()) {
1758             d->m_selectionGranularity = ParagraphGranularity;
1759             d->m_beganSelectingText = true;
1760         }
1761         
1762         if (shouldChangeSelection(selection))
1763             setSelection(selection);
1764     }
1765 }
1766
1767 void Frame::handleMousePressEventSingleClick(const MouseEventWithHitTestResults& event)
1768 {
1769     Node *innerNode = event.innerNode();
1770     
1771     if (event.event().button() == LeftButton) {
1772         if (innerNode && innerNode->renderer() &&
1773             mouseDownMayStartSelect() && innerNode->renderer()->shouldSelect()) {
1774             SelectionController sel;
1775             
1776             // Extend the selection if the Shift key is down, unless the click is in a link.
1777             bool extendSelection = event.event().shiftKey() && event.url().isNull();
1778
1779             // Don't restart the selection when the mouse is pressed on an
1780             // existing selection so we can allow for text dragging.
1781             int x, y;
1782             view()->viewportToContents(event.event().x(), event.event().y(), x, y);
1783             if (!extendSelection && isPointInsideSelection(x, y))
1784                 return;
1785
1786             VisiblePosition visiblePos(innerNode->renderer()->positionForCoordinates(x, y));
1787             if (visiblePos.isNull())
1788                 visiblePos = VisiblePosition(innerNode, innerNode->caretMinOffset(), DOWNSTREAM);
1789             Position pos = visiblePos.deepEquivalent();
1790             
1791             sel = selection();
1792             if (extendSelection && sel.isCaretOrRange()) {
1793                 sel.clearModifyBias();
1794                 
1795                 // See <rdar://problem/3668157> REGRESSION (Mail): shift-click deselects when selection 
1796                 // was created right-to-left
1797                 Position start = sel.start();
1798                 short before = Range::compareBoundaryPoints(pos.node(), pos.offset(), start.node(), start.offset());
1799                 if (before <= 0) {
1800                     sel.setBaseAndExtent(pos.node(), pos.offset(), sel.end().node(), sel.end().offset());
1801                 } else {
1802                     sel.setBaseAndExtent(start.node(), start.offset(), pos.node(), pos.offset());
1803                 }
1804
1805                 if (d->m_selectionGranularity != CharacterGranularity) {
1806                     sel.expandUsingGranularity(d->m_selectionGranularity);
1807                 }
1808                 d->m_beganSelectingText = true;
1809             } else {
1810                 sel = SelectionController(visiblePos);
1811                 d->m_selectionGranularity = CharacterGranularity;
1812             }
1813             
1814             if (shouldChangeSelection(sel))
1815                 setSelection(sel);
1816         }
1817     }
1818 }
1819
1820 void Frame::handleMousePressEvent(const MouseEventWithHitTestResults& event)
1821 {
1822     String url = event.url();
1823     Node *innerNode = event.innerNode();
1824
1825     d->m_mousePressNode = innerNode;
1826     d->m_dragStartPos = event.event().pos();
1827
1828     if (event.event().button() == LeftButton || event.event().button() == MiddleButton) {
1829         d->m_bMousePressed = true;
1830         d->m_beganSelectingText = false;
1831
1832         if (event.event().clickCount() == 2) {
1833             handleMousePressEventDoubleClick(event);
1834             return;
1835         }
1836         if (event.event().clickCount() >= 3) {
1837             handleMousePressEventTripleClick(event);
1838             return;
1839         }
1840         handleMousePressEventSingleClick(event);
1841     }
1842 }
1843
1844 void Frame::handleMouseMoveEventPart2(const MouseEventWithHitTestResults& event)
1845 {
1846     // Mouse not pressed. Do nothing.
1847     if (!d->m_bMousePressed)
1848         return;
1849
1850     Node *innerNode = event.innerNode();
1851
1852     if (event.event().button() != 0 || !innerNode || !innerNode->renderer() || !mouseDownMayStartSelect() || !innerNode->renderer()->shouldSelect())
1853         return;
1854
1855     // handle making selection
1856     int x, y;
1857     view()->viewportToContents(event.event().x(), event.event().y(), x, y);
1858     VisiblePosition pos(innerNode->renderer()->positionForCoordinates(x, y));
1859
1860     // Don't modify the selection if we're not on a node.
1861     if (pos.isNull())
1862         return;
1863
1864     // Restart the selection if this is the first mouse move. This work is usually
1865     // done in handleMousePressEvent, but not if the mouse press was on an existing selection.
1866     SelectionController sel = selection();
1867     sel.clearModifyBias();
1868     
1869     if (!d->m_beganSelectingText) {
1870         d->m_beganSelectingText = true;
1871         sel.moveTo(pos);
1872     }
1873
1874     sel.setExtent(pos);
1875     if (d->m_selectionGranularity != CharacterGranularity)
1876         sel.expandUsingGranularity(d->m_selectionGranularity);
1877
1878     if (shouldChangeSelection(sel))
1879         setSelection(sel);
1880 }
1881
1882 void Frame::handleMouseMoveEvent(const MouseEventWithHitTestResults& event)
1883 {
1884     handleMouseMoveEventPart2(event);
1885 }
1886
1887 void Frame::handleMouseReleaseEvent(const MouseEventWithHitTestResults& event)
1888 {
1889     stopAutoscrollTimer();
1890     
1891     // Used to prevent mouseMoveEvent from initiating a drag before
1892     // the mouse is pressed again.
1893     d->m_bMousePressed = false;
1894   
1895     // Clear the selection if the mouse didn't move after the last mouse press.
1896     // We do this so when clicking on the selection, the selection goes away.
1897     // However, if we are editing, place the caret.
1898     if (mouseDownMayStartSelect() && !d->m_beganSelectingText
1899             && d->m_dragStartPos == event.event().pos()
1900             && d->m_selection.isRange()) {
1901         SelectionController selection;
1902         Node *node = event.innerNode();
1903         if (node && node->isContentEditable() && node->renderer()) {
1904             int x, y;
1905             view()->viewportToContents(event.event().x(), event.event().y(), x, y);
1906             VisiblePosition pos = node->renderer()->positionForCoordinates(x, y);
1907             selection.moveTo(pos);
1908         }
1909         if (shouldChangeSelection(selection))
1910             setSelection(selection);
1911     }
1912     selectFrameElementInParentIfFullySelected();
1913 }
1914
1915 void Frame::selectAll()
1916 {
1917     if (!d->m_doc)
1918         return;
1919     
1920     Node *startNode = d->m_selection.start().node();
1921     Node *root = startNode && startNode->isContentEditable() ? startNode->rootEditableElement() : d->m_doc->documentElement();
1922     
1923     selectContentsOfNode(root);
1924     selectFrameElementInParentIfFullySelected();
1925 }
1926
1927 bool Frame::selectContentsOfNode(Node* node)
1928 {
1929     SelectionController sel = SelectionController(Position(node, 0), Position(node, maxDeepOffset(node)), DOWNSTREAM);    
1930     if (shouldChangeSelection(sel)) {
1931         setSelection(sel);
1932         return true;
1933     }
1934     return false;
1935 }
1936
1937 bool Frame::shouldChangeSelection(const SelectionController& newselection) const
1938 {
1939     return shouldChangeSelection(d->m_selection, newselection, newselection.affinity(), false);
1940 }
1941
1942 bool Frame::shouldBeginEditing(const Range *range) const
1943 {
1944     return true;
1945 }
1946
1947 bool Frame::shouldEndEditing(const Range *range) const
1948 {
1949     return true;
1950 }
1951
1952 bool Frame::isContentEditable() const 
1953 {
1954     if (!d->m_doc)
1955         return false;
1956     return d->m_doc->inDesignMode();
1957 }
1958
1959 EditCommandPtr Frame::lastEditCommand()
1960 {
1961     return d->m_lastEditCommand;
1962 }
1963
1964 void dispatchEditableContentChangedEvent(Node* root)
1965 {
1966     if (!root)
1967         return;
1968         
1969     ExceptionCode ec = 0;
1970     RefPtr<Event> evt = new Event(khtmlEditableContentChangedEvent, false, false);
1971     EventTargetNodeCast(root)->dispatchEvent(evt, ec, true);
1972 }
1973
1974 void Frame::appliedEditing(EditCommandPtr& cmd)
1975 {
1976     SelectionController sel(cmd.endingSelection());
1977     if (shouldChangeSelection(sel)) {
1978         setSelection(sel, false);
1979     }
1980     
1981     dispatchEditableContentChangedEvent(!selection().isNone() ? selection().start().node()->rootEditableElement() : 0);
1982
1983     // Now set the typing style from the command. Clear it when done.
1984     // This helps make the case work where you completely delete a piece
1985     // of styled text and then type a character immediately after.
1986     // That new character needs to take on the style of the just-deleted text.
1987     // FIXME: Improve typing style.
1988     // See this bug: <rdar://problem/3769899> Implementation of typing style needs improvement
1989     if (cmd.typingStyle()) {
1990         setTypingStyle(cmd.typingStyle());
1991         cmd.setTypingStyle(0);
1992     }
1993
1994     // Command will be equal to last edit command only in the case of typing
1995     if (d->m_lastEditCommand == cmd) {
1996         assert(cmd.isTypingCommand());
1997     }
1998     else {
1999         // Only register a new undo command if the command passed in is
2000         // different from the last command
2001         registerCommandForUndo(cmd);
2002         d->m_lastEditCommand = cmd;
2003     }
2004     respondToChangedContents();
2005 }
2006
2007 void Frame::unappliedEditing(EditCommandPtr& cmd)
2008 {
2009     SelectionController sel(cmd.startingSelection());
2010     if (shouldChangeSelection(sel)) {
2011         setSelection(sel, true);
2012     }
2013     
2014     dispatchEditableContentChangedEvent(!selection().isNone() ? selection().start().node()->rootEditableElement() : 0);
2015         
2016     registerCommandForRedo(cmd);
2017     respondToChangedContents();
2018     d->m_lastEditCommand = EditCommandPtr::emptyCommand();
2019 }
2020
2021 void Frame::reappliedEditing(EditCommandPtr& cmd)
2022 {
2023     SelectionController sel(cmd.endingSelection());
2024     if (shouldChangeSelection(sel)) {
2025         setSelection(sel, true);
2026     }
2027     
2028     dispatchEditableContentChangedEvent(!selection().isNone() ? selection().start().node()->rootEditableElement() : 0);
2029         
2030     registerCommandForUndo(cmd);
2031     respondToChangedContents();
2032     d->m_lastEditCommand = EditCommandPtr::emptyCommand();
2033 }
2034
2035 CSSMutableStyleDeclaration *Frame::typingStyle() const
2036 {
2037     return d->m_typingStyle.get();
2038 }
2039
2040 void Frame::setTypingStyle(CSSMutableStyleDeclaration *style)
2041 {
2042     d->m_typingStyle = style;
2043 }
2044
2045 void Frame::clearTypingStyle()
2046 {
2047     d->m_typingStyle = 0;
2048 }
2049
2050 JSValue* Frame::executeScript(const String& filename, int baseLine, Node* n, const DeprecatedString& script)
2051 {
2052   // FIXME: This is missing stuff that the other executeScript has.
2053   // --> d->m_runningScripts and submitFormAgain.
2054   // Why is that OK?
2055   KJSProxy *proxy = jScript();
2056   if (!proxy)
2057     return 0;
2058   JSValue* ret = proxy->evaluate(filename, baseLine, script, n);
2059   Document::updateDocumentsRendering();
2060   return ret;
2061 }
2062
2063 Frame *Frame::opener()
2064 {
2065     return d->m_opener;
2066 }
2067
2068 void Frame::setOpener(Frame* opener)
2069 {
2070     if (d->m_opener)
2071         d->m_opener->d->m_openedFrames.remove(this);
2072     if (opener)
2073         opener->d->m_openedFrames.add(this);
2074     d->m_opener = opener;
2075 }
2076
2077 bool Frame::openedByJS()
2078 {
2079     return d->m_openedByJS;
2080 }
2081
2082 void Frame::setOpenedByJS(bool _openedByJS)
2083 {
2084     d->m_openedByJS = _openedByJS;
2085 }
2086
2087 bool Frame::tabsToLinks() const
2088 {
2089     return true;
2090 }
2091
2092 bool Frame::tabsToAllControls() const
2093 {
2094     return true;
2095 }
2096
2097 void Frame::copyToPasteboard()
2098 {
2099     issueCopyCommand();
2100 }
2101
2102 void Frame::cutToPasteboard()
2103 {
2104     issueCutCommand();
2105 }
2106
2107 void Frame::pasteFromPasteboard()
2108 {
2109     issuePasteCommand();
2110 }
2111
2112 void Frame::pasteAndMatchStyle()
2113 {
2114     issuePasteAndMatchStyleCommand();
2115 }
2116
2117 void Frame::transpose()
2118 {
2119     issueTransposeCommand();
2120 }
2121
2122 void Frame::redo()
2123 {
2124     issueRedoCommand();
2125 }
2126
2127 void Frame::undo()
2128 {
2129     issueUndoCommand();
2130 }
2131
2132
2133 void Frame::computeAndSetTypingStyle(CSSStyleDeclaration *style, EditAction editingAction)
2134 {
2135     if (!style || style->length() == 0) {
2136         clearTypingStyle();
2137         return;
2138     }
2139
2140     // Calculate the current typing style.
2141     RefPtr<CSSMutableStyleDeclaration> mutableStyle = style->makeMutable();
2142     if (typingStyle()) {
2143         typingStyle()->merge(mutableStyle.get());
2144         mutableStyle = typingStyle();
2145     }
2146
2147     Node *node = VisiblePosition(selection().start(), selection().affinity()).deepEquivalent().node();
2148     CSSComputedStyleDeclaration computedStyle(node);
2149     computedStyle.diff(mutableStyle.get());
2150     
2151     // Handle block styles, substracting these from the typing style.
2152     RefPtr<CSSMutableStyleDeclaration> blockStyle = mutableStyle->copyBlockProperties();
2153     blockStyle->diff(mutableStyle.get());
2154     if (document() && blockStyle->length() > 0) {
2155         EditCommandPtr cmd(new ApplyStyleCommand(document(), blockStyle.get(), 0, editingAction));
2156         cmd.apply();
2157     }
2158     
2159     // Set the remaining style as the typing style.
2160     d->m_typingStyle = mutableStyle.release();
2161 }
2162
2163 void Frame::applyStyle(CSSStyleDeclaration *style, EditAction editingAction)
2164 {
2165     switch (selection().state()) {
2166         case Selection::NONE:
2167             // do nothing
2168             break;
2169         case Selection::CARET: {
2170             computeAndSetTypingStyle(style, editingAction);
2171             break;
2172         }
2173         case Selection::RANGE:
2174             if (document() && style) {
2175                 EditCommandPtr cmd(new ApplyStyleCommand(document(), style, 0, editingAction));
2176                 cmd.apply();
2177             }
2178             break;
2179     }
2180 }
2181
2182 void Frame::applyParagraphStyle(CSSStyleDeclaration *style, EditAction editingAction)
2183 {
2184     switch (selection().state()) {
2185         case Selection::NONE:
2186             // do nothing
2187             break;
2188         case Selection::CARET:
2189         case Selection::RANGE:
2190             if (document() && style) {
2191                 EditCommandPtr cmd(new ApplyStyleCommand(document(), style, 0, editingAction, ApplyStyleCommand::ForceBlockProperties));
2192                 cmd.apply();
2193             }
2194             break;
2195     }
2196 }
2197
2198 static void updateState(CSSMutableStyleDeclaration *desiredStyle, CSSComputedStyleDeclaration *computedStyle, bool& atStart, Frame::TriState& state)
2199 {
2200     DeprecatedValueListConstIterator<CSSProperty> end;
2201     for (DeprecatedValueListConstIterator<CSSProperty> it = desiredStyle->valuesIterator(); it != end; ++it) {
2202         int propertyID = (*it).id();
2203         String desiredProperty = desiredStyle->getPropertyValue(propertyID);
2204         String computedProperty = computedStyle->getPropertyValue(propertyID);
2205         Frame::TriState propertyState = equalIgnoringCase(desiredProperty, computedProperty)
2206             ? Frame::trueTriState : Frame::falseTriState;
2207         if (atStart) {
2208             state = propertyState;
2209             atStart = false;
2210         } else if (state != propertyState) {
2211             state = Frame::mixedTriState;
2212             break;
2213         }
2214     }
2215 }
2216
2217 Frame::TriState Frame::selectionHasStyle(CSSStyleDeclaration *style) const
2218 {
2219     bool atStart = true;
2220     TriState state = falseTriState;
2221
2222     RefPtr<CSSMutableStyleDeclaration> mutableStyle = style->makeMutable();
2223
2224     if (!d->m_selection.isRange()) {
2225         Node* nodeToRemove;
2226         RefPtr<CSSComputedStyleDeclaration> selectionStyle = selectionComputedStyle(nodeToRemove);
2227         if (!selectionStyle)
2228             return falseTriState;
2229         updateState(mutableStyle.get(), selectionStyle.get(), atStart, state);
2230         if (nodeToRemove) {
2231             ExceptionCode ec = 0;
2232             nodeToRemove->remove(ec);
2233             assert(ec == 0);
2234         }
2235     } else {
2236         for (Node* node = d->m_selection.start().node(); node; node = node->traverseNextNode()) {
2237             RefPtr<CSSComputedStyleDeclaration> computedStyle = new CSSComputedStyleDeclaration(node);
2238             if (computedStyle)
2239                 updateState(mutableStyle.get(), computedStyle.get(), atStart, state);
2240             if (state == mixedTriState)
2241                 break;
2242             if (node == d->m_selection.end().node())
2243                 break;
2244         }
2245     }
2246
2247     return state;
2248 }
2249
2250 bool Frame::selectionStartHasStyle(CSSStyleDeclaration *style) const
2251 {
2252     Node* nodeToRemove;
2253     RefPtr<CSSStyleDeclaration> selectionStyle = selectionComputedStyle(nodeToRemove);
2254     if (!selectionStyle)
2255         return false;
2256
2257     RefPtr<CSSMutableStyleDeclaration> mutableStyle = style->makeMutable();
2258
2259     bool match = true;
2260     DeprecatedValueListConstIterator<CSSProperty> end;
2261     for (DeprecatedValueListConstIterator<CSSProperty> it = mutableStyle->valuesIterator(); it != end; ++it) {
2262         int propertyID = (*it).id();
2263         if (!equalIgnoringCase(mutableStyle->getPropertyValue(propertyID), selectionStyle->getPropertyValue(propertyID))) {
2264             match = false;
2265             break;
2266         }
2267     }
2268
2269     if (nodeToRemove) {
2270         ExceptionCode ec = 0;
2271         nodeToRemove->remove(ec);
2272         assert(ec == 0);
2273     }
2274
2275     return match;
2276 }
2277
2278 String Frame::selectionStartStylePropertyValue(int stylePropertyID) const
2279 {
2280     Node *nodeToRemove;
2281     RefPtr<CSSStyleDeclaration> selectionStyle = selectionComputedStyle(nodeToRemove);
2282     if (!selectionStyle)
2283         return String();
2284
2285     String value = selectionStyle->getPropertyValue(stylePropertyID);
2286
2287     if (nodeToRemove) {
2288         ExceptionCode ec = 0;
2289         nodeToRemove->remove(ec);
2290         assert(ec == 0);
2291     }
2292
2293     return value;
2294 }
2295
2296 CSSComputedStyleDeclaration *Frame::selectionComputedStyle(Node *&nodeToRemove) const
2297 {
2298     nodeToRemove = 0;
2299
2300     if (!document())
2301         return 0;
2302
2303     if (d->m_selection.isNone())
2304         return 0;
2305
2306     RefPtr<Range> range(d->m_selection.toRange());
2307     Position pos = range->editingStartPosition();
2308
2309     Element *elem = pos.element();
2310     if (!elem)
2311         return 0;
2312     
2313     RefPtr<Element> styleElement = elem;
2314     ExceptionCode ec = 0;
2315
2316     if (d->m_typingStyle) {
2317         styleElement = document()->createElementNS(xhtmlNamespaceURI, "span", ec);
2318         assert(ec == 0);
2319
2320         styleElement->setAttribute(styleAttr, d->m_typingStyle->cssText().impl(), ec);
2321         assert(ec == 0);
2322         
2323         styleElement->appendChild(document()->createEditingTextNode(""), ec);
2324         assert(ec == 0);
2325
2326         if (elem->renderer() && elem->renderer()->canHaveChildren()) {
2327             elem->appendChild(styleElement, ec);
2328         } else {
2329             Node *parent = elem->parent();
2330             Node *next = elem->nextSibling();
2331
2332             if (next) {
2333                 parent->insertBefore(styleElement, next, ec);
2334             } else {
2335                 parent->appendChild(styleElement, ec);
2336             }
2337         }
2338         assert(ec == 0);
2339
2340         nodeToRemove = styleElement.get();
2341     }
2342
2343     return new CSSComputedStyleDeclaration(styleElement);
2344 }
2345
2346 void Frame::applyEditingStyleToBodyElement() const
2347 {
2348     if (!d->m_doc)
2349         return;
2350         
2351     RefPtr<NodeList> list = d->m_doc->getElementsByTagName("body");
2352     unsigned len = list->length();
2353     for (unsigned i = 0; i < len; i++) {
2354         applyEditingStyleToElement(static_cast<Element *>(list->item(i)));    
2355     }
2356 }
2357
2358 void Frame::removeEditingStyleFromBodyElement() const
2359 {
2360     if (!d->m_doc)
2361         return;
2362         
2363     RefPtr<NodeList> list = d->m_doc->getElementsByTagName("body");
2364     unsigned len = list->length();
2365     for (unsigned i = 0; i < len; i++) {
2366         removeEditingStyleFromElement(static_cast<Element *>(list->item(i)));    
2367     }
2368 }
2369
2370 void Frame::applyEditingStyleToElement(Element *element) const
2371 {
2372     if (!element || !element->isHTMLElement())
2373         return;
2374     
2375     static_cast<HTMLElement *>(element)->setContentEditable("true");
2376 }
2377
2378 void Frame::removeEditingStyleFromElement(Element *element) const
2379 {
2380     if (!element || !element->isHTMLElement())
2381         return;
2382         
2383     static_cast<HTMLElement *>(element)->setContentEditable("false");        
2384 }
2385
2386
2387 bool Frame::isCharacterSmartReplaceExempt(const QChar&, bool)
2388 {
2389     // no smart replace
2390     return true;
2391 }
2392
2393 #if !NDEBUG
2394 static HashSet<Frame*> lifeSupportSet;
2395 #endif
2396
2397 void Frame::endAllLifeSupport()
2398 {
2399 #if !NDEBUG
2400     HashSet<Frame*> lifeSupportCopy = lifeSupportSet;
2401     HashSet<Frame*>::iterator end = lifeSupportCopy.end();
2402     for (HashSet<Frame*>::iterator it = lifeSupportCopy.begin(); it != end; ++it)
2403         (*it)->endLifeSupport();
2404 #endif
2405 }
2406
2407 void Frame::keepAlive()
2408 {
2409     if (d->m_lifeSupportTimer.isActive())
2410         return;
2411     ref();
2412 #if !NDEBUG
2413     lifeSupportSet.add(this);
2414 #endif
2415     d->m_lifeSupportTimer.startOneShot(0);
2416 }
2417
2418 void Frame::endLifeSupport()
2419 {
2420     if (!d->m_lifeSupportTimer.isActive())
2421         return;
2422     d->m_lifeSupportTimer.stop();
2423 #if !NDEBUG
2424     lifeSupportSet.remove(this);
2425 #endif
2426     deref();
2427 }
2428
2429 void Frame::lifeSupportTimerFired(Timer<Frame>*)
2430 {
2431 #if !NDEBUG
2432     lifeSupportSet.remove(this);
2433 #endif
2434     deref();
2435 }
2436
2437 // Workaround for the fact that it's hard to delete a frame.
2438 // Call this after doing user-triggered selections to make it easy to delete the frame you entirely selected.
2439 // Can't do this implicitly as part of every setSelection call because in some contexts it might not be good
2440 // for the focus to move to another frame. So instead we call it from places where we are selecting with the
2441 // mouse or the keyboard after setting the selection.
2442 void Frame::selectFrameElementInParentIfFullySelected()
2443 {
2444     // Find the parent frame; if there is none, then we have nothing to do.
2445     Frame *parent = tree()->parent();
2446     if (!parent)
2447         return;
2448     FrameView *parentView = parent->view();
2449     if (!parentView)
2450         return;
2451
2452     // Check if the selection contains the entire frame contents; if not, then there is nothing to do.
2453     if (!d->m_selection.isRange())
2454         return;
2455     if (!isStartOfDocument(VisiblePosition(d->m_selection.start(), d->m_selection.affinity())))
2456         return;
2457     if (!isEndOfDocument(VisiblePosition(d->m_selection.end(), d->m_selection.affinity())))
2458         return;
2459
2460     // Get to the <iframe> or <frame> (or even <object>) element in the parent frame.
2461     Document *doc = document();
2462     if (!doc)
2463         return;
2464     Element *ownerElement = doc->ownerElement();
2465     if (!ownerElement)
2466         return;
2467     Node *ownerElementParent = ownerElement->parentNode();
2468     if (!ownerElementParent)
2469         return;
2470         
2471     // This method's purpose is it to make it easier to select iframes (in order to delete them).  Don't do anything if the iframe isn't deletable.
2472     if (!ownerElementParent->isContentEditable())
2473         return;
2474
2475     // Create compute positions before and after the element.
2476     unsigned ownerElementNodeIndex = ownerElement->nodeIndex();
2477     VisiblePosition beforeOwnerElement(VisiblePosition(ownerElementParent, ownerElementNodeIndex, SEL_DEFAULT_AFFINITY));
2478     VisiblePosition afterOwnerElement(VisiblePosition(ownerElementParent, ownerElementNodeIndex + 1, VP_UPSTREAM_IF_POSSIBLE));
2479
2480     // Focus on the parent frame, and then select from before this element to after.
2481     if (parent->shouldChangeSelection(SelectionController(beforeOwnerElement, afterOwnerElement))) {
2482         parentView->setFocus();
2483         parent->setSelection(SelectionController(beforeOwnerElement, afterOwnerElement));
2484     }
2485 }
2486
2487 void Frame::handleFallbackContent()
2488 {
2489     Element* owner = ownerElement();
2490     if (!owner || !owner->hasTagName(objectTag))
2491         return;
2492     static_cast<HTMLObjectElement *>(owner)->renderFallbackContent();
2493 }
2494
2495 void Frame::setSettings(KHTMLSettings *settings)
2496 {
2497     d->m_settings = settings;
2498 }
2499
2500 void Frame::provisionalLoadStarted()
2501 {
2502     // we don't want to wait until we get an actual http response back
2503     // to cancel pending redirects, otherwise they might fire before
2504     // that happens.
2505     cancelRedirection(true);
2506 }
2507
2508 bool Frame::userGestureHint()
2509 {
2510     Frame *rootFrame = this;
2511     while (rootFrame->tree()->parent())
2512         rootFrame = rootFrame->tree()->parent();
2513
2514     if (rootFrame->jScript())
2515         return rootFrame->jScript()->interpreter()->wasRunByUserGesture();
2516
2517     return true; // If JavaScript is disabled, a user gesture must have initiated the navigation
2518 }
2519
2520 RenderObject *Frame::renderer() const
2521 {
2522     Document *doc = document();
2523     return doc ? doc->renderer() : 0;
2524 }
2525
2526 Element* Frame::ownerElement()
2527 {
2528     RenderPart* ownerElementRenderer = d->m_ownerRenderer;
2529     if (!ownerElementRenderer)
2530         return 0;
2531     return static_cast<Element*>(ownerElementRenderer->element());
2532 }
2533
2534 RenderPart* Frame::ownerRenderer()
2535 {
2536     return d->m_ownerRenderer;
2537 }
2538
2539 IntRect Frame::selectionRect() const
2540 {
2541     RenderCanvas *root = static_cast<RenderCanvas *>(renderer());
2542     if (!root)
2543         return IntRect();
2544
2545     return root->selectionRect();
2546 }
2547
2548 // returns FloatRect because going through IntRect would truncate any floats
2549 FloatRect Frame::visibleSelectionRect() const
2550 {
2551     if (!d->m_view)
2552         return FloatRect();
2553     
2554     return intersection(selectionRect(), d->m_view->visibleContentRect());
2555 }
2556
2557 bool Frame::isFrameSet() const
2558 {
2559     Document* document = d->m_doc.get();
2560     if (!document || !document->isHTMLDocument())
2561         return false;
2562     Node *body = static_cast<HTMLDocument *>(document)->body();
2563     return body && body->renderer() && body->hasTagName(framesetTag);
2564 }
2565
2566 bool Frame::openURL(const KURL& URL)
2567 {
2568     ASSERT_NOT_REACHED();
2569     return true;
2570 }
2571
2572 void Frame::didNotOpenURL(const KURL& URL)
2573 {
2574     if (d->m_submittedFormURL == URL)
2575         d->m_submittedFormURL = KURL();
2576 }
2577
2578 // Scans logically forward from "start", including any child frames
2579 static HTMLFormElement *scanForForm(Node *start)
2580 {
2581     Node *n;
2582     for (n = start; n; n = n->traverseNextNode()) {
2583         if (n->hasTagName(formTag))
2584             return static_cast<HTMLFormElement *>(n);
2585         else if (n->isHTMLElement() && static_cast<HTMLElement*>(n)->isGenericFormElement())
2586             return static_cast<HTMLGenericFormElement*>(n)->form();
2587         else if (n->hasTagName(frameTag) || n->hasTagName(iframeTag)) {
2588             Node *childDoc = static_cast<HTMLFrameElement *>(n)->contentDocument();
2589             if (HTMLFormElement *frameResult = scanForForm(childDoc))
2590                 return frameResult;
2591         }
2592     }
2593     return 0;
2594 }
2595
2596 // We look for either the form containing the current focus, or for one immediately after it
2597 HTMLFormElement *Frame::currentForm() const
2598 {
2599     // start looking either at the active (first responder) node, or where the selection is
2600     Node *start = d->m_doc ? d->m_doc->focusNode() : 0;
2601     if (!start)
2602         start = selection().start().node();
2603     
2604     // try walking up the node tree to find a form element
2605     Node *n;
2606     for (n = start; n; n = n->parentNode()) {
2607         if (n->hasTagName(formTag))
2608             return static_cast<HTMLFormElement *>(n);
2609         else if (n->isHTMLElement()
2610                    && static_cast<HTMLElement *>(n)->isGenericFormElement())
2611             return static_cast<HTMLGenericFormElement *>(n)->form();
2612     }
2613     
2614     // try walking forward in the node tree to find a form element
2615     return start ? scanForForm(start) : 0;
2616 }
2617
2618 void Frame::setEncoding(const DeprecatedString& name, bool userChosen)
2619 {
2620     if (!d->m_workingURL.isEmpty())
2621         receivedFirstData();
2622     d->m_encoding = name;
2623     d->m_haveEncoding = userChosen;
2624 }
2625
2626 void Frame::addData(const char *bytes, int length)
2627 {
2628     ASSERT(d->m_workingURL.isEmpty());
2629     ASSERT(d->m_doc);
2630     ASSERT(d->m_doc->parsing());
2631     write(bytes, length);
2632 }
2633
2634 // FIXME: should this go in SelectionController?
2635 void Frame::revealSelection()
2636 {
2637     IntRect rect;
2638     
2639     switch (selection().state()) {
2640         case Selection::NONE:
2641             return;
2642             
2643         case Selection::CARET:
2644             rect = selection().caretRect();
2645             break;
2646             
2647         case Selection::RANGE:
2648             rect = selectionRect();
2649             break;
2650     }
2651     
2652     Position start = selection().start();
2653     Position end = selection().end();
2654     ASSERT(start.node());
2655     if (start.node() && start.node()->renderer()) {
2656         RenderLayer *layer = start.node()->renderer()->enclosingLayer();
2657         if (layer) {
2658             ASSERT(!end.node() || !end.node()->renderer() 
2659                    || (end.node()->renderer()->enclosingLayer() == layer));
2660             layer->scrollRectToVisible(rect);
2661         }
2662     }
2663 }
2664
2665 // FIXME: should this be here?
2666 bool Frame::scrollOverflow(KWQScrollDirection direction, KWQScrollGranularity granularity)
2667 {
2668     if (!document()) {
2669         return false;
2670     }
2671     
2672     Node *node = document()->focusNode();
2673     if (node == 0) {
2674         node = d->m_mousePressNode.get();
2675     }
2676     
2677     if (node != 0) {
2678         RenderObject *r = node->renderer();
2679         if (r != 0) {
2680             return r->scroll(direction, granularity);
2681         }
2682     }
2683     
2684     return false;
2685 }
2686
2687 void Frame::handleAutoscroll(RenderLayer* layer)
2688 {
2689     if (d->m_autoscrollTimer.isActive())
2690         return;
2691     d->m_autoscrollLayer = layer;
2692     startAutoscrollTimer();
2693 }
2694
2695 void Frame::autoscrollTimerFired(Timer<Frame>*)
2696 {
2697     bool isStillDown = PlatformMouseEvent::isMouseButtonDown(LeftButton);  
2698     if (!isStillDown){
2699         stopAutoscrollTimer();
2700         return;
2701     }
2702     if (d->m_autoscrollLayer) {
2703         d->m_autoscrollLayer->autoscroll();
2704     } 
2705 }
2706
2707 void Frame::startAutoscrollTimer()
2708 {
2709     d->m_autoscrollTimer.startRepeating(autoscrollInterval);
2710 }
2711
2712 void Frame::stopAutoscrollTimer()
2713 {
2714     d->m_autoscrollTimer.stop();
2715 }
2716
2717 // FIXME: why is this here instead of on the FrameView?
2718 void Frame::paint(GraphicsContext* p, const IntRect& rect)
2719 {
2720 #if !NDEBUG
2721     bool fillWithRed;
2722     if (p->printing())
2723         fillWithRed = false; // Printing, don't fill with red (can't remember why).
2724     else if (!document() || document()->ownerElement())
2725         fillWithRed = false; // Subframe, don't fill with red.
2726     else if (view() && view()->isTransparent())
2727         fillWithRed = false; // Transparent, don't fill with red.
2728     else if (d->m_drawSelectionOnly)
2729         fillWithRed = false; // Selections are transparent, don't fill with red.
2730     else if (d->m_elementToDraw)
2731         fillWithRed = false; // Element images are transparent, don't fill with red.
2732     else
2733         fillWithRed = true;
2734     
2735     if (fillWithRed)
2736         p->fillRect(rect, Color(0xFF, 0, 0));
2737 #endif
2738     
2739     if (renderer()) {
2740         // d->m_elementToDraw is used to draw only one element
2741         RenderObject *eltRenderer = d->m_elementToDraw ? d->m_elementToDraw->renderer() : 0;
2742         renderer()->layer()->paint(p, rect, d->m_drawSelectionOnly, eltRenderer);
2743
2744 #if __APPLE__
2745         // Regions may have changed as a result of the visibility/z-index of element changing.
2746         if (renderer()->document()->dashboardRegionsDirty())
2747             renderer()->canvas()->view()->updateDashboardRegions();
2748 #endif
2749     } else
2750         LOG_ERROR("called Frame::paint with nil renderer");
2751 }
2752
2753 void Frame::adjustPageHeight(float *newBottom, float oldTop, float oldBottom, float bottomLimit)
2754 {
2755     RenderCanvas *root = static_cast<RenderCanvas *>(document()->renderer());
2756     if (root) {
2757         // Use a printer device, with painting disabled for the pagination phase
2758         GraphicsContext painter(true);
2759         painter.setPaintingDisabled(true);
2760         
2761         root->setTruncatedAt((int)floorf(oldBottom));
2762         IntRect dirtyRect(0, (int)floorf(oldTop),
2763                         root->docWidth(), (int)ceilf(oldBottom-oldTop));
2764         root->layer()->paint(&painter, dirtyRect);
2765         *newBottom = root->bestTruncatedAt();
2766         if (*newBottom == 0)
2767             *newBottom = oldBottom;
2768     } else
2769         *newBottom = oldBottom;
2770 }
2771
2772 PausedTimeouts *Frame::pauseTimeouts()
2773 {
2774 #if SVG_SUPPORT
2775     if (d->m_doc && d->m_doc->svgExtensions())
2776         d->m_doc->accessSVGExtensions()->pauseAnimations();
2777 #endif
2778
2779     if (d->m_doc && d->m_jscript) {
2780         if (Window *w = Window::retrieveWindow(this))
2781             return w->pauseTimeouts();
2782     }
2783     return 0;
2784 }
2785
2786 void Frame::resumeTimeouts(PausedTimeouts *t)
2787 {
2788 #if SVG_SUPPORT
2789     if (d->m_doc && d->m_doc->svgExtensions())
2790         d->m_doc->accessSVGExtensions()->unpauseAnimations();
2791 #endif
2792
2793     if (d->m_doc && d->m_jscript && d->m_bJScriptEnabled) {
2794         if (Window *w = Window::retrieveWindow(this))
2795             w->resumeTimeouts(t);
2796     }
2797 }
2798
2799 bool Frame::canCachePage()
2800 {
2801     // Only save page state if:
2802     // 1.  We're not a frame or frameset.
2803     // 2.  The page has no unload handler.
2804     // 3.  The page has no password fields.
2805     // 4.  The URL for the page is not https.
2806     // 5.  The page has no applets.
2807     if (tree()->childCount() || d->m_plugins.size() ||
2808         tree()->parent() ||
2809         d->m_url.protocol().startsWith("https") || 
2810         (d->m_doc && (d->m_doc->applets()->length() != 0 ||
2811                       d->m_doc->hasWindowEventListener(unloadEvent) ||
2812                       d->m_doc->hasPasswordField()))) {
2813         return false;
2814     }
2815     return true;
2816 }
2817
2818 void Frame::saveWindowProperties(KJS::SavedProperties *windowProperties)
2819 {
2820     Window *window = Window::retrieveWindow(this);
2821     if (window)
2822         window->saveProperties(*windowProperties);
2823 }
2824
2825 void Frame::saveLocationProperties(SavedProperties *locationProperties)
2826 {
2827     Window *window = Window::retrieveWindow(this);
2828     if (window) {
2829         JSLock lock;
2830         Location *location = window->location();
2831         location->saveProperties(*locationProperties);
2832     }
2833 }
2834
2835 void Frame::restoreWindowProperties(SavedProperties *windowProperties)
2836 {
2837     Window *window = Window::retrieveWindow(this);
2838     if (window)
2839         window->restoreProperties(*windowProperties);
2840 }
2841
2842 void Frame::restoreLocationProperties(SavedProperties *locationProperties)
2843 {
2844     Window *window = Window::retrieveWindow(this);
2845     if (window) {
2846         JSLock lock;
2847         Location *location = window->location();
2848         location->restoreProperties(*locationProperties);
2849     }
2850 }
2851
2852 void Frame::saveInterpreterBuiltins(SavedBuiltins& interpreterBuiltins)
2853 {
2854     if (jScript())
2855         jScript()->interpreter()->saveBuiltins(interpreterBuiltins);
2856 }
2857
2858 void Frame::restoreInterpreterBuiltins(const SavedBuiltins& interpreterBuiltins)
2859 {
2860     if (jScript())
2861         jScript()->interpreter()->restoreBuiltins(interpreterBuiltins);
2862 }
2863
2864 Frame *Frame::frameForWidget(const Widget *widget)
2865 {
2866     ASSERT_ARG(widget, widget);
2867     
2868     Node *node = nodeForWidget(widget);
2869     if (node)
2870         return frameForNode(node);
2871     
2872     // Assume all widgets are either form controls, or FrameViews.
2873     ASSERT(widget->isFrameView());
2874     return static_cast<const FrameView *>(widget)->frame();
2875 }
2876
2877 Frame *Frame::frameForNode(Node *node)
2878 {
2879     ASSERT_ARG(node, node);
2880     return node->getDocument()->frame();
2881 }
2882
2883 Node* Frame::nodeForWidget(const Widget* widget)
2884 {
2885     ASSERT_ARG(widget, widget);
2886     WidgetClient* client = widget->client();
2887     if (!client)
2888         return 0;
2889     return client->element(const_cast<Widget*>(widget));
2890 }
2891
2892 void Frame::clearDocumentFocus(Widget *widget)
2893 {
2894     Node *node = nodeForWidget(widget);
2895     ASSERT(node);
2896     node->getDocument()->setFocusNode(0);
2897 }
2898
2899 DeprecatedPtrList<Frame>& Frame::mutableInstances()
2900 {
2901     static DeprecatedPtrList<Frame> instancesList;
2902     return instancesList;
2903 }
2904
2905 void Frame::updatePolicyBaseURL()
2906 {
2907     if (tree()->parent() && tree()->parent()->document())
2908         setPolicyBaseURL(tree()->parent()->document()->policyBaseURL());
2909     else
2910         setPolicyBaseURL(d->m_url.url());
2911 }
2912
2913 void Frame::setPolicyBaseURL(const String& s)
2914 {
2915     if (document())
2916         document()->setPolicyBaseURL(s);
2917     for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
2918         child->setPolicyBaseURL(s);
2919 }
2920
2921 void Frame::forceLayout()
2922 {
2923     FrameView *v = d->m_view.get();
2924     if (v) {
2925         v->layout();
2926         // We cannot unschedule a pending relayout, since the force can be called with
2927         // a tiny rectangle from a drawRect update.  By unscheduling we in effect
2928         // "validate" and stop the necessary full repaint from occurring.  Basically any basic
2929         // append/remove DHTML is broken by this call.  For now, I have removed the optimization
2930         // until we have a better invalidation stategy. -dwh
2931         //v->unscheduleRelayout();
2932     }
2933 }
2934
2935 void Frame::forceLayoutWithPageWidthRange(float minPageWidth, float maxPageWidth)
2936 {
2937     // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
2938     // the state of things before and after the layout
2939     RenderCanvas *root = static_cast<RenderCanvas *>(document()->renderer());
2940     if (root) {
2941         // This magic is basically copied from khtmlview::print
2942         int pageW = (int)ceilf(minPageWidth);
2943         root->setWidth(pageW);
2944         root->setNeedsLayoutAndMinMaxRecalc();
2945         forceLayout();
2946         
2947         // If we don't fit in the minimum page width, we'll lay out again. If we don't fit in the
2948         // maximum page width, we will lay out to the maximum page width and clip extra content.
2949         // FIXME: We are assuming a shrink-to-fit printing implementation.  A cropping
2950         // implementation should not do this!
2951         int rightmostPos = root->rightmostPosition();
2952         if (rightmostPos > minPageWidth) {
2953             pageW = kMin(rightmostPos, (int)ceilf(maxPageWidth));
2954             root->setWidth(pageW);
2955             root->setNeedsLayoutAndMinMaxRecalc();
2956             forceLayout();
2957         }
2958     }
2959 }
2960
2961 void Frame::sendResizeEvent()
2962 {
2963     if (Document* doc = document())
2964         doc->dispatchWindowEvent(EventNames::resizeEvent, false, false);
2965 }
2966
2967 void Frame::sendScrollEvent()
2968 {
2969     FrameView *v = d->m_view.get();
2970     if (v) {
2971         Document *doc = document();
2972         if (!doc)
2973             return;
2974         doc->dispatchHTMLEvent(scrollEvent, true, false);
2975     }
2976 }
2977
2978 bool Frame::scrollbarsVisible()
2979 {
2980     if (!view())
2981         return false;
2982     
2983     if (view()->hScrollBarMode() == ScrollBarAlwaysOff || view()->vScrollBarMode() == ScrollBarAlwaysOff)
2984         return false;
2985     
2986     return true;
2987 }
2988
2989 void Frame::addMetaData(const String& key, const String& value)
2990 {
2991     d->m_job->addMetaData(key, value);
2992 }
2993
2994 // This does the same kind of work that Frame::openURL does, except it relies on the fact
2995 // that a higher level already checked that the URLs match and the scrolling is the right thing to do.
2996 void Frame::scrollToAnchor(const KURL& URL)
2997 {
2998     d->m_url = URL;
2999     started();
3000     
3001     gotoAnchor();
3002     
3003     // It's important to model this as a load that starts and immediately finishes.
3004     // Otherwise, the parent frame may think we never finished loading.
3005     d->m_bComplete = false;
3006     checkCompleted();
3007 }
3008
3009 bool Frame::closeURL()
3010 {
3011     saveDocumentState();
3012     stopLoading(true);
3013     clearUndoRedoOperations();
3014     return true;
3015 }
3016
3017 bool Frame::canMouseDownStartSelect(Node* node)
3018 {
3019     if (!node || !node->renderer())
3020         return true;
3021     
3022     // Check to see if khtml-user-select has been set to none
3023     if (!node->renderer()->canSelect())
3024         return false;
3025     
3026     // Some controls and images can't start a select on a mouse down.
3027     for (RenderObject* curr = node->renderer(); curr; curr = curr->parent()) {
3028         if (curr->style()->userSelect() == SELECT_IGNORE)
3029             return false;
3030     }
3031     
3032     return true;
3033 }
3034
3035 void Frame::handleMouseReleaseDoubleClickEvent(const MouseEventWithHitTestResults& event)
3036 {
3037     passWidgetMouseDownEventToWidget(event, true);
3038 }
3039
3040 bool Frame::passWidgetMouseDownEventToWidget(const MouseEventWithHitTestResults& event, bool isDoubleClick)
3041 {
3042     // Figure out which view to send the event to.
3043     RenderObject *target = event.innerNode() ? event.innerNode()->renderer() : 0;
3044     if (!target)
3045         return false;
3046     
3047     Widget* widget = RenderLayer::gScrollBar;
3048     if (!widget) {
3049         if (!target->isWidget())
3050             return false;
3051         widget = static_cast<RenderWidget *>(target)->widget();
3052     }
3053     
3054     // Doubleclick events don't exist in Cocoa.  Since passWidgetMouseDownEventToWidget will
3055     // just pass _currentEvent down to the widget,  we don't want to call it for events that
3056     // don't correspond to Cocoa events.  The mousedown/ups will have already been passed on as
3057     // part of the pressed/released handling.
3058     if (!isDoubleClick)
3059         return passMouseDownEventToWidget(widget);
3060     return true;
3061 }
3062
3063 bool Frame::passWidgetMouseDownEventToWidget(RenderWidget *renderWidget)
3064 {
3065     return passMouseDownEventToWidget(renderWidget->widget());
3066 }
3067
3068 void Frame::clearTimers(FrameView *view)
3069 {
3070     if (view) {
3071         view->unscheduleRelayout();
3072         if (view->frame()) {
3073             Document* document = view->frame()->document();
3074             if (document && document->renderer() && document->renderer()->layer())
3075                 document->renderer()->layer()->suspendMarquees();
3076         }
3077     }
3078 }
3079
3080 void Frame::clearTimers()
3081 {
3082     clearTimers(d->m_view.get());
3083 }
3084
3085 // FIXME: selection controller?
3086 void Frame::centerSelectionInVisibleArea() const
3087 {
3088     IntRect rect;
3089     
3090     switch (selection().state()) {
3091         case Selection::NONE:
3092             return;
3093             
3094         case Selection::CARET:
3095             rect = selection().caretRect();
3096             break;
3097             
3098         case Selection::RANGE:
3099             rect = selectionRect();
3100             break;
3101     }
3102     
3103     Position start = selection().start();
3104     Position end = selection().end();
3105     ASSERT(start.node());
3106     if (start.node() && start.node()->renderer()) {
3107         RenderLayer *layer = start.node()->renderer()->enclosingLayer();
3108         if (layer) {
3109             ASSERT(!end.node() || !end.node()->renderer() 
3110                    || (end.node()->renderer()->enclosingLayer() == layer));
3111             layer->scrollRectToVisible(rect, RenderLayer::gAlignCenterAlways, RenderLayer::gAlignCenterAlways);
3112         }
3113     }
3114 }
3115
3116 RenderStyle *Frame::styleForSelectionStart(Node *&nodeToRemove) const
3117 {
3118     nodeToRemove = 0;
3119     
3120     if (!document())
3121         return 0;
3122     if (d->m_selection.isNone())
3123         return 0;
3124     
3125     Position pos = VisiblePosition(d->m_selection.start(), d->m_selection.affinity()).deepEquivalent();
3126     if (!pos.inRenderedContent())
3127         return 0;
3128     Node *node = pos.node();
3129     if (!node)
3130         return 0;
3131     
3132     if (!d->m_typingStyle)
3133         return node->renderer()->style();
3134     
3135     ExceptionCode ec = 0;
3136     RefPtr<Element> styleElement = document()->createElementNS(xhtmlNamespaceURI, "span", ec);
3137     ASSERT(ec == 0);
3138     
3139     styleElement->setAttribute(styleAttr, d->m_typingStyle->cssText().impl(), ec);
3140     ASSERT(ec == 0);
3141     
3142     styleElement->appendChild(document()->createEditingTextNode(""), ec);
3143     ASSERT(ec == 0);
3144     
3145     node->parentNode()->appendChild(styleElement, ec);
3146     ASSERT(ec == 0);
3147     
3148     nodeToRemove = styleElement.get();    
3149     return styleElement->renderer()->style();
3150 }
3151
3152 void Frame::setMediaType(const String& type)
3153 {
3154     if (d->m_view)
3155         d->m_view->setMediaType(type);
3156 }
3157
3158 void Frame::setSelectionFromNone()
3159 {
3160     // Put the caret someplace if the selection is empty and the part is editable.
3161     // This has the effect of flashing the caret in a contentEditable view automatically 
3162     // without requiring the programmer to set a selection explicitly.
3163     Document *doc = document();
3164     if (doc && selection().isNone() && isContentEditable()) {
3165         Node *node = doc->documentElement();
3166         while (node) {
3167             // Look for a block flow, but skip over the HTML element, since we really
3168             // want to get at least as far as the the BODY element in a document.
3169             if (node->isBlockFlow() && node->hasTagName(htmlTag))
3170                 break;
3171             node = node->traverseNextNode();
3172         }
3173         if (node)
3174             setSelection(SelectionController(Position(node, 0), DOWNSTREAM));
3175     }
3176 }
3177
3178 bool Frame::displaysWithFocusAttributes() const
3179 {
3180     return d->m_isFocused;
3181 }
3182
3183 void Frame::setDisplaysWithFocusAttributes(bool flag)
3184 {
3185     if (d->m_isFocused == flag)
3186         return;
3187     
3188     d->m_isFocused = flag;
3189
3190     // This method does the job of updating the view based on whether the view is "active".
3191     // This involves three kinds of drawing updates:
3192
3193     // 1. The background color used to draw behind selected content (active | inactive color)
3194     if (d->m_view)
3195         d->m_view->updateContents(enclosingIntRect(visibleSelectionRect()));
3196
3197     // 2. Caret blinking (blinks | does not blink)
3198     if (flag)
3199         setSelectionFromNone();
3200     setCaretVisible(flag);
3201     
3202     // 3. The drawing of a focus ring around links in web pages.
3203     Document *doc = document();
3204     if (doc) {
3205         Node *node = doc->focusNode();
3206         if (node) {
3207             node->setChanged();
3208             if (node->renderer() && node->renderer()->style()->hasAppearance())
3209                 theme()->stateChanged(node->renderer(), FocusState);
3210         }
3211     }
3212 }
3213
3214 void Frame::setWindowHasFocus(bool flag)
3215 {
3216     if (d->m_windowHasFocus == flag)
3217         return;
3218     d->m_windowHasFocus = flag;
3219     
3220     if (Document *doc = document())
3221         doc->dispatchWindowEvent(flag ? focusEvent : blurEvent, false, false);
3222 }
3223
3224 QChar Frame::backslashAsCurrencySymbol() const
3225 {
3226     Document *doc = document();
3227     if (!doc)
3228         return '\\';
3229     Decoder *decoder = doc->decoder();
3230     if (!decoder)
3231         return '\\';
3232
3233     return decoder->encoding().backslashAsCurrencySymbol();
3234 }
3235
3236 bool Frame::markedTextUsesUnderlines() const
3237 {
3238     return d->m_markedTextUsesUnderlines;
3239 }
3240
3241 DeprecatedValueList<MarkedTextUnderline> Frame::markedTextUnderlines() const
3242 {
3243     return d->m_markedTextUnderlines;
3244 }
3245
3246 unsigned Frame::highlightAllMatchesForString(const String& target, bool caseFlag)
3247 {
3248     if (target.isEmpty())
3249         return 0;
3250     
3251     RefPtr<Range> searchRange(rangeOfContents(document()));
3252     
3253     int exception = 0;
3254     unsigned matchCount = 0;
3255     do {
3256         RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, true, caseFlag));
3257         if (resultRange->collapsed(exception))
3258             break;
3259         
3260         ++matchCount;
3261         document()->addMarker(resultRange.get(), DocumentMarker::TextMatch);
3262         
3263         setStart(searchRange.get(), endVisiblePosition(resultRange.get(), DOWNSTREAM));
3264     } while (true);
3265     
3266     return matchCount;
3267 }
3268
3269 void Frame::prepareForUserAction()
3270 {
3271     // Reset the multiple form submission protection code.
3272     // We'll let you submit the same form twice if you do two separate user actions.
3273     d->m_submittedFormURL = KURL();
3274 }
3275
3276 Node *Frame::mousePressNode()
3277 {
3278     return d->m_mousePressNode.get();
3279 }
3280
3281 bool Frame::isComplete() const
3282 {
3283     return d->m_bComplete;
3284 }
3285
3286 bool Frame::isLoadingMainResource() const
3287 {
3288     return d->m_bLoadingMainResource;
3289 }
3290
3291 FrameTree *Frame::tree() const
3292 {
3293     return& d->m_treeNode;
3294 }
3295
3296 void Frame::detachFromView()
3297 {
3298 }
3299
3300 KURL Frame::url() const
3301 {
3302     return d->m_url;
3303 }
3304
3305 void Frame::startRedirectionTimer()
3306 {
3307     d->m_redirectionTimer.startOneShot(d->m_delayRedirect);
3308 }
3309
3310 void Frame::stopRedirectionTimer()
3311 {
3312     d->m_redirectionTimer.stop();
3313 }
3314
3315 void Frame::frameDetached()
3316 {
3317 }
3318
3319 void Frame::updateBaseURLForEmptyDocument()
3320 {
3321     Element* owner = ownerElement();
3322     // FIXME: Should embed be included?
3323     if (owner && (owner->hasTagName(iframeTag) || owner->hasTagName(objectTag) || owner->hasTagName(embedTag)))
3324         d->m_doc->setBaseURL(tree()->parent()->d->m_doc->baseURL());
3325 }
3326
3327 Page* Frame::page() const
3328 {
3329     return d->m_page;
3330 }
3331
3332 void Frame::completed(bool complete)
3333 {
3334     ref();
3335     for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
3336         child->parentCompleted();
3337     if (Frame* parent = tree()->parent())
3338         parent->childCompleted(complete);
3339     submitFormAgain();
3340     deref();
3341 }
3342
3343 void Frame::setStatusBarText(const String&)
3344 {
3345 }
3346
3347 void Frame::started()
3348 {
3349     for (Frame* frame = this; frame; frame = frame->tree()->parent())
3350         frame->d->m_bComplete = false;
3351 }
3352
3353 void Frame::disconnectOwnerRenderer()
3354 {
3355     d->m_ownerRenderer = 0;
3356 }
3357
3358 } // namespace WebCore