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