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