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