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