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