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