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