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