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