Reviewed by Chris Blumenberg.
[WebKit-https.git] / WebCore / khtml / khtml_part.cpp
1 // -*- c-basic-offset: 2 -*-
2 /* This file is part of the KDE project
3  *
4  * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
5  *                     1999 Lars Knoll <knoll@kde.org>
6  *                     1999 Antti Koivisto <koivisto@kde.org>
7  *                     2000 Simon Hausmann <hausmann@kde.org>
8  *                     2000 Stefan Schimanski <1Stein@gmx.de>
9  *                     2001 George Staikos <staikos@kde.org>
10  * Copyright (C) 2004 Apple Computer, Inc.
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 "khtml_part.h"
29
30 #if APPLE_CHANGES
31 #define DIRECT_LINKAGE_TO_ECMA
32 #define QT_NO_CLIPBOARD
33 #define QT_NO_DRAGANDDROP
34 #endif
35
36 #include "khtml_pagecache.h"
37
38 #include "css/csshelper.h"
39 #include "css/cssproperties.h"
40 #include "css/cssstyleselector.h"
41 #include "css/css_computedstyle.h"
42 #include "css/css_valueimpl.h"
43 #include "dom/dom_string.h"
44 #include "dom/dom_element.h"
45 #include "dom/html_document.h"
46 #include "editing/markup.h"
47 #include "editing/selection.h"
48 #include "editing/visible_position.h"
49 #include "editing/visible_text.h"
50 #include "editing/visible_units.h"
51 #include "html/html_documentimpl.h"
52 #include "html/html_baseimpl.h"
53 #include "html/html_miscimpl.h"
54 #include "html/html_imageimpl.h"
55 #include "html/html_objectimpl.h"
56 #include "rendering/render_block.h"
57 #include "rendering/render_text.h"
58 #include "rendering/render_frames.h"
59 #include "misc/htmlhashes.h"
60 #include "misc/loader.h"
61 #include "xml/dom2_eventsimpl.h"
62 #include "xml/dom2_rangeimpl.h"
63 #include "xml/xml_tokenizer.h"
64
65 using namespace DOM;
66
67 #include "khtmlview.h"
68 #include <kparts/partmanager.h>
69 #include "ecma/kjs_proxy.h"
70 #include "khtml_settings.h"
71
72 #include <sys/types.h>
73 #include <assert.h>
74 #include <unistd.h>
75
76 #include <kstandarddirs.h>
77 #include <kio/job.h>
78 #include <kio/global.h>
79 #include <kdebug.h>
80 #include <kiconloader.h>
81 #include <klocale.h>
82 #include <kcharsets.h>
83 #include <kmessagebox.h>
84 #include <kstdaction.h>
85 #include <kfiledialog.h>
86 #include <ktrader.h>
87 #include <kdatastream.h>
88 #include <ktempfile.h>
89 #include <kglobalsettings.h>
90 #include <kurldrag.h>
91 #include <kapplication.h>
92 #if !defined(QT_NO_DRAGANDDROP)
93 #include <kmultipledrag.h>
94 #endif
95
96 #include <ksslcertchain.h>
97 #include <ksslinfodlg.h>
98
99 #include <qclipboard.h>
100 #include <qfile.h>
101 #include <qmetaobject.h>
102 #include <qptrlist.h>
103 #include <private/qucomextra_p.h>
104
105 #include "khtmlpart_p.h"
106
107 #if APPLE_CHANGES
108 #include <CoreServices/CoreServices.h>
109 #endif
110
111 using khtml::ApplyStyleCommand;
112 using khtml::CHARACTER;
113 using khtml::ChildFrame;
114 using khtml::Decoder;
115 using khtml::EAffinity;
116 using khtml::EditAction;
117 using khtml::EditCommandPtr;
118 using khtml::ETextGranularity;
119 using khtml::FormData;
120 using khtml::InlineTextBox;
121 using khtml::isEndOfDocument;
122 using khtml::isStartOfDocument;
123 using khtml::PARAGRAPH;
124 using khtml::plainText;
125 using khtml::RenderObject;
126 using khtml::RenderText;
127 using khtml::RenderWidget;
128 using khtml::Selection;
129 using khtml::Tokenizer;
130 using khtml::TypingCommand;
131 using khtml::VisiblePosition;
132 using khtml::WORD;
133
134 using KParts::BrowserInterface;
135
136 const int CARET_BLINK_FREQUENCY = 500;
137
138 namespace khtml {
139     class PartStyleSheetLoader : public CachedObjectClient
140     {
141     public:
142         PartStyleSheetLoader(KHTMLPart *part, DOM::DOMString url, DocLoader* dl)
143         {
144             m_part = part;
145             m_cachedSheet = Cache::requestStyleSheet(dl, url );
146             if (m_cachedSheet)
147                 m_cachedSheet->ref( this );
148         }
149         virtual ~PartStyleSheetLoader()
150         {
151             if ( m_cachedSheet ) m_cachedSheet->deref(this);
152         }
153         virtual void setStyleSheet(const DOM::DOMString&, const DOM::DOMString &sheet)
154         {
155           if ( m_part )
156             m_part->setUserStyleSheet( sheet.string() );
157
158             delete this;
159         }
160         QGuardedPtr<KHTMLPart> m_part;
161         khtml::CachedCSSStyleSheet *m_cachedSheet;
162     };
163 }
164
165 FrameList::Iterator FrameList::find( const QString &name )
166 {
167     Iterator it = begin();
168     Iterator e = end();
169
170     for (; it!=e; ++it )
171         if ( (*it).m_name==name )
172             break;
173
174     return it;
175 }
176
177 KHTMLPart::KHTMLPart( QWidget *parentWidget, const char *widgetname, QObject *parent, const char *name,
178                       GUIProfile prof )
179 : KParts::ReadOnlyPart( parent, name )
180 {
181     d = 0;
182     KHTMLFactory::registerPart( this );
183     setInstance( KHTMLFactory::instance(), prof == BrowserViewGUI && !parentPart() );
184 #if !APPLE_CHANGES
185     init( new KHTMLView( this, parentWidget, widgetname ), prof );
186 #endif
187 }
188
189 #if !APPLE_CHANGES
190
191 KHTMLPart::KHTMLPart( KHTMLView *view, QObject *parent, const char *name, GUIProfile prof )
192 : KParts::ReadOnlyPart( parent, name )
193 {
194     d = 0;
195     KHTMLFactory::registerPart( this );
196     setInstance( KHTMLFactory::instance(), prof == BrowserViewGUI && !parentPart() );
197     assert( view );
198     init( view, prof );
199 }
200
201 #endif // APPLE_CHANGES
202
203 void KHTMLPart::init( KHTMLView *view, GUIProfile prof )
204 {
205   AtomicString::init();
206   if ( prof == DefaultGUI )
207     setXMLFile( "khtml.rc" );
208   else if ( prof == BrowserViewGUI )
209     setXMLFile( "khtml_browser.rc" );
210
211   frameCount = 0;
212
213   d = new KHTMLPartPrivate(parent());
214
215   d->m_view = view;
216   setWidget( d->m_view );
217   
218 #if !APPLE_CHANGES
219   d->m_guiProfile = prof;
220 #endif
221   d->m_extension = new KHTMLPartBrowserExtension( this );
222   d->m_hostExtension = new KHTMLPartBrowserHostExtension( this );
223
224   d->m_bSecurityInQuestion = false;
225   d->m_bMousePressed = false;
226 #if !APPLE_CHANGES
227   d->m_paLoadImages = 0;
228   d->m_paViewDocument = new KAction( i18n( "View Document Source" ), 0, this, SLOT( slotViewDocumentSource() ), actionCollection(), "viewDocumentSource" );
229   d->m_paViewFrame = new KAction( i18n( "View Frame Source" ), 0, this, SLOT( slotViewFrameSource() ), actionCollection(), "viewFrameSource" );
230   d->m_paSaveBackground = new KAction( i18n( "Save &Background Image As..." ), 0, this, SLOT( slotSaveBackground() ), actionCollection(), "saveBackground" );
231   d->m_paSaveDocument = new KAction( i18n( "&Save As..." ), CTRL+Key_S, this, SLOT( slotSaveDocument() ), actionCollection(), "saveDocument" );
232   if ( parentPart() )
233       d->m_paSaveDocument->setShortcut( KShortcut() ); // avoid clashes
234   d->m_paSaveFrame = new KAction( i18n( "Save &Frame As..." ), 0, this, SLOT( slotSaveFrame() ), actionCollection(), "saveFrame" );
235   d->m_paSecurity = new KAction( i18n( "Security..." ), "decrypted", 0, this, SLOT( slotSecurity() ), actionCollection(), "security" );
236   d->m_paDebugRenderTree = new KAction( "print rendering tree to stdout", 0, this, SLOT( slotDebugRenderTree() ), actionCollection(), "debugRenderTree" );
237   d->m_paDebugDOMTree = new KAction( "print DOM tree to stdout", 0, this, SLOT( slotDebugDOMTree() ), actionCollection(), "debugDOMTree" );
238
239   QString foo1 = i18n("Show Images");
240   QString foo2 = i18n("Show Animated Images");
241   QString foo3 = i18n("Stop Animated Images");
242
243   d->m_paSetEncoding = new KSelectAction( i18n( "Set &Encoding" ), 0, this, SLOT( slotSetEncoding() ), actionCollection(), "setEncoding" );
244   QStringList encodings = KGlobal::charsets()->descriptiveEncodingNames();
245   encodings.prepend( i18n( "Auto" ) );
246   d->m_paSetEncoding->setItems( encodings );
247   d->m_paSetEncoding->setCurrentItem(0);
248
249   d->m_paUseStylesheet = new KSelectAction( i18n( "&Use Stylesheet"), 0, this, SLOT( slotUseStylesheet() ), actionCollection(), "useStylesheet" );
250
251   d->m_paIncZoomFactor = new KHTMLZoomFactorAction( this, true, i18n( "Increase Font Sizes" ), "viewmag+", this, SLOT( slotIncZoom() ), actionCollection(), "incFontSizes" );
252   d->m_paDecZoomFactor = new KHTMLZoomFactorAction( this, false, i18n( "Decrease Font Sizes" ), "viewmag-", this, SLOT( slotDecZoom() ), actionCollection(), "decFontSizes" );
253
254   d->m_paFind = KStdAction::find( this, SLOT( slotFind() ), actionCollection(), "find" );
255   if ( parentPart() )
256       d->m_paFind->setShortcut( KShortcut() ); // avoid clashes
257
258   d->m_paPrintFrame = new KAction( i18n( "Print Frame" ), "frameprint", 0, this, SLOT( slotPrintFrame() ), actionCollection(), "printFrame" );
259
260   d->m_paSelectAll = KStdAction::selectAll( this, SLOT( slotSelectAll() ), actionCollection(), "selectAll" );
261   if ( parentPart() )
262       d->m_paSelectAll->setShortcut( KShortcut() ); // avoid clashes
263 #endif
264
265 #if !APPLE_CHANGES
266   // set the default java(script) flags according to the current host.
267   d->m_bJScriptEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaScriptEnabled();
268   d->m_bJScriptDebugEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaScriptDebugEnabled();
269   d->m_bJavaEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaEnabled();
270   d->m_bPluginsEnabled = KHTMLFactory::defaultHTMLSettings()->isPluginsEnabled();
271 #else
272   // The java, javascript, and plugin settings will be set after the settings
273   // have been initialized.
274   d->m_bJScriptEnabled = true;
275   d->m_bJScriptDebugEnabled = true;
276   d->m_bJavaEnabled = true;
277   d->m_bPluginsEnabled = true;
278 #endif
279
280 #if !APPLE_CHANGES
281   connect( this, SIGNAL( completed() ),
282            this, SLOT( updateActions() ) );
283   connect( this, SIGNAL( completed( bool ) ),
284            this, SLOT( updateActions() ) );
285   connect( this, SIGNAL( started( KIO::Job * ) ),
286            this, SLOT( updateActions() ) );
287
288   d->m_popupMenuXML = KXMLGUIFactory::readConfigFile( locate( "data", "khtml/khtml_popupmenu.rc", KHTMLFactory::instance() ) );
289 #endif
290
291   connect( khtml::Cache::loader(), SIGNAL( requestStarted( khtml::DocLoader*, khtml::CachedObject* ) ),
292            this, SLOT( slotLoaderRequestStarted( khtml::DocLoader*, khtml::CachedObject* ) ) );
293   connect( khtml::Cache::loader(), SIGNAL( requestDone( khtml::DocLoader*, khtml::CachedObject *) ),
294            this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
295   connect( khtml::Cache::loader(), SIGNAL( requestFailed( khtml::DocLoader*, khtml::CachedObject *) ),
296            this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
297
298 #if !APPLE_CHANGES
299   findTextBegin(); //reset find variables
300 #endif
301
302   connect( &d->m_redirectionTimer, SIGNAL( timeout() ),
303            this, SLOT( slotRedirect() ) );
304
305   connect(&d->m_lifeSupportTimer, SIGNAL(timeout()), this, SLOT(slotEndLifeSupport()));
306
307 #if !APPLE_CHANGES
308   d->m_dcopobject = new KHTMLPartIface(this);
309 #endif
310 }
311
312 KHTMLPart::~KHTMLPart()
313 {
314   //kdDebug(6050) << "KHTMLPart::~KHTMLPart " << this << endl;
315 #if !APPLE_CHANGES
316   if ( d->m_findDialog )
317       disconnect( d->m_findDialog, SIGNAL( destroyed() ),
318                   this, SLOT( slotFindDialogDestroyed() ) );
319
320   if ( d->m_manager )
321   {
322     d->m_manager->setActivePart( 0 );
323     // Shouldn't we delete d->m_manager here ? (David)
324     // No need to, I would say. We specify "this" as parent qobject
325     // in ::partManager() (Simon)
326   }
327 #endif
328
329   stopAutoScroll();
330   cancelRedirection();
331
332   if (!d->m_bComplete)
333     closeURL();
334
335   disconnect( khtml::Cache::loader(), SIGNAL( requestStarted( khtml::DocLoader*, khtml::CachedObject* ) ),
336            this, SLOT( slotLoaderRequestStarted( khtml::DocLoader*, khtml::CachedObject* ) ) );
337   disconnect( khtml::Cache::loader(), SIGNAL( requestDone( khtml::DocLoader*, khtml::CachedObject *) ),
338            this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
339   disconnect( khtml::Cache::loader(), SIGNAL( requestFailed( khtml::DocLoader*, khtml::CachedObject *) ),
340            this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
341
342   clear();
343
344   if ( d->m_view )
345   {
346     d->m_view->hide();
347     d->m_view->viewport()->hide();
348     d->m_view->m_part = 0;
349   }
350   
351 #if APPLE_CHANGES
352   delete d->m_hostExtension;
353 #endif
354
355   delete d; d = 0;
356   KHTMLFactory::deregisterPart( this );
357 }
358
359 bool KHTMLPart::restoreURL( const KURL &url )
360 {
361   kdDebug( 6050 ) << "KHTMLPart::restoreURL " << url.url() << endl;
362
363   cancelRedirection();
364
365   /*
366    * That's not a good idea as it will call closeURL() on all
367    * child frames, preventing them from further loading. This
368    * method gets called from restoreState() in case of a full frameset
369    * restoral, and restoreState() calls closeURL() before restoring
370    * anyway.
371   kdDebug( 6050 ) << "closing old URL" << endl;
372   closeURL();
373   */
374
375   d->m_bComplete = false;
376   d->m_bLoadEventEmitted = false;
377   d->m_workingURL = url;
378
379   // set the java(script) flags according to the current host.
380 #if !APPLE_CHANGES
381   d->m_bJScriptEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaScriptEnabled(url.host());
382   d->m_bJScriptDebugEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaScriptDebugEnabled();
383   d->m_bJavaEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaEnabled(url.host());
384   d->m_bPluginsEnabled = KHTMLFactory::defaultHTMLSettings()->isPluginsEnabled(url.host());
385 #else
386   d->m_bJScriptEnabled = d->m_settings->isJavaScriptEnabled(url.host());
387   d->m_bJScriptDebugEnabled = d->m_settings->isJavaScriptDebugEnabled();
388   d->m_bJavaEnabled = d->m_settings->isJavaEnabled(url.host());
389   d->m_bPluginsEnabled = d->m_settings->isPluginsEnabled(url.host());
390 #endif
391
392   m_url = url;
393
394   KHTMLPageCache::self()->fetchData( d->m_cacheId, this, SLOT(slotRestoreData(const QByteArray &)));
395
396   emit started( 0L );
397
398   return true;
399 }
400
401
402 #if APPLE_CHANGES
403 bool KHTMLPart::didOpenURL(const KURL &url)
404 #else
405 bool KHTMLPart::openURL( const KURL &url )
406 #endif
407 {
408   kdDebug( 6050 ) << "KHTMLPart(" << this << ")::openURL " << url.url() << endl;
409
410   if (d->m_scheduledRedirection == locationChangeScheduledDuringLoad) {
411     // We're about to get a redirect that happened before the document was
412     // created.  This can happen when one frame may change the location of a 
413     // sibling.
414     return false;
415   }
416   
417   cancelRedirection();
418   
419   // clear last edit command
420   d->m_lastEditCommand = EditCommandPtr();
421 #if APPLE_CHANGES
422   KWQ(this)->clearUndoRedoOperations();
423 #endif
424   
425 #if !APPLE_CHANGES
426   // check to see if this is an "error://" URL. This is caused when an error
427   // occurs before this part was loaded (e.g. KonqRun), and is passed to
428   // khtmlpart so that it can display the error.
429   if ( url.protocol() == "error" && url.hasSubURL() ) {
430     closeURL();
431     /**
432      * The format of the error url is that two variables are passed in the query:
433      * error = int kio error code, errText = QString error text from kio
434      * and the URL where the error happened is passed as a sub URL.
435      */
436     KURL::List urls = KURL::split( url );
437     //kdDebug() << "Handling error URL. URL count:" << urls.count() << endl;
438
439     if ( urls.count() > 1 ) {
440       KURL mainURL = urls.first();
441       int error = mainURL.queryItem( "error" ).toInt();
442       // error=0 isn't a valid error code, so 0 means it's missing from the URL
443       if ( error == 0 ) error = KIO::ERR_UNKNOWN;
444       QString errorText = mainURL.queryItem( "errText" );
445       urls.pop_front();
446       d->m_workingURL = KURL::join( urls );
447       //kdDebug() << "Emitting fixed URL " << d->m_workingURL.prettyURL() << endl;
448       emit d->m_extension->setLocationBarURL( d->m_workingURL.prettyURL() );
449       htmlError( error, errorText, d->m_workingURL );
450       return true;
451     }
452   }
453 #endif // APPLE_CHANGES
454
455   KParts::URLArgs args( d->m_extension->urlArgs() );
456
457 #if !APPLE_CHANGES
458   // in case we have a) no frameset (don't test m_frames.count(), iframes get in there)
459   // b) the url is identical with the currently
460   // displayed one (except for the htmlref!) , c) the url request is not a POST
461   // operation and d) the caller did not request to reload the page we try to
462   // be smart and instead of reloading the whole document we just jump to the
463   // request html anchor
464   if (d->m_doc) {
465       bool isFrameSet = false;
466       if ( d->m_doc->isHTMLDocument() ) {
467           HTMLDocumentImpl* htmlDoc = static_cast<HTMLDocumentImpl*>(d->m_doc);
468           isFrameSet = htmlDoc->body() && (htmlDoc->body()->id() == ID_FRAMESET);
469       }
470       if ( !isFrameSet &&
471            urlcmp( url.url(), m_url.url(), true, true ) &&
472            url.hasRef() && !args.doPost() && !args.reload )
473       {
474         kdDebug( 6050 ) << "KHTMLPart::openURL, jumping to anchor. m_url = " << url.url() << endl;
475         m_url = url;
476         emit started( 0L );
477
478         gotoAnchor();
479
480         d->m_bComplete = true;
481         d->m_doc->setParsing(false);
482
483         kdDebug( 6050 ) << "completed..." << endl;
484         emit completed();
485         return true;
486       }
487   }
488 #endif // APPLE_CHANGES
489
490   if (!d->m_restored)
491   {
492     kdDebug( 6050 ) << "closing old URL" << endl;
493     closeURL();
494   }
495
496 #if !APPLE_CHANGES
497   args.metaData().insert("main_frame_request", parentPart() == 0 ? "TRUE" : "FALSE" );
498   args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE" : "FALSE" );
499   args.metaData().insert("ssl_activate_warnings", "TRUE" );
500 #endif
501
502   if (d->m_restored)
503      d->m_cachePolicy = KIO::CC_Cache;
504   else if (args.reload)
505      d->m_cachePolicy = KIO::CC_Refresh;
506   else
507      d->m_cachePolicy = KIO::CC_Verify;
508
509   if ( args.doPost() && (url.protocol().startsWith("http")) )
510   {
511       d->m_job = KIO::http_post( url, args.postData, false );
512       d->m_job->addMetaData("content-type", args.contentType() );
513   }
514   else
515   {
516       d->m_job = KIO::get( url, false, false );
517       d->m_job->addMetaData("cache", KIO::getCacheControlString(d->m_cachePolicy));
518   }
519
520   d->m_job->addMetaData(args.metaData());
521
522   connect( d->m_job, SIGNAL( result( KIO::Job * ) ),
523            SLOT( slotFinished( KIO::Job * ) ) );
524 #if !APPLE_CHANGES
525   connect( d->m_job, SIGNAL( data( KIO::Job*, const QByteArray &)),
526            SLOT( slotData( KIO::Job*, const QByteArray &)));
527 #endif
528
529   connect( d->m_job, SIGNAL(redirection(KIO::Job*, const KURL&) ),
530            SLOT( slotRedirection(KIO::Job*,const KURL&) ) );
531
532   d->m_bComplete = false;
533   d->m_bLoadingMainResource = true;
534   d->m_bLoadEventEmitted = false;
535
536   // delete old status bar msg's from kjs (if it _was_ activated on last URL)
537   if( d->m_bJScriptEnabled )
538   {
539      d->m_kjsStatusBarText = QString::null;
540      d->m_kjsDefaultStatusBarText = QString::null;
541   }
542
543   // set the javascript flags according to the current url
544 #if !APPLE_CHANGES
545   d->m_bJScriptDebugEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaScriptDebugEnabled();
546   d->m_bJavaEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaEnabled(url.host());
547   d->m_bPluginsEnabled = KHTMLFactory::defaultHTMLSettings()->isPluginsEnabled(url.host());
548 #else
549   d->m_bJScriptDebugEnabled = d->m_settings->isJavaScriptDebugEnabled();
550   d->m_bJavaEnabled = d->m_settings->isJavaEnabled(url.host());
551   d->m_bPluginsEnabled = d->m_settings->isPluginsEnabled(url.host());
552 #endif
553
554   // initializing 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
555   // data arrives) (Simon)
556   m_url = url;
557   if(m_url.protocol().startsWith( "http" ) && !m_url.host().isEmpty() &&
558      m_url.path().isEmpty()) {
559     m_url.setPath("/");
560     emit d->m_extension->setLocationBarURL( m_url.prettyURL() );
561   }
562   // copy to m_workingURL after fixing m_url above
563   d->m_workingURL = m_url;
564
565   kdDebug( 6050 ) << "KHTMLPart::openURL now (before started) m_url = " << m_url.url() << endl;
566
567   connect( d->m_job, SIGNAL( speed( KIO::Job*, unsigned long ) ),
568            this, SLOT( slotJobSpeed( KIO::Job*, unsigned long ) ) );
569
570   connect( d->m_job, SIGNAL( percent( KIO::Job*, unsigned long ) ),
571            this, SLOT( slotJobPercent( KIO::Job*, unsigned long ) ) );
572
573   emit started( 0L );
574
575   return true;
576 }
577
578 void KHTMLPart::didExplicitOpen()
579 {
580   d->m_bComplete = false;
581   d->m_bLoadEventEmitted = false;
582 }
583
584
585 bool KHTMLPart::closeURL()
586 {    
587     if (d->m_doc && d->m_doc->tokenizer()) {
588         d->m_doc->tokenizer()->stopParsing();
589     }
590     
591   if ( d->m_job )
592   {
593     KHTMLPageCache::self()->cancelEntry(d->m_cacheId);
594     d->m_job->kill();
595     d->m_job = 0;
596   }
597
598   if ( d->m_doc && d->m_doc->isHTMLDocument() ) {
599     HTMLDocumentImpl* hdoc = static_cast<HTMLDocumentImpl*>( d->m_doc );
600
601     if ( hdoc->body() && d->m_bLoadEventEmitted && !d->m_bUnloadEventEmitted ) {
602       hdoc->body()->dispatchWindowEvent( EventImpl::UNLOAD_EVENT, false, false );
603       if ( d->m_doc )
604         d->m_doc->updateRendering();
605       d->m_bUnloadEventEmitted = true;
606     }
607   }
608     
609   d->m_bComplete = true; // to avoid emitting completed() in slotFinishedParsing() (David)
610   d->m_bLoadingMainResource = false;
611   d->m_bLoadEventEmitted = true; // don't want that one either
612   d->m_cachePolicy = KIO::CC_Verify; // Why here?
613
614   KHTMLPageCache::self()->cancelFetch(this);
615   if ( d->m_doc && d->m_doc->parsing() )
616   {
617     kdDebug( 6050 ) << " was still parsing... calling end " << endl;
618     slotFinishedParsing();
619     d->m_doc->setParsing(false);
620   }
621
622   if ( !d->m_workingURL.isEmpty() )
623   {
624     // Aborted before starting to render
625     kdDebug( 6050 ) << "Aborted before starting to render, reverting location bar to " << m_url.prettyURL() << endl;
626     emit d->m_extension->setLocationBarURL( m_url.prettyURL() );
627   }
628
629   d->m_workingURL = KURL();
630
631   if ( d->m_doc && d->m_doc->docLoader() )
632     khtml::Cache::loader()->cancelRequests( d->m_doc->docLoader() );
633
634   // tell all subframes to stop as well
635   ConstFrameIt it = d->m_frames.begin();
636   ConstFrameIt end = d->m_frames.end();
637   for (; it != end; ++it )
638     if ( !( *it ).m_part.isNull() )
639       ( *it ).m_part->closeURL();
640
641   d->m_bPendingChildRedirection = false;
642
643   // Stop any started redirections as well!! (DA)
644   cancelRedirection();
645
646 #if !KHTML_NO_CPLUSPLUS_DOM
647   // null node activated.
648   emit nodeActivated(Node());
649 #endif
650
651   return true;
652 }
653
654 #if !KHTML_NO_CPLUSPLUS_DOM
655
656 DOM::HTMLDocument KHTMLPart::htmlDocument() const
657 {
658   if (d->m_doc && d->m_doc->isHTMLDocument())
659     return static_cast<HTMLDocumentImpl*>(d->m_doc);
660   else
661     return static_cast<HTMLDocumentImpl*>(0);
662 }
663
664 DOM::Document KHTMLPart::document() const
665 {
666     return d->m_doc;
667 }
668
669 #endif
670
671 KParts::BrowserExtension *KHTMLPart::browserExtension() const
672 {
673   return d->m_extension;
674 }
675
676 KHTMLView *KHTMLPart::view() const
677 {
678   return d->m_view;
679 }
680
681 void KHTMLPart::setJScriptEnabled( bool enable )
682 {
683   if ( !enable && jScriptEnabled() && d->m_jscript ) {
684     d->m_jscript->clear();
685   }
686   d->m_bJScriptForce = enable;
687   d->m_bJScriptOverride = true;
688 }
689
690 bool KHTMLPart::jScriptEnabled() const
691 {
692   if ( d->m_bJScriptOverride )
693       return d->m_bJScriptForce;
694   return d->m_bJScriptEnabled;
695 }
696
697 void KHTMLPart::setMetaRefreshEnabled( bool enable )
698 {
699   d->m_metaRefreshEnabled = enable;
700 }
701
702 bool KHTMLPart::metaRefreshEnabled() const
703 {
704   return d->m_metaRefreshEnabled;
705 }
706
707 // Define this to disable dlopening kjs_html, when directly linking to it.
708 // You need to edit khtml/Makefile.am to add ./ecma/libkjs_html.la to LIBADD
709 // and to edit khtml/ecma/Makefile.am to s/kjs_html/libkjs_html/, remove libkhtml from LIBADD,
710 //        remove LDFLAGS line, and replace kde_module with either lib (shared) or noinst (static)
711 //#define DIRECT_LINKAGE_TO_ECMA
712
713 #ifdef DIRECT_LINKAGE_TO_ECMA
714 extern "C" { KJSProxy *kjs_html_init(KHTMLPart *khtmlpart); }
715 #endif
716
717 KJSProxy *KHTMLPart::jScript()
718 {
719   if (!jScriptEnabled()){
720     return 0;
721   }
722
723   if ( !d->m_jscript )
724   {
725 #ifndef DIRECT_LINKAGE_TO_ECMA
726     KLibrary *lib = KLibLoader::self()->library("kjs_html");
727     if ( !lib ) {
728       setJScriptEnabled( false );
729       return 0;
730     }
731     // look for plain C init function
732     void *sym = lib->symbol("kjs_html_init");
733     if ( !sym ) {
734       lib->unload();
735       setJScriptEnabled( false );
736       return 0;
737     }
738     typedef KJSProxy* (*initFunction)(KHTMLPart *);
739     initFunction initSym = (initFunction) sym;
740     d->m_jscript = (*initSym)(this);
741     d->m_kjs_lib = lib;
742 #else
743     d->m_jscript = kjs_html_init(this);
744     // d->m_kjs_lib remains 0L.
745 #endif
746     if (d->m_bJScriptDebugEnabled)
747         d->m_jscript->setDebugEnabled(true);
748   }
749
750   return d->m_jscript;
751 }
752
753 void KHTMLPart::replaceContentsWithScriptResult( const KURL &url )
754 {
755   QString script = KURL::decode_string(url.url().mid(strlen("javascript:")));
756   QVariant ret = executeScript(script);
757   
758   if (ret.type() == QVariant::String) {
759     begin();
760     write(ret.asString());
761     end();
762   }
763 }
764
765 QVariant KHTMLPart::executeScript( const QString &script, bool forceUserGesture )
766 {
767     return executeScript( 0, script, forceUserGesture );
768 }
769
770 //Enable this to see all JS scripts being executed
771 //#define KJS_VERBOSE
772
773 #if !KHTML_NO_CPLUSPLUS_DOM
774
775 QVariant KHTMLPart::executeScript( const DOM::Node &n, const QString &script, bool forceUserGesture )
776 {
777     return executeScript(n.handle(), script, forceUserGesture);
778 }
779
780 #endif
781
782 QVariant KHTMLPart::executeScript( DOM::NodeImpl *n, const QString &script, bool forceUserGesture )
783 {
784 #ifdef KJS_VERBOSE
785   kdDebug(6070) << "KHTMLPart::executeScript n=" << n.nodeName().string().latin1() << "(" << (n.isNull() ? 0 : n.nodeType()) << ") " << script << endl;
786 #endif
787   KJSProxy *proxy = jScript();
788
789   if (!proxy || proxy->paused())
790     return QVariant();
791   d->m_runningScripts++;
792   // If forceUserGesture is true, then make the script interpreter
793   // treat it as if triggered by a user gesture even if there is no
794   // current DOM event being processed.
795   QVariant ret = proxy->evaluate( forceUserGesture ? QString::null : m_url.url(), 0, script, n );
796   d->m_runningScripts--;
797   if (!d->m_runningScripts && d->m_doc && !d->m_doc->parsing() && d->m_submitForm )
798       submitFormAgain();
799     DocumentImpl::updateDocumentsRendering();
800
801 #ifdef KJS_VERBOSE
802   kdDebug(6070) << "KHTMLPart::executeScript - done" << endl;
803 #endif
804   return ret;
805 }
806
807 bool KHTMLPart::scheduleScript(DOM::NodeImpl *n, const QString& script)
808 {
809     //kdDebug(6050) << "KHTMLPart::scheduleScript "<< script << endl;
810
811     d->scheduledScript = script;
812     d->scheduledScriptNode.reset(n);
813
814     return true;
815 }
816
817 QVariant KHTMLPart::executeScheduledScript()
818 {
819   if( d->scheduledScript.isEmpty() )
820     return QVariant();
821
822   //kdDebug(6050) << "executing delayed " << d->scheduledScript << endl;
823
824   QVariant ret = executeScript( d->scheduledScriptNode.get(), d->scheduledScript );
825   d->scheduledScript = QString();
826   d->scheduledScriptNode.reset();
827
828   return ret;
829 }
830
831 void KHTMLPart::setJavaEnabled( bool enable )
832 {
833   d->m_bJavaForce = enable;
834   d->m_bJavaOverride = true;
835 }
836
837 bool KHTMLPart::javaEnabled() const
838 {
839 #ifndef Q_WS_QWS
840   if( d->m_bJavaOverride )
841       return d->m_bJavaForce;
842   return d->m_bJavaEnabled;
843 #else
844   return false;
845 #endif
846 }
847
848 KJavaAppletContext *KHTMLPart::javaContext()
849 {
850 #ifndef Q_WS_QWS
851   return d->m_javaContext;
852 #else
853   return 0;
854 #endif
855 }
856
857 KJavaAppletContext *KHTMLPart::createJavaContext()
858 {
859 #ifndef Q_WS_QWS
860   if ( !d->m_javaContext ) {
861 #if APPLE_CHANGES
862       d->m_javaContext = new KJavaAppletContext(d->m_dcopobject, this);
863 #else
864       d->m_javaContext = new KJavaAppletContext(d->m_dcopobject);
865       connect( d->m_javaContext, SIGNAL(showStatus(const QString&)),
866                this, SIGNAL(setStatusBarText(const QString&)) );
867       connect( d->m_javaContext, SIGNAL(showDocument(const QString&, const QString&)),
868                this, SLOT(slotShowDocument(const QString&, const QString&)) );
869 #endif
870   }
871
872   return d->m_javaContext;
873 #else
874   return 0;
875 #endif
876 }
877
878 void KHTMLPart::setPluginsEnabled( bool enable )
879 {
880   d->m_bPluginsForce = enable;
881   d->m_bPluginsOverride = true;
882 }
883
884 bool KHTMLPart::pluginsEnabled() const
885 {
886   if ( d->m_bPluginsOverride )
887       return d->m_bPluginsForce;
888   return d->m_bPluginsEnabled;
889 }
890
891 #if !APPLE_CHANGES
892
893 void KHTMLPart::slotShowDocument( const QString &url, const QString &target )
894 {
895   // this is mostly copied from KHTMLPart::slotChildURLRequest. The better approach
896   // would be to put those functions into a single one.
897   khtml::ChildFrame *child = 0;
898   KParts::URLArgs args;
899   args.frameName = target;
900
901   QString frameName = args.frameName.lower();
902   if ( !frameName.isEmpty() )
903   {
904     if ( frameName == QString::fromLatin1( "_top" ) )
905     {
906       emit d->m_extension->openURLRequest( url, args );
907       return;
908     }
909     else if ( frameName == QString::fromLatin1( "_blank" ) )
910     {
911       emit d->m_extension->createNewWindow( url, args );
912       return;
913     }
914     else if ( frameName == QString::fromLatin1( "_parent" ) )
915     {
916       KParts::URLArgs newArgs( args );
917       newArgs.frameName = QString::null;
918
919       emit d->m_extension->openURLRequest( url, newArgs );
920       return;
921     }
922     else if ( frameName != QString::fromLatin1( "_self" ) )
923     {
924       khtml::ChildFrame *_frame = recursiveFrameRequest( url, args );
925
926       if ( !_frame )
927       {
928         emit d->m_extension->openURLRequest( url, args );
929         return;
930       }
931
932       child = _frame;
933     }
934   }
935
936   // TODO: handle child target correctly! currently the script are always executed fur the parent
937   if ( url.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
938       executeScript( KURL::decode_string( url.right( url.length() - 11) ) );
939       return;
940   }
941
942   if ( child ) {
943       requestObject( child, KURL(url), args );
944   }  else if ( frameName==QString::fromLatin1("_self") ) // this is for embedded objects (via <object>) which want to replace the current document
945   {
946       KParts::URLArgs newArgs( args );
947       newArgs.frameName = QString::null;
948       emit d->m_extension->openURLRequest( KURL(url), newArgs );
949   }
950 }
951
952 #endif // APPLE_CHANGES
953
954 void KHTMLPart::slotDebugDOMTree()
955 {
956   if ( d->m_doc && d->m_doc->firstChild() )
957     qDebug("%s", createMarkup(d->m_doc->firstChild()).latin1());
958 }
959
960 void KHTMLPart::slotDebugRenderTree()
961 {
962 #ifndef NDEBUG
963   if ( d->m_doc )
964     d->m_doc->renderer()->printTree();
965 #endif
966 }
967
968 void KHTMLPart::setAutoloadImages( bool enable )
969 {
970   if ( d->m_doc && d->m_doc->docLoader()->autoloadImages() == enable )
971     return;
972
973   if ( d->m_doc )
974     d->m_doc->docLoader()->setAutoloadImages( enable );
975
976 #if !APPLE_CHANGES
977   unplugActionList( "loadImages" );
978
979   if ( enable ) {
980     delete d->m_paLoadImages;
981     d->m_paLoadImages = 0;
982   }
983   else if ( !d->m_paLoadImages )
984     d->m_paLoadImages = new KAction( i18n( "Display Images on Page" ), "images_display", 0, this, SLOT( slotLoadImages() ), actionCollection(), "loadImages" );
985
986   if ( d->m_paLoadImages ) {
987     QPtrList<KAction> lst;
988     lst.append( d->m_paLoadImages );
989     plugActionList( "loadImages", lst );
990   }
991 #endif
992 }
993
994 bool KHTMLPart::autoloadImages() const
995 {
996   if ( d->m_doc )
997     return d->m_doc->docLoader()->autoloadImages();
998
999   return true;
1000 }
1001
1002 void KHTMLPart::clear()
1003 {
1004   if ( d->m_bCleared )
1005     return;
1006   d->m_bCleared = true;
1007
1008   d->m_bClearing = true;
1009
1010 #if !APPLE_CHANGES
1011   {
1012     ConstFrameIt it = d->m_frames.begin();
1013     ConstFrameIt end = d->m_frames.end();
1014     for(; it != end; ++it )
1015     {
1016       // Stop HTMLRun jobs for frames
1017       if ( (*it).m_run )
1018         (*it).m_run->abort();
1019     }
1020   }
1021
1022   {
1023     QValueList<khtml::ChildFrame>::ConstIterator it = d->m_objects.begin();
1024     QValueList<khtml::ChildFrame>::ConstIterator end = d->m_objects.end();
1025     for(; it != end; ++it )
1026     {
1027       // Stop HTMLRun jobs for objects
1028       if ( (*it).m_run )
1029         (*it).m_run->abort();
1030     }
1031   }
1032
1033
1034   findTextBegin(); // resets d->m_findNode and d->m_findPos
1035 #endif
1036
1037   d->m_mousePressNode.reset();
1038
1039
1040   if ( d->m_doc )
1041     d->m_doc->detach();
1042
1043   // Moving past doc so that onUnload works.
1044   if ( d->m_jscript )
1045     d->m_jscript->clear();
1046
1047   if ( d->m_view )
1048     d->m_view->clear();
1049
1050   // do not dereference the document before the jscript and view are cleared, as some destructors
1051   // might still try to access the document.
1052   if ( d->m_doc )
1053     d->m_doc->deref();
1054   d->m_doc = 0;
1055
1056   if (d->m_decoder)
1057     d->m_decoder->deref();
1058   d->m_decoder = 0;
1059
1060   {
1061     ConstFrameIt it = d->m_frames.begin();
1062     ConstFrameIt end = d->m_frames.end();
1063     for(; it != end; ++it )
1064     {
1065       if ( (*it).m_part )
1066       {
1067         disconnectChild(&*it);
1068 #if !APPLE_CHANGES
1069         partManager()->removePart( (*it).m_part );
1070 #endif
1071         (*it).m_part->deref();
1072       }
1073     }
1074   }
1075   d->m_frames.clear();
1076
1077   {
1078     ConstFrameIt it = d->m_objects.begin();
1079     ConstFrameIt end = d->m_objects.end();
1080     for(; it != end; ++it )
1081     {
1082       if ( (*it).m_part )
1083       {
1084 #if !APPLE_CHANGES
1085         partManager()->removePart( (*it).m_part );
1086 #endif
1087         (*it).m_part->deref();
1088       }
1089     }
1090   }
1091   d->m_objects.clear();
1092
1093 #ifndef Q_WS_QWS
1094   delete d->m_javaContext;
1095   d->m_javaContext = 0;
1096 #endif
1097
1098   d->m_scheduledRedirection = noRedirectionScheduled;
1099   d->m_delayRedirect = 0;
1100   d->m_redirectURL = QString::null;
1101   d->m_redirectReferrer = QString::null;
1102   d->m_redirectLockHistory = true;
1103   d->m_redirectUserGesture = false;
1104   d->m_bHTTPRefresh = false;
1105   d->m_bClearing = false;
1106   d->m_frameNameId = 1;
1107   d->m_bFirstData = true;
1108
1109   d->m_bMousePressed = false;
1110
1111 #ifndef QT_NO_CLIPBOARD
1112   connect( kapp->clipboard(), SIGNAL( selectionChanged()), SLOT( slotClearSelection()));
1113 #endif
1114
1115 #if !APPLE_CHANGES
1116   d->m_totalObjectCount = 0;
1117   d->m_loadedObjects = 0;
1118   d->m_jobPercent = 0;
1119 #endif
1120
1121   if ( !d->m_haveEncoding )
1122     d->m_encoding = QString::null;
1123 #ifdef SPEED_DEBUG
1124   d->m_parsetime.restart();
1125 #endif
1126 }
1127
1128 bool KHTMLPart::openFile()
1129 {
1130   return true;
1131 }
1132
1133 DOM::DocumentImpl *KHTMLPart::xmlDocImpl() const
1134 {
1135     if ( d )
1136         return d->m_doc;
1137     return 0;
1138 }
1139
1140 void KHTMLPart::replaceDocImpl(DocumentImpl* newDoc)
1141 {
1142     if (d) {
1143         if (d->m_doc) {
1144             d->m_doc->detach();
1145             d->m_doc->deref();
1146         }
1147         d->m_doc = newDoc;
1148         if (newDoc)
1149             newDoc->ref();
1150     }
1151 }
1152
1153 /*bool KHTMLPart::isSSLInUse() const
1154 {
1155   return d->m_ssl_in_use;
1156 }*/
1157
1158 void KHTMLPart::receivedFirstData()
1159 {
1160     // Leave indented one extra for easier merging.
1161     
1162       //kdDebug( 6050 ) << "begin!" << endl;
1163
1164     begin( d->m_workingURL, d->m_extension->urlArgs().xOffset, d->m_extension->urlArgs().yOffset );
1165
1166
1167     d->m_doc->docLoader()->setCachePolicy(d->m_cachePolicy);
1168     d->m_workingURL = KURL();
1169
1170     d->m_cacheId = KHTMLPageCache::self()->createCacheEntry();
1171
1172     // When the first data arrives, the metadata has just been made available
1173 #if APPLE_CHANGES
1174     QString qData;
1175 #else
1176     d->m_bSecurityInQuestion = false;
1177     d->m_ssl_in_use = (d->m_job->queryMetaData("ssl_in_use") == "TRUE");
1178     kdDebug(6050) << "SSL in use? " << d->m_job->queryMetaData("ssl_in_use") << endl;
1179
1180     {
1181     KHTMLPart *p = parentPart();
1182     if (p && p->d->m_ssl_in_use != d->m_ssl_in_use) {
1183         while (p->parentPart()) p = p->parentPart();
1184
1185         p->d->m_paSecurity->setIcon( "halfencrypted" );
1186         p->d->m_bSecurityInQuestion = true;
1187         kdDebug(6050) << "parent setIcon half done." << endl;
1188     }
1189     }
1190
1191     d->m_paSecurity->setIcon( d->m_ssl_in_use ? "encrypted" : "decrypted" );
1192     kdDebug(6050) << "setIcon " << ( d->m_ssl_in_use ? "encrypted" : "decrypted" ) << " done." << endl;
1193
1194     // Shouldn't all of this be done only if ssl_in_use == true ? (DF)
1195
1196     d->m_ssl_peer_certificate = d->m_job->queryMetaData("ssl_peer_certificate");
1197     d->m_ssl_peer_chain = d->m_job->queryMetaData("ssl_peer_chain");
1198     d->m_ssl_peer_ip = d->m_job->queryMetaData("ssl_peer_ip");
1199     d->m_ssl_cipher = d->m_job->queryMetaData("ssl_cipher");
1200     d->m_ssl_cipher_desc = d->m_job->queryMetaData("ssl_cipher_desc");
1201     d->m_ssl_cipher_version = d->m_job->queryMetaData("ssl_cipher_version");
1202     d->m_ssl_cipher_used_bits = d->m_job->queryMetaData("ssl_cipher_used_bits");
1203     d->m_ssl_cipher_bits = d->m_job->queryMetaData("ssl_cipher_bits");
1204     d->m_ssl_cert_state = d->m_job->queryMetaData("ssl_cert_state");
1205
1206     // Check for charset meta-data
1207     QString qData = d->m_job->queryMetaData("charset");
1208     if ( !qData.isEmpty() && !d->m_haveEncoding ) // only use information if the user didn't override the settings
1209        d->m_encoding = qData;
1210 #endif // APPLE_CHANGES
1211
1212     // Support for http-refresh
1213     qData = d->m_job->queryMetaData("http-refresh");
1214     if( !qData.isEmpty() && d->m_metaRefreshEnabled )
1215     {
1216       kdDebug(6050) << "HTTP Refresh Request: " << qData << endl;
1217       double delay;
1218       int pos = qData.find( ';' );
1219       if ( pos == -1 )
1220         pos = qData.find( ',' );
1221
1222       if( pos == -1 )
1223       {
1224         delay = qData.stripWhiteSpace().toDouble();
1225 #if APPLE_CHANGES
1226         // We want a new history item if the refresh timeout > 1 second
1227         scheduleRedirection( delay, m_url.url(), delay <= 1);
1228 #else
1229         scheduleRedirection( delay, m_url.url());
1230 #endif
1231       }
1232       else
1233       {
1234         int end_pos = qData.length();
1235         delay = qData.left(pos).stripWhiteSpace().toDouble();
1236         while ( qData[++pos] == ' ' );
1237         if ( qData.find( "url", pos, false ) == pos )
1238         {
1239           pos += 3;
1240           while (qData[pos] == ' ' || qData[pos] == '=' )
1241               pos++;
1242           if ( qData[pos] == '"' )
1243           {
1244               pos++;
1245               int index = end_pos-1;
1246               while( index > pos )
1247               {
1248                 if ( qData[index] == '"' )
1249                     break;
1250                 index--;
1251               }
1252               if ( index > pos )
1253                 end_pos = index;
1254           }
1255         }
1256 #if APPLE_CHANGES
1257         // We want a new history item if the refresh timeout > 1 second
1258         scheduleRedirection( delay, d->m_doc->completeURL( qData.mid( pos, end_pos ) ), delay <= 1);
1259 #else
1260         scheduleRedirection( delay, d->m_doc->completeURL( qData.mid( pos, end_pos ) ));
1261 #endif
1262       }
1263       d->m_bHTTPRefresh = true;
1264     }
1265
1266     // Support for http last-modified
1267     d->m_lastModified = d->m_job->queryMetaData("modified");
1268     //kdDebug() << "KHTMLPart::slotData metadata modified: " << d->m_lastModified << endl;
1269 }
1270
1271 #if !APPLE_CHANGES
1272
1273 void KHTMLPart::slotData( KIO::Job* kio_job, const QByteArray &data )
1274 {
1275   assert ( d->m_job == kio_job );
1276
1277   //kdDebug( 6050 ) << "slotData: " << data.size() << endl;
1278   // The first data ?
1279   if ( !d->m_workingURL.isEmpty() )
1280     receivedFirstData( );
1281
1282   KHTMLPageCache::self()->addData(d->m_cacheId, data);
1283   write( data.data(), data.size() );
1284 }
1285
1286 void KHTMLPart::slotRestoreData(const QByteArray &data )
1287 {
1288   // The first data ?
1289   if ( !d->m_workingURL.isEmpty() )
1290   {
1291      long saveCacheId = d->m_cacheId;
1292      begin( d->m_workingURL, d->m_extension->urlArgs().xOffset, d->m_extension->urlArgs().yOffset );
1293      d->m_cacheId = saveCacheId;
1294      d->m_workingURL = KURL();
1295   }
1296
1297   //kdDebug( 6050 ) << "slotRestoreData: " << data.size() << endl;
1298   write( data.data(), data.size() );
1299
1300   if (data.size() == 0)
1301   {
1302       //kdDebug( 6050 ) << "slotRestoreData: <<end of data>>" << endl;
1303      // End of data.
1304     if (d->m_doc && d->m_doc->parsing())
1305         end(); //will emit completed()
1306   }
1307 }
1308
1309 void KHTMLPart::showError( KIO::Job* job )
1310 {
1311   kdDebug() << "KHTMLPart::showError d->m_bParsing=" << (d->m_doc && d->m_doc->parsing()) << " d->m_bComplete=" << d->m_bComplete
1312             << " d->m_bCleared=" << d->m_bCleared << endl;
1313
1314   if (job->error() == KIO::ERR_NO_CONTENT)
1315         return;
1316
1317   if ( (d->m_doc && d->m_doc->parsing()) || d->m_workingURL.isEmpty() ) // if we got any data already
1318     job->showErrorDialog( /*d->m_view*/ );
1319   else
1320   {
1321     htmlError( job->error(), job->errorText(), d->m_workingURL );
1322   }
1323 }
1324
1325 // This is a protected method, placed here because of it's relevance to showError
1326 void KHTMLPart::htmlError( int errorCode, const QString& text, const KURL& reqUrl )
1327 {
1328   kdDebug(6050) << "KHTMLPart::htmlError errorCode=" << errorCode << " text=" << text << endl;
1329   // make sure we're not executing any embedded JS
1330   bool bJSFO = d->m_bJScriptForce;
1331   bool bJSOO = d->m_bJScriptOverride;
1332   d->m_bJScriptForce = false;
1333   d->m_bJScriptOverride = true;
1334   begin();
1335   QString errText = QString::fromLatin1( "<HTML><HEAD><TITLE>" );
1336   errText += i18n( "Error while loading %1" ).arg( reqUrl.htmlURL() );
1337   errText += QString::fromLatin1( "</TITLE></HEAD><BODY><P>" );
1338   errText += i18n( "An error occured while loading <B>%1</B>:" ).arg( reqUrl.htmlURL() );
1339   errText += QString::fromLatin1( "</P><P>" );
1340   QString kioErrString = KIO::buildErrorString( errorCode, text );
1341
1342   kioErrString.replace(QRegExp("&"), QString("&amp;"));
1343   kioErrString.replace(QRegExp("<"), QString("&lt;"));
1344   kioErrString.replace(QRegExp(">"), QString("&gt;"));
1345
1346   // In case the error string has '\n' in it, replace with <BR/>
1347   kioErrString.replace( QRegExp("\n"), "<BR/>" );
1348
1349   errText += kioErrString;
1350   errText += QString::fromLatin1( "</P></BODY></HTML>" );
1351   write(errText);
1352   end();
1353
1354   d->m_bJScriptForce = bJSFO;
1355   d->m_bJScriptOverride = bJSOO;
1356
1357   // make the working url the current url, so that reload works and
1358   // emit the progress signals to advance one step in the history
1359   // (so that 'back' works)
1360   m_url = reqUrl; // same as d->m_workingURL
1361   d->m_workingURL = KURL();
1362   emit started( 0 );
1363   emit completed();
1364   return;
1365   // following disabled until 3.1
1366
1367   QString errorName, techName, description;
1368   QStringList causes, solutions;
1369
1370   QByteArray raw = KIO::rawErrorDetail( errorCode, text, &reqUrl );
1371   QDataStream stream(raw, IO_ReadOnly);
1372
1373   stream >> errorName >> techName >> description >> causes >> solutions;
1374
1375   QString url, protocol, datetime;
1376   url = reqUrl.prettyURL();
1377   protocol = reqUrl.protocol();
1378   datetime = KGlobal::locale()->formatDateTime( QDateTime::currentDateTime(),
1379                                                 false );
1380
1381   QString doc = QString::fromLatin1( "<html><head><title>" );
1382   doc += i18n( "Error: " );
1383   doc += errorName;
1384   doc += QString::fromLatin1( " - %1</title></head><body><h1>" ).arg( url );
1385   doc += i18n( "The requested operation could not be completed" );
1386   doc += QString::fromLatin1( "</h1><h2>" );
1387   doc += errorName;
1388   doc += QString::fromLatin1( "</h2>" );
1389   if ( techName != QString::null ) {
1390     doc += QString::fromLatin1( "<h2>" );
1391     doc += i18n( "Technical Reason: " );
1392     doc += techName;
1393     doc += QString::fromLatin1( "</h2>" );
1394   }
1395   doc += QString::fromLatin1( "<h3>" );
1396   doc += i18n( "Details of the Request:" );
1397   doc += QString::fromLatin1( "</h3><ul><li>" );
1398   doc += i18n( "URL: %1" ).arg( url );
1399   doc += QString::fromLatin1( "</li><li>" );
1400   if ( protocol != QString::null ) {
1401     // uncomment for 3.1... i18n change
1402     // doc += i18n( "Protocol: %1" ).arg( protocol ).arg( protocol );
1403     doc += QString::fromLatin1( "</li><li>" );
1404   }
1405   doc += i18n( "Date and Time: %1" ).arg( datetime );
1406   doc += QString::fromLatin1( "</li><li>" );
1407   doc += i18n( "Additional Information: %1" ).arg( text );
1408   doc += QString::fromLatin1( "</li></ul><h3>" );
1409   doc += i18n( "Description:" );
1410   doc += QString::fromLatin1( "</h3><p>" );
1411   doc += description;
1412   doc += QString::fromLatin1( "</p>" );
1413   if ( causes.count() ) {
1414     doc += QString::fromLatin1( "<h3>" );
1415     doc += i18n( "Possible Causes:" );
1416     doc += QString::fromLatin1( "</h3><ul><li>" );
1417     doc += causes.join( "</li><li>" );
1418     doc += QString::fromLatin1( "</li></ul>" );
1419   }
1420   if ( solutions.count() ) {
1421     doc += QString::fromLatin1( "<h3>" );
1422     doc += i18n( "Possible Solutions:" );
1423     doc += QString::fromLatin1( "</h3><ul><li>" );
1424     doc += solutions.join( "</li><li>" );
1425     doc += QString::fromLatin1( "</li></ul>" );
1426   }
1427   doc += QString::fromLatin1( "</body></html>" );
1428
1429   write( doc );
1430   end();
1431 }
1432
1433 #endif
1434
1435 void KHTMLPart::slotFinished( KIO::Job * job )
1436 {
1437   if (job->error())
1438   {
1439     KHTMLPageCache::self()->cancelEntry(d->m_cacheId);
1440     d->m_job = 0L;
1441 #if !APPLE_CHANGES
1442     emit canceled( job->errorString() );
1443 #endif
1444     // TODO: what else ?
1445     checkCompleted();
1446 #if !APPLE_CHANGES
1447     showError( job );
1448 #endif
1449     return;
1450   }
1451   //kdDebug( 6050 ) << "slotFinished" << endl;
1452
1453   KHTMLPageCache::self()->endData(d->m_cacheId);
1454
1455   if ( d->m_doc && d->m_doc->docLoader()->expireDate() && m_url.protocol().lower().startsWith("http"))
1456       KIO::http_update_cache(m_url, false, d->m_doc->docLoader()->expireDate());
1457
1458   d->m_workingURL = KURL();
1459   d->m_job = 0L;
1460
1461   if (d->m_doc->parsing())
1462       end(); //will emit completed()
1463 }
1464
1465 #if APPLE_CHANGES
1466 void KHTMLPart::childBegin()
1467 {
1468     // We need to do this when the child is created so as to avoid the bogus state of the parent's
1469     // child->m_bCompleted being false but the child's m_bComplete being true.  If the child gets
1470     // an error early on, we had trouble where checkingComplete on the child was a NOP because
1471     // it thought it was already complete, and thus the parent was never signaled, and never set
1472     // its child->m_bComplete.
1473     d->m_bComplete = false;
1474 }
1475 #endif
1476
1477 void KHTMLPart::begin( const KURL &url, int xOffset, int yOffset )
1478 {
1479 #if APPLE_CHANGES
1480   // If we aren't loading an actual URL, then we need to make sure
1481   // that we have at least an empty document. createEmptyDocument will
1482   // do that if we don't have a document already.
1483   if (d->m_workingURL.isEmpty()) {
1484     KWQ(this)->createEmptyDocument();
1485   }
1486 #endif
1487
1488   clear();
1489
1490 #if APPLE_CHANGES
1491   KWQ(this)->partClearedInBegin();
1492 #endif
1493
1494   // Only do this after clearing the part, so that JavaScript can
1495   // clean up properly if it was on for the last load.
1496 #if !APPLE_CHANGES
1497   d->m_bJScriptEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaScriptEnabled(url.host());
1498 #else
1499   d->m_bJScriptEnabled = d->m_settings->isJavaScriptEnabled(url.host());
1500 #endif
1501
1502   d->m_bCleared = false;
1503   d->m_cacheId = 0;
1504   d->m_bComplete = false;
1505   d->m_bLoadEventEmitted = false;
1506   d->m_bLoadingMainResource = true;
1507
1508   if(url.isValid()) {
1509 #if APPLE_CHANGES
1510       KHTMLFactory::vLinks()->insert( KWQ(this)->requestedURLString() );
1511 #else
1512       QString urlString = url.url();
1513       KHTMLFactory::vLinks()->insert( urlString );
1514       QString urlString2 = url.prettyURL();
1515       if ( urlString != urlString2 ) {
1516           KHTMLFactory::vLinks()->insert( urlString2 );
1517       }
1518 #endif
1519   }
1520
1521   // ###
1522   //stopParser();
1523
1524   KParts::URLArgs args( d->m_extension->urlArgs() );
1525   args.xOffset = xOffset;
1526   args.yOffset = yOffset;
1527   d->m_extension->setURLArgs( args );
1528
1529   KURL ref(url);
1530   ref.setUser(QSTRING_NULL);
1531   ref.setPass(QSTRING_NULL);
1532   ref.setRef(QSTRING_NULL);
1533   d->m_referrer = ref.url();
1534   m_url = url;
1535   KURL baseurl;
1536
1537 #if APPLE_CHANGES
1538   // We don't need KDE chained URI handling or window caption setting
1539   if ( !m_url.isEmpty() )
1540   {
1541     baseurl = m_url;
1542   }
1543 #else
1544   if ( !m_url.isEmpty() )
1545   {
1546     KURL::List lst = KURL::split( m_url );
1547     if ( !lst.isEmpty() )
1548       baseurl = *lst.begin();
1549
1550     KURL title( baseurl );
1551     title.setRef( QString::null );
1552     title.setQuery( QString::null );
1553     emit setWindowCaption( title.url() );
1554   }
1555   else
1556     emit setWindowCaption( i18n( "no title", "* Unknown *" ) );
1557 #endif
1558
1559   if (args.serviceType == "text/xml" || args.serviceType == "application/xml" || args.serviceType == "application/xhtml+xml" ||
1560       args.serviceType == "text/xsl" || args.serviceType == "application/rss+xml" || args.serviceType == "application/atom+xml")
1561     d->m_doc = DOMImplementationImpl::instance()->createDocument( d->m_view );
1562   else
1563     d->m_doc = DOMImplementationImpl::instance()->createHTMLDocument( d->m_view );
1564
1565   d->m_doc->ref();
1566   if (!d->m_doc->attached())
1567     d->m_doc->attach( );
1568   d->m_doc->setURL( m_url.url() );
1569   // We prefer m_baseURL over m_url because m_url changes when we are
1570   // about to load a new page.
1571   d->m_doc->setBaseURL( baseurl.url() );
1572 #if APPLE_CHANGES
1573   if (d->m_decoder)
1574     d->m_doc->setDecoder(d->m_decoder);
1575 #endif
1576 #if !APPLE_CHANGES
1577   d->m_doc->docLoader()->setShowAnimations( KHTMLFactory::defaultHTMLSettings()->showAnimations() );
1578 #else
1579   d->m_doc->docLoader()->setShowAnimations( d->m_settings->showAnimations() );
1580 #endif
1581
1582 #if APPLE_CHANGES
1583   KWQ(this)->updatePolicyBaseURL();
1584 #endif
1585
1586 #if !APPLE_CHANGES
1587   d->m_paUseStylesheet->setItems(QStringList());
1588   d->m_paUseStylesheet->setEnabled( false );
1589 #endif
1590
1591 #if !APPLE_CHANGES
1592   setAutoloadImages( KHTMLFactory::defaultHTMLSettings()->autoLoadImages() );
1593   QString userStyleSheet = KHTMLFactory::defaultHTMLSettings()->userStyleSheet();
1594 #else
1595   setAutoloadImages( d->m_settings->autoLoadImages() );
1596   QString userStyleSheet = d->m_settings->userStyleSheet();
1597 #endif
1598
1599   if ( !userStyleSheet.isEmpty() )
1600     setUserStyleSheet( KURL( userStyleSheet ) );
1601
1602 #if APPLE_CHANGES
1603   KWQ(this)->restoreDocumentState();
1604 #else
1605   d->m_doc->setRestoreState(args.docState);
1606 #endif
1607
1608   d->m_doc->implicitOpen();
1609   // clear widget
1610   if (d->m_view)
1611     d->m_view->resizeContents( 0, 0 );
1612   connect(d->m_doc,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
1613
1614 #if !APPLE_CHANGES
1615   emit d->m_extension->enableAction( "print", true );
1616 #endif
1617 }
1618
1619 void KHTMLPart::write( const char *str, int len )
1620 {
1621     if ( !d->m_decoder ) {
1622         d->m_decoder = new Decoder;
1623         if (!d->m_encoding.isNull())
1624             d->m_decoder->setEncoding(d->m_encoding.latin1(),
1625                 d->m_haveEncoding ? Decoder::UserChosenEncoding : Decoder::EncodingFromHTTPHeader);
1626         else {
1627             // Inherit the default encoding from the parent frame if there is one.
1628             const char *defaultEncoding = (parentPart() && parentPart()->d->m_decoder)
1629                 ? parentPart()->d->m_decoder->encoding() : settings()->encoding().latin1();
1630             d->m_decoder->setEncoding(defaultEncoding, Decoder::DefaultEncoding);
1631         }
1632 #if APPLE_CHANGES
1633         if (d->m_doc)
1634             d->m_doc->setDecoder(d->m_decoder);
1635 #endif
1636     }
1637   if ( len == 0 )
1638     return;
1639
1640   if ( len == -1 )
1641     len = strlen( str );
1642
1643   QString decoded = d->m_decoder->decode( str, len );
1644
1645   if(decoded.isEmpty()) return;
1646
1647   if(d->m_bFirstData) {
1648       // determine the parse mode
1649       d->m_doc->determineParseMode( decoded );
1650       d->m_bFirstData = false;
1651
1652   //kdDebug(6050) << "KHTMLPart::write haveEnc = " << d->m_haveEncoding << endl;
1653       // ### this is still quite hacky, but should work a lot better than the old solution
1654       if(d->m_decoder->visuallyOrdered()) d->m_doc->setVisuallyOrdered();
1655       d->m_doc->recalcStyle( NodeImpl::Force );
1656   }
1657
1658   if (jScript())
1659     jScript()->appendSourceFile(m_url.url(),decoded);
1660   Tokenizer* t = d->m_doc->tokenizer();
1661
1662   if(t)
1663     t->write( decoded, true );
1664 }
1665
1666 void KHTMLPart::write( const QString &str )
1667 {
1668   if ( str.isNull() )
1669     return;
1670
1671   if(d->m_bFirstData) {
1672       // determine the parse mode
1673       d->m_doc->setParseMode( DocumentImpl::Strict );
1674       d->m_bFirstData = false;
1675   }
1676   if (jScript())
1677     jScript()->appendSourceFile(m_url.url(),str);
1678   Tokenizer* t = d->m_doc->tokenizer();
1679   if(t)
1680     t->write( str, true );
1681 }
1682
1683 void KHTMLPart::end()
1684 {
1685     d->m_bLoadingMainResource = false;
1686     endIfNotLoading();
1687 }
1688
1689 void KHTMLPart::endIfNotLoading()
1690 {
1691     if (d->m_bLoadingMainResource)
1692         return;
1693
1694     // make sure nothing's left in there...
1695     if (d->m_decoder)
1696         write(d->m_decoder->flush());
1697     if (d->m_doc)
1698         d->m_doc->finishParsing();
1699     else
1700         // WebKit partially uses WebCore when loading non-HTML docs.  In these cases doc==nil, but
1701         // WebCore is enough involved that we need to checkCompleted() in order for m_bComplete to
1702         // become true.  An example is when a subframe is a pure text doc, and that subframe is the
1703         // last one to complete.
1704         checkCompleted();
1705 }
1706
1707 void KHTMLPart::stop()
1708 {
1709     // make sure nothing's left in there...
1710     Tokenizer* t = d->m_doc ? d->m_doc->tokenizer() : 0;
1711     if (t)
1712         t->stopped();
1713     if (d->m_doc)
1714         d->m_doc->finishParsing();
1715     else
1716         // WebKit partially uses WebCore when loading non-HTML docs.  In these cases doc==nil, but
1717         // WebCore is enough involved that we need to checkCompleted() in order for m_bComplete to
1718         // become true.  An example is when a subframe is a pure text doc, and that subframe is the
1719         // last one to complete.
1720         checkCompleted();
1721 }
1722
1723 #if !APPLE_CHANGES
1724
1725 void KHTMLPart::paint(QPainter *p, const QRect &rc, int yOff, bool *more)
1726 {
1727     if (!d->m_view) return;
1728     d->m_view->paint(p, rc, yOff, more);
1729 }
1730
1731 #endif
1732
1733 void KHTMLPart::stopAnimations()
1734 {
1735   if ( d->m_doc )
1736     d->m_doc->docLoader()->setShowAnimations( KHTMLSettings::KAnimationDisabled );
1737
1738   ConstFrameIt it = d->m_frames.begin();
1739   ConstFrameIt end = d->m_frames.end();
1740   for (; it != end; ++it )
1741     if ( !( *it ).m_part.isNull() && ( *it ).m_part->inherits( "KHTMLPart" ) ) {
1742       KParts::ReadOnlyPart* p = ( *it ).m_part;
1743       static_cast<KHTMLPart*>( p )->stopAnimations();
1744     }
1745 }
1746
1747 void KHTMLPart::gotoAnchor()
1748 {
1749     if (m_url.hasRef()) {
1750         QString ref = m_url.encodedHtmlRef();
1751         if (!gotoAnchor(ref)) {
1752             // Can't use htmlRef() here because it doesn't know which encoding to use to decode.
1753             // Decoding here has to match encoding in completeURL, which means it has to use the
1754             // page's encoding rather than UTF-8.
1755             if (d->m_decoder)
1756 #if !APPLE_CHANGES
1757                 gotoAnchor(KURL::decode_string(ref, d->m_decoder->codec()->mibEnum()));
1758 #else
1759                 gotoAnchor(KURL::decode_string(ref, d->m_decoder->codec()));
1760 #endif
1761         }
1762     }
1763 }
1764
1765 void KHTMLPart::slotFinishedParsing()
1766 {
1767   d->m_doc->setParsing(false);
1768
1769   if (!d->m_view)
1770     return; // We are probably being destructed.
1771     
1772   checkCompleted();
1773
1774   if (!d->m_view)
1775     return; // We are being destroyed by something checkCompleted called.
1776
1777   // check if the scrollbars are really needed for the content
1778   // if not, remove them, relayout, and repaint
1779
1780   d->m_view->restoreScrollBar();
1781   gotoAnchor();
1782 }
1783
1784 void KHTMLPart::slotLoaderRequestStarted( khtml::DocLoader* dl, khtml::CachedObject *obj )
1785 {
1786 #if !APPLE_CHANGES
1787   if ( obj && obj->type() == khtml::CachedObject::Image && d->m_doc && d->m_doc->docLoader() == dl ) {
1788     KHTMLPart* p = this;
1789     while ( p ) {
1790       KHTMLPart* op = p;
1791       p->d->m_totalObjectCount++;
1792       p = p->parentPart();
1793       if ( !p && d->m_loadedObjects <= d->m_totalObjectCount )
1794         QTimer::singleShot( 200, op, SLOT( slotProgressUpdate() ) );
1795     }
1796   }
1797 #endif
1798 }
1799
1800 void KHTMLPart::slotLoaderRequestDone( khtml::DocLoader* dl, khtml::CachedObject *obj )
1801 {
1802 #if !APPLE_CHANGES
1803   if ( obj && obj->type() == khtml::CachedObject::Image && d->m_doc && d->m_doc->docLoader() == dl ) {
1804     KHTMLPart* p = this;
1805     while ( p ) {
1806       KHTMLPart* op = p;
1807       p->d->m_loadedObjects++;
1808       p = p->parentPart();
1809       if ( !p && d->m_loadedObjects <= d->m_totalObjectCount && d->m_jobPercent >= 100 )
1810         QTimer::singleShot( 200, op, SLOT( slotProgressUpdate() ) );
1811     }
1812   }
1813 #endif
1814   // We really only need to call checkCompleted when our own resources are done loading.
1815   // So we should check that d->m_doc->docLoader() == dl here.
1816   // That might help with performance by skipping some unnecessary work, but it's too
1817   // risky to make that change right now (2005-02-07), because we might be accidentally
1818   // depending on the extra checkCompleted calls.
1819   if (d->m_doc) {
1820     checkCompleted();
1821   }
1822 }
1823
1824 #if !APPLE_CHANGES
1825
1826 void KHTMLPart::slotProgressUpdate()
1827 {
1828   int percent;
1829   if ( d->m_loadedObjects < d->m_totalObjectCount )
1830     percent = d->m_jobPercent / 4 + ( d->m_loadedObjects*300 ) / ( 4*d->m_totalObjectCount );
1831   else
1832     percent = d->m_jobPercent;
1833
1834   if ( d->m_loadedObjects < d->m_totalObjectCount && percent >= 75 )
1835     emit d->m_extension->infoMessage( i18n( "%1 of 1 Image loaded", "%1 of %n Images loaded", d->m_totalObjectCount ).arg( d->m_loadedObjects ) );
1836
1837   emit d->m_extension->loadingProgress( percent );
1838 }
1839
1840 void KHTMLPart::slotJobSpeed( KIO::Job* /*job*/, unsigned long speed )
1841 {
1842   emit d->m_extension->speedProgress( speed );
1843 }
1844
1845 void KHTMLPart::slotJobPercent( KIO::Job* /*job*/, unsigned long percent )
1846 {
1847   d->m_jobPercent = percent;
1848
1849   if ( !parentPart() )
1850     QTimer::singleShot( 0, this, SLOT( slotProgressUpdate() ) );
1851 }
1852
1853 #endif
1854
1855 void KHTMLPart::checkCompleted()
1856 {
1857 //   kdDebug( 6050 ) << "KHTMLPart::checkCompleted() parsing: " << d->m_doc->parsing() << endl;
1858 //   kdDebug( 6050 ) << "                           complete: " << d->m_bComplete << endl;
1859
1860 #if !APPLE_CHANGES
1861   // restore the cursor position
1862   if (d->m_doc && !d->m_doc->parsing() && !d->m_focusNodeRestored)
1863   {
1864       if (d->m_focusNodeNumber >= 0)
1865           d->m_doc->setFocusNode(d->m_doc->nodeWithAbsIndex(d->m_focusNodeNumber));
1866       else
1867           d->m_doc->setFocusNode(0);
1868       d->m_focusNodeRestored = true;
1869   }
1870 #endif
1871
1872   // Any frame that hasn't completed yet ?
1873   ConstFrameIt it = d->m_frames.begin();
1874   ConstFrameIt end = d->m_frames.end();
1875   for (; it != end; ++it )
1876     if ( !(*it).m_bCompleted )
1877       return;
1878
1879   // Have we completed before?
1880   if ( d->m_bComplete )
1881     return;
1882
1883   // Are we still parsing?
1884   if ( d->m_doc && d->m_doc->parsing() )
1885     return;
1886
1887   // Still waiting for images/scripts from the loader ?
1888   int requests = 0;
1889   if ( d->m_doc && d->m_doc->docLoader() )
1890     requests = khtml::Cache::loader()->numRequests( d->m_doc->docLoader() );
1891
1892   if ( requests > 0 )
1893     return;
1894
1895   // OK, completed.
1896   // Now do what should be done when we are really completed.
1897   d->m_bComplete = true;
1898
1899   checkEmitLoadEvent(); // if we didn't do it before
1900
1901 #if !APPLE_CHANGES
1902   // check that the view has not been moved by the user  
1903   if ( !m_url.hasRef() && d->m_view->contentsY() == 0 )
1904       d->m_view->setContentsPos( d->m_extension->urlArgs().xOffset,
1905                                  d->m_extension->urlArgs().yOffset );
1906 #endif
1907
1908   if ( d->m_scheduledRedirection != noRedirectionScheduled )
1909   {
1910     // Do not start redirection for frames here! That action is
1911     // deferred until the parent emits a completed signal.
1912     if ( parentPart() == 0 )
1913       d->m_redirectionTimer.start( (int)(1000 * d->m_delayRedirect), true );
1914
1915     emit completed( true );
1916   }
1917   else
1918   {
1919     if ( d->m_bPendingChildRedirection )
1920       emit completed ( true );
1921     else
1922       emit completed();
1923   }
1924
1925 #if !APPLE_CHANGES
1926   // find the alternate stylesheets
1927   QStringList sheets;
1928   if (d->m_doc)
1929      sheets = d->m_doc->availableStyleSheets();
1930   d->m_paUseStylesheet->setItems( sheets );
1931   d->m_paUseStylesheet->setEnabled( !sheets.isEmpty() );
1932   if (!sheets.isEmpty())
1933   {
1934     d->m_paUseStylesheet->setCurrentItem(kMax(sheets.findIndex(d->m_sheetUsed), 0));
1935     slotUseStylesheet();
1936   }
1937
1938   if (!parentPart())
1939       emit setStatusBarText(i18n("Done."));
1940 #endif
1941
1942 #ifdef SPEED_DEBUG
1943   kdDebug(6050) << "DONE: " <<d->m_parsetime.elapsed() << endl;
1944 #endif
1945 }
1946
1947 void KHTMLPart::checkEmitLoadEvent()
1948 {
1949   if ( d->m_bLoadEventEmitted || !d->m_doc || d->m_doc->parsing() ) return;
1950
1951   ConstFrameIt it = d->m_frames.begin();
1952   ConstFrameIt end = d->m_frames.end();
1953   for (; it != end; ++it )
1954     if ( !(*it).m_bCompleted ) // still got a frame running -> too early
1955       return;
1956
1957
1958   // All frames completed -> set their domain to the frameset's domain
1959   // This must only be done when loading the frameset initially (#22039),
1960   // not when following a link in a frame (#44162).
1961   if ( d->m_doc )
1962   {
1963     DOMString domain = d->m_doc->domain();
1964     ConstFrameIt it = d->m_frames.begin();
1965     ConstFrameIt end = d->m_frames.end();
1966     for (; it != end; ++it )
1967     {
1968       KParts::ReadOnlyPart *p = (*it).m_part;
1969       if ( p && p->inherits( "KHTMLPart" ))
1970       {
1971         KHTMLPart* htmlFrame = static_cast<KHTMLPart *>(p);
1972         if (htmlFrame->d->m_doc)
1973         {
1974           kdDebug() << "KHTMLPart::checkCompleted setting frame domain to " << domain.string() << endl;
1975           htmlFrame->d->m_doc->setDomain( domain );
1976         }
1977       }
1978     }
1979   }
1980
1981   d->m_bLoadEventEmitted = true;
1982   d->m_bUnloadEventEmitted = false;
1983   if (d->m_doc)
1984     d->m_doc->implicitClose();
1985 }
1986
1987 const KHTMLSettings *KHTMLPart::settings() const
1988 {
1989   return d->m_settings;
1990 }
1991
1992 #ifndef KDE_NO_COMPAT
1993 KURL KHTMLPart::baseURL() const
1994 {
1995   if ( !d->m_doc ) return KURL();
1996
1997   return d->m_doc->baseURL();
1998 }
1999
2000 QString KHTMLPart::baseTarget() const
2001 {
2002   if ( !d->m_doc ) return QString::null;
2003
2004   return d->m_doc->baseTarget();
2005 }
2006 #endif
2007
2008 KURL KHTMLPart::completeURL( const QString &url )
2009 {
2010   if ( !d->m_doc ) return url;
2011
2012 #if !APPLE_CHANGES
2013   if (d->m_decoder)
2014     return KURL(d->m_doc->completeURL(url), d->m_decoder->codec()->mibEnum());
2015 #endif
2016
2017   return KURL( d->m_doc->completeURL( url ) );
2018 }
2019
2020 void KHTMLPart::scheduleRedirection( double delay, const QString &url, bool doLockHistory)
2021 {
2022     kdDebug(6050) << "KHTMLPart::scheduleRedirection delay=" << delay << " url=" << url << endl;
2023     if (delay < 0 || delay > INT_MAX / 1000)
2024       return;
2025     if ( d->m_scheduledRedirection == noRedirectionScheduled || delay <= d->m_delayRedirect )
2026     {
2027        d->m_scheduledRedirection = redirectionScheduled;
2028        d->m_delayRedirect = delay;
2029        d->m_redirectURL = url;
2030        d->m_redirectReferrer = QString::null;
2031        d->m_redirectLockHistory = doLockHistory;
2032        d->m_redirectUserGesture = false;
2033
2034        d->m_redirectionTimer.stop();
2035        if ( d->m_bComplete )
2036          d->m_redirectionTimer.start( (int)(1000 * d->m_delayRedirect), true );
2037     }
2038 }
2039
2040 void KHTMLPart::scheduleLocationChange(const QString &url, const QString &referrer, bool lockHistory, bool userGesture)
2041 {
2042     // Handle a location change of a page with no document as a special case.
2043     // This may happen when a frame changes the location of another frame.
2044     d->m_scheduledRedirection = d->m_doc ? locationChangeScheduled : locationChangeScheduledDuringLoad;
2045     d->m_delayRedirect = 0;
2046     d->m_redirectURL = url;
2047     d->m_redirectReferrer = referrer;
2048     d->m_redirectLockHistory = lockHistory;
2049     d->m_redirectUserGesture = userGesture;
2050     d->m_redirectionTimer.stop();
2051     if (d->m_bComplete)
2052         d->m_redirectionTimer.start(0, true);
2053 }
2054
2055 bool KHTMLPart::isScheduledLocationChangePending() const
2056 {
2057     switch (d->m_scheduledRedirection) {
2058         case noRedirectionScheduled:
2059         case redirectionScheduled:
2060             return false;
2061         case historyNavigationScheduled:
2062         case locationChangeScheduled:
2063         case locationChangeScheduledDuringLoad:
2064             return true;
2065     }
2066     return false;
2067 }
2068
2069 void KHTMLPart::scheduleHistoryNavigation( int steps )
2070 {
2071 #if APPLE_CHANGES
2072     // navigation will always be allowed in the 0 steps case, which is OK because
2073     // that's supposed to force a reload.
2074     if (!KWQ(this)->canGoBackOrForward(steps)) {
2075         cancelRedirection();
2076         return;
2077     }
2078 #endif
2079
2080     d->m_scheduledRedirection = historyNavigationScheduled;
2081     d->m_delayRedirect = 0;
2082     d->m_redirectURL = QString::null;
2083     d->m_redirectReferrer = QString::null;
2084     d->m_scheduledHistoryNavigationSteps = steps;
2085     d->m_redirectionTimer.stop();
2086     if (d->m_bComplete)
2087         d->m_redirectionTimer.start(0, true);
2088 }
2089
2090 void KHTMLPart::cancelRedirection(bool cancelWithLoadInProgress)
2091 {
2092     if (d) {
2093         d->m_cancelWithLoadInProgress = cancelWithLoadInProgress;
2094         d->m_scheduledRedirection = noRedirectionScheduled;
2095         d->m_redirectionTimer.stop();
2096     }
2097 }
2098
2099 void KHTMLPart::slotRedirect()
2100 {
2101     if (d->m_scheduledRedirection == historyNavigationScheduled) {
2102         d->m_scheduledRedirection = noRedirectionScheduled;
2103
2104         // Special case for go(0) from a frame -> reload only the frame
2105         // go(i!=0) from a frame navigates into the history of the frame only,
2106         // in both IE and NS (but not in Mozilla).... we can't easily do that
2107         // in Konqueror...
2108         if (d->m_scheduledHistoryNavigationSteps == 0) // add && parentPart() to get only frames, but doesn't matter
2109             openURL( url() ); /// ## need args.reload=true?
2110         else {
2111             if (d->m_extension) {
2112                 BrowserInterface *interface = d->m_extension->browserInterface();
2113                 if (interface)
2114                     interface->callMethod( "goHistory(int)", d->m_scheduledHistoryNavigationSteps );
2115             }
2116         }
2117         return;
2118     }
2119   
2120   QString u = d->m_redirectURL;
2121
2122   d->m_scheduledRedirection = noRedirectionScheduled;
2123   d->m_delayRedirect = 0;
2124   d->m_redirectURL = QString::null;
2125   if ( u.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 )
2126   {
2127     QString script = KURL::decode_string( u.right( u.length() - 11 ) );
2128     //kdDebug( 6050 ) << "KHTMLPart::slotRedirect script=" << script << endl;
2129     QVariant res = executeScript( script, d->m_redirectUserGesture );
2130     if ( res.type() == QVariant::String ) {
2131       begin( url() );
2132       write( res.asString() );
2133       end();
2134     }
2135     return;
2136   }
2137   KParts::URLArgs args;
2138   if ( urlcmp( u, m_url.url(), true, false ) )
2139     args.reload = true;
2140
2141   args.setLockHistory( d->m_redirectLockHistory );
2142   if (!d->m_redirectReferrer.isEmpty())
2143     args.metaData()["referrer"] = d->m_redirectReferrer;
2144   d->m_redirectReferrer = QString::null;
2145
2146   urlSelected( u, 0, 0, "_self", args );
2147 }
2148
2149 void KHTMLPart::slotRedirection(KIO::Job*, const KURL& url)
2150 {
2151   // the slave told us that we got redirected
2152   // kdDebug( 6050 ) << "redirection by KIO to " << url.url() << endl;
2153   emit d->m_extension->setLocationBarURL( url.prettyURL() );
2154   d->m_workingURL = url;
2155 }
2156
2157 #if !APPLE_CHANGES
2158
2159 bool KHTMLPart::setEncoding( const QString &name, bool override )
2160 {
2161     d->m_encoding = name;
2162     d->m_haveEncoding = override;
2163
2164     if( !m_url.isEmpty() ) {
2165         // reload document
2166         closeURL();
2167         KURL url = m_url;
2168         m_url = 0;
2169         d->m_restored = true;
2170         openURL(url);
2171         d->m_restored = false;
2172     }
2173
2174     return true;
2175 }
2176
2177 #endif
2178
2179 QString KHTMLPart::encoding() const
2180 {
2181     if(d->m_haveEncoding && !d->m_encoding.isEmpty())
2182         return d->m_encoding;
2183
2184     if(d->m_decoder && d->m_decoder->encoding())
2185         return QString(d->m_decoder->encoding());
2186
2187     return(settings()->encoding());
2188 }
2189
2190 void KHTMLPart::setUserStyleSheet(const KURL &url)
2191 {
2192   if ( d->m_doc && d->m_doc->docLoader() )
2193     (void) new khtml::PartStyleSheetLoader(this, url.url(), d->m_doc->docLoader());
2194 }
2195
2196 void KHTMLPart::setUserStyleSheet(const QString &styleSheet)
2197 {
2198   if ( d->m_doc )
2199     d->m_doc->setUserStyleSheet( styleSheet );
2200 }
2201
2202 bool KHTMLPart::gotoAnchor( const QString &name )
2203 {
2204   if (!d->m_doc)
2205     return false;
2206
2207   NodeImpl *n = d->m_doc->getElementById(name);
2208   if (!n) {
2209     HTMLCollectionImpl *anchors =
2210         new HTMLCollectionImpl( d->m_doc, HTMLCollectionImpl::DOC_ANCHORS);
2211     anchors->ref();
2212     n = anchors->namedItem(name, !d->m_doc->inCompatMode());
2213     anchors->deref();
2214   }
2215
2216   d->m_doc->setCSSTarget(n); // Setting to null will clear the current target.
2217   
2218   // Implement the rule that "" and "top" both mean top of page as in other browsers.
2219   if (!n && !(name.isEmpty() || name.lower() == "top")) {
2220     kdDebug(6050) << "KHTMLPart::gotoAnchor node '" << name << "' not found" << endl;
2221     return false;
2222   }
2223
2224   // We need to update the layout before scrolling, otherwise we could
2225   // really mess things up if an anchor scroll comes at a bad moment.
2226   if ( d->m_doc ) {
2227     d->m_doc->updateRendering();
2228     // Only do a layout if changes have occurred that make it necessary.      
2229     if ( d->m_view && d->m_doc->renderer() && d->m_doc->renderer()->needsLayout() ) {
2230       d->m_view->layout();
2231     }
2232   }
2233   
2234   int x = 0, y = 0;
2235   if (n) {
2236     static_cast<HTMLElementImpl *>(n)->getUpperLeftCorner(x, y);
2237   }
2238   // Scroll to actual top left of element with no slop, since some pages expect anchors to be exactly scrolled to.
2239 #if APPLE_CHANGES
2240   // Call recursive version so this will expose correctly from within nested frames.
2241   d->m_view->setContentsPosRecursive(x, y);
2242 #else
2243   d->m_view->setContentsPos(x, y);
2244 #endif
2245
2246   return true;
2247 }
2248
2249 void KHTMLPart::setStandardFont( const QString &name )
2250 {
2251     d->m_settings->setStdFontName(name);
2252 }
2253
2254 void KHTMLPart::setFixedFont( const QString &name )
2255 {
2256     d->m_settings->setFixedFontName(name);
2257 }
2258
2259 #if !APPLE_CHANGES
2260
2261 void KHTMLPart::setURLCursor( const QCursor &c )
2262 {
2263   d->m_linkCursor = c;
2264 }
2265
2266 #endif
2267
2268 QCursor KHTMLPart::urlCursor() const
2269 {
2270 #if APPLE_CHANGES
2271   // Don't load the link cursor until it's actually used.
2272   // Also, we don't need setURLCursor.
2273   // This speeds up startup time.
2274   return KCursor::handCursor();
2275 #else
2276   return d->m_linkCursor;
2277 #endif
2278 }
2279
2280 bool KHTMLPart::onlyLocalReferences() const
2281 {
2282   return d->m_onlyLocalReferences;
2283 }
2284
2285 void KHTMLPart::setOnlyLocalReferences(bool enable)
2286 {
2287   d->m_onlyLocalReferences = enable;
2288 }
2289
2290 #if !APPLE_CHANGES
2291
2292 void KHTMLPart::findTextBegin(NodeImpl *startNode, int startPos)
2293 {
2294     d->m_findPos = startPos;
2295     d->m_findNode = startNode;
2296 }
2297
2298 bool KHTMLPart::findTextNext( const QString &str, bool forward, bool caseSensitive, bool isRegExp )
2299 {
2300     if ( !d->m_doc )
2301         return false;
2302
2303     if(!d->m_findNode) {
2304         if (d->m_doc->isHTMLDocument())
2305             d->m_findNode = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
2306         else
2307             d->m_findNode = d->m_doc;
2308     }
2309
2310     if ( !d->m_findNode )
2311     {
2312       kdDebug() << "KHTMLPart::findTextNext no findNode -> return false" << endl;
2313       return false;
2314     }
2315     if ( d->m_findNode->id() == ID_FRAMESET )
2316     {
2317       kdDebug() << "KHTMLPart::findTextNext FRAMESET -> return false" << endl;
2318       return false;
2319     }
2320
2321     while(1)
2322     {
2323         if( (d->m_findNode->nodeType() == Node::TEXT_NODE || d->m_findNode->nodeType() == Node::CDATA_SECTION_NODE) && d->m_findNode->renderer() )
2324         {
2325             DOMString nodeText = d->m_findNode->nodeValue();
2326             DOMStringImpl *t = nodeText.implementation();
2327             QConstString s(t->s, t->l);
2328
2329             int matchLen = 0;
2330             if ( isRegExp ) {
2331               QRegExp matcher( str );
2332               matcher.setCaseSensitive( caseSensitive );
2333               d->m_findPos = matcher.search(s.string(), d->m_findPos+1);
2334               if ( d->m_findPos != -1 )
2335                 matchLen = matcher.matchedLength();
2336             }
2337             else {
2338               d->m_findPos = s.string().find(str, d->m_findPos+1, caseSensitive);
2339               matchLen = str.length();
2340             }
2341
2342             if(d->m_findPos != -1)
2343             {
2344                 int x = 0, y = 0;
2345                 static_cast<khtml::RenderText *>(d->m_findNode->renderer())
2346                   ->posOfChar(d->m_findPos, x, y);
2347                 d->m_view->setContentsPos(x-50, y-50);
2348                 Position p1(d->m_findNode, d->m_findPos);
2349                 Position p2(d->m_findNode, d->m_findPos + matchLen);
2350                 setSelection(Selection(p1, khtml::DOWNSTREAM, p2, khtml::SEL_PREFER_UPSTREAM_AFFINITY));
2351                 return true;
2352             }
2353         }
2354         d->m_findPos = -1;
2355
2356         NodeImpl *next;
2357
2358         if ( forward )
2359         {
2360           next = d->m_findNode->firstChild();
2361
2362           if(!next) next = d->m_findNode->nextSibling();
2363           while(d->m_findNode && !next) {
2364               d->m_findNode = d->m_findNode->parentNode();
2365               if( d->m_findNode ) {
2366                   next = d->m_findNode->nextSibling();
2367               }
2368           }
2369         }
2370         else
2371         {
2372           next = d->m_findNode->lastChild();
2373
2374           if (!next ) next = d->m_findNode->previousSibling();
2375           while ( d->m_findNode && !next )
2376           {
2377             d->m_findNode = d->m_findNode->parentNode();
2378             if( d->m_findNode )
2379             {
2380               next = d->m_findNode->previousSibling();
2381             }
2382           }
2383         }
2384
2385         d->m_findNode = next;
2386         if(!d->m_findNode) return false;
2387     }
2388 }
2389
2390 #endif // APPLE_CHANGES
2391
2392 QString KHTMLPart::text(const DOM::Range &r) const
2393 {
2394     return plainText(r);
2395 }
2396
2397 QString KHTMLPart::selectedText() const
2398 {
2399     return text(selection().toRange());
2400 }
2401
2402 bool KHTMLPart::hasSelection() const
2403 {
2404     return d->m_selection.isCaretOrRange();
2405 }
2406
2407 const Selection &KHTMLPart::selection() const
2408 {
2409     return d->m_selection;
2410 }
2411
2412 ETextGranularity KHTMLPart::selectionGranularity() const
2413 {
2414     return d->m_selectionGranularity;
2415 }
2416
2417 void KHTMLPart::setSelectionGranularity(ETextGranularity granularity) const
2418 {
2419     d->m_selectionGranularity = granularity;
2420 }
2421
2422 const Selection &KHTMLPart::dragCaret() const
2423 {
2424     return d->m_dragCaret;
2425 }
2426
2427 const Selection &KHTMLPart::mark() const
2428 {
2429     return d->m_mark;
2430 }
2431
2432 void KHTMLPart::setMark(const Selection &s)
2433 {
2434     d->m_mark = s;
2435 }
2436
2437 void KHTMLPart::setSelection(const Selection &s, bool closeTyping, bool keepTypingStyle)
2438 {
2439     if (d->m_selection == s) {
2440         return;
2441     }
2442     
2443     clearCaretRectIfNeeded();
2444
2445 #if APPLE_CHANGES
2446     Selection oldSelection = d->m_selection;
2447 #endif
2448
2449     d->m_selection = s;
2450     if (!s.isNone())
2451         setFocusNodeIfNeeded();
2452
2453     selectionLayoutChanged();
2454
2455     // Always clear the x position used for vertical arrow navigation.
2456     // It will be restored by the vertical arrow navigation code if necessary.
2457     d->m_xPosForVerticalArrowNavigation = NoXPosForVerticalArrowNavigation;
2458
2459     if (closeTyping)
2460         TypingCommand::closeTyping(lastEditCommand());
2461
2462     if (!keepTypingStyle)
2463         clearTypingStyle();
2464     
2465 #if APPLE_CHANGES
2466     KWQ(this)->respondToChangedSelection(oldSelection, closeTyping);
2467 #endif
2468
2469     emitSelectionChanged();
2470 }
2471
2472 void KHTMLPart::setDragCaret(const Selection &dragCaret)
2473 {
2474     if (d->m_dragCaret != dragCaret) {
2475         d->m_dragCaret.needsCaretRepaint();
2476         d->m_dragCaret = dragCaret;
2477         d->m_dragCaret.needsCaretRepaint();
2478     }
2479 }
2480
2481 void KHTMLPart::clearSelection()
2482 {
2483     setSelection(Selection());
2484 }
2485
2486 void KHTMLPart::invalidateSelection()
2487 {
2488     clearCaretRectIfNeeded();
2489     d->m_selection.setNeedsLayout();
2490     selectionLayoutChanged();
2491 }
2492
2493 void KHTMLPart::setCaretVisible(bool flag)
2494 {
2495     if (d->m_caretVisible == flag)
2496         return;
2497     clearCaretRectIfNeeded();
2498     if (flag)
2499         setFocusNodeIfNeeded();
2500     d->m_caretVisible = flag;
2501     selectionLayoutChanged();
2502 }
2503
2504 #if !APPLE_CHANGES
2505 void KHTMLPart::slotClearSelection()
2506 {
2507     clearSelection();
2508 }
2509 #endif
2510
2511 void KHTMLPart::clearCaretRectIfNeeded()
2512 {
2513     if (d->m_caretPaint) {
2514         d->m_caretPaint = false;
2515         d->m_selection.needsCaretRepaint();
2516     }        
2517 }
2518
2519 // Helper function that tells whether a particular node is an element that has an entire
2520 // KHTMLPart and KHTMLView, a <frame>, <iframe>, or <object>.
2521 static bool isFrame(const NodeImpl *n)
2522 {
2523     if (!n)
2524         return false;
2525     RenderObject *renderer = n->renderer();
2526     if (!renderer || !renderer->isWidget())
2527         return false;
2528     QWidget *widget = static_cast<RenderWidget *>(renderer)->widget();
2529     return widget && widget->inherits("KHTMLView");
2530 }
2531
2532 void KHTMLPart::setFocusNodeIfNeeded()
2533 {
2534     if (!xmlDocImpl() || d->m_selection.isNone() || !d->m_isFocused)
2535         return;
2536
2537     NodeImpl *n = d->m_selection.start().node();
2538     NodeImpl *target = (n && n->isContentEditable()) ? n : 0;
2539     if (!target) {
2540         while (n && n != d->m_selection.end().node()) {
2541             if (n->isContentEditable()) {
2542                 target = n;
2543                 break;
2544             }
2545             n = n->traverseNextNode();
2546         }
2547     }
2548     assert(target == 0 || target->isContentEditable());
2549     
2550     if (target) {
2551         for ( ; target; target = target->parentNode()) {
2552             // We don't want to set focus on a subframe when selecting in a parent frame,
2553             // so add the !isFrame check here. There's probably a better way to make this
2554             // work in the long term, but this is the safest fix at this time.
2555             if (target->isMouseFocusable() && !isFrame(target)) {
2556                 xmlDocImpl()->setFocusNode(target);
2557                 return;
2558             }
2559         }
2560         xmlDocImpl()->setFocusNode(0);
2561     }
2562 }
2563
2564 void KHTMLPart::selectionLayoutChanged()
2565 {
2566     // kill any caret blink timer now running
2567     if (d->m_caretBlinkTimer >= 0) {
2568         killTimer(d->m_caretBlinkTimer);
2569         d->m_caretBlinkTimer = -1;
2570     }
2571
2572     // see if a new caret blink timer needs to be started
2573     if (d->m_caretVisible && d->m_caretBlinks && 
2574         d->m_selection.isCaret() && d->m_selection.start().node()->isContentEditable()) {
2575         d->m_caretBlinkTimer = startTimer(CARET_BLINK_FREQUENCY);
2576         d->m_caretPaint = true;
2577         d->m_selection.needsCaretRepaint();
2578     }
2579
2580     if (d->m_doc)
2581         d->m_doc->updateSelection();
2582 }
2583
2584 void KHTMLPart::setXPosForVerticalArrowNavigation(int x)
2585 {
2586     d->m_xPosForVerticalArrowNavigation = x;
2587 }
2588
2589 int KHTMLPart::xPosForVerticalArrowNavigation() const
2590 {
2591     return d->m_xPosForVerticalArrowNavigation;
2592 }
2593
2594 void KHTMLPart::timerEvent(QTimerEvent *e)
2595 {
2596     if (e->timerId() == d->m_caretBlinkTimer && 
2597         d->m_caretVisible && 
2598         d->m_caretBlinks && 
2599         d->m_selection.isCaret()) {
2600         if (d->m_bMousePressed) {
2601             if (!d->m_caretPaint) {
2602                 d->m_caretPaint = true;
2603                 d->m_selection.needsCaretRepaint();
2604             }
2605         }
2606         else {
2607             d->m_caretPaint = !d->m_caretPaint;
2608             d->m_selection.needsCaretRepaint();
2609         }
2610     }
2611 }
2612
2613 void KHTMLPart::paintCaret(QPainter *p, const QRect &rect) const
2614 {
2615     if (d->m_caretPaint)
2616         d->m_selection.paintCaret(p, rect);
2617 }
2618
2619 void KHTMLPart::paintDragCaret(QPainter *p, const QRect &rect) const
2620 {
2621     d->m_dragCaret.paintCaret(p, rect);
2622 }
2623
2624 #if !APPLE_CHANGES
2625
2626 void KHTMLPart::overURL( const QString &url, const QString &target, bool shiftPressed )
2627 {
2628   if ( !d->m_kjsStatusBarText.isEmpty() && !shiftPressed ) {
2629     emit onURL( url );
2630     emit setStatusBarText( d->m_kjsStatusBarText );
2631     d->m_kjsStatusBarText = QString::null;
2632     return;
2633   }
2634
2635   emit onURL( url );
2636
2637   if ( url.isEmpty() )
2638   {
2639     emit setStatusBarText(completeURL(url).htmlURL());
2640     return;
2641   }
2642
2643   if (url.find( QString::fromLatin1( "javascript:" ),0, false ) != -1 )
2644   {
2645     emit setStatusBarText( KURL::decode_string( url.mid( url.find( "javascript:", 0, false ) ) ) );
2646     return;
2647   }
2648
2649   KURL u = completeURL(url);
2650
2651   // special case for <a href="">
2652   if ( url.isEmpty() )
2653     u.setFileName( url );
2654
2655   QString com;
2656
2657   KMimeType::Ptr typ = KMimeType::findByURL( u );
2658
2659   if ( typ )
2660     com = typ->comment( u, false );
2661
2662   if ( u.isMalformed() )
2663   {
2664     emit setStatusBarText(u.htmlURL());
2665     return;
2666   }
2667
2668   if ( u.isLocalFile() )
2669   {
2670     // TODO : use KIO::stat() and create a KFileItem out of its result,
2671     // to use KFileItem::statusBarText()
2672     QCString path = QFile::encodeName( u.path() );
2673
2674     struct stat buff;
2675     bool ok = !stat( path.data(), &buff );
2676
2677     struct stat lbuff;
2678     if (ok) ok = !lstat( path.data(), &lbuff );
2679
2680     QString text = u.htmlURL();
2681     QString text2 = text;
2682
2683     if (ok && S_ISLNK( lbuff.st_mode ) )
2684     {
2685       QString tmp;
2686       if ( com.isNull() )
2687         tmp = i18n( "Symbolic Link");
2688       else
2689         tmp = i18n("%1 (Link)").arg(com);
2690       char buff_two[1024];
2691       text += " -> ";
2692       int n = readlink ( path.data(), buff_two, 1022);
2693       if (n == -1)
2694       {
2695         text2 += "  ";
2696         text2 += tmp;
2697         emit setStatusBarText(text2);
2698         return;
2699       }
2700       buff_two[n] = 0;
2701
2702       text += buff_two;
2703       text += "  ";
2704       text += tmp;
2705     }
2706     else if ( ok && S_ISREG( buff.st_mode ) )
2707     {
2708       if (buff.st_size < 1024)
2709         text = i18n("%2 (%1 bytes)").arg((long) buff.st_size).arg(text2); // always put the URL last, in case it contains '%'
2710       else
2711       {
2712         float d = (float) buff.st_size/1024.0;
2713         text = i18n("%1 (%2 K)").arg(text2).arg(KGlobal::locale()->formatNumber(d, 2)); // was %.2f
2714       }
2715       text += "  ";
2716       text += com;
2717     }
2718     else if ( ok && S_ISDIR( buff.st_mode ) )
2719     {
2720       text += "  ";
2721       text += com;
2722     }
2723     else
2724     {
2725       text += "  ";
2726       text += com;
2727     }
2728     emit setStatusBarText(text);
2729   }
2730   else
2731   {
2732     QString extra;
2733     if (target == QString::fromLatin1("_blank"))
2734     {
2735       extra = i18n(" (In new window)");
2736     }
2737     else if (!target.isEmpty() &&
2738              (target != QString::fromLatin1("_top")) &&
2739              (target != QString::fromLatin1("_self")) &&
2740              (target != QString::fromLatin1("_parent")))
2741     {
2742       extra = i18n(" (In other frame)");
2743     }
2744
2745     if (u.protocol() == QString::fromLatin1("mailto")) {
2746       QString mailtoMsg/* = QString::fromLatin1("<img src=%1>").arg(locate("icon", QString::fromLatin1("locolor/16x16/actions/mail_send.png")))*/;
2747       mailtoMsg += i18n("Email to: ") + KURL::decode_string(u.path());
2748       QStringList queries = QStringList::split('&', u.query().mid(1));
2749       for (QStringList::Iterator it = queries.begin(); it != queries.end(); ++it)
2750         if ((*it).startsWith(QString::fromLatin1("subject=")))
2751           mailtoMsg += i18n(" - Subject: ") + KURL::decode_string((*it).mid(8));
2752         else if ((*it).startsWith(QString::fromLatin1("cc=")))
2753           mailtoMsg += i18n(" - CC: ") + KURL::decode_string((*it).mid(3));
2754         else if ((*it).startsWith(QString::fromLatin1("bcc=")))
2755           mailtoMsg += i18n(" - BCC: ") + KURL::decode_string((*it).mid(4));
2756       mailtoMsg.replace(QRegExp("&"), QString("&amp;"));
2757       mailtoMsg.replace(QRegExp("<"), QString("&lt;"));
2758       mailtoMsg.replace(QRegExp(">"), QString("&gt;"));
2759       mailtoMsg.replace(QRegExp("([\n\r\t]|[ ]{10})"), "");
2760       emit setStatusBarText(mailtoMsg);
2761       return;
2762     }
2763    // Is this check neccessary at all? (Frerich)
2764 #if 0
2765     else if (u.protocol() == QString::fromLatin1("http")) {
2766         DOM::Node hrefNode = nodeUnderMouse().parentNode();
2767         while (hrefNode.nodeName().string() != QString::fromLatin1("A") && !hrefNode.isNull())
2768           hrefNode = hrefNode.parentNode();
2769
2770         if (!hrefNode.isNull()) {
2771           DOM::Node hreflangNode = hrefNode.attributes().getNamedItem("HREFLANG");
2772           if (!hreflangNode.isNull()) {
2773             QString countryCode = hreflangNode.nodeValue().string().lower();
2774             // Map the language code to an appropriate country code.
2775             if (countryCode == QString::fromLatin1("en"))
2776               countryCode = QString::fromLatin1("gb");
2777             QString flagImg = QString::fromLatin1("<img src=%1>").arg(
2778                 locate("locale", QString::fromLatin1("l10n/")
2779                 + countryCode
2780                 + QString::fromLatin1("/flag.png")));
2781             emit setStatusBarText(flagImg + u.prettyURL() + extra);
2782           }
2783         }
2784       }
2785 #endif
2786     emit setStatusBarText(u.htmlURL() + extra);
2787   }
2788 }
2789
2790 #endif // APPLE_CHANGES
2791
2792 void KHTMLPart::urlSelected( const QString &url, int button, int state, const QString &_target,
2793                              KParts::URLArgs args )
2794 {
2795   bool hasTarget = false;
2796
2797   QString target = _target;
2798   if ( target.isEmpty() && d->m_doc )
2799     target = d->m_doc->baseTarget();
2800   if ( !target.isEmpty() )
2801       hasTarget = true;
2802
2803   if ( url.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 )
2804   {
2805     executeScript( KURL::decode_string( url.right( url.length() - 11) ), true );
2806     return;
2807   }
2808
2809   KURL cURL = completeURL(url);
2810 #if !APPLE_CHANGES
2811   // special case for <a href="">
2812   if ( url.isEmpty() )
2813     cURL.setFileName( url );
2814 #endif
2815
2816   if ( !cURL.isValid() )
2817     // ### ERROR HANDLING
2818     return;
2819
2820   //kdDebug( 6000 ) << "urlSelected: complete URL:" << cURL.url() << " target = " << target << endl;
2821
2822 #if !APPLE_CHANGES
2823   if ( button == LeftButton && ( state & ShiftButton ) )
2824   {
2825     KIO::MetaData metaData;
2826     metaData["referrer"] = d->m_referrer;
2827     KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As..." ), cURL, metaData );
2828     return;
2829   }
2830
2831   if (!checkLinkSecurity(cURL,
2832                          i18n( "<qt>The link <B>%1</B><BR>leads from this untrusted page to your local filesystem.<BR>Do you want to follow the link?" ),
2833                          i18n( "Follow" )))
2834     return;
2835 #endif
2836
2837   args.frameName = target;
2838
2839   if ( d->m_bHTTPRefresh )
2840   {
2841     d->m_bHTTPRefresh = false;
2842     args.metaData()["cache"] = "refresh";
2843   }
2844
2845 #if !APPLE_CHANGES
2846   args.metaData().insert("main_frame_request",
2847                          parentPart() == 0 ? "TRUE":"FALSE");
2848   args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE");
2849   args.metaData().insert("ssl_activate_warnings", "TRUE");
2850 #endif
2851
2852 #if APPLE_CHANGES
2853   args.metaData()["referrer"] = d->m_referrer;
2854   KWQ(this)->urlSelected(cURL, button, state, args);
2855 #else
2856   if ( hasTarget )
2857   {
2858     // unknown frame names should open in a new window.
2859     khtml::ChildFrame *frame = recursiveFrameRequest( cURL, args, false );
2860     if ( frame )
2861     {
2862       args.metaData()["referrer"] = d->m_referrer;
2863       requestObject( frame, cURL, args );
2864       return;
2865     }
2866   }
2867
2868   if ( !d->m_bComplete && !hasTarget )
2869     closeURL();
2870
2871   if (!d->m_referrer.isEmpty())
2872     args.metaData()["referrer"] = d->m_referrer;
2873
2874   if ( button == MidButton && (state & ShiftButton) )
2875   {
2876     KParts::WindowArgs winArgs;
2877     winArgs.lowerWindow = true;
2878     KParts::ReadOnlyPart *newPart = 0;
2879     emit d->m_extension->createNewWindow( cURL, args, winArgs, newPart );
2880     return;
2881   }
2882   emit d->m_extension->openURLRequest( cURL, args );
2883 #endif // APPLE_CHANGES
2884 }
2885
2886 #if !APPLE_CHANGES
2887
2888 void KHTMLPart::slotViewDocumentSource()
2889 {
2890   KURL url(m_url);
2891   if (!(url.isLocalFile()) && KHTMLPageCache::self()->isValid(d->m_cacheId))
2892   {
2893      KTempFile sourceFile(QString::null, QString::fromLatin1(".html"));
2894      if (sourceFile.status() == 0)
2895      {
2896         KHTMLPageCache::self()->saveData(d->m_cacheId, sourceFile.dataStream());
2897         url = KURL();
2898         url.setPath(sourceFile.name());
2899      }
2900   }
2901
2902   //  emit d->m_extension->openURLRequest( m_url, KParts::URLArgs( false, 0, 0, QString::fromLatin1( "text/plain" ) ) );
2903   (void) KRun::runURL( url, QString::fromLatin1("text/plain") );
2904 }
2905
2906 void KHTMLPart::slotViewFrameSource()
2907 {
2908   KParts::ReadOnlyPart *frame = currentFrame();
2909   if ( !frame )
2910     return;
2911
2912   KURL url = frame->url();
2913   if (!(url.isLocalFile()) && frame->inherits("KHTMLPart"))
2914   {
2915        long cacheId = static_cast<KHTMLPart *>(frame)->d->m_cacheId;
2916
2917        if (KHTMLPageCache::self()->isValid(cacheId))
2918        {
2919            KTempFile sourceFile(QString::null, QString::fromLatin1(".html"));
2920            if (sourceFile.status() == 0)
2921            {
2922                KHTMLPageCache::self()->saveData(cacheId, sourceFile.dataStream());
2923                url = KURL();
2924                url.setPath(sourceFile.name());
2925            }
2926      }
2927   }
2928
2929   (void) KRun::runURL( url, QString::fromLatin1("text/plain") );
2930 }
2931
2932 KURL KHTMLPart::backgroundURL() const
2933 {
2934   // ### what about XML documents? get from CSS?
2935   if (!d->m_doc || !d->m_doc->isHTMLDocument())
2936     return KURL();
2937
2938   QString relURL = static_cast<HTMLDocumentImpl*>(d->m_doc)->body()->getAttribute( ATTR_BACKGROUND ).string();
2939
2940   return KURL( m_url, relURL );
2941 }
2942
2943 void KHTMLPart::slotSaveBackground()
2944 {
2945   KIO::MetaData metaData;
2946   metaData["referrer"] = d->m_referrer;
2947   KHTMLPopupGUIClient::saveURL( d->m_view, i18n("Save background image as"), backgroundURL(), metaData );
2948 }
2949
2950 void KHTMLPart::slotSaveDocument()
2951 {
2952   KURL srcURL( m_url );
2953
2954   if ( srcURL.fileName(false).isEmpty() )
2955     srcURL.setFileName( "index.html" );
2956
2957   KIO::MetaData metaData;
2958   // Referre unknown?
2959   KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), srcURL, metaData, i18n("*.html *.htm|HTML files"), d->m_cacheId );
2960 }
2961
2962 void KHTMLPart::slotSecurity()
2963 {
2964 //   kdDebug( 6050 ) << "Meta Data:" << endl
2965 //                   << d->m_ssl_peer_cert_subject
2966 //                   << endl
2967 //                   << d->m_ssl_peer_cert_issuer
2968 //                   << endl
2969 //                   << d->m_ssl_cipher
2970 //                   << endl
2971 //                   << d->m_ssl_cipher_desc
2972 //                   << endl
2973 //                   << d->m_ssl_cipher_version
2974 //                   << endl
2975 //                   << d->m_ssl_good_from
2976 //                   << endl
2977 //                   << d->m_ssl_good_until
2978 //                   << endl
2979 //                   << d->m_ssl_cert_state
2980 //                   << endl;
2981
2982   KSSLInfoDlg *kid = new KSSLInfoDlg(d->m_ssl_in_use, widget(), "kssl_info_dlg", true );
2983
2984   if (d->m_bSecurityInQuestion)
2985           kid->setSecurityInQuestion(true);
2986
2987   if (d->m_ssl_in_use) {
2988     KSSLCertificate *x = KSSLCertificate::fromString(d->m_ssl_peer_certificate.local8Bit());
2989     if (x) {
2990        // Set the chain back onto the certificate
2991        QStringList cl = QStringList::split(QString("\n"), d->m_ssl_peer_chain);
2992        QPtrList<KSSLCertificate> ncl;
2993
2994        ncl.setAutoDelete(true);
2995        for (QStringList::Iterator it = cl.begin(); it != cl.end(); ++it) {
2996           KSSLCertificate *y = KSSLCertificate::fromString((*it).local8Bit());
2997           if (y) ncl.append(y);
2998        }
2999
3000        if (ncl.count() > 0)
3001           x->chain().setChain(ncl);
3002
3003        kid->setup(x,
3004                   d->m_ssl_peer_ip,
3005                   m_url.url(),
3006                   d->m_ssl_cipher,
3007                   d->m_ssl_cipher_desc,
3008                   d->m_ssl_cipher_version,
3009                   d->m_ssl_cipher_used_bits.toInt(),
3010                   d->m_ssl_cipher_bits.toInt(),
3011                   (KSSLCertificate::KSSLValidation) d->m_ssl_cert_state.toInt()
3012                   );
3013         kid->exec();
3014         delete x;
3015      } else kid->exec();
3016   } else kid->exec();
3017 }
3018
3019 void KHTMLPart::slotSaveFrame()
3020 {
3021     if ( !d->m_activeFrame )
3022         return; // should never be the case, but one never knows :-)
3023
3024     KURL srcURL( static_cast<KParts::ReadOnlyPart *>( d->m_activeFrame )->url() );
3025
3026     if ( srcURL.fileName(false).isEmpty() )
3027         srcURL.setFileName( "index.html" );
3028
3029     KIO::MetaData metaData;
3030     // Referrer unknown?
3031     KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), srcURL, metaData, i18n("*.html *.htm|HTML files") );
3032 }
3033
3034 void KHTMLPart::slotSetEncoding()
3035 {
3036     // first Item is always auto
3037     if(d->m_paSetEncoding->currentItem() == 0)
3038         setEncoding(QString::null, false);
3039     else {
3040         // strip of the language to get the raw encoding again.
3041         QString enc = KGlobal::charsets()->encodingForName(d->m_paSetEncoding->currentText());
3042         setEncoding(enc, true);
3043     }
3044 }
3045
3046 void KHTMLPart::slotUseStylesheet()
3047 {
3048   if (d->m_doc && d->m_paUseStylesheet->currentText() != d->m_sheetUsed) {
3049     d->m_sheetUsed = d->m_paUseStylesheet->currentText();
3050     d->m_doc->updateStyleSelector();
3051   }
3052 }
3053
3054 void KHTMLPart::updateActions()
3055 {
3056   bool frames = false;
3057
3058   QValueList<khtml::ChildFrame>::ConstIterator it = d->m_frames.begin();
3059   QValueList<khtml::ChildFrame>::ConstIterator end = d->m_frames.end();
3060   for (; it != end; ++it )
3061       if ( (*it).m_type == khtml::ChildFrame::Frame )
3062       {
3063           frames = true;
3064           break;
3065       }
3066
3067   d->m_paViewFrame->setEnabled( frames );
3068   d->m_paSaveFrame->setEnabled( frames );
3069
3070   if ( frames )
3071     d->m_paFind->setText( i18n( "&Find in Frame..." ) );
3072   else
3073     d->m_paFind->setText( i18n( "&Find..." ) );
3074
3075   KParts::Part *frame = 0;
3076
3077   if ( frames )
3078     frame = currentFrame();
3079
3080   bool enableFindAndSelectAll = true;
3081
3082   if ( frame )
3083     enableFindAndSelectAll = frame->inherits( "KHTMLPart" );
3084
3085   d->m_paFind->setEnabled( enableFindAndSelectAll );
3086   d->m_paSelectAll->setEnabled( enableFindAndSelectAll );
3087
3088   bool enablePrintFrame = false;
3089
3090   if ( frame )
3091   {
3092     QObject *ext = KParts::BrowserExtension::childObject( frame );
3093     if ( ext )
3094       enablePrintFrame = ext->metaObject()->slotNames().contains( "print()" );
3095   }
3096
3097   d->m_paPrintFrame->setEnabled( enablePrintFrame );
3098
3099   QString bgURL;
3100
3101   // ### frames
3102   if ( d->m_doc && d->m_doc->isHTMLDocument() && static_cast<HTMLDocumentImpl*>(d->m_doc)->body() && !d->m_bClearing )
3103     bgURL = static_cast<HTMLDocumentImpl*>(d->m_doc)->body()->getAttribute( ATTR_BACKGROUND ).string();
3104
3105   d->m_paSaveBackground->setEnabled( !bgURL.isEmpty() );
3106 }
3107
3108 #endif
3109
3110 bool KHTMLPart::requestFrame( khtml::RenderPart *frame, const QString &url, const QString &frameName,
3111                               const QStringList &paramNames, const QStringList &paramValues, bool isIFrame )
3112 {
3113 //  kdDebug( 6050 ) << "childRequest( ..., " << url << ", " << frameName << " )" << endl;
3114   FrameIt it = d->m_frames.find( frameName );
3115   if ( it == d->m_frames.end() )
3116   {
3117     khtml::ChildFrame child;
3118 //    kdDebug( 6050 ) << "inserting new frame into frame map " << frameName << endl;
3119     child.m_name = frameName;
3120     it = d->m_frames.append( child );
3121   }
3122
3123   (*it).m_type = isIFrame ? khtml::ChildFrame::IFrame : khtml::ChildFrame::Frame;
3124   (*it).m_frame = frame;
3125   (*it).m_paramValues = paramNames;
3126   (*it).m_paramNames = paramValues;
3127
3128   // Support for <frame src="javascript:string">
3129   if ( url.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 )
3130   {
3131     if (!processObjectRequest(&(*it), "about:blank", "text/html" ))
3132       return false;
3133
3134     KHTMLPart *newPart = static_cast<KHTMLPart *>(&*(*it).m_part); 
3135     newPart->replaceContentsWithScriptResult( url );
3136
3137     return true;
3138   }
3139
3140   return requestObject( &(*it), completeURL( url ));
3141 }
3142
3143 QString KHTMLPart::requestFrameName()
3144 {
3145 #if APPLE_CHANGES
3146     return KWQ(this)->generateFrameName();
3147 #else
3148     return QString::fromLatin1("<!--frame %1-->").arg(d->m_frameNameId++);
3149 #endif
3150 }
3151
3152 bool KHTMLPart::requestObject( khtml::RenderPart *frame, const QString &url, const QString &serviceType,
3153                                const QStringList &paramNames, const QStringList &paramValues )
3154 {
3155   khtml::ChildFrame child;
3156   QValueList<khtml::ChildFrame>::Iterator it = d->m_objects.append( child );
3157   (*it).m_frame = frame;
3158   (*it).m_type = khtml::ChildFrame::Object;
3159   (*it).m_paramNames = paramNames;
3160   (*it).m_paramValues = paramValues;
3161   (*it).m_hasFallbackContent = frame->hasFallbackContent();
3162
3163   KURL completedURL;
3164   if (!url.isEmpty())
3165     completedURL = completeURL(url);
3166
3167   KParts::URLArgs args;
3168   args.serviceType = serviceType;
3169   return requestObject( &(*it), completedURL, args );
3170 }
3171
3172 bool KHTMLPart::requestObject( khtml::ChildFrame *child, const KURL &url, const KParts::URLArgs &_args )
3173 {
3174 #if !APPLE_CHANGES
3175   if (!checkLinkSecurity(url))
3176     return false;
3177 #endif
3178   if ( child->m_bPreloaded )
3179   {
3180     // kdDebug(6005) << "KHTMLPart::requestObject preload" << endl;
3181     if ( child->m_frame && child->m_part && child->m_part->widget() )
3182       child->m_frame->setWidget( child->m_part->widget() );
3183
3184     child->m_bPreloaded = false;
3185     return true;
3186   }
3187
3188   KParts::URLArgs args( _args );
3189
3190 #if !APPLE_CHANGES
3191   if ( child->m_run )
3192     child->m_run->abort();
3193 #endif
3194
3195   if ( child->m_part && !args.reload && urlcmp( child->m_part->url().url(), url.url(), true, true ) )
3196     args.serviceType = child->m_serviceType;
3197
3198   child->m_args = args;
3199   child->m_args.reload = (d->m_cachePolicy == KIO::CC_Reload) || (d->m_cachePolicy == KIO::CC_Refresh);
3200   child->m_serviceName = QString::null;
3201   if (!d->m_referrer.isEmpty() && !child->m_args.metaData().contains( "referrer" ))
3202     child->m_args.metaData()["referrer"] = d->m_referrer;
3203
3204 #if !APPLE_CHANGES
3205   child->m_args.metaData().insert("main_frame_request",
3206                                   parentPart() == 0 ? "TRUE":"FALSE");
3207   child->m_args.metaData().insert("ssl_was_in_use",
3208                                   d->m_ssl_in_use ? "TRUE":"FALSE");
3209   child->m_args.metaData().insert("ssl_activate_warnings", "TRUE");
3210 #endif
3211
3212   // We want a KHTMLPart if the HTML says <frame src=""> or <frame src="about:blank">
3213   if ((url.isEmpty() || url.url() == "about:blank") && args.serviceType.isEmpty())
3214     args.serviceType = QString::fromLatin1( "text/html" );
3215
3216 #if APPLE_CHANGES
3217   return processObjectRequest( child, url, args.serviceType );
3218 #else
3219   if ( args.serviceType.isEmpty() ) {
3220     child->m_run = new KHTMLRun( this, child, url, child->m_args,
3221                                  child->m_type != khtml::ChildFrame::Frame );
3222     return false;
3223   } else {
3224     return processObjectRequest( child, url, args.serviceType );
3225   }
3226 #endif
3227 }
3228
3229 bool KHTMLPart::processObjectRequest( khtml::ChildFrame *child, const KURL &_url, const QString &mimetype )
3230 {
3231   //kdDebug( 6050 ) << "KHTMLPart::processObjectRequest trying to create part for " << mimetype << endl;
3232
3233   // IMPORTANT: create a copy of the url here, because it is just a reference, which was likely to be given
3234   // by an emitting frame part (emit openURLRequest( blahurl, ... ) . A few lines below we delete the part
3235   // though -> the reference becomes invalid -> crash is likely
3236   KURL url( _url );
3237
3238   // khtmlrun called us this way to indicate a loading error
3239   if ( d->m_onlyLocalReferences || ( url.isEmpty() && mimetype.isEmpty() ) )
3240   {
3241       checkEmitLoadEvent();
3242       child->m_bCompleted = true;
3243       return true;
3244   }
3245
3246   if (child->m_bNotify)
3247   {
3248       child->m_bNotify = false;
3249       if ( !child->m_args.lockHistory() )
3250           emit d->m_extension->openURLNotify();
3251   }
3252
3253 #if APPLE_CHANGES
3254   if ( child->m_part )
3255   {
3256     KHTMLPart *part = static_cast<KHTMLPart *>(&*child->m_part);
3257     if (part && part->inherits("KHTMLPart")) {
3258       KParts::URLArgs args;
3259       if (!d->m_referrer.isEmpty())
3260         args.metaData()["referrer"] = d->m_referrer;
3261       KWQ(part)->openURLRequest(url, args);
3262     }
3263   }
3264   else
3265   {
3266     KParts::ReadOnlyPart *part = KWQ(this)->createPart(*child, url, mimetype);
3267     KHTMLPart *khtml_part = static_cast<KHTMLPart *>(part);
3268     if (khtml_part && khtml_part->inherits("KHTMLPart"))
3269       khtml_part->childBegin();
3270 #else
3271   if ( !child->m_services.contains( mimetype ) )
3272   {
3273     KParts::ReadOnlyPart *part = createPart( d->m_view->viewport(), child->m_name.ascii(), this, child->m_name.ascii(), mimetype, child->m_serviceName, child->m_services, child->m_params );
3274 #endif
3275
3276     if (!part) {
3277         checkEmitLoadEvent();
3278         return false;
3279     }
3280
3281     //CRITICAL STUFF
3282     if ( child->m_part )
3283     {
3284       disconnectChild(child);
3285 #if !APPLE_CHANGES
3286       partManager()->removePart( (KParts::ReadOnlyPart *)child->m_part );
3287 #endif
3288       child->m_part->deref();
3289     }
3290
3291     child->m_serviceType = mimetype;
3292     if ( child->m_frame && part->widget() )
3293       child->m_frame->setWidget( part->widget() );
3294
3295 #if !APPLE_CHANGES
3296     if ( child->m_type != khtml::ChildFrame::Object )
3297       partManager()->addPart( part, false );
3298 //  else
3299 //      kdDebug(6005) << "AH! NO FRAME!!!!!" << endl;
3300 #endif
3301
3302     child->m_part = part;
3303     assert( ((void*) child->m_part) != 0);
3304
3305     connectChild(child);
3306
3307 #if APPLE_CHANGES
3308   }
3309 #else
3310     child->m_extension = KParts::BrowserExtension::childObject( part );
3311
3312     if ( child->m_extension )
3313     {
3314       connect( child->m_extension, SIGNAL( openURLNotify() ),
3315                d->m_extension, SIGNAL( openURLNotify() ) );
3316
3317       connect( child->m_extension, SIGNAL( openURLRequestDelayed( const KURL &, const KParts::URLArgs & ) ),
3318                this, SLOT( slotChildURLRequest( const KURL &, const KParts::URLArgs & ) ) );
3319
3320       connect( child->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ),
3321                d->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ) );
3322       connect( child->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs &, const KParts::WindowArgs &, KParts::ReadOnlyPart *& ) ),
3323                d->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & , const KParts::WindowArgs &, KParts::ReadOnlyPart *&) ) );
3324
3325       connect( child->m_extension, SIGNAL( popupMenu( const QPoint &, const KFileItemList & ) ),
3326                d->m_extension, SIGNAL( popupMenu( const QPoint &, const KFileItemList & ) ) );
3327       connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList & ) ),
3328                d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList & ) ) );
3329       connect( child->m_extension, SIGNAL( popupMenu( const QPoint &, const KURL &, const QString &, mode_t ) ),
3330                d->m_extension, SIGNAL( popupMenu( const QPoint &, const KURL &, const QString &, mode_t ) ) );
3331       connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const QString &, mode_t ) ),
3332                d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const QString &, mode_t ) ) );
3333
3334       connect( child->m_extension, SIGNAL( infoMessage( const QString & ) ),
3335                d->m_extension, SIGNAL( infoMessage( const QString & ) ) );
3336
3337       child->m_extension->setBrowserInterface( d->m_extension->browserInterface() );
3338     }
3339   }
3340 #endif
3341
3342   checkEmitLoadEvent();
3343   // Some JS code in the load event may have destroyed the part
3344   // In that case, abort
3345   if ( !child->m_part )
3346     return false;
3347
3348   if ( child->m_bPreloaded )
3349   {
3350     if ( child->m_frame && child->m_part )
3351       child->m_frame->setWidget( child->m_part->widget() );
3352
3353     child->m_bPreloaded = false;
3354     return true;
3355   }
3356
3357   child->m_args.reload = (d->m_cachePolicy == KIO::CC_Reload) || (d->m_cachePolicy == KIO::CC_Refresh);
3358
3359   // make sure the part has a way to find out about the mimetype.
3360   // we actually set it in child->m_args in requestObject already,
3361   // but it's useless if we had to use a KHTMLRun instance, as the
3362   // point the run object is to find out exactly the mimetype.
3363   child->m_args.serviceType = mimetype;
3364
3365   child->m_bCompleted = false;
3366   if ( child->m_extension )
3367     child->m_extension->setURLArgs( child->m_args );
3368
3369 #if APPLE_CHANGES
3370   // In these cases, the synchronous load would have finished
3371   // before we could connect the signals, so make sure to send the 
3372   // completed() signal for the child by hand
3373   // FIXME: In this case the KHTMLPart will have finished loading before 
3374   // it's being added to the child list.  It would be a good idea to
3375   // create the child first, then invoke the loader separately  
3376   if (url.isEmpty() || url.url() == "about:blank") {
3377       ReadOnlyPart *readOnlyPart = child->m_part;
3378       KHTMLPart *part = static_cast<KHTMLPart *>(readOnlyPart);
3379       if (part && part->inherits("KHTMLPart")) {
3380           part->completed();
3381           part->checkCompleted();
3382       }
3383   }
3384 #else
3385   if(url.protocol() == "javascript" || url.url() == "about:blank") {
3386       if (!child->m_part->inherits("KHTMLPart"))
3387           return false;
3388
3389       KHTMLPart* p = static_cast<KHTMLPart*>(static_cast<KParts::ReadOnlyPart *>(child->m_part));
3390
3391       p->begin();
3392       if (d->m_doc && p->d->m_doc)
3393         p->d->m_doc->setBaseURL(d->m_doc->baseURL());
3394       if (!url.url().startsWith("about:")) {
3395         p->write(url.path());
3396       } else {
3397         p->m_url = url;
3398       }
3399       p->end();
3400       return true;
3401   }
3402   else if ( !url.isEmpty() )
3403   {
3404       //kdDebug( 6050 ) << "opening " << url.url() << " in frame " << child->m_part << endl;
3405       return child->m_part->openURL( url );
3406   }
3407   else
3408 #endif
3409       return true;
3410 }
3411
3412 #if !APPLE_CHANGES
3413
3414 KParts::ReadOnlyPart *KHTMLPart::createPart( QWidget *parentWidget, const char *widgetName,
3415                                              QObject *parent, const char *name, const QString &mimetype,
3416                                              QString &serviceName, QStringList &serviceTypes,
3417                                              const QStringList &params )
3418 {
3419   QString constr;
3420   if ( !serviceName.isEmpty() )
3421     constr.append( QString::fromLatin1( "Name == '%1'" ).arg( serviceName ) );
3422
3423   KTrader::OfferList offers = KTrader::self()->query( mimetype, "KParts/ReadOnlyPart", constr, QString::null );
3424
3425   if ( offers.isEmpty() )
3426     return 0L;
3427
3428   KService::Ptr service = *offers.begin();
3429
3430   KLibFactory *factory = KLibLoader::self()->factory( QFile::encodeName(service->library()) );
3431
3432   if ( !factory )
3433     return 0L;
3434
3435   KParts::ReadOnlyPart *res = 0L;
3436
3437   const char *className = "KParts::ReadOnlyPart";
3438   if ( service->serviceTypes().contains( "Browser/View" ) )
3439     className = "Browser/View";
3440
3441   if ( factory->inherits( "KParts::Factory" ) )
3442     res = static_cast<KParts::ReadOnlyPart *>(static_cast<KParts::Factory *>( factory )->createPart( parentWidget, widgetName, parent, name, className, params ));
3443   else
3444   res = static_cast<KParts::ReadOnlyPart *>(factory->create( parentWidget, widgetName, className ));
3445
3446   if ( !res )
3447     return res;
3448
3449   serviceTypes = service->serviceTypes();
3450   serviceName = service->name();
3451
3452   return res;
3453 }
3454
3455 KParts::PartManager *KHTMLPart::partManager()
3456 {
3457   if ( !d->m_manager )
3458   {
3459     d->m_manager = new KParts::PartManager( d->m_view->topLevelWidget(), this, "khtml part manager" );
3460     d->m_manager->setAllowNestedParts( true );
3461     connect( d->m_manager, SIGNAL( activePartChanged( KParts::Part * ) ),
3462              this, SLOT( slotActiveFrameChanged( KParts::Part * ) ) );
3463     connect( d->m_manager, SIGNAL( partRemoved( KParts::Part * ) ),
3464              this, SLOT( slotPartRemoved( KParts::Part * ) ) );
3465   }
3466
3467   return d->m_manager;
3468 }
3469
3470 #endif
3471
3472 void KHTMLPart::submitFormAgain()
3473 {
3474   if( d->m_doc && !d->m_doc->parsing() && d->m_submitForm)
3475     KHTMLPart::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 );
3476
3477   delete d->m_submitForm;
3478   d->m_submitForm = 0;
3479   disconnect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
3480 }
3481
3482 void KHTMLPart::submitForm( const char *action, const QString &url, const FormData &formData, const QString &_target, const QString& contentType, const QString& boundary )
3483 {
3484   kdDebug(6000) << this << ": KHTMLPart::submitForm target=" << _target << " url=" << url << endl;
3485   KURL u = completeURL( url );
3486
3487   if ( !u.isValid() )
3488   {
3489     // ### ERROR HANDLING!
3490     return;
3491   }
3492
3493 #if !APPLE_CHANGES
3494   // Form security checks
3495   //
3496
3497   /* This is separate for a reason.  It has to be _before_ all script, etc,
3498    * AND I don't want to break anything that uses checkLinkSecurity() in
3499    * other places.
3500    */
3501
3502   // This causes crashes... needs to be fixed.
3503   if (!d->m_submitForm && u.protocol() != "https" && u.protocol() != "mailto") {
3504         if (d->m_ssl_in_use) {    // Going from SSL -> nonSSL
3505                 int rc = KMessageBox::warningContinueCancel(NULL, i18n("Warning:  This is a secure form but it is attempting to send your data back unencrypted."
3506                                         "\nA third party may be able to intercept and view this information."
3507                                         "\nAre you sure you wish to continue?"),
3508                                 i18n("SSL"));
3509                 if (rc == KMessageBox::Cancel)
3510                         return;
3511         } else {                  // Going from nonSSL -> nonSSL
3512                 KSSLSettings kss(true);
3513                 if (kss.warnOnUnencrypted()) {
3514                         int rc = KMessageBox::warningContinueCancel(NULL,
3515                                         i18n("Warning: Your data is about to be transmitted across the network unencrypted."
3516                                         "\nAre you sure you wish to continue?"),
3517                                         i18n("KDE"),
3518                                                                     QString::null,
3519                                         "WarnOnUnencryptedForm");
3520                         // Move this setting into KSSL instead
3521                         KConfig *config = kapp->config();
3522                         QString grpNotifMsgs = QString::fromLatin1("Notification Messages");
3523                         KConfigGroupSaver saver( config, grpNotifMsgs );
3524
3525                         if (!config->readBoolEntry("WarnOnUnencryptedForm", true)) {
3526                                 config->deleteEntry("WarnOnUnencryptedForm");
3527                                 config->sync();
3528                                 kss.setWarnOnUnencrypted(false);
3529                                 kss.save();
3530                         }
3531                         if (rc == KMessageBox::Cancel)
3532                           return;
3533         }
3534     }
3535   }
3536
3537   if (!d->m_submitForm && u.protocol() == "mailto") {
3538      int rc = KMessageBox::warningContinueCancel(NULL, 
3539                  i18n("This site is attempting to submit form data via email."),
3540                  i18n("KDE"), 
3541                  QString::null, 
3542                  "WarnTriedEmailSubmit");
3543
3544      if (rc == KMessageBox::Cancel) {
3545          return;
3546      }
3547   }
3548
3549   // End form security checks
3550   //
3551 #endif // APPLE_CHANGES
3552
3553   QString urlstring = u.url();
3554
3555   if ( urlstring.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
3556     urlstring = KURL::decode_string(urlstring);
3557     d->m_executingJavaScriptFormAction = true;
3558     executeScript( urlstring.right( urlstring.length() - 11) );
3559     d->m_executingJavaScriptFormAction = false;
3560     return;
3561   }
3562
3563 #if !APPLE_CHANGES
3564   if (!checkLinkSecurity(u,
3565                          i18n( "<qt>The form will be submitted to <BR><B>%1</B><BR>on your local filesystem.<BR>Do you want to submit the form?" ),
3566                          i18n( "Submit" )))
3567     return;
3568 #endif
3569
3570   KParts::URLArgs args;
3571
3572   if (!d->m_referrer.isEmpty())
3573      args.metaData()["referrer"] = d->m_referrer;
3574
3575 #if !APPLE_CHANGES
3576   args.metaData().insert("main_frame_request",
3577                          parentPart() == 0 ? "TRUE":"FALSE");
3578   args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE");
3579   args.metaData().insert("ssl_activate_warnings", "TRUE");
3580 #endif
3581   args.frameName = _target.isEmpty() ? d->m_doc->baseTarget() : _target ;
3582
3583   // Handle mailto: forms
3584   if (u.protocol() == "mailto") {
3585       // 1)  Check for attach= and strip it
3586       QString q = u.query().mid(1);
3587       QStringList nvps = QStringList::split("&", q);
3588       bool triedToAttach = false;
3589
3590       for (QStringList::Iterator nvp = nvps.begin(); nvp != nvps.end(); ++nvp) {
3591          QStringList pair = QStringList::split("=", *nvp);
3592          if (pair.count() >= 2) {
3593             if (pair.first().lower() == "attach") {
3594                nvp = nvps.remove(nvp);
3595                triedToAttach = true;
3596             }
3597          }
3598       }
3599
3600 #if !APPLE_CHANGES
3601       if (triedToAttach)
3602          KMessageBox::information(NULL, i18n("This site attempted to attach a file from your computer in the form submission. The attachment was removed for your protection."), i18n("KDE"), "WarnTriedAttach");
3603 #endif
3604
3605       // 2)  Append body=
3606       QString bodyEnc;
3607       if (contentType.lower() == "multipart/form-data") {
3608          // FIXME: is this correct?  I suspect not
3609          bodyEnc = KURL::encode_string(formData.flattenToString());
3610       } else if (contentType.lower() == "text/plain") {
3611          // Convention seems to be to decode, and s/&/\n/
3612          QString tmpbody = formData.flattenToString();
3613          tmpbody.replace('&', '\n');
3614          tmpbody.replace('+', ' ');
3615          tmpbody = KURL::decode_string(tmpbody);  // Decode the rest of it
3616          bodyEnc = KURL::encode_string(tmpbody);  // Recode for the URL
3617       } else {
3618          bodyEnc = KURL::encode_string(formData.flattenToString());
3619       }
3620
3621       nvps.append(QString("body=%1").arg(bodyEnc));
3622       q = nvps.join("&");
3623       u.setQuery(q);
3624   } 
3625
3626   if ( strcmp( action, "get" ) == 0 ) {
3627     if (u.protocol() != "mailto")
3628        u.setQuery( formData.flattenToString() );
3629     args.setDoPost( false );
3630   }
3631   else {
3632 #if APPLE_CHANGES
3633     args.postData = formData;
3634 #else
3635     args.postData = formData.flatten();
3636 #endif
3637     args.setDoPost( true );
3638
3639     // construct some user headers if necessary
3640     if (contentType.isNull() || contentType == "application/x-www-form-urlencoded")
3641       args.setContentType( "Content-Type: application/x-www-form-urlencoded" );
3642     else // contentType must be "multipart/form-data"
3643       args.setContentType( "Content-Type: " + contentType + "; boundary=" + boundary );
3644   }
3645
3646   if ( d->m_doc->parsing() || d->m_runningScripts > 0 ) {
3647     if( d->m_submitForm ) {
3648       kdDebug(6000) << "KHTMLPart::submitForm ABORTING!" << endl;
3649       return;
3650     }
3651     d->m_submitForm = new KHTMLPartPrivate::SubmitForm;
3652     d->m_submitForm->submitAction = action;
3653     d->m_submitForm->submitUrl = url;
3654     d->m_submitForm->submitFormData = formData;
3655     d->m_submitForm->target = _target;
3656     d->m_submitForm->submitContentType = contentType;
3657     d->m_submitForm->submitBoundary = boundary;
3658     connect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
3659   }
3660   else
3661   {
3662 #if APPLE_CHANGES
3663     KWQ(this)->submitForm( u, args);
3664 #else
3665     emit d->m_extension->openURLRequest( u, args );
3666 #endif
3667   }
3668 }
3669
3670 #if !APPLE_CHANGES
3671
3672 void KHTMLPart::popupMenu( const QString &linkUrl )
3673 {
3674   KURL popupURL;
3675   KURL linkKURL;
3676   if ( linkUrl.isEmpty() ) // click on background
3677     popupURL = this->url();
3678   else {               // click on link
3679     popupURL = completeURL( linkUrl );
3680     linkKURL = popupURL;
3681   }
3682
3683   KXMLGUIClient *client = new KHTMLPopupGUIClient( this, d->m_popupMenuXML, linkKURL );
3684
3685   emit d->m_extension->popupMenu( client, QCursor::pos(), popupURL,
3686                                   QString::fromLatin1( "text/html" ), S_IFREG /*always a file*/ );
3687
3688   delete client;
3689
3690   emit popupMenu(linkUrl, QCursor::pos());
3691 }
3692
3693 #endif
3694
3695 void KHTMLPart::slotParentCompleted()
3696 {
3697   if ( d->m_scheduledRedirection != noRedirectionScheduled && !d->m_redirectionTimer.isActive() )
3698   {
3699     // kdDebug(6050) << this << ": Child redirection -> " << d->m_redirectURL << endl;
3700     d->m_redirectionTimer.start( (int)(1000 * d->m_delayRedirect), true );
3701   }
3702 }
3703
3704 void KHTMLPart::slotChildStarted( KIO::Job *job )
3705 {