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