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