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