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