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