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