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