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