3ec4a79f9ef6fb4624542a2556746d18c2d0c454
[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 (!parentFrame())
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 && parentFrame() 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 QString 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 && parentFrame() == 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 Frame *Frame::parentFrame() const
1940 {
1941   return parent();
1942 }
1943
1944 int Frame::zoomFactor() const
1945 {
1946   return d->m_zoomFactor;
1947 }
1948
1949 // ### make the list configurable ?
1950 static const int zoomSizes[] = { 20, 40, 60, 80, 90, 95, 100, 105, 110, 120, 140, 160, 180, 200, 250, 300 };
1951 static const int zoomSizeCount = (sizeof(zoomSizes) / sizeof(int));
1952 static const int minZoom = 20;
1953 static const int maxZoom = 300;
1954
1955 void Frame::slotIncZoom()
1956 {
1957   int zoomFactor = d->m_zoomFactor;
1958
1959   if (zoomFactor < maxZoom) {
1960     // find the entry nearest to the given zoomsizes
1961     for (int i = 0; i < zoomSizeCount; ++i)
1962       if (zoomSizes[i] > zoomFactor) {
1963         zoomFactor = zoomSizes[i];
1964         break;
1965       }
1966     setZoomFactor(zoomFactor);
1967   }
1968 }
1969
1970 void Frame::slotDecZoom()
1971 {
1972     int zoomFactor = d->m_zoomFactor;
1973     if (zoomFactor > minZoom) {
1974       // find the entry nearest to the given zoomsizes
1975       for (int i = zoomSizeCount-1; i >= 0; --i)
1976         if (zoomSizes[i] < zoomFactor) {
1977           zoomFactor = zoomSizes[i];
1978           break;
1979         }
1980       setZoomFactor(zoomFactor);
1981     }
1982 }
1983
1984 void Frame::setZoomFactor (int percent)
1985 {
1986   
1987   if (d->m_zoomFactor == percent) return;
1988   d->m_zoomFactor = percent;
1989
1990   if(d->m_doc) {
1991     d->m_doc->recalcStyle( NodeImpl::Force );
1992   }
1993
1994   ConstFrameIt it = d->m_frames.begin();
1995   ConstFrameIt end = d->m_frames.end();
1996   for (; it != end; ++it )
1997     if ((*it).m_frame && (*it).m_frame->inherits("Frame")) {
1998       ObjectContents* p = (*it).m_frame.get();
1999       static_cast<Frame*>(p)->setZoomFactor(d->m_zoomFactor);
2000     }
2001
2002   if (d->m_doc && d->m_doc->renderer() && d->m_doc->renderer()->needsLayout())
2003     view()->layout();
2004 }
2005
2006 void Frame::setJSStatusBarText( const QString &text )
2007 {
2008    d->m_kjsStatusBarText = text;
2009    emit setStatusBarText( d->m_kjsStatusBarText );
2010 }
2011
2012 void Frame::setJSDefaultStatusBarText( const QString &text )
2013 {
2014    d->m_kjsDefaultStatusBarText = text;
2015    emit setStatusBarText( d->m_kjsDefaultStatusBarText );
2016 }
2017
2018 QString Frame::jsStatusBarText() const
2019 {
2020     return d->m_kjsStatusBarText;
2021 }
2022
2023 QString Frame::jsDefaultStatusBarText() const
2024 {
2025    return d->m_kjsDefaultStatusBarText;
2026 }
2027
2028 QString Frame::referrer() const
2029 {
2030    return d->m_referrer;
2031 }
2032
2033 QString Frame::lastModified() const
2034 {
2035   return d->m_lastModified;
2036 }
2037
2038
2039 void Frame::reparseConfiguration()
2040 {
2041   setAutoloadImages( d->m_settings->autoLoadImages() );
2042   if (d->m_doc)
2043      d->m_doc->docLoader()->setShowAnimations( d->m_settings->showAnimations() );
2044
2045   d->m_bJScriptEnabled = d->m_settings->isJavaScriptEnabled(d->m_url.host());
2046   d->m_bJavaEnabled = d->m_settings->isJavaEnabled(d->m_url.host());
2047   d->m_bPluginsEnabled = d->m_settings->isPluginsEnabled(d->m_url.host());
2048
2049   QString userStyleSheet = d->m_settings->userStyleSheet();
2050   if ( !userStyleSheet.isEmpty() )
2051     setUserStyleSheet( KURL( userStyleSheet ) );
2052   else
2053     setUserStyleSheet( QString() );
2054
2055   if(d->m_doc) d->m_doc->updateStyleSelector();
2056 }
2057
2058 QStringList Frame::frameNames() const
2059 {
2060   QStringList res;
2061
2062   ConstFrameIt it = d->m_frames.begin();
2063   ConstFrameIt end = d->m_frames.end();
2064   for (; it != end; ++it )
2065     if (!(*it).m_bPreloaded)
2066       res += (*it).m_name;
2067
2068   return res;
2069 }
2070
2071 QPtrList<ObjectContents> Frame::frames() const
2072 {
2073   QPtrList<ObjectContents> res;
2074
2075   ConstFrameIt it = d->m_frames.begin();
2076   ConstFrameIt end = d->m_frames.end();
2077   for (; it != end; ++it )
2078     if (!(*it).m_bPreloaded)
2079       res.append((*it).m_frame.get());
2080
2081   return res;
2082 }
2083
2084 Frame *Frame::childFrameNamed(const QString &name) const
2085 {
2086   FrameList::Iterator it = d->m_frames.find(name);
2087   if (it != d->m_frames.end())
2088     return static_cast<Frame *>(&*(*it).m_frame);
2089   return NULL;
2090 }
2091
2092 bool Frame::shouldDragAutoNode(NodeImpl *node, int x, int y) const
2093 {
2094     // No KDE impl yet
2095     return false;
2096 }
2097
2098 bool Frame::isPointInsideSelection(int x, int y)
2099 {
2100     // Treat a collapsed selection like no selection.
2101     if (!d->m_selection.isRange())
2102         return false;
2103     if (!document()->renderer()) 
2104         return false;
2105     
2106     RenderObject::NodeInfo nodeInfo(true, true);
2107     document()->renderer()->layer()->hitTest(nodeInfo, x, y);
2108     NodeImpl *innerNode = nodeInfo.innerNode();
2109     if (!innerNode || !innerNode->renderer())
2110         return false;
2111     
2112     Position pos(innerNode->renderer()->positionForCoordinates(x, y).deepEquivalent());
2113     if (pos.isNull())
2114         return false;
2115
2116     NodeImpl *n = d->m_selection.start().node();
2117     while (n) {
2118         if (n == pos.node()) {
2119             if ((n == d->m_selection.start().node() && pos.offset() < d->m_selection.start().offset()) ||
2120                 (n == d->m_selection.end().node() && pos.offset() > d->m_selection.end().offset())) {
2121                 return false;
2122             }
2123             return true;
2124         }
2125         if (n == d->m_selection.end().node())
2126             break;
2127         n = n->traverseNextNode();
2128     }
2129
2130    return false;
2131 }
2132
2133 void Frame::selectClosestWordFromMouseEvent(QMouseEvent *mouse, NodeImpl *innerNode, int x, int y)
2134 {
2135     SelectionController selection;
2136
2137     if (innerNode && innerNode->renderer() && mouseDownMayStartSelect() && innerNode->renderer()->shouldSelect()) {
2138         VisiblePosition pos(innerNode->renderer()->positionForCoordinates(x, y));
2139         if (pos.isNotNull()) {
2140             selection.moveTo(pos);
2141             selection.expandUsingGranularity(WORD);
2142         }
2143     }
2144     
2145     if (selection.isRange()) {
2146         d->m_selectionGranularity = WORD;
2147         d->m_beganSelectingText = true;
2148     }
2149     
2150     if (shouldChangeSelection(selection))
2151         setSelection(selection);
2152 }
2153
2154 void Frame::handleMousePressEventDoubleClick(MousePressEvent *event)
2155 {
2156     if (event->qmouseEvent()->button() == LeftButton) {
2157         if (selection().isRange()) {
2158             // A double-click when range is already selected
2159             // should not change the selection.  So, do not call
2160             // selectClosestWordFromMouseEvent, but do set
2161             // m_beganSelectingText to prevent khtmlMouseReleaseEvent
2162             // from setting caret selection.
2163             d->m_beganSelectingText = true;
2164         } else {
2165             selectClosestWordFromMouseEvent(event->qmouseEvent(), event->innerNode(), event->x(), event->y());
2166         }
2167     }
2168 }
2169
2170 void Frame::handleMousePressEventTripleClick(MousePressEvent *event)
2171 {
2172     QMouseEvent *mouse = event->qmouseEvent();
2173     NodeImpl *innerNode = event->innerNode();
2174     
2175     if (mouse->button() == LeftButton && innerNode && innerNode->renderer() &&
2176         mouseDownMayStartSelect() && innerNode->renderer()->shouldSelect()) {
2177         SelectionController selection;
2178         VisiblePosition pos(innerNode->renderer()->positionForCoordinates(event->x(), event->y()));
2179         if (pos.isNotNull()) {
2180             selection.moveTo(pos);
2181             selection.expandUsingGranularity(PARAGRAPH);
2182         }
2183         if (selection.isRange()) {
2184             d->m_selectionGranularity = PARAGRAPH;
2185             d->m_beganSelectingText = true;
2186         }
2187         
2188         if (shouldChangeSelection(selection))
2189             setSelection(selection);
2190     }
2191 }
2192
2193 void Frame::handleMousePressEventSingleClick(MousePressEvent *event)
2194 {
2195     QMouseEvent *mouse = event->qmouseEvent();
2196     NodeImpl *innerNode = event->innerNode();
2197     
2198     if (mouse->button() == LeftButton) {
2199         if (innerNode && innerNode->renderer() &&
2200             mouseDownMayStartSelect() && innerNode->renderer()->shouldSelect()) {
2201             SelectionController sel;
2202             
2203             // Extend the selection if the Shift key is down, unless the click is in a link.
2204             bool extendSelection = (mouse->state() & ShiftButton) && (event->url().isNull());
2205
2206             // Don't restart the selection when the mouse is pressed on an
2207             // existing selection so we can allow for text dragging.
2208             if (!extendSelection && isPointInsideSelection(event->x(), event->y())) {
2209                 return;
2210             }
2211
2212             VisiblePosition visiblePos(innerNode->renderer()->positionForCoordinates(event->x(), event->y()));
2213             if (visiblePos.isNull())
2214                 visiblePos = VisiblePosition(innerNode, innerNode->caretMinOffset(), DOWNSTREAM);
2215             Position pos = visiblePos.deepEquivalent();
2216             
2217             sel = selection();
2218             if (extendSelection && sel.isCaretOrRange()) {
2219                 sel.clearModifyBias();
2220                 
2221                 // See <rdar://problem/3668157> REGRESSION (Mail): shift-click deselects when selection 
2222                 // was created right-to-left
2223                 Position start = sel.start();
2224                 short before = RangeImpl::compareBoundaryPoints(pos.node(), pos.offset(), start.node(), start.offset());
2225                 if (before <= 0) {
2226                     sel.setBaseAndExtent(pos.node(), pos.offset(), sel.end().node(), sel.end().offset());
2227                 } else {
2228                     sel.setBaseAndExtent(start.node(), start.offset(), pos.node(), pos.offset());
2229                 }
2230
2231                 if (d->m_selectionGranularity != CHARACTER) {
2232                     sel.expandUsingGranularity(d->m_selectionGranularity);
2233                 }
2234                 d->m_beganSelectingText = true;
2235             } else {
2236                 sel = SelectionController(visiblePos);
2237                 d->m_selectionGranularity = CHARACTER;
2238             }
2239             
2240             if (shouldChangeSelection(sel))
2241                 setSelection(sel);
2242         }
2243     }
2244 }
2245
2246 void Frame::khtmlMousePressEvent(MousePressEvent *event)
2247 {
2248     DOMString url = event->url();
2249     QMouseEvent *mouse = event->qmouseEvent();
2250     NodeImpl *innerNode = event->innerNode();
2251
2252     d->m_mousePressNode = innerNode;
2253     d->m_dragStartPos = mouse->pos();
2254
2255     if (!event->url().isNull()) {
2256         d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
2257     } else {
2258         d->m_strSelectedURL = event->url().qstring();
2259         d->m_strSelectedURLTarget = event->target().qstring();
2260     }
2261
2262     if (mouse->button() == LeftButton || mouse->button() == MidButton) {
2263         d->m_bMousePressed = true;
2264         d->m_beganSelectingText = false;
2265
2266         if (mouse->clickCount() == 2) {
2267             handleMousePressEventDoubleClick(event);
2268             return;
2269         } else if (mouse->clickCount() >= 3) {
2270             handleMousePressEventTripleClick(event);
2271             return;
2272         }
2273         handleMousePressEventSingleClick(event);
2274     }
2275 }
2276
2277 void Frame::handleMouseMoveEventSelection(MouseMoveEvent *event)
2278 {
2279     // Mouse not pressed. Do nothing.
2280     if (!d->m_bMousePressed)
2281         return;
2282
2283     QMouseEvent *mouse = event->qmouseEvent();
2284     NodeImpl *innerNode = event->innerNode();
2285
2286     if (mouse->state() != LeftButton || !innerNode || !innerNode->renderer() ||
2287             !mouseDownMayStartSelect() || !innerNode->renderer()->shouldSelect())
2288         return;
2289
2290     // handle making selection
2291     VisiblePosition pos(innerNode->renderer()->positionForCoordinates(event->x(), event->y()));
2292
2293     // Don't modify the selection if we're not on a node.
2294     if (pos.isNull())
2295         return;
2296
2297     // Restart the selection if this is the first mouse move. This work is usually
2298     // done in khtmlMousePressEvent, but not if the mouse press was on an existing selection.
2299     SelectionController sel = selection();
2300     sel.clearModifyBias();
2301     
2302     if (!d->m_beganSelectingText) {
2303         d->m_beganSelectingText = true;
2304         sel.moveTo(pos);
2305     }
2306
2307     sel.setExtent(pos);
2308     if (d->m_selectionGranularity != CHARACTER)
2309         sel.expandUsingGranularity(d->m_selectionGranularity);
2310
2311     if (shouldChangeSelection(sel))
2312         setSelection(sel);
2313 }
2314
2315 void Frame::khtmlMouseMoveEvent(MouseMoveEvent *event)
2316 {
2317     handleMouseMoveEventSelection(event);
2318 }
2319
2320 void Frame::khtmlMouseReleaseEvent( MouseReleaseEvent *event )
2321 {
2322     // Used to prevent mouseMoveEvent from initiating a drag before
2323     // the mouse is pressed again.
2324     d->m_bMousePressed = false;
2325   
2326     // Clear the selection if the mouse didn't move after the last mouse press.
2327     // We do this so when clicking on the selection, the selection goes away.
2328     // However, if we are editing, place the caret.
2329     if (mouseDownMayStartSelect() && !d->m_beganSelectingText
2330             && d->m_dragStartPos.x() == event->qmouseEvent()->x()
2331             && d->m_dragStartPos.y() == event->qmouseEvent()->y()
2332             && d->m_selection.isRange()) {
2333         SelectionController selection;
2334         NodeImpl *node = event->innerNode();
2335         if (node && node->isContentEditable() && node->renderer()) {
2336             VisiblePosition pos = node->renderer()->positionForCoordinates(event->x(), event->y());
2337             selection.moveTo(pos);
2338         }
2339         if (shouldChangeSelection(selection))
2340             setSelection(selection);
2341     }
2342     selectFrameElementInParentIfFullySelected();
2343 }
2344
2345 void Frame::selectAll()
2346 {
2347     if (!d->m_doc)
2348         return;
2349     
2350     NodeImpl *startNode = d->m_selection.start().node();
2351     NodeImpl *root = startNode && startNode->isContentEditable() ? startNode->rootEditableElement() : d->m_doc->documentElement();
2352     
2353     selectContentsOfNode(root);
2354     selectFrameElementInParentIfFullySelected();
2355 }
2356
2357 bool Frame::selectContentsOfNode(NodeImpl* node)
2358 {
2359     SelectionController sel = SelectionController(Position(node, 0), Position(node, maxDeepOffset(node)), DOWNSTREAM);    
2360     if (shouldChangeSelection(sel)) {
2361         setSelection(sel);
2362         return true;
2363     }
2364     return false;
2365 }
2366
2367 bool Frame::shouldChangeSelection(const SelectionController &newselection) const
2368 {
2369     return shouldChangeSelection(d->m_selection, newselection, newselection.affinity(), false);
2370 }
2371
2372 bool Frame::shouldBeginEditing(const RangeImpl *range) const
2373 {
2374     return true;
2375 }
2376
2377 bool Frame::shouldEndEditing(const RangeImpl *range) const
2378 {
2379     return true;
2380 }
2381
2382 bool Frame::isContentEditable() const 
2383 {
2384     if (!d->m_doc)
2385         return false;
2386     return d->m_doc->inDesignMode();
2387 }
2388
2389 EditCommandPtr Frame::lastEditCommand()
2390 {
2391     return d->m_lastEditCommand;
2392 }
2393
2394 void Frame::appliedEditing(EditCommandPtr &cmd)
2395 {
2396     SelectionController sel(cmd.endingSelection());
2397     if (shouldChangeSelection(sel)) {
2398         setSelection(sel, false);
2399     }
2400
2401     // Now set the typing style from the command. Clear it when done.
2402     // This helps make the case work where you completely delete a piece
2403     // of styled text and then type a character immediately after.
2404     // That new character needs to take on the style of the just-deleted text.
2405     // FIXME: Improve typing style.
2406     // See this bug: <rdar://problem/3769899> Implementation of typing style needs improvement
2407     if (cmd.typingStyle()) {
2408         setTypingStyle(cmd.typingStyle());
2409         cmd.setTypingStyle(0);
2410     }
2411
2412     // Command will be equal to last edit command only in the case of typing
2413     if (d->m_lastEditCommand == cmd) {
2414         assert(cmd.isTypingCommand());
2415     }
2416     else {
2417         // Only register a new undo command if the command passed in is
2418         // different from the last command
2419         registerCommandForUndo(cmd);
2420         d->m_lastEditCommand = cmd;
2421     }
2422     respondToChangedContents();
2423 }
2424
2425 void Frame::unappliedEditing(EditCommandPtr &cmd)
2426 {
2427     SelectionController sel(cmd.startingSelection());
2428     if (shouldChangeSelection(sel)) {
2429         setSelection(sel, true);
2430     }
2431     registerCommandForRedo(cmd);
2432     respondToChangedContents();
2433     d->m_lastEditCommand = EditCommandPtr::emptyCommand();
2434 }
2435
2436 void Frame::reappliedEditing(EditCommandPtr &cmd)
2437 {
2438     SelectionController sel(cmd.endingSelection());
2439     if (shouldChangeSelection(sel)) {
2440         setSelection(sel, true);
2441     }
2442     registerCommandForUndo(cmd);
2443     respondToChangedContents();
2444     d->m_lastEditCommand = EditCommandPtr::emptyCommand();
2445 }
2446
2447 CSSMutableStyleDeclarationImpl *Frame::typingStyle() const
2448 {
2449     return d->m_typingStyle;
2450 }
2451
2452 void Frame::setTypingStyle(CSSMutableStyleDeclarationImpl *style)
2453 {
2454     if (d->m_typingStyle == style)
2455         return;
2456         
2457     CSSMutableStyleDeclarationImpl *old = d->m_typingStyle;
2458     d->m_typingStyle = style;
2459     if (d->m_typingStyle)
2460         d->m_typingStyle->ref();
2461     if (old)
2462         old->deref();
2463 }
2464
2465 void Frame::clearTypingStyle()
2466 {
2467     setTypingStyle(0);
2468 }
2469
2470 JSValue* Frame::executeScript(const QString& filename, int baseLine, NodeImpl* n, const QString &script)
2471 {
2472   // FIXME: This is missing stuff that the other executeScript has.
2473   // --> d->m_runningScripts and submitFormAgain.
2474   // Why is that OK?
2475   KJSProxyImpl *proxy = jScript();
2476   if (!proxy)
2477     return 0;
2478   JSValue* ret = proxy->evaluate(filename, baseLine, script, n);
2479   DocumentImpl::updateDocumentsRendering();
2480   return ret;
2481 }
2482
2483 void Frame::slotPartRemoved(ObjectContents  *part)
2484 {
2485     if (part == d->m_activeFrame)
2486         d->m_activeFrame = 0;
2487 }
2488
2489 Frame *Frame::opener()
2490 {
2491     return d->m_opener;
2492 }
2493
2494 void Frame::setOpener(Frame *_opener)
2495 {
2496     d->m_opener = _opener;
2497 }
2498
2499 bool Frame::openedByJS()
2500 {
2501     return d->m_openedByJS;
2502 }
2503
2504 void Frame::setOpenedByJS(bool _openedByJS)
2505 {
2506     d->m_openedByJS = _openedByJS;
2507 }
2508
2509 void Frame::preloadStyleSheet(const QString &url, const QString &stylesheet)
2510 {
2511     Cache::preloadStyleSheet(url, stylesheet);
2512 }
2513
2514 void Frame::preloadScript(const QString &url, const QString &script)
2515 {
2516     Cache::preloadScript(url, script);
2517 }
2518
2519
2520 bool Frame::restored() const
2521 {
2522   return d->m_restored;
2523 }
2524
2525 void Frame::incrementFrameCount()
2526 {
2527   frameCount++;
2528   if (parentFrame()) {
2529     parentFrame()->incrementFrameCount();
2530   }
2531 }
2532
2533 void Frame::decrementFrameCount()
2534 {
2535   frameCount--;
2536   if (parentFrame()) {
2537     parentFrame()->decrementFrameCount();
2538   }
2539 }
2540
2541 int Frame::topLevelFrameCount()
2542 {
2543   if (parentFrame()) {
2544     return parentFrame()->topLevelFrameCount();
2545   }
2546
2547   return frameCount;
2548 }
2549
2550 bool Frame::tabsToLinks() const
2551 {
2552     return true;
2553 }
2554
2555 bool Frame::tabsToAllControls() const
2556 {
2557     return true;
2558 }
2559
2560 void Frame::copyToPasteboard()
2561 {
2562     issueCopyCommand();
2563 }
2564
2565 void Frame::cutToPasteboard()
2566 {
2567     issueCutCommand();
2568 }
2569
2570 void Frame::pasteFromPasteboard()
2571 {
2572     issuePasteCommand();
2573 }
2574
2575 void Frame::pasteAndMatchStyle()
2576 {
2577     issuePasteAndMatchStyleCommand();
2578 }
2579
2580 void Frame::transpose()
2581 {
2582     issueTransposeCommand();
2583 }
2584
2585 void Frame::redo()
2586 {
2587     issueRedoCommand();
2588 }
2589
2590 void Frame::undo()
2591 {
2592     issueUndoCommand();
2593 }
2594
2595
2596 void Frame::computeAndSetTypingStyle(CSSStyleDeclarationImpl *style, EditAction editingAction)
2597 {
2598     if (!style || style->length() == 0) {
2599         clearTypingStyle();
2600         return;
2601     }
2602
2603     // Calculate the current typing style.
2604     CSSMutableStyleDeclarationImpl *mutableStyle = style->makeMutable();
2605     mutableStyle->ref();
2606     if (typingStyle()) {
2607         typingStyle()->merge(mutableStyle);
2608         mutableStyle->deref();
2609         mutableStyle = typingStyle();
2610         mutableStyle->ref();
2611     }
2612
2613     NodeImpl *node = VisiblePosition(selection().start(), selection().affinity()).deepEquivalent().node();
2614     CSSComputedStyleDeclarationImpl computedStyle(node);
2615     computedStyle.diff(mutableStyle);
2616     
2617     // Handle block styles, substracting these from the typing style.
2618     CSSMutableStyleDeclarationImpl *blockStyle = mutableStyle->copyBlockProperties();
2619     blockStyle->ref();
2620     blockStyle->diff(mutableStyle);
2621     if (document() && blockStyle->length() > 0) {
2622         EditCommandPtr cmd(new ApplyStyleCommand(document(), blockStyle, editingAction));
2623         cmd.apply();
2624     }
2625     blockStyle->deref();
2626     
2627     // Set the remaining style as the typing style.
2628     setTypingStyle(mutableStyle);
2629     mutableStyle->deref();
2630 }
2631
2632 void Frame::applyStyle(CSSStyleDeclarationImpl *style, EditAction editingAction)
2633 {
2634     switch (selection().state()) {
2635         case Selection::NONE:
2636             // do nothing
2637             break;
2638         case Selection::CARET: {
2639             computeAndSetTypingStyle(style, editingAction);
2640             break;
2641         }
2642         case Selection::RANGE:
2643             if (document() && style) {
2644                 EditCommandPtr cmd(new ApplyStyleCommand(document(), style, editingAction));
2645                 cmd.apply();
2646             }
2647             break;
2648     }
2649 }
2650
2651 void Frame::applyParagraphStyle(CSSStyleDeclarationImpl *style, EditAction editingAction)
2652 {
2653     switch (selection().state()) {
2654         case Selection::NONE:
2655             // do nothing
2656             break;
2657         case Selection::CARET:
2658         case Selection::RANGE:
2659             if (document() && style) {
2660                 EditCommandPtr cmd(new ApplyStyleCommand(document(), style, editingAction, ApplyStyleCommand::ForceBlockProperties));
2661                 cmd.apply();
2662             }
2663             break;
2664     }
2665 }
2666
2667 static void updateState(CSSMutableStyleDeclarationImpl *desiredStyle, CSSComputedStyleDeclarationImpl *computedStyle, bool &atStart, Frame::TriState &state)
2668 {
2669     QValueListConstIterator<CSSProperty> end;
2670     for (QValueListConstIterator<CSSProperty> it = desiredStyle->valuesIterator(); it != end; ++it) {
2671         int propertyID = (*it).id();
2672         DOMString desiredProperty = desiredStyle->getPropertyValue(propertyID);
2673         DOMString computedProperty = computedStyle->getPropertyValue(propertyID);
2674         Frame::TriState propertyState = equalIgnoringCase(desiredProperty, computedProperty)
2675             ? Frame::trueTriState : Frame::falseTriState;
2676         if (atStart) {
2677             state = propertyState;
2678             atStart = false;
2679         } else if (state != propertyState) {
2680             state = Frame::mixedTriState;
2681             break;
2682         }
2683     }
2684 }
2685
2686 Frame::TriState Frame::selectionHasStyle(CSSStyleDeclarationImpl *style) const
2687 {
2688     bool atStart = true;
2689     TriState state = falseTriState;
2690
2691     CSSMutableStyleDeclarationImpl *mutableStyle = style->makeMutable();
2692     RefPtr<CSSStyleDeclarationImpl> protectQueryStyle(mutableStyle);
2693
2694     if (!d->m_selection.isRange()) {
2695         NodeImpl *nodeToRemove;
2696         CSSComputedStyleDeclarationImpl *selectionStyle = selectionComputedStyle(nodeToRemove);
2697         if (!selectionStyle)
2698             return falseTriState;
2699         selectionStyle->ref();
2700         updateState(mutableStyle, selectionStyle, atStart, state);
2701         selectionStyle->deref();
2702         if (nodeToRemove) {
2703             int exceptionCode = 0;
2704             nodeToRemove->remove(exceptionCode);
2705             assert(exceptionCode == 0);
2706         }
2707     } else {
2708         for (NodeImpl *node = d->m_selection.start().node(); node; node = node->traverseNextNode()) {
2709             CSSComputedStyleDeclarationImpl *computedStyle = new CSSComputedStyleDeclarationImpl(node);
2710             if (computedStyle) {
2711                 computedStyle->ref();
2712                 updateState(mutableStyle, computedStyle, atStart, state);
2713                 computedStyle->deref();
2714             }
2715             if (state == mixedTriState)
2716                 break;
2717             if (node == d->m_selection.end().node())
2718                 break;
2719         }
2720     }
2721
2722     return state;
2723 }
2724
2725 bool Frame::selectionStartHasStyle(CSSStyleDeclarationImpl *style) const
2726 {
2727     NodeImpl *nodeToRemove;
2728     CSSStyleDeclarationImpl *selectionStyle = selectionComputedStyle(nodeToRemove);
2729     if (!selectionStyle)
2730         return false;
2731
2732     CSSMutableStyleDeclarationImpl *mutableStyle = style->makeMutable();
2733
2734     RefPtr<CSSStyleDeclarationImpl> protectSelectionStyle(selectionStyle);
2735     RefPtr<CSSStyleDeclarationImpl> protectQueryStyle(mutableStyle);
2736
2737     bool match = true;
2738     QValueListConstIterator<CSSProperty> end;
2739     for (QValueListConstIterator<CSSProperty> it = mutableStyle->valuesIterator(); it != end; ++it) {
2740         int propertyID = (*it).id();
2741         if (!equalIgnoringCase(mutableStyle->getPropertyValue(propertyID), selectionStyle->getPropertyValue(propertyID))) {
2742             match = false;
2743             break;
2744         }
2745     }
2746
2747     if (nodeToRemove) {
2748         int exceptionCode = 0;
2749         nodeToRemove->remove(exceptionCode);
2750         assert(exceptionCode == 0);
2751     }
2752
2753     return match;
2754 }
2755
2756 DOMString Frame::selectionStartStylePropertyValue(int stylePropertyID) const
2757 {
2758     NodeImpl *nodeToRemove;
2759     CSSStyleDeclarationImpl *selectionStyle = selectionComputedStyle(nodeToRemove);
2760     if (!selectionStyle)
2761         return DOMString();
2762
2763     selectionStyle->ref();
2764     DOMString value = selectionStyle->getPropertyValue(stylePropertyID);
2765     selectionStyle->deref();
2766
2767     if (nodeToRemove) {
2768         int exceptionCode = 0;
2769         nodeToRemove->remove(exceptionCode);
2770         assert(exceptionCode == 0);
2771     }
2772
2773     return value;
2774 }
2775
2776 CSSComputedStyleDeclarationImpl *Frame::selectionComputedStyle(NodeImpl *&nodeToRemove) const
2777 {
2778     nodeToRemove = 0;
2779
2780     if (!document())
2781         return 0;
2782
2783     if (d->m_selection.isNone())
2784         return 0;
2785
2786     RefPtr<RangeImpl> range(d->m_selection.toRange());
2787     Position pos = range->editingStartPosition();
2788
2789     ElementImpl *elem = pos.element();
2790     if (!elem)
2791         return 0;
2792     
2793     ElementImpl *styleElement = elem;
2794     int exceptionCode = 0;
2795
2796     if (d->m_typingStyle) {
2797         styleElement = document()->createElementNS(xhtmlNamespaceURI, "span", exceptionCode);
2798         assert(exceptionCode == 0);
2799
2800         styleElement->ref();
2801         
2802         styleElement->setAttribute(styleAttr, d->m_typingStyle->cssText().impl(), exceptionCode);
2803         assert(exceptionCode == 0);
2804         
2805         TextImpl *text = document()->createEditingTextNode("");
2806         styleElement->appendChild(text, exceptionCode);
2807         assert(exceptionCode == 0);
2808
2809         if (elem->renderer() && elem->renderer()->canHaveChildren()) {
2810             elem->appendChild(styleElement, exceptionCode);
2811         } else {
2812             NodeImpl *parent = elem->parent();
2813             NodeImpl *next = elem->nextSibling();
2814
2815             if (next) {
2816                 parent->insertBefore(styleElement, next, exceptionCode);
2817             } else {
2818                 parent->appendChild(styleElement, exceptionCode);
2819             }
2820         }
2821         assert(exceptionCode == 0);
2822
2823         styleElement->deref();
2824
2825         nodeToRemove = styleElement;
2826     }
2827
2828     return new CSSComputedStyleDeclarationImpl(styleElement);
2829 }
2830
2831 static CSSMutableStyleDeclarationImpl *editingStyle()
2832 {
2833     static CSSMutableStyleDeclarationImpl *editingStyle = 0;
2834     if (!editingStyle) {
2835         editingStyle = new CSSMutableStyleDeclarationImpl;
2836         int exceptionCode;
2837         editingStyle->setCssText("word-wrap: break-word; -khtml-nbsp-mode: space; -khtml-line-break: after-white-space;", exceptionCode);
2838     }
2839     return editingStyle;
2840 }
2841
2842 void Frame::applyEditingStyleToBodyElement() const
2843 {
2844     if (!d->m_doc)
2845         return;
2846         
2847     RefPtr<NodeListImpl> list = d->m_doc->getElementsByTagName("body");
2848     unsigned len = list->length();
2849     for (unsigned i = 0; i < len; i++) {
2850         applyEditingStyleToElement(static_cast<ElementImpl *>(list->item(i)));    
2851     }
2852 }
2853
2854 void Frame::removeEditingStyleFromBodyElement() const
2855 {
2856     if (!d->m_doc)
2857         return;
2858         
2859     RefPtr<NodeListImpl> list = d->m_doc->getElementsByTagName("body");
2860     unsigned len = list->length();
2861     for (unsigned i = 0; i < len; i++) {
2862         removeEditingStyleFromElement(static_cast<ElementImpl *>(list->item(i)));    
2863     }
2864 }
2865
2866 void Frame::applyEditingStyleToElement(ElementImpl *element) const
2867 {
2868     if (!element || !element->isHTMLElement())
2869         return;
2870         
2871     RenderObject *renderer = element->renderer();
2872     if (!renderer || !renderer->isBlockFlow())
2873         return;
2874     
2875     CSSMutableStyleDeclarationImpl *currentStyle = static_cast<HTMLElementImpl *>(element)->getInlineStyleDecl();
2876     CSSMutableStyleDeclarationImpl *mergeStyle = editingStyle();
2877     if (mergeStyle) {
2878         currentStyle->merge(mergeStyle);
2879         element->setAttribute(styleAttr, currentStyle->cssText());
2880     }
2881 }
2882
2883 void Frame::removeEditingStyleFromElement(ElementImpl *element) const
2884 {
2885     if (!element || !element->isHTMLElement())
2886         return;
2887         
2888     RenderObject *renderer = element->renderer();
2889     if (!renderer || !renderer->isBlockFlow())
2890         return;
2891     
2892     CSSMutableStyleDeclarationImpl *currentStyle = static_cast<HTMLElementImpl *>(element)->getInlineStyleDecl();
2893     bool changed = false;
2894     changed |= !currentStyle->removeProperty(CSS_PROP_WORD_WRAP, false).isNull();
2895     changed |= !currentStyle->removeProperty(CSS_PROP__KHTML_NBSP_MODE, false).isNull();
2896     changed |= !currentStyle->removeProperty(CSS_PROP__KHTML_LINE_BREAK, false).isNull();
2897     if (changed)
2898         currentStyle->setChanged();
2899
2900     element->setAttribute(styleAttr, currentStyle->cssText());
2901 }
2902
2903
2904 bool Frame::isCharacterSmartReplaceExempt(const QChar &, bool)
2905 {
2906     // no smart replace
2907     return true;
2908 }
2909
2910 void Frame::connectChild(const ChildFrame *child) const
2911 {
2912     ObjectContents *part = child->m_frame.get();
2913     if (part && child->m_type != ChildFrame::Object)
2914     {
2915         connect( part, SIGNAL( started( KIO::Job *) ),
2916                  this, SLOT( slotChildStarted( KIO::Job *) ) );
2917         connect( part, SIGNAL( completed() ),
2918                  this, SLOT( slotChildCompleted() ) );
2919         connect( part, SIGNAL( completed(bool) ),
2920                  this, SLOT( slotChildCompleted(bool) ) );
2921         connect( part, SIGNAL( setStatusBarText( const QString & ) ),
2922                  this, SIGNAL( setStatusBarText( const QString & ) ) );
2923         connect( this, SIGNAL( completed() ),
2924                  part, SLOT( slotParentCompleted() ) );
2925         connect( this, SIGNAL( completed(bool) ),
2926                  part, SLOT( slotParentCompleted() ) );
2927     }
2928 }
2929
2930 void Frame::disconnectChild(const ChildFrame *child) const
2931 {
2932     ObjectContents *part = child->m_frame.get();
2933     if (part && child->m_type != ChildFrame::Object)
2934     {
2935         disconnect( part, SIGNAL( started( KIO::Job *) ),
2936                     this, SLOT( slotChildStarted( KIO::Job *) ) );
2937         disconnect( part, SIGNAL( completed() ),
2938                     this, SLOT( slotChildCompleted() ) );
2939         disconnect( part, SIGNAL( completed(bool) ),
2940                     this, SLOT( slotChildCompleted(bool) ) );
2941         disconnect( part, SIGNAL( setStatusBarText( const QString & ) ),
2942                     this, SIGNAL( setStatusBarText( const QString & ) ) );
2943         disconnect( this, SIGNAL( completed() ),
2944                     part, SLOT( slotParentCompleted() ) );
2945         disconnect( this, SIGNAL( completed(bool) ),
2946                     part, SLOT( slotParentCompleted() ) );
2947     }
2948 }
2949
2950 #if !NDEBUG
2951 static HashSet<Frame*> lifeSupportSet;
2952 #endif
2953
2954 void Frame::endAllLifeSupport()
2955 {
2956 #if !NDEBUG
2957     HashSet<Frame*> lifeSupportCopy = lifeSupportSet;
2958     HashSet<Frame*>::iterator end = lifeSupportCopy.end();
2959     for (HashSet<Frame*>::iterator it = lifeSupportCopy.begin(); it != end; ++it)
2960         (*it)->endLifeSupport();
2961 #endif
2962 }
2963
2964 void Frame::keepAlive()
2965 {
2966     if (d->m_lifeSupportTimer.isActive())
2967         return;
2968     ref();
2969 #if !NDEBUG
2970     lifeSupportSet.add(this);
2971 #endif
2972     d->m_lifeSupportTimer.startOneShot(0);
2973 }
2974
2975 void Frame::endLifeSupport()
2976 {
2977     if (!d->m_lifeSupportTimer.isActive())
2978         return;
2979     d->m_lifeSupportTimer.stop();
2980 #if !NDEBUG
2981     lifeSupportSet.remove(this);
2982 #endif
2983     deref();
2984 }
2985
2986 void Frame::lifeSupportTimerFired(Timer<Frame>*)
2987 {
2988 #if !NDEBUG
2989     lifeSupportSet.remove(this);
2990 #endif
2991     deref();
2992 }
2993
2994 // Workaround for the fact that it's hard to delete a frame.
2995 // Call this after doing user-triggered selections to make it easy to delete the frame you entirely selected.
2996 // Can't do this implicitly as part of every setSelection call because in some contexts it might not be good
2997 // for the focus to move to another frame. So instead we call it from places where we are selecting with the
2998 // mouse or the keyboard after setting the selection.
2999 void Frame::selectFrameElementInParentIfFullySelected()
3000 {
3001     // Find the parent frame; if there is none, then we have nothing to do.
3002     Frame *parent = parentFrame();
3003     if (!parent)
3004         return;
3005     FrameView *parentView = parent->view();
3006     if (!parentView)
3007         return;
3008
3009     // Check if the selection contains the entire frame contents; if not, then there is nothing to do.
3010     if (!d->m_selection.isRange())
3011         return;
3012     if (!isStartOfDocument(VisiblePosition(d->m_selection.start(), d->m_selection.affinity())))
3013         return;
3014     if (!isEndOfDocument(VisiblePosition(d->m_selection.end(), d->m_selection.affinity())))
3015         return;
3016
3017     // Get to the <iframe> or <frame> (or even <object>) element in the parent frame.
3018     DocumentImpl *doc = document();
3019     if (!doc)
3020         return;
3021     ElementImpl *ownerElement = doc->ownerElement();
3022     if (!ownerElement)
3023         return;
3024     NodeImpl *ownerElementParent = ownerElement->parentNode();
3025     if (!ownerElementParent)
3026         return;
3027
3028     // Create compute positions before and after the element.
3029     unsigned ownerElementNodeIndex = ownerElement->nodeIndex();
3030     VisiblePosition beforeOwnerElement(VisiblePosition(ownerElementParent, ownerElementNodeIndex, SEL_DEFAULT_AFFINITY));
3031     VisiblePosition afterOwnerElement(VisiblePosition(ownerElementParent, ownerElementNodeIndex + 1, VP_UPSTREAM_IF_POSSIBLE));
3032
3033     // Focus on the parent frame, and then select from before this element to after.
3034     if (parent->shouldChangeSelection(SelectionController(beforeOwnerElement, afterOwnerElement))) {
3035         parentView->setFocus();
3036         parent->setSelection(SelectionController(beforeOwnerElement, afterOwnerElement));
3037     }
3038 }
3039
3040 void Frame::handleFallbackContent()
3041 {
3042     Frame *parent = parentFrame();
3043     if (!parent)
3044         return;
3045     ChildFrame *childFrame = parent->childFrame(this);
3046     if (!childFrame || childFrame->m_type != ChildFrame::Object)
3047         return;
3048     RenderPart *renderPart = childFrame->m_renderer;
3049     if (!renderPart)
3050         return;
3051     NodeImpl *node = renderPart->element();
3052     if (!node || !node->hasTagName(objectTag))
3053         return;
3054     static_cast<HTMLObjectElementImpl *>(node)->renderFallbackContent();
3055 }
3056
3057 void Frame::setSettings(KHTMLSettings *settings)
3058 {
3059     d->m_settings = settings;
3060 }
3061
3062 void Frame::provisionalLoadStarted()
3063 {
3064     // we don't want to wait until we get an actual http response back
3065     // to cancel pending redirects, otherwise they might fire before
3066     // that happens.
3067     cancelRedirection(true);
3068 }
3069
3070 bool Frame::userGestureHint()
3071 {
3072     Frame *rootFrame = this;
3073     while (rootFrame->parentFrame())
3074         rootFrame = rootFrame->parentFrame();
3075
3076     if (rootFrame->jScript() && rootFrame->jScript()->interpreter())
3077         return rootFrame->jScript()->interpreter()->wasRunByUserGesture();
3078
3079     return true; // If JavaScript is disabled, a user gesture must have initiated the navigation
3080 }
3081
3082 RenderObject *Frame::renderer() const
3083 {
3084     DocumentImpl *doc = document();
3085     return doc ? doc->renderer() : 0;
3086 }
3087
3088 IntRect Frame::selectionRect() const
3089 {
3090     RenderCanvas *root = static_cast<RenderCanvas *>(renderer());
3091     if (!root)
3092         return IntRect();
3093
3094     return root->selectionRect();
3095 }
3096
3097 bool Frame::isFrameSet() const
3098 {
3099     DocumentImpl *document = d->m_doc;
3100     if (!document || !document->isHTMLDocument())
3101         return false;
3102     NodeImpl *body = static_cast<HTMLDocumentImpl *>(document)->body();
3103     return body && body->renderer() && body->hasTagName(framesetTag);
3104 }
3105
3106 bool Frame::openURL(const KURL &URL)
3107 {
3108     ASSERT_NOT_REACHED();
3109     return true;
3110 }
3111
3112 void Frame::didNotOpenURL(const KURL &URL)
3113 {
3114     if (_submittedFormURL == URL) {
3115         _submittedFormURL = KURL();
3116     }
3117 }
3118
3119 // Scans logically forward from "start", including any child frames
3120 static HTMLFormElementImpl *scanForForm(NodeImpl *start)
3121 {
3122     NodeImpl *n;
3123     for (n = start; n; n = n->traverseNextNode()) {
3124         if (n->hasTagName(formTag)) {
3125             return static_cast<HTMLFormElementImpl *>(n);
3126         } else if (n->isHTMLElement()
3127                    && static_cast<HTMLElementImpl *>(n)->isGenericFormElement()) {
3128             return static_cast<HTMLGenericFormElementImpl *>(n)->form();
3129         } else if (n->hasTagName(frameTag) || n->hasTagName(iframeTag)) {
3130             NodeImpl *childDoc = static_cast<HTMLFrameElementImpl *>(n)->contentDocument();
3131             HTMLFormElementImpl *frameResult = scanForForm(childDoc);
3132             if (frameResult) {
3133                 return frameResult;
3134             }
3135         }
3136     }
3137     return 0;
3138 }
3139
3140 // We look for either the form containing the current focus, or for one immediately after it
3141 HTMLFormElementImpl *Frame::currentForm() const
3142 {
3143     // start looking either at the active (first responder) node, or where the selection is
3144     NodeImpl *start = d->m_doc ? d->m_doc->focusNode() : 0;
3145     if (!start)
3146         start = selection().start().node();
3147     
3148     // try walking up the node tree to find a form element
3149     NodeImpl *n;
3150     for (n = start; n; n = n->parentNode()) {
3151         if (n->hasTagName(formTag))
3152             return static_cast<HTMLFormElementImpl *>(n);
3153         else if (n->isHTMLElement()
3154                    && static_cast<HTMLElementImpl *>(n)->isGenericFormElement())
3155             return static_cast<HTMLGenericFormElementImpl *>(n)->form();
3156     }
3157     
3158     // try walking forward in the node tree to find a form element
3159     return start ? scanForForm(start) : 0;
3160 }
3161
3162 void Frame::setEncoding(const QString &name, bool userChosen)
3163 {
3164     if (!d->m_workingURL.isEmpty())
3165         receivedFirstData();
3166     d->m_encoding = name;
3167     d->m_haveEncoding = userChosen;
3168 }
3169
3170 void Frame::addData(const char *bytes, int length)
3171 {
3172     ASSERT(d->m_workingURL.isEmpty());
3173     ASSERT(d->m_doc);
3174     ASSERT(d->m_doc->parsing());
3175     write(bytes, length);
3176 }
3177
3178 // FIXME: should this go in SelectionController?
3179 void Frame::revealSelection()
3180 {
3181     IntRect rect;
3182     
3183     switch (selection().state()) {
3184         case Selection::NONE:
3185             return;
3186             
3187         case Selection::CARET:
3188             rect = selection().caretRect();
3189             break;
3190             
3191         case Selection::RANGE:
3192             rect = selectionRect();
3193             break;
3194     }
3195     
3196     Position start = selection().start();
3197     Position end = selection().end();
3198     ASSERT(start.node());
3199     if (start.node() && start.node()->renderer()) {
3200         RenderLayer *layer = start.node()->renderer()->enclosingLayer();
3201         if (layer) {
3202             ASSERT(!end.node() || !end.node()->renderer() 
3203                    || (end.node()->renderer()->enclosingLayer() == layer));
3204             layer->scrollRectToVisible(rect);
3205         }
3206     }
3207 }
3208
3209 // FIXME: should this be here?
3210 bool Frame::scrollOverflow(KWQScrollDirection direction, KWQScrollGranularity granularity)
3211 {
3212     if (!document()) {
3213         return false;
3214     }
3215     
3216     NodeImpl *node = document()->focusNode();
3217     if (node == 0) {
3218         node = d->m_mousePressNode.get();
3219     }
3220     
3221     if (node != 0) {
3222         RenderObject *r = node->renderer();
3223         if (r != 0) {
3224             return r->scroll(direction, granularity);
3225         }
3226     }
3227     
3228     return false;
3229 }
3230
3231 // FIXME: why is this here instead of on the FrameView?
3232 void Frame::paint(QPainter *p, const IntRect& rect)
3233 {
3234 #if !NDEBUG
3235     bool fillWithRed;
3236     if (p->printing())
3237         fillWithRed = false; // Printing, don't fill with red (can't remember why).
3238     else if (!document() || document()->ownerElement())
3239         fillWithRed = false; // Subframe, don't fill with red.
3240     else if (view() && view()->isTransparent())
3241         fillWithRed = false; // Transparent, don't fill with red.
3242     else if (_drawSelectionOnly)
3243         fillWithRed = false; // Selections are transparent, don't fill with red.
3244     else if (_elementToDraw)
3245         fillWithRed = false; // Element images are transparent, don't fill with red.
3246     else
3247         fillWithRed = true;
3248     
3249     if (fillWithRed)
3250         p->fillRect(rect, Color(0xFF, 0, 0));
3251 #endif
3252     
3253     if (renderer()) {
3254         // _elementToDraw is used to draw only one element
3255         RenderObject *eltRenderer = _elementToDraw ? _elementToDraw->renderer() : 0;
3256         renderer()->layer()->paint(p, rect, _drawSelectionOnly, eltRenderer);
3257
3258 #if __APPLE__
3259         // Regions may have changed as a result of the visibility/z-index of element changing.
3260         if (renderer()->document()->dashboardRegionsDirty())
3261             renderer()->canvas()->view()->updateDashboardRegions();
3262 #endif
3263     } else
3264         ERROR("called Frame::paint with nil renderer");
3265 }
3266
3267 void Frame::adjustPageHeight(float *newBottom, float oldTop, float oldBottom, float bottomLimit)
3268 {
3269     RenderCanvas *root = static_cast<RenderCanvas *>(document()->renderer());
3270     if (root) {
3271         // Use a printer device, with painting disabled for the pagination phase
3272         QPainter painter(true);
3273         painter.setPaintingDisabled(true);
3274         
3275         root->setTruncatedAt((int)floor(oldBottom));
3276         IntRect dirtyRect(0, (int)floor(oldTop),
3277                         root->docWidth(), (int)ceil(oldBottom-oldTop));
3278         root->layer()->paint(&painter, dirtyRect);
3279         *newBottom = root->bestTruncatedAt();
3280         if (*newBottom == 0)
3281             *newBottom = oldBottom;
3282     } else
3283         *newBottom = oldBottom;
3284 }
3285
3286 PausedTimeouts *Frame::pauseTimeouts()
3287 {
3288 #if SVG_SUPPORT
3289     if (d->m_doc && d->m_doc->svgExtensions())
3290         d->m_doc->accessSVGExtensions()->pauseAnimations();
3291 #endif
3292
3293     if (d->m_doc && d->m_jscript) {
3294         Window *w = Window::retrieveWindow(this);
3295         if (w)
3296             return w->pauseTimeouts();
3297     }
3298     return 0;
3299 }
3300
3301 void Frame::resumeTimeouts(PausedTimeouts *t)
3302 {
3303 #if SVG_SUPPORT
3304     if (d->m_doc && d->m_doc->svgExtensions())
3305         d->m_doc->accessSVGExtensions()->unpauseAnimations();
3306 #endif
3307
3308     if (d->m_doc && d->m_jscript && d->m_bJScriptEnabled) {
3309         Window *w = Window::retrieveWindow(this);
3310         if (w)
3311             w->resumeTimeouts(t);
3312     }
3313 }
3314
3315 bool Frame::canCachePage()
3316 {
3317     // Only save page state if:
3318     // 1.  We're not a frame or frameset.
3319     // 2.  The page has no unload handler.
3320     // 3.  The page has no password fields.
3321     // 4.  The URL for the page is not https.
3322     // 5.  The page has no applets.
3323     if (d->m_frames.count() || d->m_objects.count() ||
3324         parentFrame() ||
3325         d->m_url.protocol().startsWith("https") || 
3326         (d->m_doc && (d->m_doc->applets()->length() != 0 ||
3327                       d->m_doc->hasWindowEventListener(unloadEvent) ||
3328                       d->m_doc->hasPasswordField()))) {
3329         return false;
3330     }
3331     return true;
3332 }
3333
3334 void Frame::saveWindowProperties(KJS::SavedProperties *windowProperties)
3335 {
3336     Window *window = Window::retrieveWindow(this);
3337     if (window)
3338         window->saveProperties(*windowProperties);
3339 }
3340
3341 void Frame::saveLocationProperties(SavedProperties *locationProperties)
3342 {
3343     Window *window = Window::retrieveWindow(this);
3344     if (window) {
3345         JSLock lock;
3346         Location *location = window->location();
3347         location->saveProperties(*locationProperties);
3348     }
3349 }
3350
3351 void Frame::restoreWindowProperties(SavedProperties *windowProperties)
3352 {
3353     Window *window = Window::retrieveWindow(this);
3354     if (window)
3355         window->restoreProperties(*windowProperties);
3356 }
3357
3358 void Frame::restoreLocationProperties(SavedProperties *locationProperties)
3359 {
3360     Window *window = Window::retrieveWindow(this);
3361     if (window) {
3362         JSLock lock;
3363         Location *location = window->location();
3364         location->restoreProperties(*locationProperties);
3365     }
3366 }
3367
3368 void Frame::saveInterpreterBuiltins(SavedBuiltins &interpreterBuiltins)
3369 {
3370     if (jScript() && jScript()->interpreter())
3371         jScript()->interpreter()->saveBuiltins(interpreterBuiltins);
3372 }
3373
3374 void Frame::restoreInterpreterBuiltins(const SavedBuiltins &interpreterBuiltins)
3375 {
3376     if (jScript() && jScript()->interpreter())
3377         jScript()->interpreter()->restoreBuiltins(interpreterBuiltins);
3378 }
3379
3380 Frame *Frame::frameForWidget(const QWidget *widget)
3381 {
3382     ASSERT_ARG(widget, widget);
3383     
3384     NodeImpl *node = nodeForWidget(widget);
3385     if (node)
3386         return frameForNode(node);
3387     
3388     // Assume all widgets are either form controls, or FrameViews.
3389     ASSERT(widget->isFrameView());
3390     return static_cast<const FrameView *>(widget)->frame();
3391 }
3392
3393 Frame *Frame::frameForNode(NodeImpl *node)
3394 {
3395     ASSERT_ARG(node, node);
3396     return node->getDocument()->frame();
3397 }
3398
3399 NodeImpl *Frame::nodeForWidget(const QWidget *widget)
3400 {
3401     ASSERT_ARG(widget, widget);
3402     const QObject *o = widget->eventFilterObject();
3403     return o ? static_cast<const RenderWidget *>(o)->element() : 0;
3404 }
3405
3406 void Frame::setDocumentFocus(QWidget *widget)
3407 {
3408     NodeImpl *node = nodeForWidget(widget);
3409     ASSERT(node);
3410     node->getDocument()->setFocusNode(node);
3411 }
3412
3413 void Frame::clearDocumentFocus(QWidget *widget)
3414 {
3415     NodeImpl *node = nodeForWidget(widget);
3416     ASSERT(node);
3417     node->getDocument()->setFocusNode(0);
3418 }
3419
3420 QPtrList<Frame> &Frame::mutableInstances()
3421 {
3422     static QPtrList<Frame> instancesList;
3423     return instancesList;
3424 }
3425
3426 void Frame::updatePolicyBaseURL()
3427 {
3428     if (parentFrame() && parentFrame()->document())
3429         setPolicyBaseURL(parentFrame()->document()->policyBaseURL());
3430     else
3431         setPolicyBaseURL(d->m_url.url());
3432 }
3433
3434 void Frame::setPolicyBaseURL(const DOMString &s)
3435 {
3436     if (document())
3437         document()->setPolicyBaseURL(s);
3438     ConstFrameIt end = d->m_frames.end();
3439     for (ConstFrameIt it = d->m_frames.begin(); it != end; ++it) {
3440         ObjectContents *subpart = (*it).m_frame.get();
3441         static_cast<Frame *>(subpart)->setPolicyBaseURL(s);
3442     }
3443 }
3444
3445 void Frame::forceLayout()
3446 {
3447     FrameView *v = d->m_view;
3448     if (v) {
3449         v->layout();
3450         // We cannot unschedule a pending relayout, since the force can be called with
3451         // a tiny rectangle from a drawRect update.  By unscheduling we in effect
3452         // "validate" and stop the necessary full repaint from occurring.  Basically any basic
3453         // append/remove DHTML is broken by this call.  For now, I have removed the optimization
3454         // until we have a better invalidation stategy. -dwh
3455         //v->unscheduleRelayout();
3456     }
3457 }
3458
3459 void Frame::forceLayoutWithPageWidthRange(float minPageWidth, float maxPageWidth)
3460 {
3461     // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
3462     // the state of things before and after the layout
3463     RenderCanvas *root = static_cast<RenderCanvas *>(document()->renderer());
3464     if (root) {
3465         // This magic is basically copied from khtmlview::print
3466         int pageW = (int)ceil(minPageWidth);
3467         root->setWidth(pageW);
3468         root->setNeedsLayoutAndMinMaxRecalc();
3469         forceLayout();
3470         
3471         // If we don't fit in the minimum page width, we'll lay out again. If we don't fit in the
3472         // maximum page width, we will lay out to the maximum page width and clip extra content.
3473         // FIXME: We are assuming a shrink-to-fit printing implementation.  A cropping
3474         // implementation should not do this!
3475         int rightmostPos = root->rightmostPosition();
3476         if (rightmostPos > minPageWidth) {
3477             pageW = kMin(rightmostPos, (int)ceil(maxPageWidth));
3478             root->setWidth(pageW);
3479             root->setNeedsLayoutAndMinMaxRecalc();
3480             forceLayout();
3481         }
3482     }
3483 }
3484
3485 void Frame::sendResizeEvent()
3486 {
3487     FrameView *v = d->m_view;
3488     if (v) {
3489         QResizeEvent e;
3490         v->resizeEvent(&e);
3491     }
3492 }
3493
3494 void Frame::sendScrollEvent()
3495 {
3496     FrameView *v = d->m_view;
3497     if (v) {
3498         DocumentImpl *doc = document();
3499         if (!doc)
3500             return;
3501         doc->dispatchHTMLEvent(scrollEvent, true, false);
3502     }
3503 }
3504
3505 bool Frame::scrollbarsVisible()
3506 {
3507     if (!view())
3508         return false;
3509     
3510     if (view()->hScrollBarMode() == QScrollView::AlwaysOff || view()->vScrollBarMode() == QScrollView::AlwaysOff)
3511         return false;
3512     
3513     return true;
3514 }
3515
3516 void Frame::addMetaData(const QString &key, const QString &value)
3517 {
3518     d->m_job->addMetaData(key, value);
3519 }
3520
3521 // This does the same kind of work that Frame::openURL does, except it relies on the fact
3522 // that a higher level already checked that the URLs match and the scrolling is the right thing to do.
3523 void Frame::scrollToAnchor(const KURL &URL)
3524 {
3525     d->m_url = URL;
3526     started(0);
3527     
3528     gotoAnchor();
3529     
3530     // It's important to model this as a load that starts and immediately finishes.
3531     // Otherwise, the parent frame may think we never finished loading.
3532     d->m_bComplete = false;
3533     checkCompleted();
3534 }
3535
3536 bool Frame::closeURL()
3537 {
3538     saveDocumentState();
3539     stopLoading(true);
3540     return true;
3541 }
3542
3543 bool Frame::canMouseDownStartSelect(NodeImpl* node)
3544 {
3545     if (!node || !node->renderer())
3546         return true;
3547     
3548     // Check to see if khtml-user-select has been set to none
3549     if (!node->renderer()->canSelect())
3550         return false;
3551     
3552     // Some controls and images can't start a select on a mouse down.
3553     for (RenderObject* curr = node->renderer(); curr; curr = curr->parent()) {
3554         if (curr->style()->userSelect() == SELECT_IGNORE)
3555             return false;
3556     }
3557     
3558     return true;
3559 }
3560
3561 void Frame::khtmlMouseDoubleClickEvent(MouseDoubleClickEvent *event)
3562 {
3563     passWidgetMouseDownEventToWidget(event, true);
3564 }
3565
3566 bool Frame::passWidgetMouseDownEventToWidget(MouseEvent *event, bool isDoubleClick)
3567 {
3568     // Figure out which view to send the event to.
3569     RenderObject *target = event->innerNode() ? event->innerNode()->renderer() : 0;
3570     if (!target)
3571         return false;
3572     
3573     QWidget* widget = RenderLayer::gScrollBar;
3574     if (!widget) {
3575         if (!target->isWidget())
3576             return false;
3577         widget = static_cast<RenderWidget *>(target)->widget();
3578     }
3579     
3580     // Doubleclick events don't exist in Cocoa.  Since passWidgetMouseDownEventToWidget will
3581     // just pass _currentEvent down to the widget,  we don't want to call it for events that
3582     // don't correspond to Cocoa events.  The mousedown/ups will have already been passed on as
3583     // part of the pressed/released handling.
3584     if (!isDoubleClick)
3585         return passMouseDownEventToWidget(widget);
3586     return true;
3587 }
3588
3589 bool Frame::passWidgetMouseDownEventToWidget(RenderWidget *renderWidget)
3590 {
3591     return passMouseDownEventToWidget(renderWidget->widget());
3592 }
3593
3594 void Frame::clearTimers(FrameView *view)
3595 {
3596     if (view) {
3597         view->unscheduleRelayout();
3598         if (view->frame()) {
3599             DocumentImpl* document = view->frame()->document();
3600             if (document && document->renderer() && document->renderer()->layer())
3601                 document->renderer()->layer()->suspendMarquees();
3602         }
3603     }
3604 }
3605
3606 void Frame::clearTimers()
3607 {
3608     clearTimers(d->m_view);
3609 }
3610
3611 // FIXME: selection controller?
3612 void Frame::centerSelectionInVisibleArea() const
3613 {
3614     IntRect rect;
3615     
3616     switch (selection().state()) {
3617         case Selection::NONE:
3618             return;
3619             
3620         case Selection::CARET:
3621             rect = selection().caretRect();
3622             break;
3623             
3624         case Selection::RANGE:
3625             rect = selectionRect();
3626             break;
3627     }
3628     
3629     Position start = selection().start();
3630     Position end = selection().end();
3631     ASSERT(start.node());
3632     if (start.node() && start.node()->renderer()) {
3633         RenderLayer *layer = start.node()->renderer()->enclosingLayer();
3634         if (layer) {
3635             ASSERT(!end.node() || !end.node()->renderer() 
3636                    || (end.node()->renderer()->enclosingLayer() == layer));
3637             layer->scrollRectToVisible(rect, RenderLayer::gAlignCenterAlways, RenderLayer::gAlignCenterAlways);
3638         }
3639     }
3640 }
3641
3642 RenderStyle *Frame::styleForSelectionStart(NodeImpl *&nodeToRemove) const
3643 {
3644     nodeToRemove = 0;
3645     
3646     if (!document())
3647         return 0;
3648     if (d->m_selection.isNone())
3649         return 0;
3650     
3651     Position pos = VisiblePosition(d->m_selection.start(), d->m_selection.affinity()).deepEquivalent();
3652     if (!pos.inRenderedContent())
3653         return 0;
3654     NodeImpl *node = pos.node();
3655     if (!node)
3656         return 0;
3657     
3658     if (!d->m_typingStyle)
3659         return node->renderer()->style();
3660     
3661     int exceptionCode = 0;
3662     ElementImpl *styleElement = document()->createElementNS(xhtmlNamespaceURI, "span", exceptionCode);
3663     ASSERT(exceptionCode == 0);
3664     
3665     styleElement->ref();
3666     
3667     styleElement->setAttribute(styleAttr, d->m_typingStyle->cssText().impl(), exceptionCode);
3668     ASSERT(exceptionCode == 0);
3669     
3670     TextImpl *text = document()->createEditingTextNode("");
3671     styleElement->appendChild(text, exceptionCode);
3672     ASSERT(exceptionCode == 0);
3673     
3674     node->parentNode()->appendChild(styleElement, exceptionCode);
3675     ASSERT(exceptionCode == 0);
3676     
3677     styleElement->deref();
3678     
3679     nodeToRemove = styleElement;    
3680     return styleElement->renderer()->style();
3681 }
3682
3683 void Frame::setMediaType(const QString &type)
3684 {
3685     if (d->m_view)
3686         d->m_view->setMediaType(type);
3687 }
3688
3689 void Frame::setSelectionFromNone()
3690 {
3691     // Put the caret someplace if the selection is empty and the part is editable.
3692     // This has the effect of flashing the caret in a contentEditable view automatically 
3693     // without requiring the programmer to set a selection explicitly.
3694     DocumentImpl *doc = document();
3695     if (doc && selection().isNone() && isContentEditable()) {
3696         NodeImpl *node = doc->documentElement();
3697         while (node) {
3698             // Look for a block flow, but skip over the HTML element, since we really
3699             // want to get at least as far as the the BODY element in a document.
3700             if (node->isBlockFlow() && node->hasTagName(htmlTag))
3701                 break;
3702             node = node->traverseNextNode();
3703         }
3704         if (node)
3705             setSelection(SelectionController(Position(node, 0), DOWNSTREAM));
3706     }
3707 }
3708
3709 bool Frame::displaysWithFocusAttributes() const
3710 {
3711     return d->m_isFocused;
3712 }
3713
3714 void Frame::setWindowHasFocus(bool flag)
3715 {
3716     if (m_windowHasFocus == flag)
3717         return;
3718     m_windowHasFocus = flag;
3719     
3720     if (DocumentImpl *doc = document())
3721         if (NodeImpl *body = doc->body())
3722             body->dispatchWindowEvent(flag ? focusEvent : blurEvent, false, false);
3723 }
3724
3725 QChar Frame::backslashAsCurrencySymbol() const
3726 {
3727     DocumentImpl *doc = document();
3728     if (!doc)
3729         return '\\';
3730     Decoder *decoder = doc->decoder();
3731     if (!decoder)
3732         return '\\';
3733     const QTextCodec *codec = decoder->codec();
3734     if (!codec)
3735         return '\\';
3736
3737     return codec->backslashAsCurrencySymbol();
3738 }
3739
3740 void Frame::setName(const QString& name)
3741 {
3742     QString n = name;
3743     
3744     Frame *parent = parentFrame();
3745     
3746     // FIXME: is the blank rule needed or useful?
3747     if (parent && (name.isEmpty() || parent->frameExists(name) || name == "_blank"))
3748         n = parent->requestFrameName();
3749     
3750     d->m_name = name;
3751 }
3752
3753 const QString& Frame::name()
3754 {
3755     return d->m_name;
3756 }
3757
3758 void Frame::setParent(Frame* parent) 
3759
3760     d->m_parent = parent; 
3761 }
3762
3763 Frame* Frame::parent() const 
3764
3765     return d->m_parent; 
3766 }
3767
3768 bool Frame::markedTextUsesUnderlines() const
3769 {
3770     return m_markedTextUsesUnderlines;
3771 }
3772
3773 QValueList<MarkedTextUnderline> Frame::markedTextUnderlines() const
3774 {
3775     return m_markedTextUnderlines;
3776 }
3777
3778 void Frame::prepareForUserAction()
3779 {
3780     // Reset the multiple form submission protection code.
3781     // We'll let you submit the same form twice if you do two separate user actions.
3782     _submittedFormURL = KURL();
3783 }
3784
3785 bool Frame::isFrame() const
3786 {
3787     return true;
3788 }
3789
3790 NodeImpl *Frame::mousePressNode()
3791 {
3792     return d->m_mousePressNode.get();
3793 }
3794
3795 bool Frame::isComplete()
3796 {
3797     return d->m_bComplete;
3798 }
3799
3800 FrameTreeNode *Frame::treeNode()
3801 {
3802     return &d->m_treeNode;
3803 }
3804
3805 void Frame::detachFromView()
3806 {
3807 }
3808
3809 KURL Frame::url() const
3810 {
3811     return d->m_url;
3812 }
3813
3814 void Frame::startRedirectionTimer()
3815 {
3816     d->m_redirectionTimer.startOneShot(d->m_delayRedirect);
3817 }
3818
3819 void Frame::stopRedirectionTimer()
3820 {
3821     d->m_redirectionTimer.stop();
3822 }
3823
3824 }