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