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