66532000897444df475a61674cf8738f8034231a
[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     d->m_scheduledRedirection = historyNavigationScheduled;
1994     d->m_delayRedirect = 0;
1995     d->m_redirectURL = QString::null;
1996     d->m_scheduledHistoryNavigationSteps = steps;
1997     if ( d->m_bComplete ) {
1998         d->m_redirectionTimer.stop();
1999         d->m_redirectionTimer.start( (int)(1000 * d->m_delayRedirect), true );
2000     }
2001 }
2002
2003 void KHTMLPart::cancelRedirection(bool cancelWithLoadInProgress)
2004 {
2005     if (d) {
2006         d->m_cancelWithLoadInProgress = cancelWithLoadInProgress;
2007         d->m_scheduledRedirection = noRedirectionScheduled;
2008         d->m_redirectionTimer.stop();
2009     }
2010 }
2011
2012 void KHTMLPart::slotRedirect()
2013 {
2014     if (d->m_scheduledRedirection == historyNavigationScheduled) {
2015         d->m_scheduledRedirection = noRedirectionScheduled;
2016
2017         // Special case for go(0) from a frame -> reload only the frame
2018         // go(i!=0) from a frame navigates into the history of the frame only,
2019         // in both IE and NS (but not in Mozilla).... we can't easily do that
2020         // in Konqueror...
2021         if (d->m_scheduledHistoryNavigationSteps == 0) // add && parentPart() to get only frames, but doesn't matter
2022             openURL( url() ); /// ## need args.reload=true?
2023         else {
2024             if (d->m_extension) {
2025                 BrowserInterface *interface = d->m_extension->browserInterface();
2026                 if (interface)
2027                     interface->callMethod( "goHistory(int)", d->m_scheduledHistoryNavigationSteps );
2028             }
2029         }
2030         return;
2031     }
2032   
2033   QString u = d->m_redirectURL;
2034   d->m_scheduledRedirection = noRedirectionScheduled;
2035   d->m_delayRedirect = 0;
2036   d->m_redirectURL = QString::null;
2037   if ( u.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 )
2038   {
2039     QString script = KURL::decode_string( u.right( u.length() - 11 ) );
2040     //kdDebug( 6050 ) << "KHTMLPart::slotRedirect script=" << script << endl;
2041     QVariant res = executeScript( script, d->m_redirectUserGesture );
2042     if ( res.type() == QVariant::String ) {
2043       begin( url() );
2044       write( res.asString() );
2045       end();
2046     }
2047     return;
2048   }
2049   KParts::URLArgs args;
2050   if ( urlcmp( u, m_url.url(), true, false ) )
2051     args.reload = true;
2052
2053   args.setLockHistory( d->m_redirectLockHistory );
2054   urlSelected( u, 0, 0, "_self", args );
2055 }
2056
2057 void KHTMLPart::slotRedirection(KIO::Job*, const KURL& url)
2058 {
2059   // the slave told us that we got redirected
2060   // kdDebug( 6050 ) << "redirection by KIO to " << url.url() << endl;
2061   emit d->m_extension->setLocationBarURL( url.prettyURL() );
2062   d->m_workingURL = url;
2063 }
2064
2065 #if !APPLE_CHANGES
2066
2067 bool KHTMLPart::setEncoding( const QString &name, bool override )
2068 {
2069     d->m_encoding = name;
2070     d->m_haveEncoding = override;
2071
2072     if( !m_url.isEmpty() ) {
2073         // reload document
2074         closeURL();
2075         KURL url = m_url;
2076         m_url = 0;
2077         d->m_restored = true;
2078         openURL(url);
2079         d->m_restored = false;
2080     }
2081
2082     return true;
2083 }
2084
2085 #endif
2086
2087 QString KHTMLPart::encoding() const
2088 {
2089     if(d->m_haveEncoding && !d->m_encoding.isEmpty())
2090         return d->m_encoding;
2091
2092     if(d->m_decoder && d->m_decoder->encoding())
2093         return QString(d->m_decoder->encoding());
2094
2095     return(settings()->encoding());
2096 }
2097
2098 void KHTMLPart::setUserStyleSheet(const KURL &url)
2099 {
2100   if ( d->m_doc && d->m_doc->docLoader() )
2101     (void) new khtml::PartStyleSheetLoader(this, url.url(), d->m_doc->docLoader());
2102 }
2103
2104 void KHTMLPart::setUserStyleSheet(const QString &styleSheet)
2105 {
2106   if ( d->m_doc )
2107     d->m_doc->setUserStyleSheet( styleSheet );
2108 }
2109
2110 bool KHTMLPart::gotoAnchor( const QString &name )
2111 {
2112   if (!d->m_doc)
2113     return false;
2114
2115   NodeImpl *n = d->m_doc->getElementById(name);
2116   if (!n) {
2117     HTMLCollectionImpl *anchors =
2118         new HTMLCollectionImpl( d->m_doc, HTMLCollectionImpl::DOC_ANCHORS);
2119     anchors->ref();
2120     n = anchors->namedItem(name, !d->m_doc->inCompatMode());
2121     anchors->deref();
2122   }
2123
2124   d->m_doc->setCSSTarget(n); // Setting to null will clear the current target.
2125   
2126   // Implement the rule that "" and "top" both mean top of page as in other browsers.
2127   if (!n && !(name.isEmpty() || name.lower() == "top")) {
2128     kdDebug(6050) << "KHTMLPart::gotoAnchor node '" << name << "' not found" << endl;
2129     return false;
2130   }
2131
2132   // We need to update the layout before scrolling, otherwise we could
2133   // really mess things up if an anchor scroll comes at a bad moment.
2134   if ( d->m_doc ) {
2135     d->m_doc->updateRendering();
2136     // Only do a layout if changes have occurred that make it necessary.      
2137     if ( d->m_view && d->m_doc->renderer() && d->m_doc->renderer()->needsLayout() ) {
2138       d->m_view->layout();
2139     }
2140   }
2141   
2142   int x = 0, y = 0;
2143   if (n) {
2144     static_cast<HTMLElementImpl *>(n)->getUpperLeftCorner(x, y);
2145   }
2146   // Scroll to actual top left of element with no slop, since some pages expect anchors to be exactly scrolled to.
2147 #if APPLE_CHANGES
2148   // Call recursive version so this will expose correctly from within nested frames.
2149   d->m_view->setContentsPosRecursive(x, y);
2150 #else
2151   d->m_view->setContentsPos(x, y);
2152 #endif
2153
2154   return true;
2155 }
2156
2157 void KHTMLPart::setStandardFont( const QString &name )
2158 {
2159     d->m_settings->setStdFontName(name);
2160 }
2161
2162 void KHTMLPart::setFixedFont( const QString &name )
2163 {
2164     d->m_settings->setFixedFontName(name);
2165 }
2166
2167 #if !APPLE_CHANGES
2168
2169 void KHTMLPart::setURLCursor( const QCursor &c )
2170 {
2171   d->m_linkCursor = c;
2172 }
2173
2174 #endif
2175
2176 QCursor KHTMLPart::urlCursor() const
2177 {
2178 #if APPLE_CHANGES
2179   // Don't load the link cursor until it's actually used.
2180   // Also, we don't need setURLCursor.
2181   // This speeds up startup time.
2182   return KCursor::handCursor();
2183 #else
2184   return d->m_linkCursor;
2185 #endif
2186 }
2187
2188 bool KHTMLPart::onlyLocalReferences() const
2189 {
2190   return d->m_onlyLocalReferences;
2191 }
2192
2193 void KHTMLPart::setOnlyLocalReferences(bool enable)
2194 {
2195   d->m_onlyLocalReferences = enable;
2196 }
2197
2198 #if !APPLE_CHANGES
2199
2200 void KHTMLPart::findTextBegin(NodeImpl *startNode, int startPos)
2201 {
2202     d->m_findPos = startPos;
2203     d->m_findNode = startNode;
2204 }
2205
2206 bool KHTMLPart::findTextNext( const QString &str, bool forward, bool caseSensitive, bool isRegExp )
2207 {
2208     if ( !d->m_doc )
2209         return false;
2210
2211     if(!d->m_findNode) {
2212         if (d->m_doc->isHTMLDocument())
2213             d->m_findNode = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
2214         else
2215             d->m_findNode = d->m_doc;
2216     }
2217
2218     if ( !d->m_findNode )
2219     {
2220       kdDebug() << "KHTMLPart::findTextNext no findNode -> return false" << endl;
2221       return false;
2222     }
2223     if ( d->m_findNode->id() == ID_FRAMESET )
2224     {
2225       kdDebug() << "KHTMLPart::findTextNext FRAMESET -> return false" << endl;
2226       return false;
2227     }
2228
2229     while(1)
2230     {
2231         if( (d->m_findNode->nodeType() == Node::TEXT_NODE || d->m_findNode->nodeType() == Node::CDATA_SECTION_NODE) && d->m_findNode->renderer() )
2232         {
2233             DOMString nodeText = d->m_findNode->nodeValue();
2234             DOMStringImpl *t = nodeText.implementation();
2235             QConstString s(t->s, t->l);
2236
2237             int matchLen = 0;
2238             if ( isRegExp ) {
2239               QRegExp matcher( str );
2240               matcher.setCaseSensitive( caseSensitive );
2241               d->m_findPos = matcher.search(s.string(), d->m_findPos+1);
2242               if ( d->m_findPos != -1 )
2243                 matchLen = matcher.matchedLength();
2244             }
2245             else {
2246               d->m_findPos = s.string().find(str, d->m_findPos+1, caseSensitive);
2247               matchLen = str.length();
2248             }
2249
2250             if(d->m_findPos != -1)
2251             {
2252                 int x = 0, y = 0;
2253                 static_cast<khtml::RenderText *>(d->m_findNode->renderer())
2254                   ->posOfChar(d->m_findPos, x, y);
2255                 d->m_view->setContentsPos(x-50, y-50);
2256                 Position p1(d->m_findNode, d->m_findPos);
2257                 Position p2(d->m_findNode, d->m_findPos + matchLen);
2258                 setSelection(Selection(p1, p2));
2259                 return true;
2260             }
2261         }
2262         d->m_findPos = -1;
2263
2264         NodeImpl *next;
2265
2266         if ( forward )
2267         {
2268           next = d->m_findNode->firstChild();
2269
2270           if(!next) next = d->m_findNode->nextSibling();
2271           while(d->m_findNode && !next) {
2272               d->m_findNode = d->m_findNode->parentNode();
2273               if( d->m_findNode ) {
2274                   next = d->m_findNode->nextSibling();
2275               }
2276           }
2277         }
2278         else
2279         {
2280           next = d->m_findNode->lastChild();
2281
2282           if (!next ) next = d->m_findNode->previousSibling();
2283           while ( d->m_findNode && !next )
2284           {
2285             d->m_findNode = d->m_findNode->parentNode();
2286             if( d->m_findNode )
2287             {
2288               next = d->m_findNode->previousSibling();
2289             }
2290           }
2291         }
2292
2293         d->m_findNode = next;
2294         if(!d->m_findNode) return false;
2295     }
2296 }
2297
2298 #endif // APPLE_CHANGES
2299
2300 QString KHTMLPart::text(const DOM::Range &r) const
2301 {
2302     return plainText(r);
2303 }
2304
2305 QString KHTMLPart::selectedText() const
2306 {
2307     return text(selection().toRange());
2308 }
2309
2310 bool KHTMLPart::hasSelection() const
2311 {
2312     return !d->m_selection.isEmpty();
2313 }
2314
2315 const Selection &KHTMLPart::selection() const
2316 {
2317     return d->m_selection;
2318 }
2319
2320 const Selection &KHTMLPart::dragCaret() const
2321 {
2322     return d->m_dragCaret;
2323 }
2324
2325 void KHTMLPart::setSelection(const Selection &s, bool closeTyping)
2326 {
2327     if (d->m_selection != s) {
2328         clearCaretRectIfNeeded(); 
2329         setFocusNodeIfNeeded(s);
2330 #if APPLE_CHANGES
2331         // Mark misspellings in the soon-to-be previous selection.  When typing we check spelling
2332         // elsewhere, so don't redo it here
2333         if (closeTyping) {
2334             KWQ(this)->markMisspellingsInSelection(d->m_selection);
2335         }
2336 #endif
2337         d->m_selection = s;
2338         notifySelectionChanged(closeTyping);
2339     }
2340 }
2341
2342 void KHTMLPart::setDragCaret(const DOM::Selection &dragCaret)
2343 {
2344     if (d->m_dragCaret != dragCaret) {
2345         d->m_dragCaret.needsCaretRepaint();
2346         d->m_dragCaret = dragCaret;
2347         d->m_dragCaret.needsCaretRepaint();
2348     }
2349 }
2350
2351 void KHTMLPart::clearSelection()
2352 {
2353     clearCaretRectIfNeeded();
2354     setFocusNodeIfNeeded(d->m_selection);
2355     d->m_selection = Selection();
2356     notifySelectionChanged();
2357 }
2358
2359 void KHTMLPart::invalidateSelection()
2360 {
2361     clearCaretRectIfNeeded();
2362     d->m_selection.setNeedsLayout();
2363     selectionLayoutChanged();
2364 }
2365
2366 void KHTMLPart::setCaretVisible(bool flag)
2367 {
2368     if (d->m_caretVisible == flag)
2369         return;
2370
2371     clearCaretRectIfNeeded();
2372     setFocusNodeIfNeeded(d->m_selection);
2373     d->m_caretVisible = flag;
2374     selectionLayoutChanged();
2375 }
2376
2377 void KHTMLPart::slotClearSelection()
2378 {
2379     clearCaretRectIfNeeded();
2380     bool hadSelection = hasSelection();
2381     d->m_selection.clear();
2382     if (hadSelection)
2383         notifySelectionChanged();
2384 }
2385
2386 void KHTMLPart::clearCaretRectIfNeeded()
2387 {
2388     if (d->m_caretPaint) {
2389         d->m_caretPaint = false;
2390         d->m_selection.needsCaretRepaint();
2391     }        
2392 }
2393
2394 void KHTMLPart::setFocusNodeIfNeeded(const Selection &s)
2395 {
2396     if (!xmlDocImpl() || s.state() == Selection::NONE)
2397         return;
2398
2399     NodeImpl *n = s.start().node();
2400     NodeImpl *target = (n && n->isContentEditable()) ? n : 0;
2401     if (!target) {
2402         while (n && n != s.end().node()) {
2403             if (n->isContentEditable()) {
2404                 target = n;
2405                 break;
2406             }
2407             n = n->traverseNextNode();
2408         }
2409     }
2410     assert(target == 0 || target->isContentEditable());
2411     
2412     if (target) {
2413         for ( ; target && !target->isFocusable(); target = target->parentNode()); // loop
2414         if (target && target->isMouseFocusable())
2415             xmlDocImpl()->setFocusNode(target);
2416         else if (!target || !target->focused())
2417             xmlDocImpl()->setFocusNode(0);
2418     }
2419 }
2420
2421 void KHTMLPart::selectionLayoutChanged()
2422 {
2423     // kill any caret blink timer now running
2424     if (d->m_caretBlinkTimer >= 0) {
2425         killTimer(d->m_caretBlinkTimer);
2426         d->m_caretBlinkTimer = -1;
2427     }
2428
2429     // see if a new caret blink timer needs to be started
2430     if (d->m_caretVisible && d->m_caretBlinks && 
2431         d->m_selection.state() == Selection::CARET && d->m_selection.start().node()->isContentEditable()) {
2432         d->m_caretBlinkTimer = startTimer(CARET_BLINK_FREQUENCY);
2433         d->m_caretPaint = true;
2434         d->m_selection.needsCaretRepaint();
2435     }
2436
2437     if (d->m_doc)
2438         d->m_doc->updateSelection();
2439
2440     // Always clear the x position used for vertical arrow navigation.
2441     // It will be restored by the vertical arrow navigation code if necessary.
2442     d->m_xPosForVerticalArrowNavigation = NoXPosForVerticalArrowNavigation;
2443 }
2444
2445 void KHTMLPart::notifySelectionChanged(bool closeTyping)
2446 {
2447     selectionLayoutChanged();
2448
2449     if (closeTyping)
2450         TypingCommand::closeTyping(lastEditCommand());
2451
2452     clearTypingStyle();
2453     
2454     emitSelectionChanged();
2455     
2456 #if APPLE_CHANGES
2457     KWQ(this)->respondToChangedSelection();
2458 #endif
2459 }
2460
2461 void KHTMLPart::setXPosForVerticalArrowNavigation(int x)
2462 {
2463     d->m_xPosForVerticalArrowNavigation = x;
2464 }
2465
2466 int KHTMLPart::xPosForVerticalArrowNavigation() const
2467 {
2468     return d->m_xPosForVerticalArrowNavigation;
2469 }
2470
2471 void KHTMLPart::timerEvent(QTimerEvent *e)
2472 {
2473     if (e->timerId() == d->m_caretBlinkTimer && 
2474         d->m_caretVisible && 
2475         d->m_caretBlinks && 
2476         d->m_selection.state() == Selection::CARET) {
2477         d->m_caretPaint = !d->m_caretPaint;
2478         d->m_selection.needsCaretRepaint();
2479     }
2480 }
2481
2482 void KHTMLPart::paintCaret(QPainter *p, const QRect &rect) const
2483 {
2484     if (d->m_caretPaint)
2485         d->m_selection.paintCaret(p, rect);
2486 }
2487
2488 void KHTMLPart::paintDragCaret(QPainter *p, const QRect &rect) const
2489 {
2490     d->m_dragCaret.paintCaret(p, rect);
2491 }
2492
2493 #if !APPLE_CHANGES
2494
2495 void KHTMLPart::overURL( const QString &url, const QString &target, bool shiftPressed )
2496 {
2497   if ( !d->m_kjsStatusBarText.isEmpty() && !shiftPressed ) {
2498     emit onURL( url );
2499     emit setStatusBarText( d->m_kjsStatusBarText );
2500     d->m_kjsStatusBarText = QString::null;
2501     return;
2502   }
2503
2504   emit onURL( url );
2505
2506   if ( url.isEmpty() )
2507   {
2508     emit setStatusBarText(completeURL(url).htmlURL());
2509     return;
2510   }
2511
2512   if (url.find( QString::fromLatin1( "javascript:" ),0, false ) != -1 )
2513   {
2514     emit setStatusBarText( KURL::decode_string( url.mid( url.find( "javascript:", 0, false ) ) ) );
2515     return;
2516   }
2517
2518   KURL u = completeURL(url);
2519
2520   // special case for <a href="">
2521   if ( url.isEmpty() )
2522     u.setFileName( url );
2523
2524   QString com;
2525
2526   KMimeType::Ptr typ = KMimeType::findByURL( u );
2527
2528   if ( typ )
2529     com = typ->comment( u, false );
2530
2531   if ( u.isMalformed() )
2532   {
2533     emit setStatusBarText(u.htmlURL());
2534     return;
2535   }
2536
2537   if ( u.isLocalFile() )
2538   {
2539     // TODO : use KIO::stat() and create a KFileItem out of its result,
2540     // to use KFileItem::statusBarText()
2541     QCString path = QFile::encodeName( u.path() );
2542
2543     struct stat buff;
2544     bool ok = !stat( path.data(), &buff );
2545
2546     struct stat lbuff;
2547     if (ok) ok = !lstat( path.data(), &lbuff );
2548
2549     QString text = u.htmlURL();
2550     QString text2 = text;
2551
2552     if (ok && S_ISLNK( lbuff.st_mode ) )
2553     {
2554       QString tmp;
2555       if ( com.isNull() )
2556         tmp = i18n( "Symbolic Link");
2557       else
2558         tmp = i18n("%1 (Link)").arg(com);
2559       char buff_two[1024];
2560       text += " -> ";
2561       int n = readlink ( path.data(), buff_two, 1022);
2562       if (n == -1)
2563       {
2564         text2 += "  ";
2565         text2 += tmp;
2566         emit setStatusBarText(text2);
2567         return;
2568       }
2569       buff_two[n] = 0;
2570
2571       text += buff_two;
2572       text += "  ";
2573       text += tmp;
2574     }
2575     else if ( ok && S_ISREG( buff.st_mode ) )
2576     {
2577       if (buff.st_size < 1024)
2578         text = i18n("%2 (%1 bytes)").arg((long) buff.st_size).arg(text2); // always put the URL last, in case it contains '%'
2579       else
2580       {
2581         float d = (float) buff.st_size/1024.0;
2582         text = i18n("%1 (%2 K)").arg(text2).arg(KGlobal::locale()->formatNumber(d, 2)); // was %.2f
2583       }
2584       text += "  ";
2585       text += com;
2586     }
2587     else if ( ok && S_ISDIR( buff.st_mode ) )
2588     {
2589       text += "  ";
2590       text += com;
2591     }
2592     else
2593     {
2594       text += "  ";
2595       text += com;
2596     }
2597     emit setStatusBarText(text);
2598   }
2599   else
2600   {
2601     QString extra;
2602     if (target == QString::fromLatin1("_blank"))
2603     {
2604       extra = i18n(" (In new window)");
2605     }
2606     else if (!target.isEmpty() &&
2607              (target != QString::fromLatin1("_top")) &&
2608              (target != QString::fromLatin1("_self")) &&
2609              (target != QString::fromLatin1("_parent")))
2610     {
2611       extra = i18n(" (In other frame)");
2612     }
2613
2614     if (u.protocol() == QString::fromLatin1("mailto")) {
2615       QString mailtoMsg/* = QString::fromLatin1("<img src=%1>").arg(locate("icon", QString::fromLatin1("locolor/16x16/actions/mail_send.png")))*/;
2616       mailtoMsg += i18n("Email to: ") + KURL::decode_string(u.path());
2617       QStringList queries = QStringList::split('&', u.query().mid(1));
2618       for (QStringList::Iterator it = queries.begin(); it != queries.end(); ++it)
2619         if ((*it).startsWith(QString::fromLatin1("subject=")))
2620           mailtoMsg += i18n(" - Subject: ") + KURL::decode_string((*it).mid(8));
2621         else if ((*it).startsWith(QString::fromLatin1("cc=")))
2622           mailtoMsg += i18n(" - CC: ") + KURL::decode_string((*it).mid(3));
2623         else if ((*it).startsWith(QString::fromLatin1("bcc=")))
2624           mailtoMsg += i18n(" - BCC: ") + KURL::decode_string((*it).mid(4));
2625       mailtoMsg.replace(QRegExp("&"), QString("&amp;"));
2626       mailtoMsg.replace(QRegExp("<"), QString("&lt;"));
2627       mailtoMsg.replace(QRegExp(">"), QString("&gt;"));
2628       mailtoMsg.replace(QRegExp("([\n\r\t]|[ ]{10})"), "");
2629       emit setStatusBarText(mailtoMsg);
2630       return;
2631     }
2632    // Is this check neccessary at all? (Frerich)
2633 #if 0
2634     else if (u.protocol() == QString::fromLatin1("http")) {
2635         DOM::Node hrefNode = nodeUnderMouse().parentNode();
2636         while (hrefNode.nodeName().string() != QString::fromLatin1("A") && !hrefNode.isNull())
2637           hrefNode = hrefNode.parentNode();
2638
2639         if (!hrefNode.isNull()) {
2640           DOM::Node hreflangNode = hrefNode.attributes().getNamedItem("HREFLANG");
2641           if (!hreflangNode.isNull()) {
2642             QString countryCode = hreflangNode.nodeValue().string().lower();
2643             // Map the language code to an appropriate country code.
2644             if (countryCode == QString::fromLatin1("en"))
2645               countryCode = QString::fromLatin1("gb");
2646             QString flagImg = QString::fromLatin1("<img src=%1>").arg(
2647                 locate("locale", QString::fromLatin1("l10n/")
2648                 + countryCode
2649                 + QString::fromLatin1("/flag.png")));
2650             emit setStatusBarText(flagImg + u.prettyURL() + extra);
2651           }
2652         }
2653       }
2654 #endif
2655     emit setStatusBarText(u.htmlURL() + extra);
2656   }
2657 }
2658
2659 #endif // APPLE_CHANGES
2660
2661 void KHTMLPart::urlSelected( const QString &url, int button, int state, const QString &_target,
2662                              KParts::URLArgs args )
2663 {
2664   bool hasTarget = false;
2665
2666   QString target = _target;
2667   if ( target.isEmpty() && d->m_doc )
2668     target = d->m_doc->baseTarget();
2669   if ( !target.isEmpty() )
2670       hasTarget = true;
2671
2672   if ( url.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 )
2673   {
2674     executeScript( KURL::decode_string( url.right( url.length() - 11) ), true );
2675     return;
2676   }
2677
2678   KURL cURL = completeURL(url);
2679 #if !APPLE_CHANGES
2680   // special case for <a href="">
2681   if ( url.isEmpty() )
2682     cURL.setFileName( url );
2683 #endif
2684
2685   if ( !cURL.isValid() )
2686     // ### ERROR HANDLING
2687     return;
2688
2689   //kdDebug( 6000 ) << "urlSelected: complete URL:" << cURL.url() << " target = " << target << endl;
2690
2691 #if !APPLE_CHANGES
2692   if ( button == LeftButton && ( state & ShiftButton ) )
2693   {
2694     KIO::MetaData metaData;
2695     metaData["referrer"] = d->m_referrer;
2696     KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As..." ), cURL, metaData );
2697     return;
2698   }
2699
2700   if (!checkLinkSecurity(cURL,
2701                          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?" ),
2702                          i18n( "Follow" )))
2703     return;
2704 #endif
2705
2706   args.frameName = target;
2707
2708   if ( d->m_bHTTPRefresh )
2709   {
2710     d->m_bHTTPRefresh = false;
2711     args.metaData()["cache"] = "refresh";
2712   }
2713
2714 #if !APPLE_CHANGES
2715   args.metaData().insert("main_frame_request",
2716                          parentPart() == 0 ? "TRUE":"FALSE");
2717   args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE");
2718   args.metaData().insert("ssl_activate_warnings", "TRUE");
2719 #endif
2720
2721 #if APPLE_CHANGES
2722   args.metaData()["referrer"] = d->m_referrer;
2723   KWQ(this)->urlSelected(cURL, button, state, args);
2724 #else
2725   if ( hasTarget )
2726   {
2727     // unknown frame names should open in a new window.
2728     khtml::ChildFrame *frame = recursiveFrameRequest( cURL, args, false );
2729     if ( frame )
2730     {
2731       args.metaData()["referrer"] = d->m_referrer;
2732       requestObject( frame, cURL, args );
2733       return;
2734     }
2735   }
2736
2737   if ( !d->m_bComplete && !hasTarget )
2738     closeURL();
2739
2740   if (!d->m_referrer.isEmpty())
2741     args.metaData()["referrer"] = d->m_referrer;
2742
2743   if ( button == MidButton && (state & ShiftButton) )
2744   {
2745     KParts::WindowArgs winArgs;
2746     winArgs.lowerWindow = true;
2747     KParts::ReadOnlyPart *newPart = 0;
2748     emit d->m_extension->createNewWindow( cURL, args, winArgs, newPart );
2749     return;
2750   }
2751   emit d->m_extension->openURLRequest( cURL, args );
2752 #endif // APPLE_CHANGES
2753 }
2754
2755 #if !APPLE_CHANGES
2756
2757 void KHTMLPart::slotViewDocumentSource()
2758 {
2759   KURL url(m_url);
2760   if (!(url.isLocalFile()) && KHTMLPageCache::self()->isValid(d->m_cacheId))
2761   {
2762      KTempFile sourceFile(QString::null, QString::fromLatin1(".html"));
2763      if (sourceFile.status() == 0)
2764      {
2765         KHTMLPageCache::self()->saveData(d->m_cacheId, sourceFile.dataStream());
2766         url = KURL();
2767         url.setPath(sourceFile.name());
2768      }
2769   }
2770
2771   //  emit d->m_extension->openURLRequest( m_url, KParts::URLArgs( false, 0, 0, QString::fromLatin1( "text/plain" ) ) );
2772   (void) KRun::runURL( url, QString::fromLatin1("text/plain") );
2773 }
2774
2775 void KHTMLPart::slotViewFrameSource()
2776 {
2777   KParts::ReadOnlyPart *frame = currentFrame();
2778   if ( !frame )
2779     return;
2780
2781   KURL url = frame->url();
2782   if (!(url.isLocalFile()) && frame->inherits("KHTMLPart"))
2783   {
2784        long cacheId = static_cast<KHTMLPart *>(frame)->d->m_cacheId;
2785
2786        if (KHTMLPageCache::self()->isValid(cacheId))
2787        {
2788            KTempFile sourceFile(QString::null, QString::fromLatin1(".html"));
2789            if (sourceFile.status() == 0)
2790            {
2791                KHTMLPageCache::self()->saveData(cacheId, sourceFile.dataStream());
2792                url = KURL();
2793                url.setPath(sourceFile.name());
2794            }
2795      }
2796   }
2797
2798   (void) KRun::runURL( url, QString::fromLatin1("text/plain") );
2799 }
2800
2801 KURL KHTMLPart::backgroundURL() const
2802 {
2803   // ### what about XML documents? get from CSS?
2804   if (!d->m_doc || !d->m_doc->isHTMLDocument())
2805     return KURL();
2806
2807   QString relURL = static_cast<HTMLDocumentImpl*>(d->m_doc)->body()->getAttribute( ATTR_BACKGROUND ).string();
2808
2809   return KURL( m_url, relURL );
2810 }
2811
2812 void KHTMLPart::slotSaveBackground()
2813 {
2814   KIO::MetaData metaData;
2815   metaData["referrer"] = d->m_referrer;
2816   KHTMLPopupGUIClient::saveURL( d->m_view, i18n("Save background image as"), backgroundURL(), metaData );
2817 }
2818
2819 void KHTMLPart::slotSaveDocument()
2820 {
2821   KURL srcURL( m_url );
2822
2823   if ( srcURL.fileName(false).isEmpty() )
2824     srcURL.setFileName( "index.html" );
2825
2826   KIO::MetaData metaData;
2827   // Referre unknown?
2828   KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), srcURL, metaData, i18n("*.html *.htm|HTML files"), d->m_cacheId );
2829 }
2830
2831 void KHTMLPart::slotSecurity()
2832 {
2833 //   kdDebug( 6050 ) << "Meta Data:" << endl
2834 //                   << d->m_ssl_peer_cert_subject
2835 //                   << endl
2836 //                   << d->m_ssl_peer_cert_issuer
2837 //                   << endl
2838 //                   << d->m_ssl_cipher
2839 //                   << endl
2840 //                   << d->m_ssl_cipher_desc
2841 //                   << endl
2842 //                   << d->m_ssl_cipher_version
2843 //                   << endl
2844 //                   << d->m_ssl_good_from
2845 //                   << endl
2846 //                   << d->m_ssl_good_until
2847 //                   << endl
2848 //                   << d->m_ssl_cert_state
2849 //                   << endl;
2850
2851   KSSLInfoDlg *kid = new KSSLInfoDlg(d->m_ssl_in_use, widget(), "kssl_info_dlg", true );
2852
2853   if (d->m_bSecurityInQuestion)
2854           kid->setSecurityInQuestion(true);
2855
2856   if (d->m_ssl_in_use) {
2857     KSSLCertificate *x = KSSLCertificate::fromString(d->m_ssl_peer_certificate.local8Bit());
2858     if (x) {
2859        // Set the chain back onto the certificate
2860        QStringList cl = QStringList::split(QString("\n"), d->m_ssl_peer_chain);
2861        QPtrList<KSSLCertificate> ncl;
2862
2863        ncl.setAutoDelete(true);
2864        for (QStringList::Iterator it = cl.begin(); it != cl.end(); ++it) {
2865           KSSLCertificate *y = KSSLCertificate::fromString((*it).local8Bit());
2866           if (y) ncl.append(y);
2867        }
2868
2869        if (ncl.count() > 0)
2870           x->chain().setChain(ncl);
2871
2872        kid->setup(x,
2873                   d->m_ssl_peer_ip,
2874                   m_url.url(),
2875                   d->m_ssl_cipher,
2876                   d->m_ssl_cipher_desc,
2877                   d->m_ssl_cipher_version,
2878                   d->m_ssl_cipher_used_bits.toInt(),
2879                   d->m_ssl_cipher_bits.toInt(),
2880                   (KSSLCertificate::KSSLValidation) d->m_ssl_cert_state.toInt()
2881                   );
2882         kid->exec();
2883         delete x;
2884      } else kid->exec();
2885   } else kid->exec();
2886 }
2887
2888 void KHTMLPart::slotSaveFrame()
2889 {
2890     if ( !d->m_activeFrame )
2891         return; // should never be the case, but one never knows :-)
2892
2893     KURL srcURL( static_cast<KParts::ReadOnlyPart *>( d->m_activeFrame )->url() );
2894
2895     if ( srcURL.fileName(false).isEmpty() )
2896         srcURL.setFileName( "index.html" );
2897
2898     KIO::MetaData metaData;
2899     // Referrer unknown?
2900     KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), srcURL, metaData, i18n("*.html *.htm|HTML files") );
2901 }
2902
2903 void KHTMLPart::slotSetEncoding()
2904 {
2905     // first Item is always auto
2906     if(d->m_paSetEncoding->currentItem() == 0)
2907         setEncoding(QString::null, false);
2908     else {
2909         // strip of the language to get the raw encoding again.
2910         QString enc = KGlobal::charsets()->encodingForName(d->m_paSetEncoding->currentText());
2911         setEncoding(enc, true);
2912     }
2913 }
2914
2915 void KHTMLPart::slotUseStylesheet()
2916 {
2917   if (d->m_doc && d->m_paUseStylesheet->currentText() != d->m_sheetUsed) {
2918     d->m_sheetUsed = d->m_paUseStylesheet->currentText();
2919     d->m_doc->updateStyleSelector();
2920   }
2921 }
2922
2923 void KHTMLPart::updateActions()
2924 {
2925   bool frames = false;
2926
2927   QValueList<khtml::ChildFrame>::ConstIterator it = d->m_frames.begin();
2928   QValueList<khtml::ChildFrame>::ConstIterator end = d->m_frames.end();
2929   for (; it != end; ++it )
2930       if ( (*it).m_type == khtml::ChildFrame::Frame )
2931       {
2932           frames = true;
2933           break;
2934       }
2935
2936   d->m_paViewFrame->setEnabled( frames );
2937   d->m_paSaveFrame->setEnabled( frames );
2938
2939   if ( frames )
2940     d->m_paFind->setText( i18n( "&Find in Frame..." ) );
2941   else
2942     d->m_paFind->setText( i18n( "&Find..." ) );
2943
2944   KParts::Part *frame = 0;
2945
2946   if ( frames )
2947     frame = currentFrame();
2948
2949   bool enableFindAndSelectAll = true;
2950
2951   if ( frame )
2952     enableFindAndSelectAll = frame->inherits( "KHTMLPart" );
2953
2954   d->m_paFind->setEnabled( enableFindAndSelectAll );
2955   d->m_paSelectAll->setEnabled( enableFindAndSelectAll );
2956
2957   bool enablePrintFrame = false;
2958
2959   if ( frame )
2960   {
2961     QObject *ext = KParts::BrowserExtension::childObject( frame );
2962     if ( ext )
2963       enablePrintFrame = ext->metaObject()->slotNames().contains( "print()" );
2964   }
2965
2966   d->m_paPrintFrame->setEnabled( enablePrintFrame );
2967
2968   QString bgURL;
2969
2970   // ### frames
2971   if ( d->m_doc && d->m_doc->isHTMLDocument() && static_cast<HTMLDocumentImpl*>(d->m_doc)->body() && !d->m_bClearing )
2972     bgURL = static_cast<HTMLDocumentImpl*>(d->m_doc)->body()->getAttribute( ATTR_BACKGROUND ).string();
2973
2974   d->m_paSaveBackground->setEnabled( !bgURL.isEmpty() );
2975 }
2976
2977 #endif
2978
2979 bool KHTMLPart::requestFrame( khtml::RenderPart *frame, const QString &url, const QString &frameName,
2980                               const QStringList &params, bool isIFrame )
2981 {
2982 //  kdDebug( 6050 ) << "childRequest( ..., " << url << ", " << frameName << " )" << endl;
2983   FrameIt it = d->m_frames.find( frameName );
2984   if ( it == d->m_frames.end() )
2985   {
2986     khtml::ChildFrame child;
2987 //    kdDebug( 6050 ) << "inserting new frame into frame map " << frameName << endl;
2988     child.m_name = frameName;
2989     it = d->m_frames.append( child );
2990   }
2991
2992   (*it).m_type = isIFrame ? khtml::ChildFrame::IFrame : khtml::ChildFrame::Frame;
2993   (*it).m_frame = frame;
2994   (*it).m_params = params;
2995
2996   // Support for <frame src="javascript:string">
2997   if ( url.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 )
2998   {
2999     if (!processObjectRequest(&(*it), "about:blank", "text/html" ))
3000       return false;
3001
3002     KHTMLPart *newPart = static_cast<KHTMLPart *>(&*(*it).m_part); 
3003     newPart->replaceContentsWithScriptResult( url );
3004
3005     return true;
3006   }
3007
3008   return requestObject( &(*it), completeURL( url ));
3009 }
3010
3011 QString KHTMLPart::requestFrameName()
3012 {
3013 #if APPLE_CHANGES
3014     return KWQ(this)->generateFrameName();
3015 #else
3016     return QString::fromLatin1("<!--frame %1-->").arg(d->m_frameNameId++);
3017 #endif
3018 }
3019
3020 bool KHTMLPart::requestObject( khtml::RenderPart *frame, const QString &url, const QString &serviceType,
3021                                const QStringList &params )
3022 {
3023   khtml::ChildFrame child;
3024   QValueList<khtml::ChildFrame>::Iterator it = d->m_objects.append( child );
3025   (*it).m_frame = frame;
3026   (*it).m_type = khtml::ChildFrame::Object;
3027   (*it).m_params = params;
3028
3029   KURL completedURL;
3030   if (!url.isEmpty())
3031     completedURL = completeURL(url);
3032
3033   KParts::URLArgs args;
3034   args.serviceType = serviceType;
3035   return requestObject( &(*it), completedURL, args );
3036 }
3037
3038 bool KHTMLPart::requestObject( khtml::ChildFrame *child, const KURL &url, const KParts::URLArgs &_args )
3039 {
3040 #if !APPLE_CHANGES
3041   if (!checkLinkSecurity(url))
3042     return false;
3043 #endif
3044   if ( child->m_bPreloaded )
3045   {
3046     // kdDebug(6005) << "KHTMLPart::requestObject preload" << endl;
3047     if ( child->m_frame && child->m_part && child->m_part->widget() )
3048       child->m_frame->setWidget( child->m_part->widget() );
3049
3050     child->m_bPreloaded = false;
3051     return true;
3052   }
3053
3054   KParts::URLArgs args( _args );
3055
3056 #if !APPLE_CHANGES
3057   if ( child->m_run )
3058     child->m_run->abort();
3059 #endif
3060
3061   if ( child->m_part && !args.reload && urlcmp( child->m_part->url().url(), url.url(), true, true ) )
3062     args.serviceType = child->m_serviceType;
3063
3064   child->m_args = args;
3065   child->m_args.reload = (d->m_cachePolicy == KIO::CC_Reload) || (d->m_cachePolicy == KIO::CC_Refresh);
3066   child->m_serviceName = QString::null;
3067   if (!d->m_referrer.isEmpty() && !child->m_args.metaData().contains( "referrer" ))
3068     child->m_args.metaData()["referrer"] = d->m_referrer;
3069
3070 #if !APPLE_CHANGES
3071   child->m_args.metaData().insert("main_frame_request",
3072                                   parentPart() == 0 ? "TRUE":"FALSE");
3073   child->m_args.metaData().insert("ssl_was_in_use",
3074                                   d->m_ssl_in_use ? "TRUE":"FALSE");
3075   child->m_args.metaData().insert("ssl_activate_warnings", "TRUE");
3076 #endif
3077
3078   // We want a KHTMLPart if the HTML says <frame src=""> or <frame src="about:blank">
3079   if ((url.isEmpty() || url.url() == "about:blank") && args.serviceType.isEmpty())
3080     args.serviceType = QString::fromLatin1( "text/html" );
3081
3082 #if APPLE_CHANGES
3083   return processObjectRequest( child, url, args.serviceType );
3084 #else
3085   if ( args.serviceType.isEmpty() ) {
3086     child->m_run = new KHTMLRun( this, child, url, child->m_args,
3087                                  child->m_type != khtml::ChildFrame::Frame );
3088     return false;
3089   } else {
3090     return processObjectRequest( child, url, args.serviceType );
3091   }
3092 #endif
3093 }
3094
3095 bool KHTMLPart::processObjectRequest( khtml::ChildFrame *child, const KURL &_url, const QString &mimetype )
3096 {
3097   //kdDebug( 6050 ) << "KHTMLPart::processObjectRequest trying to create part for " << mimetype << endl;
3098
3099   // IMPORTANT: create a copy of the url here, because it is just a reference, which was likely to be given
3100   // by an emitting frame part (emit openURLRequest( blahurl, ... ) . A few lines below we delete the part
3101   // though -> the reference becomes invalid -> crash is likely
3102   KURL url( _url );
3103
3104   // khtmlrun called us this way to indicate a loading error
3105   if ( d->m_onlyLocalReferences || ( url.isEmpty() && mimetype.isEmpty() ) )
3106   {
3107       checkEmitLoadEvent();
3108       child->m_bCompleted = true;
3109       return true;
3110   }
3111
3112   if (child->m_bNotify)
3113   {
3114       child->m_bNotify = false;
3115       if ( !child->m_args.lockHistory() )
3116           emit d->m_extension->openURLNotify();
3117   }
3118
3119 #if APPLE_CHANGES
3120   if ( child->m_part )
3121   {
3122     KHTMLPart *part = dynamic_cast<KHTMLPart *>(&*child->m_part);
3123     if (part)
3124       part->openURL(url);
3125   }
3126   else
3127   {
3128     KParts::ReadOnlyPart *part = KWQ(this)->createPart(*child, url, mimetype);
3129     KHTMLPart *khtml_part = dynamic_cast<KHTMLPart *>(part);
3130     if (khtml_part)
3131       khtml_part->childBegin();
3132 #else
3133   if ( !child->m_services.contains( mimetype ) )
3134   {
3135     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 );
3136 #endif
3137
3138     if ( !part )
3139     {
3140         if ( child->m_frame )
3141           if (child->m_frame->partLoadingErrorNotify( child, url, mimetype ))
3142             return true; // we succeeded after all (a fallback was used)
3143
3144         checkEmitLoadEvent();
3145         return false;
3146     }
3147
3148     //CRITICAL STUFF
3149     if ( child->m_part )
3150     {
3151       disconnectChild(child);
3152 #if !APPLE_CHANGES
3153       partManager()->removePart( (KParts::ReadOnlyPart *)child->m_part );
3154 #endif
3155       child->m_part->deref();
3156     }
3157
3158     child->m_serviceType = mimetype;
3159     if ( child->m_frame && part->widget() )
3160       child->m_frame->setWidget( part->widget() );
3161
3162 #if !APPLE_CHANGES
3163     if ( child->m_type != khtml::ChildFrame::Object )
3164       partManager()->addPart( part, false );
3165 //  else
3166 //      kdDebug(6005) << "AH! NO FRAME!!!!!" << endl;
3167 #endif
3168
3169     child->m_part = part;
3170     assert( ((void*) child->m_part) != 0);
3171
3172     connectChild(child);
3173
3174 #if APPLE_CHANGES
3175   }
3176 #else
3177     child->m_extension = KParts::BrowserExtension::childObject( part );
3178
3179     if ( child->m_extension )
3180     {
3181       connect( child->m_extension, SIGNAL( openURLNotify() ),
3182                d->m_extension, SIGNAL( openURLNotify() ) );
3183
3184       connect( child->m_extension, SIGNAL( openURLRequestDelayed( const KURL &, const KParts::URLArgs & ) ),
3185                this, SLOT( slotChildURLRequest( const KURL &, const KParts::URLArgs & ) ) );
3186
3187       connect( child->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ),
3188                d->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ) );
3189       connect( child->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs &, const KParts::WindowArgs &, KParts::ReadOnlyPart *& ) ),
3190                d->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & , const KParts::WindowArgs &, KParts::ReadOnlyPart *&) ) );
3191
3192       connect( child->m_extension, SIGNAL( popupMenu( const QPoint &, const KFileItemList & ) ),
3193                d->m_extension, SIGNAL( popupMenu( const QPoint &, const KFileItemList & ) ) );
3194       connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList & ) ),
3195                d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList & ) ) );
3196       connect( child->m_extension, SIGNAL( popupMenu( const QPoint &, const KURL &, const QString &, mode_t ) ),
3197                d->m_extension, SIGNAL( popupMenu( const QPoint &, const KURL &, const QString &, mode_t ) ) );
3198       connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const QString &, mode_t ) ),
3199                d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const QString &, mode_t ) ) );
3200
3201       connect( child->m_extension, SIGNAL( infoMessage( const QString & ) ),
3202                d->m_extension, SIGNAL( infoMessage( const QString & ) ) );
3203
3204       child->m_extension->setBrowserInterface( d->m_extension->browserInterface() );
3205     }
3206   }
3207 #endif
3208
3209   checkEmitLoadEvent();
3210   // Some JS code in the load event may have destroyed the part
3211   // In that case, abort
3212   if ( !child->m_part )
3213     return false;
3214
3215   if ( child->m_bPreloaded )
3216   {
3217     if ( child->m_frame && child->m_part )
3218       child->m_frame->setWidget( child->m_part->widget() );
3219
3220     child->m_bPreloaded = false;
3221     return true;
3222   }
3223
3224   child->m_args.reload = (d->m_cachePolicy == KIO::CC_Reload) || (d->m_cachePolicy == KIO::CC_Refresh);
3225
3226   // make sure the part has a way to find out about the mimetype.
3227   // we actually set it in child->m_args in requestObject already,
3228   // but it's useless if we had to use a KHTMLRun instance, as the
3229   // point the run object is to find out exactly the mimetype.
3230   child->m_args.serviceType = mimetype;
3231
3232   child->m_bCompleted = false;
3233   if ( child->m_extension )
3234     child->m_extension->setURLArgs( child->m_args );
3235
3236 #if APPLE_CHANGES
3237     // In these cases, the synchronous load would have finished
3238     // before we could connect the signals, so make sure to send the
3239     // completed() signal for the child by hand:
3240     if (url.isEmpty() || url.url() == "about:blank") {
3241       ReadOnlyPart *readOnlyPart = child->m_part;
3242       KHTMLPart *part = dynamic_cast<KHTMLPart *>(readOnlyPart);
3243       if (part) {
3244         part->completed();
3245       }
3246     }
3247 #else
3248   if(url.protocol() == "javascript" || url.url() == "about:blank") {
3249       if (!child->m_part->inherits("KHTMLPart"))
3250           return false;
3251
3252       KHTMLPart* p = static_cast<KHTMLPart*>(static_cast<KParts::ReadOnlyPart *>(child->m_part));
3253
3254       p->begin();
3255       if (d->m_doc && p->d->m_doc)
3256         p->d->m_doc->setBaseURL(d->m_doc->baseURL());
3257       if (!url.url().startsWith("about:")) {
3258         p->write(url.path());
3259       } else {
3260         p->m_url = url;
3261       }
3262       p->end();
3263       return true;
3264   }
3265   else if ( !url.isEmpty() )
3266   {
3267       //kdDebug( 6050 ) << "opening " << url.url() << " in frame " << child->m_part << endl;
3268       return child->m_part->openURL( url );
3269   }
3270   else
3271 #endif
3272       return true;
3273 }
3274
3275 #if !APPLE_CHANGES
3276
3277 KParts::ReadOnlyPart *KHTMLPart::createPart( QWidget *parentWidget, const char *widgetName,
3278                                              QObject *parent, const char *name, const QString &mimetype,
3279                                              QString &serviceName, QStringList &serviceTypes,
3280                                              const QStringList &params )
3281 {
3282   QString constr;
3283   if ( !serviceName.isEmpty() )
3284     constr.append( QString::fromLatin1( "Name == '%1'" ).arg( serviceName ) );
3285
3286   KTrader::OfferList offers = KTrader::self()->query( mimetype, "KParts/ReadOnlyPart", constr, QString::null );
3287
3288   if ( offers.isEmpty() )
3289     return 0L;
3290
3291   KService::Ptr service = *offers.begin();
3292
3293   KLibFactory *factory = KLibLoader::self()->factory( QFile::encodeName(service->library()) );
3294
3295   if ( !factory )
3296     return 0L;
3297
3298   KParts::ReadOnlyPart *res = 0L;
3299
3300   const char *className = "KParts::ReadOnlyPart";
3301   if ( service->serviceTypes().contains( "Browser/View" ) )
3302     className = "Browser/View";
3303
3304   if ( factory->inherits( "KParts::Factory" ) )
3305     res = static_cast<KParts::ReadOnlyPart *>(static_cast<KParts::Factory *>( factory )->createPart( parentWidget, widgetName, parent, name, className, params ));
3306   else
3307   res = static_cast<KParts::ReadOnlyPart *>(factory->create( parentWidget, widgetName, className ));
3308
3309   if ( !res )
3310     return res;
3311
3312   serviceTypes = service->serviceTypes();
3313   serviceName = service->name();
3314
3315   return res;
3316 }
3317
3318 KParts::PartManager *KHTMLPart::partManager()
3319 {
3320   if ( !d->m_manager )
3321   {
3322     d->m_manager = new KParts::PartManager( d->m_view->topLevelWidget(), this, "khtml part manager" );
3323     d->m_manager->setAllowNestedParts( true );
3324     connect( d->m_manager, SIGNAL( activePartChanged( KParts::Part * ) ),
3325              this, SLOT( slotActiveFrameChanged( KParts::Part * ) ) );
3326     connect( d->m_manager, SIGNAL( partRemoved( KParts::Part * ) ),
3327              this, SLOT( slotPartRemoved( KParts::Part * ) ) );
3328   }
3329
3330   return d->m_manager;
3331 }
3332
3333 #endif
3334
3335 void KHTMLPart::submitFormAgain()
3336 {
3337   if( d->m_doc && !d->m_doc->parsing() && d->m_submitForm)
3338     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 );
3339
3340   delete d->m_submitForm;
3341   d->m_submitForm = 0;
3342   disconnect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
3343 }
3344
3345 void KHTMLPart::submitForm( const char *action, const QString &url, const QByteArray &formData, const QString &_target, const QString& contentType, const QString& boundary )
3346 {
3347   kdDebug(6000) << this << ": KHTMLPart::submitForm target=" << _target << " url=" << url << endl;
3348   KURL u = completeURL( url );
3349
3350   if ( !u.isValid() )
3351   {
3352     // ### ERROR HANDLING!
3353     return;
3354   }
3355
3356 #if !APPLE_CHANGES
3357   // Form security checks
3358   //
3359
3360   /* This is separate for a reason.  It has to be _before_ all script, etc,
3361    * AND I don't want to break anything that uses checkLinkSecurity() in
3362    * other places.
3363    */
3364
3365   // This causes crashes... needs to be fixed.
3366   if (!d->m_submitForm && u.protocol() != "https" && u.protocol() != "mailto") {
3367         if (d->m_ssl_in_use) {    // Going from SSL -> nonSSL
3368                 int rc = KMessageBox::warningContinueCancel(NULL, i18n("Warning:  This is a secure form but it is attempting to send your data back unencrypted."
3369                                         "\nA third party may be able to intercept and view this information."
3370                                         "\nAre you sure you wish to continue?"),
3371                                 i18n("SSL"));
3372                 if (rc == KMessageBox::Cancel)
3373                         return;
3374         } else {                  // Going from nonSSL -> nonSSL
3375                 KSSLSettings kss(true);
3376                 if (kss.warnOnUnencrypted()) {
3377                         int rc = KMessageBox::warningContinueCancel(NULL,
3378                                         i18n("Warning: Your data is about to be transmitted across the network unencrypted."
3379                                         "\nAre you sure you wish to continue?"),
3380                                         i18n("KDE"),
3381                                                                     QString::null,
3382                                         "WarnOnUnencryptedForm");
3383                         // Move this setting into KSSL instead
3384                         KConfig *config = kapp->config();
3385                         QString grpNotifMsgs = QString::fromLatin1("Notification Messages");
3386                         KConfigGroupSaver saver( config, grpNotifMsgs );
3387
3388                         if (!config->readBoolEntry("WarnOnUnencryptedForm", true)) {
3389                                 config->deleteEntry("WarnOnUnencryptedForm");
3390                                 config->sync();
3391                                 kss.setWarnOnUnencrypted(false);
3392                                 kss.save();
3393                         }
3394                         if (rc == KMessageBox::Cancel)
3395                           return;
3396         }
3397     }
3398   }
3399
3400   if (!d->m_submitForm && u.protocol() == "mailto") {
3401      int rc = KMessageBox::warningContinueCancel(NULL, 
3402                  i18n("This site is attempting to submit form data via email."),
3403                  i18n("KDE"), 
3404                  QString::null, 
3405                  "WarnTriedEmailSubmit");
3406
3407      if (rc == KMessageBox::Cancel) {
3408          return;
3409      }
3410   }
3411
3412   // End form security checks
3413   //
3414 #endif // APPLE_CHANGES
3415
3416   QString urlstring = u.url();
3417
3418   if ( urlstring.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
3419     urlstring = KURL::decode_string(urlstring);
3420     d->m_executingJavaScriptFormAction = true;
3421     executeScript( urlstring.right( urlstring.length() - 11) );
3422     d->m_executingJavaScriptFormAction = false;
3423     return;
3424   }
3425
3426 #if !APPLE_CHANGES
3427   if (!checkLinkSecurity(u,
3428                          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?" ),
3429                          i18n( "Submit" )))
3430     return;
3431 #endif
3432
3433   KParts::URLArgs args;
3434
3435   if (!d->m_referrer.isEmpty())
3436      args.metaData()["referrer"] = d->m_referrer;
3437
3438 #if !APPLE_CHANGES
3439   args.metaData().insert("main_frame_request",
3440                          parentPart() == 0 ? "TRUE":"FALSE");
3441   args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE");
3442   args.metaData().insert("ssl_activate_warnings", "TRUE");
3443 #endif
3444   args.frameName = _target.isEmpty() ? d->m_doc->baseTarget() : _target ;
3445
3446   // Handle mailto: forms
3447   if (u.protocol() == "mailto") {
3448       // 1)  Check for attach= and strip it
3449       QString q = u.query().mid(1);
3450       QStringList nvps = QStringList::split("&", q);
3451       bool triedToAttach = false;
3452
3453       for (QStringList::Iterator nvp = nvps.begin(); nvp != nvps.end(); ++nvp) {
3454          QStringList pair = QStringList::split("=", *nvp);
3455          if (pair.count() >= 2) {
3456             if (pair.first().lower() == "attach") {
3457                nvp = nvps.remove(nvp);
3458                triedToAttach = true;
3459             }
3460          }
3461       }
3462
3463 #if !APPLE_CHANGES
3464       if (triedToAttach)
3465          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");
3466 #endif
3467
3468       // 2)  Append body=
3469       QString bodyEnc;
3470       if (contentType.lower() == "multipart/form-data") {
3471          // FIXME: is this correct?  I suspect not
3472          bodyEnc = KURL::encode_string(QString::fromLatin1(formData.data(), 
3473                                                            formData.size()));
3474       } else if (contentType.lower() == "text/plain") {
3475          // Convention seems to be to decode, and s/&/\n/
3476          QString tmpbody = QString::fromLatin1(formData.data(), 
3477                                                formData.size());
3478          tmpbody.replace(QRegExp("[&]"), "\n");
3479          tmpbody.replace(QRegExp("[+]"), " ");
3480          tmpbody = KURL::decode_string(tmpbody);  // Decode the rest of it
3481          bodyEnc = KURL::encode_string(tmpbody);  // Recode for the URL
3482       } else {
3483          bodyEnc = KURL::encode_string(QString::fromLatin1(formData.data(), 
3484                                                            formData.size()));
3485       }
3486
3487       nvps.append(QString("body=%1").arg(bodyEnc));
3488       q = nvps.join("&");
3489       u.setQuery(q);
3490   } 
3491
3492   if ( strcmp( action, "get" ) == 0 ) {
3493     if (u.protocol() != "mailto")
3494        u.setQuery( QString::fromLatin1( formData.data(), formData.size() ) );
3495     args.setDoPost( false );
3496   }
3497   else {
3498     args.postData = formData;
3499     args.setDoPost( true );
3500
3501     // construct some user headers if necessary
3502     if (contentType.isNull() || contentType == "application/x-www-form-urlencoded")
3503       args.setContentType( "Content-Type: application/x-www-form-urlencoded" );
3504     else // contentType must be "multipart/form-data"
3505       args.setContentType( "Content-Type: " + contentType + "; boundary=" + boundary );
3506   }
3507
3508   if ( d->m_doc->parsing() || d->m_runningScripts > 0 ) {
3509     if( d->m_submitForm ) {
3510       kdDebug(6000) << "KHTMLPart::submitForm ABORTING!" << endl;
3511       return;
3512     }
3513     d->m_submitForm = new KHTMLPartPrivate::SubmitForm;
3514     d->m_submitForm->submitAction = action;
3515     d->m_submitForm->submitUrl = url;
3516     d->m_submitForm->submitFormData = formData;
3517     d->m_submitForm->target = _target;
3518     d->m_submitForm->submitContentType = contentType;
3519     d->m_submitForm->submitBoundary = boundary;
3520     connect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
3521   }
3522   else
3523   {
3524 #if APPLE_CHANGES
3525     KWQ(this)->submitForm( u, args);
3526 #else
3527     emit d->m_extension->openURLRequest( u, args );
3528 #endif
3529   }
3530 }
3531
3532 #if !APPLE_CHANGES
3533
3534 void KHTMLPart::popupMenu( const QString &linkUrl )
3535 {
3536   KURL popupURL;
3537   KURL linkKURL;
3538   if ( linkUrl.isEmpty() ) // click on background
3539     popupURL = this->url();
3540   else {               // click on link
3541     popupURL = completeURL( linkUrl );
3542     linkKURL = popupURL;
3543   }
3544
3545   KXMLGUIClient *client = new KHTMLPopupGUIClient( this, d->m_popupMenuXML, linkKURL );
3546
3547   emit d->m_extension->popupMenu( client, QCursor::pos(), popupURL,
3548                                   QString::fromLatin1( "text/html" ), S_IFREG /*always a file*/ );
3549
3550   delete client;
3551
3552   emit popupMenu(linkUrl, QCursor::pos());
3553 }
3554
3555 #endif
3556
3557 void KHTMLPart::slotParentCompleted()
3558 {
3559   if ( d->m_scheduledRedirection != noRedirectionScheduled && !d->m_redirectionTimer.isActive() )
3560   {
3561     // kdDebug(6050) << this << ": Child redirection -> " << d->m_redirectURL << endl;
3562     d->m_redirectionTimer.start( (int)(1000 * d->m_delayRedirect), true );
3563   }
3564 }
3565
3566 void KHTMLPart::slotChildStarted( KIO::Job *job )
3567 {
3568   khtml::ChildFrame *child = childFrame( sender() );
3569
3570   assert( child );
3571
3572   child->m_bCompleted = false;
3573
3574   if ( d->m_bComplete )
3575   {
3576 #if 0
3577     // WABA: Looks like this belongs somewhere else
3578     if ( !parentPart() ) // "toplevel" html document? if yes, then notify the hosting browser about the document (url) changes
3579     {
3580       emit d->m_extension->openURLNotify();
3581     }
3582 #endif
3583     d->m_bComplete = false;
3584     emit started( job );
3585   }
3586 }
3587
3588 void KHTMLPart::slotChildCompleted()
3589 {
3590   slotChildCompleted( false );
3591 }
3592
3593 void KHTMLPart::slotChildCompleted( bool complete )
3594 {
3595   khtml::ChildFrame *child = childFrame( sender() );
3596
3597   assert( child );
3598
3599   child->m_bCompleted = true;
3600   child->m_args = KParts::URLArgs();
3601
3602   if ( complete && parentPart() == 0 )
3603     d->m_bPendingChildRedirection = true;
3604
3605   checkCompleted();
3606 }
3607
3608 #if !APPLE_CHANGES
3609
3610 void KHTMLPart::slotChildURLRequest( const KURL &url, const KParts::URLArgs &args )
3611 {
3612   khtml::ChildFrame *child = childFrame( sender()->parent() );
3613
3614   QString frameName = args.frameName.lower();
3615   if ( !frameName.isEmpty() )
3616   {
3617     if ( frameName == QString::fromLatin1( "_top" ) )
3618     {
3619       emit d->m_extension->openURLRequest( url, args );
3620       return;
3621     }
3622     else if ( frameName == QString::fromLatin1( "_blank" ) )
3623     {
3624       emit d->m_extension->createNewWindow( url, args );
3625       return;
3626     }
3627     else if ( frameName == QString::fromLatin1( "_parent" ) )
3628     {
3629       KParts::URLArgs newArgs( args );
3630       newArgs.frameName = QString::null;
3631
3632       emit d->m_extension->openURLRequest( url, newArgs );
3633       return;
3634     }
3635     else if ( frameName != QString::fromLatin1( "_self" ) )
3636     {
3637       khtml::ChildFrame *_frame = recursiveFrameRequest( url, args );
3638
3639       if ( !_frame )
3640       {
3641         emit d->m_extension->openURLRequest( url, args );
3642         return;
3643       }
3644
3645       child = _frame;
3646     }
3647   }
3648
3649   // TODO: handle child target correctly! currently the script are always executed fur the parent
3650   QString urlStr = url.url();
3651   if ( urlStr.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
3652       executeScript( KURL::decode_string( urlStr.right( urlStr.length() - 11) ) );
3653       return;
3654   }
3655
3656   if ( child ) {
3657       // Inform someone that we are about to show something else.
3658       child->m_bNotify = true;
3659       requestObject( child, url, args );
3660   }  else if ( frameName==QString::fromLatin1("_self") ) // this is for embedded objects (via <object>) which want to replace the current document
3661   {
3662       KParts::URLArgs newArgs( args );
3663       newArgs.frameName = QString::null;
3664       emit d->m_extension->openURLRequest( url, newArgs );
3665   }
3666 }
3667
3668 #endif // APPLE_CHANGES
3669
3670 khtml::ChildFrame *KHTMLPart::childFrame( const QObject *obj )
3671 {
3672     assert( obj->inherits( "KParts::ReadOnlyPart" ) );
3673     const ReadOnlyPart *part = static_cast<const ReadOnlyPart *>( obj );
3674
3675     FrameIt it = d->m_frames.begin();
3676     FrameIt end = d->m_frames.end();
3677     for (; it != end; ++it )
3678       if ( static_cast<ReadOnlyPart *>((*it).m_part) == part )
3679         return &(*it);
3680
3681     it = d->m_objects.begin();
3682     end = d->m_objects.end();
3683     for (; it != end; ++it )
3684       if ( static_cast<ReadOnlyPart *>((*it).m_part) == part )
3685         return &(*it);
3686
3687     return 0L;
3688 }
3689
3690 KHTMLPart *KHTMLPart::findFrame( const QString &f )
3691 {
3692 #if 0
3693   kdDebug() << "KHTMLPart::findFrame '" << f << "'" << endl;
3694   FrameIt it2 = d->m_frames.begin();
3695   FrameIt end = d->m_frames.end();
3696   for (; it2 != end; ++it2 )
3697       kdDebug() << "  - having frame '" << (*it2).m_name << "'" << endl;
3698 #endif
3699
3700   // ### http://www.w3.org/TR/html4/appendix/notes.html#notes-frames
3701   ConstFrameIt it = d->m_frames.find( f );
3702   if ( it == d->m_frames.end() )
3703   {
3704     //kdDebug() << "KHTMLPart::findFrame frame " << f << " not found" << endl;
3705     return 0L;
3706   }
3707   else {
3708     KParts::ReadOnlyPart *p = (*it).m_part;
3709     if ( p && p->inherits( "KHTMLPart" ))
3710     {
3711       //kdDebug() << "KHTMLPart::findFrame frame " << f << " is a KHTMLPart, ok" << endl;
3712       return (KHTMLPart*)p;
3713     }
3714     else
3715     {
3716 #if 0
3717       if (p)
3718         kdWarning() << "KHTMLPart::findFrame frame " << f << " found but isn't a KHTMLPart ! " << p->className() << endl;
3719       else
3720         kdWarning() << "KHTMLPart::findFrame frame " << f << " found but m_part=0L" << endl;
3721 #endif
3722       return 0L;
3723     }
3724   }
3725 }
3726
3727 #if !APPLE_CHANGES
3728
3729 KParts::ReadOnlyPart *KHTMLPart::currentFrame() const
3730 {
3731   KParts::ReadOnlyPart* part = (KParts::ReadOnlyPart*)(this);
3732   // Find active part in our frame manager, in case we are a frameset
3733   // and keep doing that (in case of nested framesets).
3734   // Just realized we could also do this recursively, calling part->currentFrame()...
3735   while ( part && part->inherits("KHTMLPart") &&
3736           static_cast<KHTMLPart *>(part)->d->m_frames.count() > 0 ) {
3737     KHTMLPart* frameset = static_cast<KHTMLPart *>(part);
3738     part = static_cast<KParts::ReadOnlyPart *>(frameset->partManager()->activePart());
3739     if ( !part ) return frameset;
3740   }
3741   return part;
3742 }
3743
3744 #endif // APPLE_CHANGES
3745
3746 bool KHTMLPart::frameExists( const QString &frameName )
3747 {
3748   ConstFrameIt it = d->m_frames.find( frameName );
3749   if ( it == d->m_frames.end() )
3750     return false;
3751
3752   // WABA: We only return true if the child actually has a frame
3753   // set. Otherwise we might find our preloaded-selve.
3754   // This happens when we restore the frameset.
3755   return (!(*it).m_frame.isNull());
3756 }
3757
3758 KHTMLPart *KHTMLPart::parentPart() const
3759 {
3760   if ( !parent() || !parent()->inherits( "KHTMLPart" ) )
3761     return 0L;
3762
3763   return (KHTMLPart *)parent();
3764 }
3765
3766 #if !APPLE_CHANGES
3767
3768 khtml::ChildFrame *KHTMLPart::recursiveFrameRequest( const KURL &url, const KParts::URLArgs &args,
3769                                                      bool callParent )
3770 {
3771   FrameIt it = d->m_frames.find( args.frameName );
3772
3773   if ( it != d->m_frames.end() )
3774     return &(*it);
3775
3776   it = d->m_frames.begin();
3777   FrameIt end = d->m_frames.end();
3778   for (; it != end; ++it )
3779     if ( (*it).m_part && (*it).m_part->inherits( "KHTMLPart" ) )
3780     {
3781       KHTMLPart *childPart = (KHTMLPart *)(KParts::ReadOnlyPart *)(*it).m_part;
3782
3783       khtml::ChildFrame *res = childPart->recursiveFrameRequest( url, args, false );
3784       if ( !res )
3785         continue;
3786
3787       childPart->requestObject( res, url, args );
3788       return 0L;
3789     }
3790
3791   if ( parentPart() && callParent )
3792   {
3793     khtml::ChildFrame *res = parentPart()->recursiveFrameRequest( url, args );
3794
3795     if ( res )
3796       parentPart()->requestObject( res, url, args );
3797
3798     return 0L;
3799   }
3800
3801   return 0L;
3802 }
3803
3804 void KHTMLPart::saveState( QDataStream &stream )
3805 {
3806   kdDebug( 6050 ) << "KHTMLPart::saveState saving URL " << m_url.url() << endl;
3807
3808   stream << m_url << (Q_INT32)d->m_view->contentsX() << (Q_INT32)d->m_view->contentsY()
3809          << (Q_INT32) d->m_view->contentsWidth() << (Q_INT32) d->m_view->contentsHeight() << (Q_INT32) d->m_view->marginWidth() << (Q_INT32) d->m_view->marginHeight();
3810
3811   // save link cursor position
3812   int focusNodeNumber;
3813   if (!d->m_focusNodeRestored)
3814       focusNodeNumber = d->m_focusNodeNumber;
3815   else if (d->m_doc->focusNode())
3816       focusNodeNumber = d->m_doc->nodeAbsIndex(d->m_doc->focusNode());
3817   else
3818       focusNodeNumber = -1;
3819   stream << focusNodeNumber;
3820
3821   // Save the doc's cache id.
3822   stream << d->m_cacheId;
3823
3824   // Save the state of the document (Most notably the state of any forms)
3825   QStringList docState;
3826   if (d->m_doc)
3827   {
3828      docState = d->m_doc->docState();
3829   }
3830   stream << d->m_encoding << d->m_sheetUsed << docState;
3831
3832   stream << d->m_zoomFactor;
3833
3834   // Save ssl data
3835   stream << d->m_ssl_in_use
3836          << d->m_ssl_peer_certificate
3837          << d->m_ssl_peer_chain
3838          << d->m_ssl_peer_ip
3839          << d->m_ssl_cipher
3840          << d->m_ssl_cipher_desc
3841          << d->m_ssl_cipher_version
3842          << d->m_ssl_cipher_used_bits
3843          << d->m_ssl_cipher_bits
3844          << d->m_ssl_cert_state;
3845
3846
3847   QStringList frameNameLst, frameServiceTypeLst, frameServiceNameLst;
3848   KURL::List frameURLLst;
3849   QValueList<QByteArray> frameStateBufferLst;
3850
3851   ConstFrameIt it = d->m_frames.begin();
3852   ConstFrameIt end = d->m_frames.end();
3853   for (; it != end; ++it )
3854   {
3855     if ( !(*it).m_part )
3856        continue;
3857
3858     frameNameLst << (*it).m_name;
3859     frameServiceTypeLst << (*it).m_serviceType;
3860     frameServiceNameLst << (*it).m_serviceName;
3861     frameURLLst << (*it).m_part->url();
3862
3863     QByteArray state;
3864     QDataStream frameStream( state, IO_WriteOnly );
3865
3866     if ( (*it).m_extension )
3867       (*it).m_extension->saveState( frameStream );
3868
3869     frameStateBufferLst << state;
3870   }
3871
3872   // Save frame data
3873   stream << (Q_UINT32) frameNameLst.count();
3874   stream << frameNameLst << frameServiceTypeLst << frameServiceNameLst << frameURLLst << frameStateBufferLst;
3875 }
3876
3877 void KHTMLPart::restoreState( QDataStream &stream )
3878 {
3879   KURL u;
3880   Q_INT32 xOffset, yOffset, wContents, hContents, mWidth, mHeight;
3881   Q_UINT32 frameCount;
3882   QStringList frameNames, frameServiceTypes, docState, frameServiceNames;
3883   KURL::List frameURLs;
3884   QValueList<QByteArray> frameStateBuffers;
3885   QValueList<int> fSizes;
3886   QString encoding, sheetUsed;
3887   long old_cacheId = d->m_cacheId;
3888
3889   stream >> u >> xOffset >> yOffset >> wContents >> hContents >> mWidth >> mHeight;
3890
3891   d->m_view->setMarginWidth( mWidth );
3892   d->m_view->setMarginHeight( mHeight );
3893
3894   // restore link cursor position
3895   // nth node is active. value is set in checkCompleted()
3896   stream >> d->m_focusNodeNumber;
3897   d->m_focusNodeRestored = false;
3898   kdDebug(6050)<<"new focus Node number is:"<<d->m_focusNodeNumber<<endl;
3899
3900   stream >> d->m_cacheId;
3901
3902   stream >> encoding >> sheetUsed >> docState;
3903   d->m_encoding = encoding;
3904   d->m_sheetUsed = sheetUsed;
3905
3906   int zoomFactor;
3907   stream >> zoomFactor;
3908   setZoomFactor(zoomFactor);
3909
3910   // Restore ssl data
3911   stream >> d->m_ssl_in_use
3912          >> d->m_ssl_peer_certificate
3913          >> d->m_ssl_peer_chain
3914          >> d->m_ssl_peer_ip
3915          >> d->m_ssl_cipher
3916          >> d->m_ssl_cipher_desc
3917          >> d->m_ssl_cipher_version
3918          >> d->m_ssl_cipher_used_bits
3919          >> d->m_ssl_cipher_bits
3920          >> d->m_ssl_cert_state;
3921
3922   d->m_paSecurity->setIcon( d->m_ssl_in_use ? "encrypted" : "decrypted" );
3923
3924   stream >> frameCount >> frameNames >> frameServiceTypes >> frameServiceNames
3925          >> frameURLs >> frameStateBuffers;
3926
3927   d->m_bComplete = false;
3928   d->m_bLoadEventEmitted = false;
3929
3930 //   kdDebug( 6050 ) << "restoreStakte() docState.count() = " << docState.count() << endl;
3931 //   kdDebug( 6050 ) << "m_url " << m_url.url() << " <-> " << u.url() << endl;
3932 //   kdDebug( 6050 ) << "m_frames.count() " << d->m_frames.count() << " <-> " << frameCount << endl;
3933
3934   if (d->m_cacheId == old_cacheId)
3935   {
3936     // Partial restore
3937     cancelRedirection();
3938
3939     FrameIt fIt = d->m_frames.begin();
3940     FrameIt fEnd = d->m_frames.end();
3941
3942     for (; fIt != fEnd; ++fIt )
3943         (*fIt).m_bCompleted = false;
3944
3945     fIt = d->m_frames.begin();
3946
3947     QStringList::ConstIterator fNameIt = frameNames.begin();
3948     QStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin();
3949     QStringList::ConstIterator fServiceNameIt = frameServiceNames.begin();
3950     KURL::List::ConstIterator fURLIt = frameURLs.begin();
3951     QValueList<QByteArray>::ConstIterator fBufferIt = frameStateBuffers.begin();
3952
3953     for (; fIt != fEnd; ++fIt, ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt )
3954     {
3955       khtml::ChildFrame *child = &(*fIt);
3956
3957 //      kdDebug( 6050 ) <<  *fNameIt  << " ---- " <<  *fServiceTypeIt << endl;
3958
3959       if ( child->m_name != *fNameIt || child->m_serviceType != *fServiceTypeIt )
3960       {
3961         child->m_bPreloaded = true;
3962         child->m_name = *fNameIt;
3963         child->m_serviceName = *fServiceNameIt;
3964         processObjectRequest( child, *fURLIt, *fServiceTypeIt );
3965       }
3966
3967       if ( child->m_part )
3968       {
3969         child->m_bCompleted = false;
3970         if ( child->m_extension && !(*fBufferIt).isEmpty() )
3971         {
3972           QDataStream frameStream( *fBufferIt, IO_ReadOnly );
3973           child->m_extension->restoreState( frameStream );
3974         }
3975         else
3976           child->m_part->openURL( *fURLIt );
3977       }
3978     }
3979
3980     KParts::URLArgs args( d->m_extension->urlArgs() );
3981     args.xOffset = xOffset;
3982     args.yOffset = yOffset;
3983     args.docState = docState; // WABA: How are we going to restore this??
3984     d->m_extension->setURLArgs( args );
3985
3986     d->m_view->resizeContents( wContents,  hContents);
3987     d->m_view->setContentsPos( xOffset, yOffset );
3988   }
3989   else
3990   {
3991     // Full restore.
3992     closeURL();
3993     // We must force a clear because we want to be sure to delete all
3994     // frames.
3995     d->m_bCleared = false;
3996     clear();
3997     d->m_encoding = encoding;
3998     d->m_sheetUsed = sheetUsed;
3999
4000     QStringList::ConstIterator fNameIt = frameNames.begin();
4001     QStringList::ConstIterator fNameEnd = frameNames.end();
4002
4003     QStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin();
4004     QStringList::ConstIterator fServiceNameIt = frameServiceNames.begin();
4005     KURL::List::ConstIterator fURLIt = frameURLs.begin();
4006     QValueList<QByteArray>::ConstIterator fBufferIt = frameStateBuffers.begin();
4007
4008     for (; fNameIt != fNameEnd; ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt )
4009     {
4010       khtml::ChildFrame newChild;
4011       newChild.m_bPreloaded = true;
4012       newChild.m_name = *fNameIt;
4013       newChild.m_serviceName = *fServiceNameIt;
4014
4015 //      kdDebug( 6050 ) << *fNameIt << " ---- " << *fServiceTypeIt << endl;
4016
4017       FrameIt childFrame = d->m_frames.append( newChild );
4018
4019       processObjectRequest( &(*childFrame), *fURLIt, *fServiceTypeIt );
4020
4021       (*childFrame).m_bPreloaded = true;
4022
4023       if ( (*childFrame).m_part )
4024       {
4025         if ( (*childFrame).m_extension )
4026         if ( (*childFrame).m_extension && !(*fBufferIt).isEmpty() )
4027         {
4028           QDataStream frameStream( *fBufferIt, IO_ReadOnly );
4029           (*childFrame).m_extension->restoreState( frameStream );
4030         }
4031         else
4032           (*childFrame).m_part->openURL( *fURLIt );
4033       }
4034     }
4035
4036     KParts::URLArgs args( d->m_extension->urlArgs() );
4037     args.xOffset = xOffset;
4038     args.yOffset = yOffset;
4039     args.docState = docState;
4040     d->m_extension->setURLArgs( args );
4041     if (!KHTMLPageCache::self()->isValid(d->m_cacheId))
4042     {
4043        d->m_restored = true;
4044        openURL( u );
4045        d->m_restored = false;
4046     }
4047     else
4048     {
4049        restoreURL( u );
4050     }
4051   }
4052
4053 }
4054
4055 void KHTMLPart::show()
4056 {
4057   if ( d->m_view )
4058     d->m_view->show();
4059 }
4060
4061 void KHTMLPart::hide()
4062 {
4063   if ( d->m_view )
4064     d->m_view->hide();
4065 }
4066
4067 #endif // APPLE_CHANGES
4068
4069 DOM::Node KHTMLPart::nodeUnderMouse() const
4070 {
4071     return d->m_view->nodeUnderMouse();
4072 }
4073
4074 void KHTMLPart::emitSelectionChanged()
4075 {
4076 #if !APPLE_CHANGES
4077   emit d->m_extension->enableAction( "copy", hasSelection() );
4078   emit d->m_extension->selectionInfo( selectedText() );
4079   emit selectionChanged();
4080 #endif
4081 }
4082
4083 int KHTMLPart::zoomFactor() const
4084 {
4085   return d->m_zoomFactor;
4086 }
4087
4088 // ### make the list configurable ?
4089 static const int zoomSizes[] = { 20, 40, 60, 80, 90, 95, 100, 105, 110, 120, 140, 160, 180, 200, 250, 300 };
4090 static const int zoomSizeCount = (sizeof(zoomSizes) / sizeof(int));
4091 static const int minZoom = 20;
4092 static const int maxZoom = 300;
4093
4094 void KHTMLPart::slotIncZoom()
4095 {
4096   int zoomFactor = d->m_zoomFactor;
4097
4098   if (zoomFactor < maxZoom) {
4099     // find the entry nearest to the given zoomsizes
4100     for (int i = 0; i < zoomSizeCount; ++i)
4101       if (zoomSizes[i] > zoomFactor) {
4102         zoomFactor = zoomSizes[i];
4103         break;
4104       }
4105     setZoomFactor(zoomFactor);
4106   }
4107 }
4108
4109 void KHTMLPart::slotDecZoom()
4110 {
4111     int zoomFactor = d->m_zoomFactor;
4112     if (zoomFactor > minZoom) {
4113       // find the entry nearest to the given zoomsizes
4114       for (int i = zoomSizeCount-1; i >= 0; --i)
4115         if (zoomSizes[i] < zoomFactor) {
4116           zoomFactor = zoomSizes[i];
4117           break;
4118         }
4119       setZoomFactor(zoomFactor);
4120     }
4121 }
4122
4123 void KHTMLPart::setZoomFactor (int percent)
4124 {
4125 #if !APPLE_CHANGES // limits are client's responsibility
4126   if (percent < minZoom) percent = minZoom;
4127   if (percent > maxZoom) percent = maxZoom;
4128 #endif
4129   
4130   if (d->m_zoomFactor == percent) return;
4131   d->m_zoomFactor = percent;
4132
4133   if(d->m_doc) {
4134 #if !APPLE_CHANGES
4135       QApplication::setOverrideCursor( waitCursor );
4136 #endif
4137     d->m_doc->recalcStyle( NodeImpl::Force );
4138 #if !APPLE_CHANGES
4139     QApplication::restoreOverrideCursor();
4140 #endif
4141   }
4142
4143   ConstFrameIt it = d->m_frames.begin();
4144   ConstFrameIt end = d->m_frames.end();
4145   for (; it != end; ++it )
4146     if ( !( *it ).m_part.isNull() && ( *it ).m_part->inherits( "KHTMLPart" ) ) {
4147       KParts::ReadOnlyPart* p = ( *it ).m_part;
4148       static_cast<KHTMLPart*>( p )->setZoomFactor(d->m_zoomFactor);
4149     }
4150
4151 #if !APPLE_CHANGES
4152   d->m_paDecZoomFactor->setEnabled( d->m_zoomFactor > minZoom );
4153   d->m_paIncZoomFactor->setEnabled( d->m_zoomFactor < maxZoom );
4154 #endif
4155
4156   if (d->m_doc && d->m_doc->renderer() && d->m_doc->renderer()->needsLayout())
4157     view()->layout();
4158 }
4159
4160 void KHTMLPart::setJSStatusBarText( const QString &text )
4161 {
4162    d->m_kjsStatusBarText = text;
4163    emit setStatusBarText( d->m_kjsStatusBarText );
4164 }
4165
4166 void KHTMLPart::setJSDefaultStatusBarText( const QString &text )
4167 {
4168    d->m_kjsDefaultStatusBarText = text;
4169    emit setStatusBarText( d->m_kjsDefaultStatusBarText );
4170 }
4171
4172 QString KHTMLPart::jsStatusBarText() const
4173 {
4174     return d->m_kjsStatusBarText;
4175 }
4176
4177 QString KHTMLPart::jsDefaultStatusBarText() const
4178 {
4179    return d->m_kjsDefaultStatusBarText;
4180 }
4181
4182 QString KHTMLPart::referrer() const
4183 {
4184    return d->m_referrer;
4185 }
4186
4187 QString KHTMLPart::lastModified() const
4188 {
4189   return d->m_lastModified;
4190 }
4191
4192 #if !APPLE_CHANGES
4193
4194 void KHTMLPart::slotLoadImages()
4195 {
4196   if (d->m_doc )
4197     d->m_doc->docLoader()->setAutoloadImages( !d->m_doc->docLoader()->autoloadImages() );
4198
4199   ConstFrameIt it = d->m_frames.begin();
4200   ConstFrameIt end = d->m_frames.end();
4201   for (; it != end; ++it )
4202     if ( !( *it ).m_part.isNull() && ( *it ).m_part->inherits( "KHTMLPart" ) ) {
4203       KParts::ReadOnlyPart* p = ( *it ).m_part;
4204       static_cast<KHTMLPart*>( p )->slotLoadImages();
4205     }
4206 }
4207
4208 #endif
4209
4210 void KHTMLPart::reparseConfiguration()
4211 {
4212 #if !APPLE_CHANGES
4213   setAutoloadImages( settings->autoLoadImages() );
4214   if (d->m_doc)
4215      d->m_doc->docLoader()->setShowAnimations( settings->showAnimations() );
4216
4217   d->m_bJScriptEnabled = settings->isJavaScriptEnabled(m_url.host());
4218   d->m_bJScriptDebugEnabled = settings->isJavaScriptDebugEnabled();
4219   d->m_bJavaEnabled = settings->isJavaEnabled(m_url.host());
4220   d->m_bPluginsEnabled = settings->isPluginsEnabled(m_url.host());
4221   delete d->m_settings;
4222   d->m_settings = new KHTMLSettings(*KHTMLFactory::defaultHTMLSettings());
4223
4224   QString userStyleSheet = KHTMLFactory::defaultHTMLSettings()->userStyleSheet();
4225 #else
4226   setAutoloadImages( d->m_settings->autoLoadImages() );
4227   if (d->m_doc)
4228      d->m_doc->docLoader()->setShowAnimations( d->m_settings->showAnimations() );
4229
4230   d->m_bJScriptEnabled = d->m_settings->isJavaScriptEnabled(m_url.host());
4231   d->m_bJScriptDebugEnabled = d->m_settings->isJavaScriptDebugEnabled();
4232   d->m_bJavaEnabled = d->m_settings->isJavaEnabled(m_url.host());
4233   d->m_bPluginsEnabled = d->m_settings->isPluginsEnabled(m_url.host());
4234
4235   QString userStyleSheet = d->m_settings->userStyleSheet();
4236 #endif
4237   if ( !userStyleSheet.isEmpty() )
4238     setUserStyleSheet( KURL( userStyleSheet ) );
4239   else
4240     setUserStyleSheet( QString() );
4241
4242 #if !APPLE_CHANGES
4243   QApplication::setOverrideCursor( waitCursor );
4244 #endif
4245   if(d->m_doc) d->m_doc->updateStyleSelector();
4246 #if !APPLE_CHANGES
4247   QApplication::restoreOverrideCursor();
4248 #endif
4249 }
4250
4251 QStringList KHTMLPart::frameNames() const
4252 {
4253   QStringList res;
4254
4255   ConstFrameIt it = d->m_frames.begin();
4256   ConstFrameIt end = d->m_frames.end();
4257   for (; it != end; ++it )
4258     if (!(*it).m_bPreloaded)
4259       res += (*it).m_name;
4260
4261   return res;
4262 }
4263
4264 QPtrList<KParts::ReadOnlyPart> KHTMLPart::frames() const
4265 {
4266   QPtrList<KParts::ReadOnlyPart> res;
4267
4268   ConstFrameIt it = d->m_frames.begin();
4269   ConstFrameIt end = d->m_frames.end();
4270   for (; it != end; ++it )
4271     if (!(*it).m_bPreloaded)
4272       res.append( (*it).m_part );
4273
4274   return res;
4275 }
4276
4277 #if !APPLE_CHANGES
4278
4279 bool KHTMLPart::openURLInFrame( const KURL &url, const KParts::URLArgs &urlArgs )
4280 {
4281   FrameIt it = d->m_frames.find( urlArgs.frameName );
4282
4283   if ( it == d->m_frames.end() )
4284     return false;
4285
4286   // Inform someone that we are about to show something else.
4287   if ( !urlArgs.lockHistory() )
4288       emit d->m_extension->openURLNotify();
4289
4290   requestObject( &(*it), url, urlArgs );
4291
4292   return true;
4293 }
4294
4295 #endif
4296
4297 void KHTMLPart::setDNDEnabled( bool b )
4298 {
4299   d->m_bDnd = b;
4300 }
4301
4302 bool KHTMLPart::dndEnabled() const
4303 {
4304   return d->m_bDnd;
4305 }
4306
4307 bool KHTMLPart::shouldDragAutoNode(DOM::NodeImpl *node, int x, int y) const
4308 {
4309     // No KDE impl yet
4310     return false;
4311 }
4312
4313 void KHTMLPart::customEvent( QCustomEvent *event )
4314 {
4315   if ( khtml::MousePressEvent::test( event ) )
4316   {
4317     khtmlMousePressEvent( static_cast<khtml::MousePressEvent *>( event ) );
4318     return;
4319   }
4320
4321   if ( khtml::MouseDoubleClickEvent::test( event ) )
4322   {
4323     khtmlMouseDoubleClickEvent( static_cast<khtml::MouseDoubleClickEvent *>( event ) );
4324     return;
4325   }
4326
4327   if ( khtml::MouseMoveEvent::test( event ) )
4328   {
4329     khtmlMouseMoveEvent( static_cast<khtml::MouseMoveEvent *>( event ) );
4330     return;
4331   }
4332
4333   if ( khtml::MouseReleaseEvent::test( event ) )
4334   {
4335     khtmlMouseReleaseEvent( static_cast<khtml::MouseReleaseEvent *>( event ) );
4336     return;
4337   }
4338
4339   if ( khtml::DrawContentsEvent::test( event ) )
4340   {
4341     khtmlDrawContentsEvent( static_cast<khtml::DrawContentsEvent *>( event ) );
4342     return;
4343   }
4344
4345   KParts::ReadOnlyPart::customEvent( event );
4346 }
4347
4348 bool KHTMLPart::isPointInsideSelection(int x, int y)
4349 {
4350     // Treat a collapsed selection like no selection.
4351     if (d->m_selection.state() == Selection::CARET)
4352         return false;
4353     if (!xmlDocImpl()->renderer()) 
4354         return false;
4355     
4356     RenderObject::NodeInfo nodeInfo(true, true);
4357     xmlDocImpl()->renderer()->layer()->nodeAtPoint(nodeInfo, x, y);
4358     NodeImpl *innerNode = nodeInfo.innerNode();
4359     if (!innerNode || !innerNode->renderer())
4360         return false;
4361     
4362     Position pos(innerNode->positionForCoordinates(x, y));
4363     if (pos.isEmpty())
4364         return false;
4365
4366     NodeImpl *n = d->m_selection.start().node();
4367     while (n) {
4368         if (n == pos.node()) {
4369             if ((n == d->m_selection.start().node() && pos.offset() < d->m_selection.start().offset()) ||
4370                 (n == d->m_selection.end().node() && pos.offset() > d->m_selection.end().offset())) {
4371                 return false;
4372             }
4373             return true;
4374         }
4375         if (n == d->m_selection.end().node())
4376             break;
4377         n = n->traverseNextNode();
4378     }
4379
4380    return false;
4381 }
4382
4383 void KHTMLPart::handleMousePressEventDoubleClick(khtml::MousePressEvent *event)
4384 {
4385     QMouseEvent *mouse = event->qmouseEvent();
4386     DOM::Node innerNode = event->innerNode();
4387
4388     Selection selection;
4389
4390     if (mouse->button() == LeftButton && !innerNode.isNull() && innerNode.handle()->renderer() &&
4391         innerNode.handle()->renderer()->shouldSelect()) {
4392         Position pos(innerNode.handle()->positionForCoordinates(event->x(), event->y()));
4393         if (pos.node() && (pos.node()->nodeType() == Node::TEXT_NODE || pos.node()->nodeType() == Node::CDATA_SECTION_NODE)) {
4394             selection.moveTo(pos);
4395             selection.expandUsingGranularity(Selection::WORD);
4396         }
4397     }
4398     
4399     if (selection.state() != Selection::CARET) {
4400         d->m_selectionGranularity = Selection::WORD;
4401         d->m_beganSelectingText = true;
4402     }
4403     
4404     setSelection(selection);
4405     startAutoScroll();
4406 }
4407
4408 void KHTMLPart::handleMousePressEventTripleClick(khtml::MousePressEvent *event)
4409 {
4410     QMouseEvent *mouse = event->qmouseEvent();
4411     DOM::Node innerNode = event->innerNode();