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