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