khtml Library API Documentation

khtml_part.cpp

00001 // -*- c-basic-offset: 2 -*-
00002 /* This file is part of the KDE project
00003  *
00004  * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
00005  *                     1999 Lars Knoll <knoll@kde.org>
00006  *                     1999 Antti Koivisto <koivisto@kde.org>
00007  *                     2000 Simon Hausmann <hausmann@kde.org>
00008  *                     2000 Stefan Schimanski <1Stein@gmx.de>
00009  *                     2001 George Staikos <staikos@kde.org>
00010  *                     2001-2003 Dirk Mueller <mueller@kde.org>
00011  *                     2002 Apple Computer, Inc.
00012  *
00013  * This library is free software; you can redistribute it and/or
00014  * modify it under the terms of the GNU Library General Public
00015  * License as published by the Free Software Foundation; either
00016  * version 2 of the License, or (at your option) any later version.
00017  *
00018  * This library is distributed in the hope that it will be useful,
00019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00021  * Library General Public License for more details.
00022  *
00023  * You should have received a copy of the GNU Library General Public License
00024  * along with this library; see the file COPYING.LIB.  If not, write to
00025  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00026  * Boston, MA 02111-1307, USA.
00027  */
00028 
00029 //#define SPEED_DEBUG
00030 #include "khtml_part.h"
00031 
00032 #include "khtml_pagecache.h"
00033 
00034 #include "dom/dom_string.h"
00035 #include "dom/dom_element.h"
00036 #include "html/html_documentimpl.h"
00037 #include "html/html_baseimpl.h"
00038 #include "html/html_miscimpl.h"
00039 #include "html/html_imageimpl.h"
00040 #include "rendering/render_text.h"
00041 #include "rendering/render_frames.h"
00042 #include "misc/htmlhashes.h"
00043 #include "misc/loader.h"
00044 #include "xml/dom2_eventsimpl.h"
00045 #include "xml/xml_tokenizer.h"
00046 #include "css/cssstyleselector.h"
00047 #include "css/csshelper.h"
00048 using namespace DOM;
00049 
00050 #include "khtmlview.h"
00051 #include <kparts/partmanager.h>
00052 #include "ecma/kjs_proxy.h"
00053 #include "khtml_settings.h"
00054 
00055 #include "htmlpageinfo.h"
00056 
00057 #include <sys/types.h>
00058 #include <assert.h>
00059 #include <unistd.h>
00060 
00061 #include <kstandarddirs.h>
00062 #include <kstringhandler.h>
00063 #include <kio/job.h>
00064 #include <kio/global.h>
00065 #include <kdebug.h>
00066 #include <kiconloader.h>
00067 #include <klocale.h>
00068 #include <kcharsets.h>
00069 #include <kmessagebox.h>
00070 #include <kstdaction.h>
00071 #include <kfiledialog.h>
00072 #include <ktrader.h>
00073 #include <kdatastream.h>
00074 #include <ktempfile.h>
00075 #include <kglobalsettings.h>
00076 #include <kurldrag.h>
00077 #include <kapplication.h>
00078 #include <kparts/browserinterface.h>
00079 #if !defined(QT_NO_DRAGANDDROP)
00080 #include <kmultipledrag.h>
00081 #endif
00082 #include "../kutils/kfinddialog.h"
00083 #include "../kutils/kfind.h"
00084 
00085 #include <ksslcertchain.h>
00086 #include <ksslinfodlg.h>
00087 
00088 #include <kfileitem.h>
00089 #include <kurifilter.h>
00090 
00091 #include <qclipboard.h>
00092 #include <qfile.h>
00093 #include <qmetaobject.h>
00094 #include <private/qucomextra_p.h>
00095 
00096 #include "khtmlpart_p.h"
00097 
00098 namespace khtml {
00099     class PartStyleSheetLoader : public CachedObjectClient
00100     {
00101     public:
00102         PartStyleSheetLoader(KHTMLPart *part, DOM::DOMString url, DocLoader* dl)
00103         {
00104             m_part = part;
00105             m_cachedSheet = Cache::requestStyleSheet(dl, url );
00106             if (m_cachedSheet)
00107         m_cachedSheet->ref( this );
00108         }
00109         virtual ~PartStyleSheetLoader()
00110         {
00111             if ( m_cachedSheet ) m_cachedSheet->deref(this);
00112         }
00113         virtual void setStyleSheet(const DOM::DOMString&, const DOM::DOMString &sheet)
00114         {
00115           if ( m_part )
00116             m_part->setUserStyleSheet( sheet.string() );
00117 
00118             delete this;
00119         }
00120         QGuardedPtr<KHTMLPart> m_part;
00121         khtml::CachedCSSStyleSheet *m_cachedSheet;
00122     };
00123 }
00124 
00125 
00126 FrameList::Iterator FrameList::find( const QString &name )
00127 {
00128     Iterator it = begin();
00129     Iterator e = end();
00130 
00131     for (; it!=e; ++it )
00132         if ( (*it).m_name==name )
00133             break;
00134 
00135     return it;
00136 }
00137 
00138 KHTMLPart::KHTMLPart( QWidget *parentWidget, const char *widgetname, QObject *parent, const char *name,
00139                       GUIProfile prof )
00140 : KParts::ReadOnlyPart( parent, name )
00141 {
00142     d = 0;
00143     KHTMLFactory::registerPart( this );
00144     setInstance( KHTMLFactory::instance(), prof == BrowserViewGUI && !parentPart() );
00145     init( new KHTMLView( this, parentWidget, widgetname ), prof );
00146 }
00147 
00148 KHTMLPart::KHTMLPart( KHTMLView *view, QObject *parent, const char *name, GUIProfile prof )
00149 : KParts::ReadOnlyPart( parent, name )
00150 {
00151     d = 0;
00152     KHTMLFactory::registerPart( this );
00153     setInstance( KHTMLFactory::instance(), prof == BrowserViewGUI && !parentPart() );
00154     assert( view );
00155     init( view, prof );
00156 }
00157 
00158 void KHTMLPart::init( KHTMLView *view, GUIProfile prof )
00159 {
00160   if ( prof == DefaultGUI )
00161     setXMLFile( "khtml.rc" );
00162   else if ( prof == BrowserViewGUI )
00163     setXMLFile( "khtml_browser.rc" );
00164 
00165   d = new KHTMLPartPrivate(parent());
00166 
00167   d->m_view = view;
00168   setWidget( d->m_view );
00169 
00170   d->m_guiProfile = prof;
00171   d->m_extension = new KHTMLPartBrowserExtension( this );
00172   d->m_hostExtension = new KHTMLPartBrowserHostExtension( this );
00173 
00174   d->m_bSecurityInQuestion = false;
00175   d->m_paLoadImages = 0;
00176   d->m_bMousePressed = false;
00177   d->m_bRightMousePressed = false;
00178   d->m_paViewDocument = new KAction( i18n( "View Document Source" ), 0, this, SLOT( slotViewDocumentSource() ), actionCollection(), "viewDocumentSource" );
00179   d->m_paViewFrame = new KAction( i18n( "View Frame Source" ), 0, this, SLOT( slotViewFrameSource() ), actionCollection(), "viewFrameSource" );
00180   d->m_paViewInfo = new KAction( i18n( "View Document Information" ), 0, this, SLOT( slotViewPageInfo() ), actionCollection(), "viewPageInfo" );
00181   d->m_paSaveBackground = new KAction( i18n( "Save &Background Image As..." ), 0, this, SLOT( slotSaveBackground() ), actionCollection(), "saveBackground" );
00182   d->m_paSaveDocument = new KAction( i18n( "&Save As..." ), CTRL+Key_S, this, SLOT( slotSaveDocument() ), actionCollection(), "saveDocument" );
00183   if ( parentPart() )
00184       d->m_paSaveDocument->setShortcut( KShortcut() ); // avoid clashes
00185   d->m_paSaveFrame = new KAction( i18n( "Save &Frame As..." ), 0, this, SLOT( slotSaveFrame() ), actionCollection(), "saveFrame" );
00186   d->m_paSecurity = new KAction( i18n( "Security..." ), "decrypted", 0, this, SLOT( slotSecurity() ), actionCollection(), "security" );
00187   d->m_paDebugRenderTree = new KAction( "Print Rendering Tree to STDOUT", 0, this, SLOT( slotDebugRenderTree() ), actionCollection(), "debugRenderTree" );
00188   d->m_paDebugDOMTree = new KAction( "Print DOM Tree to STDOUT", 0, this, SLOT( slotDebugDOMTree() ), actionCollection(), "debugDOMTree" );
00189 
00190   QString foo1 = i18n("Show Images");
00191   QString foo2 = i18n("Show Animated Images");
00192   QString foo3 = i18n("Stop Animated Images");
00193 
00194   d->m_paSetEncoding = new KSelectAction( i18n( "Set &Encoding" ), 0, this, SLOT( slotSetEncoding() ), actionCollection(), "setEncoding" );
00195   QStringList encodings = KGlobal::charsets()->descriptiveEncodingNames();
00196   encodings.prepend( i18n( "Auto" ) );
00197   d->m_paSetEncoding->setItems( encodings );
00198   d->m_paSetEncoding->setCurrentItem(0);
00199 
00200   d->m_paUseStylesheet = new KSelectAction( i18n( "Use S&tylesheet"), 0, this, SLOT( slotUseStylesheet() ), actionCollection(), "useStylesheet" );
00201 
00202   d->m_paIncZoomFactor = new KHTMLZoomFactorAction( this, true, i18n( "Increase Font Sizes" ), "viewmag+", this, SLOT( slotIncZoom() ), actionCollection(), "incFontSizes" );
00203   d->m_paDecZoomFactor = new KHTMLZoomFactorAction( this, false, i18n( "Decrease Font Sizes" ), "viewmag-", this, SLOT( slotDecZoom() ), actionCollection(), "decFontSizes" );
00204 
00205   d->m_paFind = KStdAction::find( this, SLOT( slotFind() ), actionCollection(), "find" );
00206   d->m_paFindNext = KStdAction::findNext( this, SLOT( slotFindNext() ), actionCollection(), "findNext" );
00207   if ( parentPart() )
00208   {
00209       d->m_paFind->setShortcut( KShortcut() ); // avoid clashes
00210       d->m_paFindNext->setShortcut( KShortcut() ); // avoid clashes
00211   }
00212 
00213   d->m_paPrintFrame = new KAction( i18n( "Print Frame" ), "frameprint", 0, this, SLOT( slotPrintFrame() ), actionCollection(), "printFrame" );
00214 
00215   d->m_paSelectAll = KStdAction::selectAll( this, SLOT( slotSelectAll() ), actionCollection(), "selectAll" );
00216   if ( parentPart() )
00217       d->m_paSelectAll->setShortcut( KShortcut() ); // avoid clashes
00218 
00219   // set the default java(script) flags according to the current host.
00220   d->m_bBackRightClick = d->m_settings->isBackRightClickEnabled();
00221   d->m_bJScriptEnabled = d->m_settings->isJavaScriptEnabled();
00222   d->m_bJScriptDebugEnabled = d->m_settings->isJavaScriptDebugEnabled();
00223   d->m_bJavaEnabled = d->m_settings->isJavaEnabled();
00224   d->m_bPluginsEnabled = d->m_settings->isPluginsEnabled();
00225 
00226   // Set the meta-refresh flag...
00227   d->m_metaRefreshEnabled = d->m_settings->isAutoDelayedActionsEnabled ();
00228 
00229   connect( view, SIGNAL( zoomView( int ) ), SLOT( slotZoomView( int ) ) );
00230 
00231   connect( this, SIGNAL( completed() ),
00232            this, SLOT( updateActions() ) );
00233   connect( this, SIGNAL( completed( bool ) ),
00234            this, SLOT( updateActions() ) );
00235   connect( this, SIGNAL( started( KIO::Job * ) ),
00236            this, SLOT( updateActions() ) );
00237 
00238   d->m_popupMenuXML = KXMLGUIFactory::readConfigFile( locate( "data", "khtml/khtml_popupmenu.rc", KHTMLFactory::instance() ) );
00239 
00240   connect( khtml::Cache::loader(), SIGNAL( requestStarted( khtml::DocLoader*, khtml::CachedObject* ) ),
00241            this, SLOT( slotLoaderRequestStarted( khtml::DocLoader*, khtml::CachedObject* ) ) );
00242   connect( khtml::Cache::loader(), SIGNAL( requestDone( khtml::DocLoader*, khtml::CachedObject *) ),
00243            this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
00244   connect( khtml::Cache::loader(), SIGNAL( requestFailed( khtml::DocLoader*, khtml::CachedObject *) ),
00245            this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
00246 
00247   connect ( &d->m_progressUpdateTimer, SIGNAL( timeout() ), this, SLOT( slotProgressUpdate() ) );
00248 
00249   findTextBegin(); //reset find variables
00250 
00251   connect( &d->m_redirectionTimer, SIGNAL( timeout() ),
00252            this, SLOT( slotRedirect() ) );
00253 
00254   d->m_dcopobject = new KHTMLPartIface(this);
00255 
00256   // "khtml" catalogue does not exist, our translations are in kdelibs.
00257   // removing this catalogue from KGlobal::locale() prevents problems
00258   // with changing the language in applications at runtime -Thomas Reitelbach
00259   KGlobal::locale()->removeCatalogue("khtml");
00260 }
00261 
00262 KHTMLPart::~KHTMLPart()
00263 {
00264   //kdDebug(6050) << "KHTMLPart::~KHTMLPart " << this << endl;
00265 
00266   delete d->m_find;
00267   d->m_find = 0;
00268 
00269   if ( d->m_manager )
00270   {
00271     d->m_manager->setActivePart( 0 );
00272     // We specify "this" as parent qobject for d->manager, so no need to delete it.
00273   }
00274 
00275   stopAutoScroll();
00276   d->m_redirectionTimer.stop();
00277 
00278   if (!d->m_bComplete)
00279     closeURL();
00280 
00281   disconnect( khtml::Cache::loader(), SIGNAL( requestStarted( khtml::DocLoader*, khtml::CachedObject* ) ),
00282            this, SLOT( slotLoaderRequestStarted( khtml::DocLoader*, khtml::CachedObject* ) ) );
00283   disconnect( khtml::Cache::loader(), SIGNAL( requestDone( khtml::DocLoader*, khtml::CachedObject *) ),
00284            this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
00285   disconnect( khtml::Cache::loader(), SIGNAL( requestFailed( khtml::DocLoader*, khtml::CachedObject *) ),
00286            this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
00287 
00288   clear();
00289 
00290   if ( d->m_view )
00291   {
00292     d->m_view->hide();
00293     d->m_view->viewport()->hide();
00294     d->m_view->m_part = 0;
00295   }
00296 
00297   delete d; d = 0;
00298   KHTMLFactory::deregisterPart( this );
00299 }
00300 
00301 bool KHTMLPart::restoreURL( const KURL &url )
00302 {
00303   kdDebug( 6050 ) << "KHTMLPart::restoreURL " << url.url() << endl;
00304 
00305   d->m_redirectionTimer.stop();
00306 
00307   /*
00308    * That's not a good idea as it will call closeURL() on all
00309    * child frames, preventing them from further loading. This
00310    * method gets called from restoreState() in case of a full frameset
00311    * restoral, and restoreState() calls closeURL() before restoring
00312    * anyway.
00313   kdDebug( 6050 ) << "closing old URL" << endl;
00314   closeURL();
00315   */
00316 
00317   d->m_bComplete = false;
00318   d->m_bLoadEventEmitted = false;
00319   d->m_workingURL = url;
00320 
00321   // set the java(script) flags according to the current host.
00322   d->m_bJScriptEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaScriptEnabled(url.host());
00323   d->m_bJScriptDebugEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaScriptDebugEnabled();
00324   d->m_bJavaEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaEnabled(url.host());
00325   d->m_bPluginsEnabled = KHTMLFactory::defaultHTMLSettings()->isPluginsEnabled(url.host());
00326 
00327   m_url = url;
00328 
00329   KHTMLPageCache::self()->fetchData( d->m_cacheId, this, SLOT(slotRestoreData(const QByteArray &)));
00330 
00331   emit started( 0L );
00332 
00333   return true;
00334 }
00335 
00336 
00337 bool KHTMLPart::openURL( const KURL &url )
00338 {
00339   kdDebug( 6050 ) << "KHTMLPart(" << this << ")::openURL " << url.url() << endl;
00340 
00341   d->m_redirectionTimer.stop();
00342 
00343   // check to see if this is an "error://" URL. This is caused when an error
00344   // occurs before this part was loaded (e.g. KonqRun), and is passed to
00345   // khtmlpart so that it can display the error.
00346   if ( url.protocol() == "error" && url.hasSubURL() ) {
00347     closeURL();
00348 
00349     if(  d->m_bJScriptEnabled )
00350       d->m_statusBarText[BarOverrideText] = d->m_statusBarText[BarDefaultText] = QString::null;
00351 
00357     KURL::List urls = KURL::split( url );
00358     //kdDebug(6050) << "Handling error URL. URL count:" << urls.count() << endl;
00359 
00360     if ( urls.count() > 1 ) {
00361       KURL mainURL = urls.first();
00362       int error = mainURL.queryItem( "error" ).toInt();
00363       // error=0 isn't a valid error code, so 0 means it's missing from the URL
00364       if ( error == 0 ) error = KIO::ERR_UNKNOWN;
00365       QString errorText = mainURL.queryItem( "errText" );
00366       urls.pop_front();
00367       d->m_workingURL = KURL::join( urls );
00368       //kdDebug(6050) << "Emitting fixed URL " << d->m_workingURL.prettyURL() << endl;
00369       emit d->m_extension->setLocationBarURL( d->m_workingURL.prettyURL() );
00370       htmlError( error, errorText, d->m_workingURL );
00371       return true;
00372     }
00373   }
00374 
00375   KParts::URLArgs args( d->m_extension->urlArgs() );
00376   // in case we have a) no frameset (don't test m_frames.count(), iframes get in there)
00377   // b) the url is identical with the currently
00378   // displayed one (except for the htmlref!) , c) the url request is not a POST
00379   // operation and d) the caller did not request to reload the page we try to
00380   // be smart and instead of reloading the whole document we just jump to the
00381   // request html anchor
00382   bool isFrameSet = false;
00383   if ( d->m_doc && d->m_doc->isHTMLDocument() ) {
00384       HTMLDocumentImpl* htmlDoc = static_cast<HTMLDocumentImpl*>(d->m_doc);
00385       isFrameSet = htmlDoc->body() && (htmlDoc->body()->id() == ID_FRAMESET);
00386   }
00387   if ( !isFrameSet && !args.redirectedRequest() &&
00388        urlcmp( url.url(), m_url.url(), true, true ) &&
00389        url.hasRef() && !args.doPost() && !args.reload )
00390   {
00391     kdDebug( 6050 ) << "KHTMLPart::openURL, jumping to anchor. m_url = " << url.url() << endl;
00392     m_url = url;
00393     emit started( 0L );
00394 
00395     if ( !gotoAnchor( url.encodedHtmlRef()) )
00396        gotoAnchor( url.htmlRef() );
00397 
00398     d->m_bComplete = true;
00399     if (d->m_doc)
00400        d->m_doc->setParsing(false);
00401 
00402     kdDebug( 6050 ) << "completed..." << endl;
00403     emit completed();
00404     return true;
00405   }
00406 
00407   if (!d->m_restored)
00408   {
00409     kdDebug( 6050 ) << "closing old URL" << endl;
00410     closeURL();
00411   }
00412 
00413   // 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
00414   // data arrives) (Simon)
00415   m_url = url;
00416   if(m_url.protocol().startsWith( "http" ) && !m_url.host().isEmpty() &&
00417      m_url.path().isEmpty()) {
00418     m_url.setPath("/");
00419     emit d->m_extension->setLocationBarURL( m_url.prettyURL() );
00420   }
00421   // copy to m_workingURL after fixing m_url above
00422   d->m_workingURL = m_url;
00423 
00424   args.metaData().insert("main_frame_request", parentPart() == 0 ? "TRUE" : "FALSE" );
00425   args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
00426   args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
00427   args.metaData().insert("PropagateHttpHeader", "true");
00428   args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE" : "FALSE" );
00429   args.metaData().insert("ssl_activate_warnings", "TRUE" );
00430   if (d->m_restored)
00431      d->m_cachePolicy = KIO::CC_Cache;
00432   else if (args.reload)
00433      d->m_cachePolicy = KIO::CC_Refresh;
00434   else
00435      d->m_cachePolicy = KIO::CC_Verify;
00436 
00437   if ( args.doPost() && (m_url.protocol().startsWith("http")) )
00438   {
00439       d->m_job = KIO::http_post( m_url, args.postData, false );
00440       d->m_job->addMetaData("content-type", args.contentType() );
00441   }
00442   else
00443   {
00444       d->m_job = KIO::get( m_url, false, false );
00445       d->m_job->addMetaData("cache", KIO::getCacheControlString(d->m_cachePolicy));
00446   }
00447 
00448   if (widget())
00449      d->m_job->setWindow(widget()->topLevelWidget());
00450   d->m_job->addMetaData(args.metaData());
00451 
00452   connect( d->m_job, SIGNAL( result( KIO::Job * ) ),
00453            SLOT( slotFinished( KIO::Job * ) ) );
00454   connect( d->m_job, SIGNAL( data( KIO::Job*, const QByteArray &)),
00455            SLOT( slotData( KIO::Job*, const QByteArray &)));
00456   connect ( d->m_job, SIGNAL( infoMessage( KIO::Job*,  const QString& ) ),
00457             SLOT( slotInfoMessage(KIO::Job*, const QString& ) ) );
00458   connect( d->m_job, SIGNAL(redirection(KIO::Job*, const KURL&) ),
00459            SLOT( slotRedirection(KIO::Job*,const KURL&) ) );
00460 
00461   d->m_bComplete = false;
00462   d->m_bLoadEventEmitted = false;
00463 
00464   // delete old status bar msg's from kjs (if it _was_ activated on last URL)
00465   if( d->m_bJScriptEnabled )
00466     d->m_statusBarText[BarOverrideText] = d->m_statusBarText[BarDefaultText] = QString::null;
00467 
00468   // set the javascript flags according to the current url
00469   d->m_bJScriptEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaScriptEnabled(url.host());
00470   d->m_bJScriptDebugEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaScriptDebugEnabled();
00471   d->m_bJavaEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaEnabled(url.host());
00472   d->m_bPluginsEnabled = KHTMLFactory::defaultHTMLSettings()->isPluginsEnabled(url.host());
00473 
00474 
00475   kdDebug( 6050 ) << "KHTMLPart::openURL now (before started) m_url = " << m_url.url() << endl;
00476 
00477   connect( d->m_job, SIGNAL( speed( KIO::Job*, unsigned long ) ),
00478            this, SLOT( slotJobSpeed( KIO::Job*, unsigned long ) ) );
00479 
00480   connect( d->m_job, SIGNAL( percent( KIO::Job*, unsigned long ) ),
00481            this, SLOT( slotJobPercent( KIO::Job*, unsigned long ) ) );
00482 
00483   connect( d->m_job, SIGNAL( result( KIO::Job* ) ),
00484            this, SLOT( slotJobDone( KIO::Job* ) ) );
00485 
00486   d->m_jobspeed = 0;
00487   emit started( 0L );
00488 
00489   return true;
00490 }
00491 
00492 bool KHTMLPart::closeURL()
00493 {
00494   if ( d->m_job )
00495   {
00496     KHTMLPageCache::self()->cancelEntry(d->m_cacheId);
00497     d->m_job->kill();
00498     d->m_job = 0;
00499   }
00500 
00501   if ( d->m_doc && d->m_doc->isHTMLDocument() ) {
00502     HTMLDocumentImpl* hdoc = static_cast<HTMLDocumentImpl*>( d->m_doc );
00503 
00504     if ( hdoc->body() && d->m_bLoadEventEmitted ) {
00505       hdoc->body()->dispatchWindowEvent( EventImpl::UNLOAD_EVENT, false, false );
00506       if ( d->m_doc )
00507         d->m_doc->updateRendering();
00508       d->m_bLoadEventEmitted = false;
00509     }
00510   }
00511 
00512   d->m_bComplete = true; // to avoid emitting completed() in slotFinishedParsing() (David)
00513   d->m_bLoadEventEmitted = true; // don't want that one either
00514   d->m_cachePolicy = KIO::CC_Verify; // reset cache policy
00515 
00516   KHTMLPageCache::self()->cancelFetch(this);
00517   if ( d->m_doc && d->m_doc->parsing() )
00518   {
00519     kdDebug( 6050 ) << " was still parsing... calling end " << endl;
00520     slotFinishedParsing();
00521     d->m_doc->setParsing(false);
00522   }
00523 
00524   if ( !d->m_workingURL.isEmpty() )
00525   {
00526     // Aborted before starting to render
00527     kdDebug( 6050 ) << "Aborted before starting to render, reverting location bar to " << m_url.prettyURL() << endl;
00528     emit d->m_extension->setLocationBarURL( m_url.prettyURL() );
00529   }
00530 
00531   d->m_workingURL = KURL();
00532 
00533   if ( d->m_doc && d->m_doc->docLoader() )
00534     khtml::Cache::loader()->cancelRequests( d->m_doc->docLoader() );
00535 
00536   // tell all subframes to stop as well
00537   ConstFrameIt it = d->m_frames.begin();
00538   ConstFrameIt end = d->m_frames.end();
00539   for (; it != end; ++it )
00540   {
00541     if ( (*it).m_run )
00542       (*it).m_run->abort();
00543     if ( !( *it ).m_part.isNull() )
00544       ( *it ).m_part->closeURL();
00545   }
00546 
00547   // Stop any started redirections as well!! (DA)
00548   if ( d && d->m_redirectionTimer.isActive() )
00549     d->m_redirectionTimer.stop();
00550 
00551   // null node activated.
00552   emit nodeActivated(Node());
00553 
00554   // make sure before clear() runs, we pop out of a dialog's message loop
00555   if ( d->m_view )
00556     d->m_view->closeChildDialogs();
00557 
00558   return true;
00559 }
00560 
00561 DOM::HTMLDocument KHTMLPart::htmlDocument() const
00562 {
00563   if (d->m_doc && d->m_doc->isHTMLDocument())
00564     return static_cast<HTMLDocumentImpl*>(d->m_doc);
00565   else
00566     return static_cast<HTMLDocumentImpl*>(0);
00567 }
00568 
00569 DOM::Document KHTMLPart::document() const
00570 {
00571     return d->m_doc;
00572 }
00573 
00574 KParts::BrowserExtension *KHTMLPart::browserExtension() const
00575 {
00576   return d->m_extension;
00577 }
00578 
00579 KParts::BrowserHostExtension *KHTMLPart::browserHostExtension() const
00580 {
00581   return d->m_hostExtension;
00582 }
00583 
00584 KHTMLView *KHTMLPart::view() const
00585 {
00586   return d->m_view;
00587 }
00588 
00589 void KHTMLPart::setJScriptEnabled( bool enable )
00590 {
00591   if ( !enable && jScriptEnabled() && d->m_jscript ) {
00592     d->m_jscript->clear();
00593   }
00594   d->m_bJScriptForce = enable;
00595   d->m_bJScriptOverride = true;
00596 }
00597 
00598 bool KHTMLPart::jScriptEnabled() const
00599 {
00600   if ( d->m_bJScriptOverride )
00601       return d->m_bJScriptForce;
00602   return d->m_bJScriptEnabled;
00603 }
00604 
00605 void KHTMLPart::setMetaRefreshEnabled( bool enable )
00606 {
00607   d->m_metaRefreshEnabled = enable;
00608 }
00609 
00610 bool KHTMLPart::metaRefreshEnabled() const
00611 {
00612   return d->m_metaRefreshEnabled;
00613 }
00614 
00615 // Define this to disable dlopening kjs_html, when directly linking to it.
00616 // You need to edit khtml/Makefile.am to add ./ecma/libkjs_html.la to LIBADD
00617 // and to edit khtml/ecma/Makefile.am to s/kjs_html/libkjs_html/, remove libkhtml from LIBADD,
00618 //        remove LDFLAGS line, and replace kde_module with either lib (shared) or noinst (static)
00619 //        Also, change the order of "ecma" and "." in khtml's SUBDIRS line.
00620 // OK - that's the default now, use the opposite of the above instructions to go back
00621 // to "dlopening it" - but it breaks exception catching in kjs_binding.cpp
00622 #define DIRECT_LINKAGE_TO_ECMA
00623 
00624 #ifdef DIRECT_LINKAGE_TO_ECMA
00625 extern "C" { KJSProxy *kjs_html_init(KHTMLPart *khtmlpart); }
00626 #endif
00627 
00628 KJSProxy *KHTMLPart::jScript()
00629 {
00630   if (!jScriptEnabled()) return 0;
00631 
00632   if ( !d->m_jscript )
00633   {
00634 #ifndef DIRECT_LINKAGE_TO_ECMA
00635     KLibrary *lib = KLibLoader::self()->library("kjs_html");
00636     if ( !lib ) {
00637       setJScriptEnabled( false );
00638       return 0;
00639     }
00640     // look for plain C init function
00641     void *sym = lib->symbol("kjs_html_init");
00642     if ( !sym ) {
00643       lib->unload();
00644       setJScriptEnabled( false );
00645       return 0;
00646     }
00647     typedef KJSProxy* (*initFunction)(KHTMLPart *);
00648     initFunction initSym = (initFunction) sym;
00649     d->m_jscript = (*initSym)(this);
00650     d->m_kjs_lib = lib;
00651 #else
00652     d->m_jscript = kjs_html_init(this);
00653     // d->m_kjs_lib remains 0L.
00654 #endif
00655     if (d->m_bJScriptDebugEnabled)
00656         d->m_jscript->setDebugEnabled(true);
00657   }
00658 
00659   return d->m_jscript;
00660 }
00661 
00662 QVariant KHTMLPart::executeScript( const QString &script )
00663 {
00664     return executeScript( DOM::Node(), script );
00665 }
00666 
00667 //Enable this to see all JS scripts being executed
00668 //#define KJS_VERBOSE
00669 
00670 QVariant KHTMLPart::executeScript( const DOM::Node &n, const QString &script )
00671 {
00672 #ifdef KJS_VERBOSE
00673   kdDebug(6070) << "KHTMLPart::executeScript n=" << n.nodeName().string().latin1() << "(" << (n.isNull() ? 0 : n.nodeType()) << ") " << script << endl;
00674 #endif
00675   KJSProxy *proxy = jScript();
00676 
00677   if (!proxy || proxy->paused())
00678     return QVariant();
00679   d->m_runningScripts++;
00680   QVariant ret = proxy->evaluate( QString::null, 0, script, n );
00681   d->m_runningScripts--;
00682   if (!d->m_runningScripts && d->m_doc && !d->m_doc->parsing() && d->m_submitForm )
00683       submitFormAgain();
00684 
00685 #ifdef KJS_VERBOSE
00686   kdDebug(6070) << "KHTMLPart::executeScript - done" << endl;
00687 #endif
00688   return ret;
00689 }
00690 
00691 bool KHTMLPart::scheduleScript(const DOM::Node &n, const QString& script)
00692 {
00693     //kdDebug(6050) << "KHTMLPart::scheduleScript "<< script << endl;
00694 
00695     d->scheduledScript = script;
00696     d->scheduledScriptNode = n;
00697 
00698     return true;
00699 }
00700 
00701 QVariant KHTMLPart::executeScheduledScript()
00702 {
00703   if( d->scheduledScript.isEmpty() )
00704     return QVariant();
00705 
00706   //kdDebug(6050) << "executing delayed " << d->scheduledScript << endl;
00707 
00708   QVariant ret = executeScript( d->scheduledScriptNode, d->scheduledScript );
00709   d->scheduledScript = QString();
00710   d->scheduledScriptNode = DOM::Node();
00711 
00712   return ret;
00713 }
00714 
00715 void KHTMLPart::setJavaEnabled( bool enable )
00716 {
00717   d->m_bJavaForce = enable;
00718   d->m_bJavaOverride = true;
00719 }
00720 
00721 bool KHTMLPart::javaEnabled() const
00722 {
00723 #ifndef Q_WS_QWS
00724   if( d->m_bJavaOverride )
00725       return d->m_bJavaForce;
00726   return d->m_bJavaEnabled;
00727 #else
00728   return false;
00729 #endif
00730 }
00731 
00732 KJavaAppletContext *KHTMLPart::javaContext()
00733 {
00734 #ifndef Q_WS_QWS
00735   return d->m_javaContext;
00736 #else
00737   return 0;
00738 #endif
00739 }
00740 
00741 KJavaAppletContext *KHTMLPart::createJavaContext()
00742 {
00743 #ifndef Q_WS_QWS
00744   if ( !d->m_javaContext ) {
00745       d->m_javaContext = new KJavaAppletContext();
00746       connect( d->m_javaContext, SIGNAL(showStatus(const QString&)),
00747                this, SIGNAL(setStatusBarText(const QString&)) );
00748       connect( d->m_javaContext, SIGNAL(showDocument(const QString&, const QString&)),
00749                this, SLOT(slotShowDocument(const QString&, const QString&)) );
00750       connect( d->m_javaContext, SIGNAL(appletLoaded()),
00751                this, SLOT(checkCompleted()) );
00752   }
00753 
00754   return d->m_javaContext;
00755 #else
00756   return 0;
00757 #endif
00758 }
00759 
00760 void KHTMLPart::setPluginsEnabled( bool enable )
00761 {
00762   d->m_bPluginsForce = enable;
00763   d->m_bPluginsOverride = true;
00764 }
00765 
00766 bool KHTMLPart::pluginsEnabled() const
00767 {
00768   if ( d->m_bPluginsOverride )
00769       return d->m_bPluginsForce;
00770   return d->m_bPluginsEnabled;
00771 }
00772 
00773 void KHTMLPart::slotShowDocument( const QString &url, const QString &target )
00774 {
00775   // this is mostly copied from KHTMLPart::slotChildURLRequest. The better approach
00776   // would be to put those functions into a single one.
00777   khtml::ChildFrame *child = 0;
00778   KParts::URLArgs args;
00779   args.frameName = target;
00780 
00781   QString frameName = args.frameName.lower();
00782   if ( !frameName.isEmpty() )
00783   {
00784     if ( frameName == QString::fromLatin1( "_top" ) )
00785     {
00786       emit d->m_extension->openURLRequest( url, args );
00787       return;
00788     }
00789     else if ( frameName == QString::fromLatin1( "_blank" ) )
00790     {
00791       emit d->m_extension->createNewWindow( url, args );
00792       return;
00793     }
00794     else if ( frameName == QString::fromLatin1( "_parent" ) )
00795     {
00796       KParts::URLArgs newArgs( args );
00797       newArgs.frameName = QString::null;
00798 
00799       emit d->m_extension->openURLRequest( url, newArgs );
00800       return;
00801     }
00802     else if ( frameName != QString::fromLatin1( "_self" ) )
00803     {
00804       khtml::ChildFrame *_frame = recursiveFrameRequest( this, url, args );
00805 
00806       if ( !_frame )
00807       {
00808         emit d->m_extension->openURLRequest( url, args );
00809         return;
00810       }
00811 
00812       child = _frame;
00813     }
00814   }
00815 
00816   // TODO: handle child target correctly! currently the script are always executed fur the parent
00817   if ( url.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
00818       executeScript( KURL::decode_string( url.right( url.length() - 11) ) );
00819       return;
00820   }
00821 
00822   if ( child ) {
00823       requestObject( child, KURL(url), args );
00824   }  else if ( frameName == "_self" )
00825   {
00826       KParts::URLArgs newArgs( args );
00827       newArgs.frameName = QString::null;
00828       emit d->m_extension->openURLRequest( KURL(url), newArgs );
00829   }
00830 }
00831 
00832 void KHTMLPart::slotDebugDOMTree()
00833 {
00834   if ( d->m_doc && d->m_doc->firstChild() )
00835     qDebug("%s", d->m_doc->firstChild()->toHTML().latin1());
00836 }
00837 
00838 void KHTMLPart::slotDebugRenderTree()
00839 {
00840 #ifndef NDEBUG
00841   if ( d->m_doc )
00842     d->m_doc->renderer()->printTree();
00843 #endif
00844 }
00845 
00846 void KHTMLPart::setAutoloadImages( bool enable )
00847 {
00848   if ( d->m_doc && d->m_doc->docLoader()->autoloadImages() == enable )
00849     return;
00850 
00851   if ( d->m_doc )
00852     d->m_doc->docLoader()->setAutoloadImages( enable );
00853 
00854   unplugActionList( "loadImages" );
00855 
00856   if ( enable ) {
00857     delete d->m_paLoadImages;
00858     d->m_paLoadImages = 0;
00859   }
00860   else if ( !d->m_paLoadImages )
00861     d->m_paLoadImages = new KAction( i18n( "Display Images on Page" ), "images_display", 0, this, SLOT( slotLoadImages() ), actionCollection(), "loadImages" );
00862 
00863   if ( d->m_paLoadImages ) {
00864     QPtrList<KAction> lst;
00865     lst.append( d->m_paLoadImages );
00866     plugActionList( "loadImages", lst );
00867   }
00868 }
00869 
00870 bool KHTMLPart::autoloadImages() const
00871 {
00872   if ( d->m_doc )
00873     return d->m_doc->docLoader()->autoloadImages();
00874 
00875   return true;
00876 }
00877 
00878 void KHTMLPart::clear()
00879 {
00880   if ( d->m_bCleared )
00881     return;
00882   d->m_bCleared = true;
00883 
00884   d->m_bClearing = true;
00885 
00886   {
00887     ConstFrameIt it = d->m_frames.begin();
00888     ConstFrameIt end = d->m_frames.end();
00889     for(; it != end; ++it )
00890     {
00891       // Stop HTMLRun jobs for frames
00892       if ( (*it).m_run )
00893         (*it).m_run->abort();
00894     }
00895   }
00896 
00897   {
00898     QValueList<khtml::ChildFrame>::ConstIterator it = d->m_objects.begin();
00899     QValueList<khtml::ChildFrame>::ConstIterator end = d->m_objects.end();
00900     for(; it != end; ++it )
00901     {
00902       // Stop HTMLRun jobs for objects
00903       if ( (*it).m_run )
00904         (*it).m_run->abort();
00905     }
00906   }
00907 
00908 
00909   findTextBegin(); // resets d->m_findNode and d->m_findPos
00910 
00911   d->m_mousePressNode = DOM::Node();
00912 
00913 
00914   if ( d->m_doc )
00915     d->m_doc->detach();
00916 
00917   // Moving past doc so that onUnload works.
00918   if ( d->m_jscript )
00919     d->m_jscript->clear();
00920 
00921   if ( d->m_view )
00922     d->m_view->clear();
00923 
00924   // do not dereference the document before the jscript and view are cleared, as some destructors
00925   // might still try to access the document.
00926   if ( d->m_doc )
00927     d->m_doc->deref();
00928   d->m_doc = 0;
00929 
00930   delete d->m_decoder;
00931   d->m_decoder = 0;
00932 
00933   {
00934     ConstFrameIt it = d->m_frames.begin();
00935     ConstFrameIt end = d->m_frames.end();
00936     for(; it != end; ++it )
00937     {
00938       if ( (*it).m_part )
00939       {
00940         partManager()->removePart( (*it).m_part );
00941         delete (KParts::ReadOnlyPart *)(*it).m_part;
00942       }
00943     }
00944   }
00945 
00946   d->m_frames.clear();
00947   d->m_objects.clear();
00948 
00949 #ifndef Q_WS_QWS
00950   if( d->m_javaContext )
00951   {
00952     d->m_javaContext->deleteLater();
00953     d->m_javaContext = 0;
00954   }
00955 #endif
00956 
00957   d->m_delayRedirect = 0;
00958   d->m_redirectURL = QString::null;
00959   d->m_redirectLockHistory = true;
00960   d->m_bHTTPRefresh = false;
00961   d->m_bClearing = false;
00962   d->m_frameNameId = 1;
00963   d->m_bFirstData = true;
00964 
00965   d->m_bMousePressed = false;
00966 
00967   d->m_selectionStart = DOM::Node();
00968   d->m_selectionEnd = DOM::Node();
00969   d->m_startOffset = 0;
00970   d->m_endOffset = 0;
00971 #ifndef QT_NO_CLIPBOARD
00972   connect( kapp->clipboard(), SIGNAL( selectionChanged()), SLOT( slotClearSelection()));
00973 #endif
00974 
00975   d->m_jobPercent = 0;
00976 
00977   if ( !d->m_haveEncoding )
00978     d->m_encoding = QString::null;
00979 #ifdef SPEED_DEBUG
00980   d->m_parsetime.restart();
00981 #endif
00982 }
00983 
00984 bool KHTMLPart::openFile()
00985 {
00986   return true;
00987 }
00988 
00989 DOM::HTMLDocumentImpl *KHTMLPart::docImpl() const
00990 {
00991     if ( d && d->m_doc && d->m_doc->isHTMLDocument() )
00992         return static_cast<HTMLDocumentImpl*>(d->m_doc);
00993     return 0;
00994 }
00995 
00996 DOM::DocumentImpl *KHTMLPart::xmlDocImpl() const
00997 {
00998     if ( d )
00999         return d->m_doc;
01000     return 0;
01001 }
01002 
01003 void KHTMLPart::slotInfoMessage(KIO::Job* kio_job, const QString& msg)
01004 {
01005   assert(d->m_job == kio_job);
01006 
01007   if (!parentPart())
01008     setStatusBarText(msg, BarDefaultText);
01009 }
01010 
01011 void KHTMLPart::slotData( KIO::Job* kio_job, const QByteArray &data )
01012 {
01013   assert ( d->m_job == kio_job );
01014 
01015   //kdDebug( 6050 ) << "slotData: " << data.size() << endl;
01016   // The first data ?
01017   if ( !d->m_workingURL.isEmpty() )
01018   {
01019       //kdDebug( 6050 ) << "begin!" << endl;
01020 
01021     d->m_job->suspend();
01022     begin( d->m_workingURL, d->m_extension->urlArgs().xOffset, d->m_extension->urlArgs().yOffset );
01023     d->m_job->resume();
01024 
01025 
01026     d->m_doc->docLoader()->setCachePolicy(d->m_cachePolicy);
01027     d->m_workingURL = KURL();
01028 
01029     d->m_cacheId = KHTMLPageCache::self()->createCacheEntry();
01030 
01031     // When the first data arrives, the metadata has just been made available
01032     d->m_httpHeaders = d->m_job->queryMetaData("HTTP-Headers");
01033     time_t cacheCreationDate =  d->m_job->queryMetaData("cache-creation-date").toLong();
01034     d->m_doc->docLoader()->setCacheCreationDate(cacheCreationDate);
01035 
01036     d->m_pageServices = d->m_job->queryMetaData("PageServices");
01037 
01038     d->m_bSecurityInQuestion = false;
01039     d->m_ssl_in_use = (d->m_job->queryMetaData("ssl_in_use") == "TRUE");
01040     kdDebug(6050) << "SSL in use? " << d->m_job->queryMetaData("ssl_in_use") << endl;
01041 
01042     {
01043     KHTMLPart *p = parentPart();
01044     if (p && p->d->m_ssl_in_use != d->m_ssl_in_use) {
01045     while (p->parentPart()) p = p->parentPart();
01046 
01047     p->d->m_paSecurity->setIcon( "halfencrypted" );
01048         p->d->m_bSecurityInQuestion = true;
01049     kdDebug(6050) << "parent setIcon half done." << endl;
01050     }
01051     }
01052 
01053     d->m_paSecurity->setIcon( d->m_ssl_in_use ? "encrypted" : "decrypted" );
01054     kdDebug(6050) << "setIcon " << ( d->m_ssl_in_use ? "encrypted" : "decrypted" ) << " done." << endl;
01055 
01056     // Shouldn't all of this be done only if ssl_in_use == true ? (DF)
01057 
01058     d->m_ssl_parent_ip = d->m_job->queryMetaData("ssl_parent_ip");
01059     d->m_ssl_parent_cert = d->m_job->queryMetaData("ssl_parent_cert");
01060     d->m_ssl_peer_certificate = d->m_job->queryMetaData("ssl_peer_certificate");
01061     d->m_ssl_peer_chain = d->m_job->queryMetaData("ssl_peer_chain");
01062     d->m_ssl_peer_ip = d->m_job->queryMetaData("ssl_peer_ip");
01063     d->m_ssl_cipher = d->m_job->queryMetaData("ssl_cipher");
01064     d->m_ssl_cipher_desc = d->m_job->queryMetaData("ssl_cipher_desc");
01065     d->m_ssl_cipher_version = d->m_job->queryMetaData("ssl_cipher_version");
01066     d->m_ssl_cipher_used_bits = d->m_job->queryMetaData("ssl_cipher_used_bits");
01067     d->m_ssl_cipher_bits = d->m_job->queryMetaData("ssl_cipher_bits");
01068     d->m_ssl_cert_state = d->m_job->queryMetaData("ssl_cert_state");
01069 
01070     // Check for charset meta-data
01071     QString qData = d->m_job->queryMetaData("charset");
01072     if ( !qData.isEmpty() && !d->m_haveEncoding ) // only use information if the user didn't override the settings
01073        d->m_encoding = qData;
01074 
01075     // Support for http-refresh
01076     qData = d->m_job->queryMetaData("http-refresh");
01077     if( !qData.isEmpty() && d->m_metaRefreshEnabled )
01078     {
01079       kdDebug(6050) << "HTTP Refresh Request: " << qData << endl;
01080       int delay;
01081       int pos = qData.find( ';' );
01082       if ( pos == -1 )
01083         pos = qData.find( ',' );
01084 
01085       if( pos == -1 )
01086       {
01087         delay = qData.stripWhiteSpace().toInt();
01088         scheduleRedirection( qData.toInt(), m_url.url());
01089       }
01090       else
01091       {
01092         int end_pos = qData.length();
01093         delay = qData.left(pos).stripWhiteSpace().toInt();
01094         while ( qData[++pos] == ' ' );
01095         if ( qData.find( "url", pos, false ) == pos )
01096         {
01097           pos += 3;
01098           while (qData[pos] == ' ' || qData[pos] == '=' )
01099               pos++;
01100           if ( qData[pos] == '"' )
01101           {
01102               pos++;
01103               int index = end_pos-1;
01104               while( index > pos )
01105               {
01106                 if ( qData[index] == '"' )
01107                     break;
01108                 index--;
01109               }
01110               if ( index > pos )
01111                 end_pos = index;
01112           }
01113         }
01114         scheduleRedirection( delay, d->m_doc->completeURL( qData.mid( pos, end_pos ) ));
01115       }
01116       d->m_bHTTPRefresh = true;
01117     }
01118 
01119     if ( !m_url.isLocalFile() ) {
01120         // Support for http last-modified
01121         d->m_lastModified = d->m_job->queryMetaData("modified");
01122     } else
01123         d->m_lastModified = QString::null; // done on-demand by lastModified()
01124   }
01125 
01126   KHTMLPageCache::self()->addData(d->m_cacheId, data);
01127   write( data.data(), data.size() );
01128 }
01129 
01130 void KHTMLPart::slotRestoreData(const QByteArray &data )
01131 {
01132   // The first data ?
01133   if ( !d->m_workingURL.isEmpty() )
01134   {
01135      long saveCacheId = d->m_cacheId;
01136      begin( d->m_workingURL, d->m_extension->urlArgs().xOffset, d->m_extension->urlArgs().yOffset );
01137      d->m_cacheId = saveCacheId;
01138      d->m_workingURL = KURL();
01139   }
01140 
01141   //kdDebug( 6050 ) << "slotRestoreData: " << data.size() << endl;
01142   write( data.data(), data.size() );
01143 
01144   if (data.size() == 0)
01145   {
01146       //kdDebug( 6050 ) << "slotRestoreData: <<end of data>>" << endl;
01147      // End of data.
01148     if (d->m_doc && d->m_doc->parsing())
01149         end(); //will emit completed()
01150   }
01151 }
01152 
01153 void KHTMLPart::showError( KIO::Job* job )
01154 {
01155   kdDebug(6050) << "KHTMLPart::showError d->m_bParsing=" << (d->m_doc && d->m_doc->parsing()) << " d->m_bComplete=" << d->m_bComplete
01156                 << " d->m_bCleared=" << d->m_bCleared << endl;
01157 
01158   if (job->error() == KIO::ERR_NO_CONTENT)
01159     return;
01160 
01161   if ( (d->m_doc && d->m_doc->parsing()) || d->m_workingURL.isEmpty() ) // if we got any data already
01162     job->showErrorDialog( /*d->m_view*/ );
01163   else
01164   {
01165     htmlError( job->error(), job->errorText(), d->m_workingURL );
01166   }
01167 }
01168 
01169 // This is a protected method, placed here because of it's relevance to showError
01170 void KHTMLPart::htmlError( int errorCode, const QString& text, const KURL& reqUrl )
01171 {
01172   kdDebug(6050) << "KHTMLPart::htmlError errorCode=" << errorCode << " text=" << text << endl;
01173   // make sure we're not executing any embedded JS
01174   bool bJSFO = d->m_bJScriptForce;
01175   bool bJSOO = d->m_bJScriptOverride;
01176   d->m_bJScriptForce = false;
01177   d->m_bJScriptOverride = true;
01178   begin();
01179   QString errText = QString::fromLatin1( "<HTML><HEAD><TITLE>" );
01180   errText += i18n( "Error while loading %1" ).arg( reqUrl.htmlURL() );
01181   errText += QString::fromLatin1( "</TITLE></HEAD><BODY><P>" );
01182   errText += i18n( "An error occured while loading <B>%1</B>:" ).arg( reqUrl.htmlURL() );
01183   errText += QString::fromLatin1( "</P><P>" );
01184   QString kioErrString = KIO::buildErrorString( errorCode, text );
01185 
01186   kioErrString.replace(QRegExp("&"), QString("&amp;"));
01187   kioErrString.replace(QRegExp("<"), QString("&lt;"));
01188   kioErrString.replace(QRegExp(">"), QString("&gt;"));
01189 
01190   // In case the error string has '\n' in it, replace with <BR/>
01191   kioErrString.replace( QRegExp("\n"), "<BR/>" );
01192 
01193   errText += kioErrString;
01194   errText += QString::fromLatin1( "</P></BODY></HTML>" );
01195   write(errText);
01196   end();
01197 
01198   d->m_bJScriptForce = bJSFO;
01199   d->m_bJScriptOverride = bJSOO;
01200 
01201   // make the working url the current url, so that reload works and
01202   // emit the progress signals to advance one step in the history
01203   // (so that 'back' works)
01204   m_url = reqUrl; // same as d->m_workingURL
01205   d->m_workingURL = KURL();
01206   emit started( 0 );
01207   emit completed();
01208   return;
01209   // following disabled until 3.1
01210 
01211   QString errorName, techName, description;
01212   QStringList causes, solutions;
01213 
01214   QByteArray raw = KIO::rawErrorDetail( errorCode, text, &reqUrl );
01215   QDataStream stream(raw, IO_ReadOnly);
01216 
01217   stream >> errorName >> techName >> description >> causes >> solutions;
01218 
01219   QString url, protocol, datetime;
01220   url = reqUrl.prettyURL();
01221   protocol = reqUrl.protocol();
01222   datetime = KGlobal::locale()->formatDateTime( QDateTime::currentDateTime(),
01223                                                 false );
01224 
01225   QString doc = QString::fromLatin1( "<html><head><title>" );
01226   doc += i18n( "Error: " );
01227   doc += errorName;
01228   doc += QString::fromLatin1( " - %1</title></head><body><h1>" ).arg( url );
01229   doc += i18n( "The requested operation could not be completed" );
01230   doc += QString::fromLatin1( "</h1><h2>" );
01231   doc += errorName;
01232   doc += QString::fromLatin1( "</h2>" );
01233   if ( techName != QString::null ) {
01234     doc += QString::fromLatin1( "<h2>" );
01235     doc += i18n( "Technical Reason: " );
01236     doc += techName;
01237     doc += QString::fromLatin1( "</h2>" );
01238   }
01239   doc += QString::fromLatin1( "<h3>" );
01240   doc += i18n( "Details of the Request:" );
01241   doc += QString::fromLatin1( "</h3><ul><li>" );
01242   doc += i18n( "URL: %1" ).arg( url );
01243   doc += QString::fromLatin1( "</li><li>" );
01244   if ( protocol != QString::null ) {
01245     // uncomment for 3.1... i18n change
01246     // doc += i18n( "Protocol: %1" ).arg( protocol ).arg( protocol );
01247     doc += QString::fromLatin1( "</li><li>" );
01248   }
01249   doc += i18n( "Date and Time: %1" ).arg( datetime );
01250   doc += QString::fromLatin1( "</li><li>" );
01251   doc += i18n( "Additional Information: %1" ).arg( text );
01252   doc += QString::fromLatin1( "</li></ul><h3>" );
01253   doc += i18n( "Description:" );
01254   doc += QString::fromLatin1( "</h3><p>" );
01255   doc += description;
01256   doc += QString::fromLatin1( "</p>" );
01257   if ( causes.count() ) {
01258     doc += QString::fromLatin1( "<h3>" );
01259     doc += i18n( "Possible Causes:" );
01260     doc += QString::fromLatin1( "</h3><ul><li>" );
01261     doc += causes.join( "</li><li>" );
01262     doc += QString::fromLatin1( "</li></ul>" );
01263   }
01264   if ( solutions.count() ) {
01265     doc += QString::fromLatin1( "<h3>" );
01266     doc += i18n( "Possible Solutions:" );
01267     doc += QString::fromLatin1( "</h3><ul><li>" );
01268     doc += solutions.join( "</li><li>" );
01269     doc += QString::fromLatin1( "</li></ul>" );
01270   }
01271   doc += QString::fromLatin1( "</body></html>" );
01272 
01273   write( doc );
01274   end();
01275 }
01276 
01277 void KHTMLPart::slotFinished( KIO::Job * job )
01278 {
01279   d->m_job = 0L;
01280   d->m_jobspeed = 0L;
01281 
01282   if (job->error())
01283   {
01284     KHTMLPageCache::self()->cancelEntry(d->m_cacheId);
01285     emit canceled( job->errorString() );
01286     // TODO: what else ?
01287     checkCompleted();
01288     showError( job );
01289     return;
01290   }
01291   //kdDebug( 6050 ) << "slotFinished" << endl;
01292 
01293   KHTMLPageCache::self()->endData(d->m_cacheId);
01294 
01295   if ( d->m_doc && d->m_doc->docLoader()->expireDate() && m_url.protocol().lower().startsWith("http"))
01296       KIO::http_update_cache(m_url, false, d->m_doc->docLoader()->expireDate());
01297 
01298   d->m_workingURL = KURL();
01299 
01300   if (d->m_doc->parsing())
01301     end(); //will emit completed()
01302 }
01303 
01304 void KHTMLPart::begin( const KURL &url, int xOffset, int yOffset )
01305 {
01306   clear();
01307   d->m_bCleared = false;
01308   d->m_cacheId = 0;
01309   d->m_bComplete = false;
01310   d->m_bLoadEventEmitted = false;
01311 
01312   if(url.isValid()) {
01313       QString urlString = url.url();
01314       KHTMLFactory::vLinks()->insert( urlString );
01315       QString urlString2 = url.prettyURL();
01316       if ( urlString != urlString2 ) {
01317           KHTMLFactory::vLinks()->insert( urlString2 );
01318       }
01319   }
01320 
01321   // ###
01322   //stopParser();
01323 
01324   KParts::URLArgs args( d->m_extension->urlArgs() );
01325   args.xOffset = xOffset;
01326   args.yOffset = yOffset;
01327   d->m_extension->setURLArgs( args );
01328 
01329   if ( d->m_referrer != url.url() )
01330       d->m_pageReferrer = d->m_referrer;
01331 
01332   KURL ref(url);
01333   ref.setRef(QString::null);
01334   ref.setUser(QString::null);
01335   ref.setPass(QString::null);
01336   d->m_referrer = ref.protocol().startsWith("http") ? ref.url() : QString::fromLatin1( "" );
01337 
01338   m_url = url;
01339   KURL baseurl;
01340 
01341   if ( !m_url.isEmpty() )
01342   {
01343     KURL::List lst = KURL::split( m_url );
01344     if ( !lst.isEmpty() )
01345       baseurl = *lst.begin();
01346 
01347     KURL title( baseurl );
01348     title.setRef( QString::null );
01349     title.setQuery( QString::null );
01350     emit setWindowCaption( title.prettyURL() );
01351   }
01352   else
01353     emit setWindowCaption( i18n( "no title", "* Unknown *" ) );
01354 
01355   // ### not sure if XHTML documents served as text/xml should use DocumentImpl or HTMLDocumentImpl
01356   if (args.serviceType == "text/xml")
01357     d->m_doc = DOMImplementationImpl::instance()->createDocument( d->m_view );
01358   else
01359     d->m_doc = DOMImplementationImpl::instance()->createHTMLDocument( d->m_view );
01360 
01361   d->m_doc->ref();
01362   if (!d->m_doc->attached())
01363     d->m_doc->attach( );
01364   d->m_doc->setURL( m_url.url() );
01365   // We prefer m_baseURL over m_url because m_url changes when we are
01366   // about to load a new page.
01367   d->m_doc->setBaseURL( baseurl.url() );
01368   d->m_doc->docLoader()->setShowAnimations( KHTMLFactory::defaultHTMLSettings()->showAnimations() );
01369   emit docCreated(); // so that the parent can set the domain
01370 
01371   d->m_paUseStylesheet->setItems(QStringList());
01372   d->m_paUseStylesheet->setEnabled( false );
01373 
01374   setAutoloadImages( KHTMLFactory::defaultHTMLSettings()->autoLoadImages() );
01375   QString userStyleSheet = KHTMLFactory::defaultHTMLSettings()->userStyleSheet();
01376   if ( !userStyleSheet.isEmpty() )
01377     setUserStyleSheet( KURL( userStyleSheet ) );
01378 
01379   d->m_doc->setRestoreState(args.docState);
01380   d->m_doc->open();
01381   // clear widget
01382   d->m_view->resizeContents( 0, 0 );
01383   connect(d->m_doc,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
01384 
01385   emit d->m_extension->enableAction( "print", true );
01386 
01387   d->m_doc->setParsing(true);
01388 }
01389 
01390 void KHTMLPart::write( const char *str, int len )
01391 {
01392     if ( !d->m_decoder ) {
01393         d->m_decoder = new khtml::Decoder();
01394         if(!d->m_encoding.isNull())
01395             d->m_decoder->setEncoding(d->m_encoding.latin1(), d->m_haveEncoding);
01396         else
01397             d->m_decoder->setEncoding(settings()->encoding().latin1(), d->m_haveEncoding);
01398     }
01399   if ( len == 0 )
01400     return;
01401 
01402   if ( len == -1 )
01403     len = strlen( str );
01404 
01405   QString decoded = d->m_decoder->decode( str, len );
01406 
01407   if(decoded.isEmpty()) return;
01408 
01409   if(d->m_bFirstData) {
01410       // determine the parse mode
01411       d->m_doc->determineParseMode( decoded );
01412       d->m_bFirstData = false;
01413 
01414   //kdDebug(6050) << "KHTMLPart::write haveEnc = " << d->m_haveEncoding << endl;
01415       // ### this is still quite hacky, but should work a lot better than the old solution
01416       if(d->m_decoder->visuallyOrdered()) d->m_doc->setVisuallyOrdered();
01417       d->m_doc->setDecoderCodec(d->m_decoder->codec());
01418       d->m_doc->recalcStyle( NodeImpl::Force );
01419   }
01420 
01421   if (jScript())
01422     jScript()->appendSourceFile(m_url.url(),decoded);
01423   Tokenizer* t = d->m_doc->tokenizer();
01424   if(t)
01425     t->write( decoded, true );
01426 }
01427 
01428 void KHTMLPart::write( const QString &str )
01429 {
01430   if ( str.isNull() )
01431     return;
01432 
01433   if(d->m_bFirstData) {
01434       // determine the parse mode
01435       d->m_doc->setParseMode( DocumentImpl::Strict );
01436       d->m_bFirstData = false;
01437   }
01438   if (jScript())
01439     jScript()->appendSourceFile(m_url.url(),str);
01440   Tokenizer* t = d->m_doc->tokenizer();
01441   if(t)
01442     t->write( str, true );
01443 }
01444 
01445 void KHTMLPart::end()
01446 {
01447     // make sure nothing's left in there...
01448     if(d->m_decoder)
01449         write(d->m_decoder->flush());
01450     if (d->m_doc)
01451     d->m_doc->finishParsing();
01452 }
01453 
01454 void KHTMLPart::paint(QPainter *p, const QRect &rc, int yOff, bool *more)
01455 {
01456     if (!d->m_view) return;
01457     d->m_view->paint(p, rc, yOff, more);
01458 }
01459 
01460 void KHTMLPart::stopAnimations()
01461 {
01462   if ( d->m_doc )
01463     d->m_doc->docLoader()->setShowAnimations( KHTMLSettings::KAnimationDisabled );
01464 
01465   ConstFrameIt it = d->m_frames.begin();
01466   ConstFrameIt end = d->m_frames.end();
01467   for (; it != end; ++it )
01468     if ( !( *it ).m_part.isNull() && ( *it ).m_part->inherits( "KHTMLPart" ) ) {
01469       KParts::ReadOnlyPart* p = ( *it ).m_part;
01470       static_cast<KHTMLPart*>( p )->stopAnimations();
01471     }
01472 }
01473 
01474 void KHTMLPart::slotFinishedParsing()
01475 {
01476   d->m_doc->setParsing(false);
01477   checkEmitLoadEvent();
01478   disconnect(d->m_doc,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
01479 
01480   if (!d->m_view)
01481     return; // We are probably being destructed.
01482   // check if the scrollbars are really needed for the content
01483   // if not, remove them, relayout, and repaint
01484 
01485   d->m_view->restoreScrollBar();
01486 
01487   if ( !m_url.encodedHtmlRef().isEmpty() )
01488     if ( !gotoAnchor( m_url.encodedHtmlRef()) )
01489        gotoAnchor( m_url.htmlRef() );
01490 
01491   checkCompleted();
01492 }
01493 
01494 void KHTMLPart::slotLoaderRequestStarted( khtml::DocLoader* dl, khtml::CachedObject *obj )
01495 {
01496   if ( obj && obj->type() == khtml::CachedObject::Image && d->m_doc && d->m_doc->docLoader() == dl ) {
01497     KHTMLPart* p = this;
01498     while ( p ) {
01499       KHTMLPart* op = p;
01500       p->d->m_totalObjectCount++;
01501       p = p->parentPart();
01502       if ( !p && op->d->m_loadedObjects <= op->d->m_totalObjectCount
01503         && !op->d->m_progressUpdateTimer.isActive())
01504     op->d->m_progressUpdateTimer.start( 200, true );
01505     }
01506   }
01507 }
01508 
01509 void KHTMLPart::slotLoaderRequestDone( khtml::DocLoader* dl, khtml::CachedObject *obj )
01510 {
01511   if ( obj && obj->type() == khtml::CachedObject::Image && d->m_doc && d->m_doc->docLoader() == dl ) {
01512     KHTMLPart* p = this;
01513     while ( p ) {
01514       KHTMLPart* op = p;
01515       p->d->m_loadedObjects++;
01516       p = p->parentPart();
01517       if ( !p && op->d->m_loadedObjects <= op->d->m_totalObjectCount && op->d->m_jobPercent <= 100
01518         && !op->d->m_progressUpdateTimer.isActive())
01519     op->d->m_progressUpdateTimer.start( 200, true );
01520     }
01521   }
01522 
01523   checkCompleted();
01524 }
01525 
01526 void KHTMLPart::slotProgressUpdate()
01527 {
01528   int percent;
01529   if ( d->m_loadedObjects < d->m_totalObjectCount )
01530     percent = d->m_jobPercent / 4 + ( d->m_loadedObjects*300 ) / ( 4*d->m_totalObjectCount );
01531   else
01532     percent = d->m_jobPercent;
01533 
01534   if( d->m_bComplete )
01535     percent = 100;
01536 
01537   if( d->m_bComplete )
01538     emit d->m_extension->infoMessage( i18n( "Page loaded." ));
01539   else if ( d->m_loadedObjects < d->m_totalObjectCount && percent >= 75 )
01540     emit d->m_extension->infoMessage( i18n( "%n Image of %1 loaded.", "%n Images of %1 loaded.", d->m_loadedObjects).arg(d->m_totalObjectCount) );
01541 
01542   emit d->m_extension->loadingProgress( percent );
01543 }
01544 
01545 void KHTMLPart::slotJobSpeed( KIO::Job* /*job*/, unsigned long speed )
01546 {
01547   d->m_jobspeed = speed;
01548   if (!parentPart())
01549     setStatusBarText(jsStatusBarText(), BarOverrideText);
01550 }
01551 
01552 void KHTMLPart::slotJobPercent( KIO::Job* /*job*/, unsigned long percent )
01553 {
01554   d->m_jobPercent = percent;
01555 
01556   if ( !parentPart() )
01557     d->m_progressUpdateTimer.start( 0, true );
01558 }
01559 
01560 void KHTMLPart::slotJobDone( KIO::Job* /*job*/ )
01561 {
01562   d->m_jobPercent = 100;
01563 
01564   if ( !parentPart() )
01565     d->m_progressUpdateTimer.start( 0, true );
01566 }
01567 
01568 void KHTMLPart::checkCompleted()
01569 {
01570   //kdDebug( 6050 ) << "KHTMLPart::checkCompleted() parsing: " << (d->m_doc && d->m_doc->parsing()) << endl;
01571   //kdDebug( 6050 ) << "                           complete: " << d->m_bComplete << endl;
01572 
01573   // restore the cursor position
01574   if (d->m_doc && !d->m_doc->parsing() && !d->m_focusNodeRestored)
01575   {
01576       if (d->m_focusNodeNumber >= 0)
01577           d->m_doc->setFocusNode(d->m_doc->nodeWithAbsIndex(d->m_focusNodeNumber));
01578       else
01579           d->m_doc->setFocusNode(0);
01580       d->m_focusNodeRestored = true;
01581   }
01582 
01583   bool bPendingChildRedirection = false;
01584   // Any frame that hasn't completed yet ?
01585   ConstFrameIt it = d->m_frames.begin();
01586   ConstFrameIt end = d->m_frames.end();
01587   for (; it != end; ++it ) {
01588     if ( !(*it).m_bCompleted )
01589       return;
01590     // Check for frames with pending redirections
01591     if ( (*it).m_bPendingRedirection )
01592       bPendingChildRedirection = true;
01593   }
01594 
01595   // Are we still parsing - or have we done the completed stuff already ?
01596   if ( d->m_bComplete || (d->m_doc && d->m_doc->parsing()) )
01597     return;
01598 
01599   // Still waiting for images/scripts from the loader ?
01600   int requests = 0;
01601   if ( d->m_doc && d->m_doc->docLoader() )
01602     requests = khtml::Cache::loader()->numRequests( d->m_doc->docLoader() );
01603 
01604   if ( requests > 0 )
01605     return;
01606 
01607 #ifndef Q_WS_QWS
01608   if (d->m_javaContext && !d->m_javaContext->appletsLoaded())
01609       return;
01610 #endif
01611 
01612   // OK, completed.
01613   // Now do what should be done when we are really completed.
01614   d->m_bComplete = true;
01615   d->m_cachePolicy = KIO::CC_Verify; // reset cache policy
01616   d->m_totalObjectCount = 0;
01617   d->m_loadedObjects = 0;
01618 
01619   KHTMLPart* p = this;
01620   while ( p ) {
01621     KHTMLPart* op = p;
01622     p = p->parentPart();
01623     if ( !p && !op->d->m_progressUpdateTimer.isActive())
01624       op->d->m_progressUpdateTimer.start( 0, true );
01625   }
01626 
01627   checkEmitLoadEvent(); // if we didn't do it before
01628 
01629   // check that the view has not been moved by the user
01630   if ( m_url.encodedHtmlRef().isEmpty() && d->m_view->contentsY() == 0 )
01631       d->m_view->setContentsPos( d->m_extension->urlArgs().xOffset,
01632                                  d->m_extension->urlArgs().yOffset );
01633 
01634   d->m_view->complete();
01635 
01636   if ( !d->m_redirectURL.isEmpty() )
01637   {
01638     // Do not start redirection for frames here! That action is
01639     // deferred until the parent emits a completed signal.
01640     if ( parentPart() == 0 )
01641       d->m_redirectionTimer.start( 1000 * d->m_delayRedirect, true );
01642 
01643     emit completed( true );
01644   }
01645   else
01646   {
01647     if ( bPendingChildRedirection )
01648       emit completed( true );
01649     else
01650       emit completed();
01651   }
01652 
01653   // find the alternate stylesheets
01654   QStringList sheets;
01655   if (d->m_doc)
01656      sheets = d->m_doc->availableStyleSheets();
01657   d->m_paUseStylesheet->setItems( sheets );
01658   d->m_paUseStylesheet->setEnabled( !sheets.isEmpty() );
01659   if (!sheets.isEmpty())
01660   {
01661     d->m_paUseStylesheet->setCurrentItem(kMax(sheets.findIndex(d->m_sheetUsed), 0));
01662     slotUseStylesheet();
01663   }
01664 
01665   setJSDefaultStatusBarText(QString::null);
01666 
01667 #ifdef SPEED_DEBUG
01668   kdDebug(6050) << "DONE: " <<d->m_parsetime.elapsed() << endl;
01669 #endif
01670 }
01671 
01672 void KHTMLPart::checkEmitLoadEvent()
01673 {
01674   if ( d->m_bLoadEventEmitted || !d->m_doc || d->m_doc->parsing() ) return;
01675 
01676   ConstFrameIt it = d->m_frames.begin();
01677   ConstFrameIt end = d->m_frames.end();
01678   for (; it != end; ++it )
01679     if ( !(*it).m_bCompleted ) // still got a frame running -> too early
01680       return;
01681 
01682 #ifndef Q_WS_QWS
01683   if (d->m_javaContext && !d->m_javaContext->appletsLoaded())
01684       return;
01685 #endif
01686   // Still waiting for images/scripts from the loader ?
01687   // (onload must happen afterwards, #45607)
01688   // ## This makes this method very similar to checkCompleted. A brave soul should try merging them.
01689   int requests = 0;
01690   if ( d->m_doc && d->m_doc->docLoader() )
01691     requests = khtml::Cache::loader()->numRequests( d->m_doc->docLoader() );
01692 
01693   if ( requests > 0 )
01694     return;
01695 
01696   d->m_bLoadEventEmitted = true;
01697   if (d->m_doc)
01698     d->m_doc->close();
01699 }
01700 
01701 const KHTMLSettings *KHTMLPart::settings() const
01702 {
01703   return d->m_settings;
01704 }
01705 
01706 #ifndef KDE_NO_COMPAT
01707 KURL KHTMLPart::baseURL() const
01708 {
01709   if ( !d->m_doc ) return KURL();
01710 
01711   return d->m_doc->baseURL();
01712 }
01713 
01714 QString KHTMLPart::baseTarget() const
01715 {
01716   if ( !d->m_doc ) return QString::null;
01717 
01718   return d->m_doc->baseTarget();
01719 }
01720 #endif
01721 
01722 KURL KHTMLPart::completeURL( const QString &url )
01723 {
01724   if ( !d->m_doc ) return url;
01725 
01726   if (d->m_decoder)
01727     return KURL(d->m_doc->completeURL(url), d->m_decoder->codec()->mibEnum());
01728 
01729   return KURL( d->m_doc->completeURL( url ) );
01730 }
01731 
01732 void KHTMLPart::scheduleRedirection( int delay, const QString &url, bool doLockHistory )
01733 {
01734   //kdDebug(6050) << "KHTMLPart::scheduleRedirection delay=" << delay << " url=" << url << endl;
01735     if ( delay < 24*60*60 &&
01736        ( d->m_redirectURL.isEmpty() || delay < d->m_delayRedirect ) )
01737     {
01738        d->m_delayRedirect = delay;
01739        d->m_redirectURL = url;
01740        d->m_redirectLockHistory = doLockHistory;
01741        if ( d->m_bComplete ) {
01742          d->m_redirectionTimer.stop();
01743          d->m_redirectionTimer.start( kMax(0, 1000 * d->m_delayRedirect), true );
01744        }
01745     }
01746 }
01747 
01748 void KHTMLPart::slotRedirect()
01749 {
01750   QString u = d->m_redirectURL;
01751   d->m_delayRedirect = 0;
01752   d->m_redirectURL = QString::null;
01753   d->m_pageReferrer = d->m_referrer = "";
01754   // SYNC check with ecma/kjs_window.cpp::goURL !
01755   if ( u.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 )
01756   {
01757     QString script = KURL::decode_string( u.right( u.length() - 11 ) );
01758     //kdDebug( 6050 ) << "KHTMLPart::slotRedirect script=" << script << endl;
01759     QVariant res = executeScript( script );
01760     if ( res.type() == QVariant::String ) {
01761       begin( url() );
01762       write( res.asString() );
01763       end();
01764     }
01765     return;
01766   }
01767   KParts::URLArgs args;
01768   // Redirecting to the current URL leads to a reload.
01769   // But jumping to an anchor never leads to a reload.
01770   KURL cUrl( m_url );
01771   KURL url( u );
01772 
01773   // handle windows opened by JS
01774   if ( openedByJS() && d->m_opener )
01775       cUrl = d->m_opener->url();
01776 
01777   if (!kapp || !kapp->kapp->authorizeURLAction("redirect", cUrl, url))
01778   {
01779     kdWarning(6050) << "KHTMLPart::scheduleRedirection: Redirection from " << cUrl.prettyURL() << " to " << url.prettyURL() << " REJECTED!" << endl;
01780     return;
01781   }
01782 
01783   if ( !url.hasRef() && urlcmp( u, m_url.url(), true, true ) )
01784   {
01785     args.reload = true;
01786   }
01787 
01788   // Indicate that this request is due to a redirection.
01789   args.setRedirectedRequest(true);
01790 
01791   args.setLockHistory( d->m_redirectLockHistory );
01792   // _self: make sure we don't use any <base target=>'s
01793   urlSelected( u, 0, 0, "_self", args );
01794 }
01795 
01796 void KHTMLPart::slotRedirection(KIO::Job*, const KURL& url)
01797 {
01798   // the slave told us that we got redirected
01799   // kdDebug( 6050 ) << "redirection by KIO to " << url.url() << endl;
01800   emit d->m_extension->setLocationBarURL( url.prettyURL() );
01801   d->m_workingURL = url;
01802 }
01803 
01804 bool KHTMLPart::setEncoding( const QString &name, bool override )
01805 {
01806     d->m_encoding = name;
01807     d->m_haveEncoding = override;
01808 
01809     if( !m_url.isEmpty() ) {
01810         // reload document
01811         closeURL();
01812         KURL url = m_url;
01813         m_url = 0;
01814         d->m_restored = true;
01815         openURL(url);
01816         d->m_restored = false;
01817     }
01818 
01819     return true;
01820 }
01821 
01822 QString KHTMLPart::encoding() const
01823 {
01824     if(d->m_haveEncoding && !d->m_encoding.isEmpty())
01825         return d->m_encoding;
01826 
01827     if(d->m_decoder && d->m_decoder->encoding())
01828         return QString(d->m_decoder->encoding());
01829 
01830     return(settings()->encoding());
01831 }
01832 
01833 void KHTMLPart::setUserStyleSheet(const KURL &url)
01834 {
01835   if ( d->m_doc && d->m_doc->docLoader() )
01836     (void) new khtml::PartStyleSheetLoader(this, url.url(), d->m_doc->docLoader());
01837 }
01838 
01839 void KHTMLPart::setUserStyleSheet(const QString &styleSheet)
01840 {
01841   if ( d->m_doc )
01842     d->m_doc->setUserStyleSheet( styleSheet );
01843 }
01844 
01845 bool KHTMLPart::gotoAnchor( const QString &name )
01846 {
01847   if (!d->m_doc)
01848     return false;
01849 
01850   HTMLCollectionImpl *anchors =
01851       new HTMLCollectionImpl( d->m_doc, HTMLCollectionImpl::DOC_ANCHORS);
01852   anchors->ref();
01853   NodeImpl *n = anchors->namedItem(name);
01854   anchors->deref();
01855 
01856   if(!n) {
01857       n = d->m_doc->getElementById( name );
01858   }
01859 
01860   if(!n) {
01861       kdDebug(6050) << "KHTMLPart::gotoAnchor node '" << name << "' not found" << endl;
01862       return false;
01863   }
01864 
01865   int x = 0, y = 0;
01866   int gox, dummy;
01867   HTMLElementImpl *a = static_cast<HTMLElementImpl *>(n);
01868 
01869   a->getUpperLeftCorner(x, y);
01870   if (x <= d->m_view->contentsX())
01871     gox = x - 10;
01872   else {
01873     gox = d->m_view->contentsX();
01874     if ( x + 10 > d->m_view->contentsX()+d->m_view->visibleWidth()) {
01875       a->getLowerRightCorner(x, dummy);
01876       gox = x - d->m_view->visibleWidth() + 10;
01877     }
01878   }
01879 
01880   d->m_view->setContentsPos(gox, y-20);
01881 
01882   return true;
01883 }
01884 
01885 void KHTMLPart::setStandardFont( const QString &name )
01886 {
01887     d->m_settings->setStdFontName(name);
01888 }
01889 
01890 void KHTMLPart::setFixedFont( const QString &name )
01891 {
01892     d->m_settings->setFixedFontName(name);
01893 }
01894 
01895 void KHTMLPart::setURLCursor( const QCursor &c )
01896 {
01897   d->m_linkCursor = c;
01898 }
01899 
01900 QCursor KHTMLPart::urlCursor() const
01901 {
01902   return d->m_linkCursor;
01903 }
01904 
01905 bool KHTMLPart::onlyLocalReferences() const
01906 {
01907   return d->m_onlyLocalReferences;
01908 }
01909 
01910 void KHTMLPart::setOnlyLocalReferences(bool enable)
01911 {
01912   d->m_onlyLocalReferences = enable;
01913 }
01914 
01915 void KHTMLPart::findTextBegin()
01916 {
01917   d->m_findPos = -1;
01918   d->m_findNode = 0;
01919   d->m_findPosEnd = -1;
01920   d->m_findNodeEnd= 0;
01921   d->m_paFindNext->setEnabled( false ); // needs a 'find' first
01922 }
01923 
01924 bool KHTMLPart::initFindNode( bool selection, bool reverse )
01925 {
01926     if ( !d->m_doc )
01927         return false;
01928 
01929     if(!d->m_findNode) {
01930         if (d->m_doc->isHTMLDocument())
01931             d->m_findNode = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
01932         else
01933             d->m_findNode = d->m_doc;
01934     }
01935 
01936     if ( !d->m_findNode )
01937     {
01938       kdDebug(6050) << k_funcinfo << "no findNode -> return false" << endl;
01939       return false;
01940     }
01941     if ( d->m_findNode->id() == ID_FRAMESET )
01942     {
01943       kdDebug(6050) << k_funcinfo << "FRAMESET -> return false" << endl;
01944       return false;
01945     }
01946 
01947     if ( selection && hasSelection() )
01948     {
01949       kdDebug(6050) << k_funcinfo << "using selection" << endl;
01950       d->m_findNode = d->m_selectionStart.handle();
01951       d->m_findPos = d->m_startOffset;
01952       d->m_findNodeEnd = d->m_selectionEnd.handle();
01953       d->m_findPosEnd = d->m_endOffset;
01954       if ( reverse ) {
01955         qSwap( d->m_findNode, d->m_findNodeEnd );
01956         qSwap( d->m_findPos, d->m_findPosEnd );
01957       }
01958     }
01959     else // whole document
01960     {
01961       //kdDebug(6050) << k_funcinfo << "whole doc" << endl;
01962       d->m_findPos = 0;
01963       d->m_findPosEnd = -1;
01964       d->m_findNodeEnd = 0;
01965       if ( reverse ) {
01966         qSwap( d->m_findPos, d->m_findPosEnd );
01967         // Need to find out the really last object, to start from it
01968         while ( d->m_findNode->lastChild() )
01969           d->m_findNode = d->m_findNode->lastChild();
01970       }
01971     }
01972     return true;
01973 }
01974 
01975 // Old method (its API limits the available features - remove in KDE-4)
01976 bool KHTMLPart::findTextNext( const QString &str, bool forward, bool caseSensitive, bool isRegExp )
01977 {
01978     if ( !initFindNode( false, !forward ) )
01979       return false;
01980     while(1)
01981     {
01982         if( (d->m_findNode->nodeType() == Node::TEXT_NODE || d->m_findNode->nodeType() == Node::CDATA_SECTION_NODE) && d->m_findNode->renderer() )
01983         {
01984             DOMString nodeText = d->m_findNode->nodeValue();
01985             DOMStringImpl *t = nodeText.implementation();
01986             QConstString s(t->s, t->l);
01987 
01988             int matchLen = 0;
01989             if ( isRegExp ) {
01990               QRegExp matcher( str );
01991               matcher.setCaseSensitive( caseSensitive );
01992               d->m_findPos = matcher.search(s.string(), d->m_findPos+1);
01993               if ( d->m_findPos != -1 )
01994                 matchLen = matcher.matchedLength();
01995             }
01996             else {
01997               d->m_findPos = s.string().find(str, d->m_findPos+1, caseSensitive);
01998               matchLen = str.length();
01999             }
02000 
02001             if(d->m_findPos != -1)
02002             {
02003                 int x = 0, y = 0;
02004                 if(static_cast<khtml::RenderText *>(d->m_findNode->renderer())
02005                   ->posOfChar(d->m_findPos, x, y))
02006                     d->m_view->setContentsPos(x-50, y-50);
02007 
02008                 d->m_selectionStart = d->m_findNode;
02009                 d->m_startOffset = d->m_findPos;
02010                 d->m_selectionEnd = d->m_findNode;
02011                 d->m_endOffset = d->m_findPos + matchLen;
02012                 d->m_startBeforeEnd = true;
02013 
02014                 d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset,
02015                                         d->m_selectionEnd.handle(), d->m_endOffset );
02016                 emitSelectionChanged();
02017                 return true;
02018             }
02019         }
02020         d->m_findPos = -1;
02021 
02022         NodeImpl *next;
02023 
02024         if ( forward )
02025         {
02026           next = d->m_findNode->firstChild();
02027 
02028           if(!next) next = d->m_findNode->nextSibling();
02029           while(d->m_findNode && !next) {
02030               d->m_findNode = d->m_findNode->parentNode();
02031               if( d->m_findNode ) {
02032                   next = d->m_findNode->nextSibling();
02033               }
02034           }
02035         }
02036         else
02037         {
02038           next = d->m_findNode->lastChild();
02039 
02040           if (!next ) next = d->m_findNode->previousSibling();
02041           while ( d->m_findNode && !next )
02042           {
02043             d->m_findNode = d->m_findNode->parentNode();
02044             if( d->m_findNode )
02045             {
02046               next = d->m_findNode->previousSibling();
02047             }
02048           }
02049         }
02050 
02051         d->m_findNode = next;
02052         if(!d->m_findNode) return false;
02053     }
02054 }
02055 
02056 
02057 void KHTMLPart::slotFind()
02058 {
02059   KParts::ReadOnlyPart *part = currentFrame();
02060   if (!part)
02061     return;
02062   if (!part->inherits("KHTMLPart") )
02063   {
02064       kdError(6000) << "slotFind: part is a " << part->className() << ", can't do a search into it" << endl;
02065       return;
02066   }
02067   static_cast<KHTMLPart *>( part )->findText();
02068 }
02069 
02070 void KHTMLPart::slotFindNext()
02071 {
02072   KParts::ReadOnlyPart *part = currentFrame();
02073   if (!part)
02074     return;
02075   if (!part->inherits("KHTMLPart") )
02076   {
02077       kdError(6000) << "slotFindNext: part is a " << part->className() << ", can't do a search into it" << endl;
02078       return;
02079   }
02080   static_cast<KHTMLPart *>( part )->findTextNext();
02081 }
02082 
02083 void KHTMLPart::slotFindDone()
02084 {
02085   // ### remove me
02086 }
02087 
02088 void KHTMLPart::slotFindDialogDestroyed()
02089 {
02090   // ### remove me
02091 }
02092 
02093 void KHTMLPart::findText()
02094 {
02095   // First do some init to make sure we can search in this frame
02096   if ( !d->m_doc )
02097     return;
02098 
02099   // The lineedit of the dialog would make khtml lose its selection, otherwise
02100 #ifndef QT_NO_CLIPBOARD
02101   disconnect( kapp->clipboard(), SIGNAL(selectionChanged()), this, SLOT(slotClearSelection()) );
02102 #endif
02103 
02104   // Now show the dialog in which the user can choose options.
02105   KFindDialog optionsDialog( widget(), "khtmlfind" );
02106   optionsDialog.setHasSelection( hasSelection() );
02107   optionsDialog.setHasCursor( d->m_findNode != 0 );
02108   if ( d->m_findNode ) // has a cursor -> default to 'FromCursor'
02109     d->m_lastFindState.options |= KFindDialog::FromCursor;
02110 
02111   // TODO? optionsDialog.setPattern( d->m_lastFindState.text );
02112   optionsDialog.setFindHistory( d->m_lastFindState.history );
02113   optionsDialog.setOptions( d->m_lastFindState.options );
02114 
02115   if ( optionsDialog.exec() != QDialog::Accepted )
02116       return;
02117 
02118 #ifndef QT_NO_CLIPBOARD
02119   connect( kapp->clipboard(), SIGNAL(selectionChanged()), SLOT(slotClearSelection()) );
02120 #endif
02121 
02122   // Save for next time
02123   //d->m_lastFindState.text = optionsDialog.pattern();
02124   int options = optionsDialog.options();
02125   d->m_lastFindState.options = options;
02126   d->m_lastFindState.history = optionsDialog.findHistory();
02127 
02128   // Create the KFind object
02129   delete d->m_find;
02130   d->m_find = new KFind( optionsDialog.pattern(), options, widget() );
02131   connect(d->m_find, SIGNAL( highlight( const QString &, int, int ) ),
02132           this, SLOT( slotHighlight( const QString &, int, int ) ) );
02133   connect(d->m_find, SIGNAL( findNext() ),
02134           this, SLOT( slotFindNext() ) );
02135 
02136   if ( options & KFindDialog::SelectedText )
02137     Q_ASSERT( hasSelection() );
02138 
02139   if ( (options & KFindDialog::FromCursor) == 0 )
02140       (void) initFindNode( options & KFindDialog::SelectedText, options & KFindDialog::FindBackwards );
02141   findTextNext();
02142 }
02143 
02144 // New method
02145 void KHTMLPart::findTextNext()
02146 {
02147   if (!d->m_find) // shouldn't be called before find is activated
02148     return;
02149 
02150   long options = d->m_find->options();
02151   KFind::Result res = KFind::NoMatch;
02152   khtml::RenderObject* obj = d->m_findNode ? d->m_findNode->renderer() : 0;
02153   khtml::RenderObject* end = d->m_findNodeEnd ? d->m_findNodeEnd->renderer() : 0;
02154   //kdDebug(6050) << k_funcinfo << "obj=" << obj << " end=" << end << endl;
02155   while( res == KFind::NoMatch )
02156   {
02157     if ( d->m_find->needData() )
02158     {
02159       if ( !obj ) {
02160         //kdDebug(6050) << k_funcinfo << "obj=0 -> done" << endl;
02161         break; // we're done
02162       }
02163       //kdDebug(6050) << k_funcinfo << " gathering data" << endl;
02164       // First make up the QString for the current 'line' (i.e. up to \n)
02165       // We also want to remember the DOMNode for every portion of the string.
02166       // We store this in an index->node list.
02167 
02168       d->m_stringPortions.clear();
02169       int newLinePos = -1;
02170       QString str;
02171       DOM::NodeImpl* lastNode = d->m_findNode;
02172       while ( obj && newLinePos == -1 )
02173       {
02174         // Grab text from render object
02175         QString s;
02176         if ( obj->isText() )
02177         {
02178           s = static_cast<khtml::RenderText *>(obj)->data().string();
02179           s = s.replace(0xa0, ' ');
02180         }
02181         else if ( obj->isBR() )
02182           s = '\n';
02183         else if ( !obj->isInline() && !str.isEmpty() )
02184           s = '\n';
02185         if ( lastNode == d->m_findNodeEnd )
02186           s.truncate( d->m_findPosEnd );
02187         if ( !s.isEmpty() )
02188         {
02189           newLinePos = s.find( '\n' ); // did we just get a newline?
02190           int index = str.length();
02191           if ( newLinePos != -1 )
02192             newLinePos += index;
02193           str += s;
02194           //kdDebug(6050) << "StringPortion: " << index << "-" << index+s.length()-1 << " -> " << node << endl;
02195           d->m_stringPortions.append( KHTMLPartPrivate::StringPortion( index, lastNode ) );
02196         }
02197         // Compare obj and end _after_ we processed the 'end' node itself
02198         if ( obj == end )
02199           obj = 0L;
02200         else
02201         {
02202           // Move on to next object (note: if we found a \n already, then obj (and lastNode)
02203           // will point to the _next_ object, i.e. they are in advance.
02204           do {
02205             // We advance until the next RenderObject that has a NodeImpl as its element().
02206             // Otherwise (if we keep the 'last node', and it has a '\n') we might be stuck
02207             // on that object forever...
02208             obj = (options & KFindDialog::FindBackwards) ? obj->objectAbove() : obj->objectBelow();
02209           } while ( obj && !obj->element() );
02210         }
02211         if ( obj )
02212           lastNode = obj->element();
02213         else
02214           lastNode = 0;
02215       } // end while
02216 
02217       if ( !str.isEmpty() )
02218       {
02219         //kdDebug(6050) << "str=" << str << endl;
02220         d->m_find->setData( str, d->m_findPos );
02221       }
02222 
02223       d->m_findPos = -1; // not used during the findnext loops. Only during init.
02224       d->m_findNode = lastNode;
02225     }
02226     if ( !d->m_find->needData() ) // happens if str was empty
02227     {
02228       // Let KFind inspect the text fragment, and display a dialog if a match is found
02229       res = d->m_find->find();
02230     }
02231   } // end while
02232 
02233   if ( res == KFind::NoMatch ) // i.e. we're done
02234   {
02235     if ( d->m_find->shouldRestart() )
02236     {
02237       //kdDebug(6050) << "Restarting" << endl;
02238       initFindNode( false, options & KFindDialog::FindBackwards );
02239       findTextNext();
02240     }
02241     else // really done, close 'find next' dialog
02242     {
02243       //kdDebug(6050) << "Finishing" << endl;
02244       delete d->m_find;
02245       d->m_find = 0L;
02246       slotClearSelection();
02247     }
02248   }
02249   d->m_paFindNext->setEnabled( d->m_find != 0L  ); // true, except when completely done
02250 }
02251 
02252 void KHTMLPart::slotHighlight( const QString &, int index, int length )
02253 {
02254   //kdDebug(6050) << "slotHighlight index=" << index << " length=" << length << endl;
02255   QValueList<KHTMLPartPrivate::StringPortion>::Iterator it = d->m_stringPortions.begin();
02256   QValueList<KHTMLPartPrivate::StringPortion>::Iterator prev = it;
02257   // We stop at the first portion whose index is 'greater than', and then use the previous one
02258   while ( it != d->m_stringPortions.end() && (*it).index <= index )
02259   {
02260     prev = it;
02261     ++it;
02262   }
02263   Q_ASSERT ( prev != d->m_stringPortions.end() );
02264   DOM::NodeImpl* node = (*prev).node;
02265   Q_ASSERT( node );
02266 
02267   d->m_selectionStart = node;
02268   d->m_startOffset = index - (*prev).index;
02269 
02270   Q_ASSERT( node->renderer() );
02271   if ( node->renderer() )
02272   {
02273     int x = 0, y = 0;
02274     if (static_cast<khtml::RenderText *>(node->renderer())
02275       ->posOfChar(d->m_startOffset, x, y))
02276         d->m_view->setContentsPos(x-50, y-50);
02277   }
02278 
02279   // Now look for end node
02280   it = prev; // no need to start from beginning again
02281   while ( it != d->m_stringPortions.end() && (*it).index < index + length )
02282   {
02283     prev = it;
02284     ++it;
02285   }
02286   Q_ASSERT ( prev != d->m_stringPortions.end() );
02287 
02288   d->m_selectionEnd = (*prev).node;
02289   d->m_endOffset = index + length - (*prev).index;
02290   d->m_startBeforeEnd = true;
02291 
02292 #if 0
02293   kdDebug(6050) << "slotHighlight: " << d->m_selectionStart.handle() << "," << d->m_startOffset << " - " <<
02294     d->m_selectionEnd.handle() << "," << d->m_endOffset << endl;
02295   it = d->m_stringPortions.begin();
02296   for ( ; it != d->m_stringPortions.end() ; ++it )
02297     kdDebug(6050) << "  StringPortion: from index=" << (*it).index << " -> node=" << (*it).node << endl;
02298 #endif
02299   d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset,
02300                           d->m_selectionEnd.handle(), d->m_endOffset );
02301   emitSelectionChanged();
02302 }
02303 
02304 QString KHTMLPart::selectedText() const
02305 {
02306   bool hasNewLine = true;
02307   QString text;
02308   DOM::Node n = d->m_selectionStart;
02309   while(!n.isNull()) {
02310       if(n.nodeType() == DOM::Node::TEXT_NODE && n.handle()->renderer()) {
02311         QString str = n.nodeValue().string();
02312         hasNewLine = false;
02313         if(n == d->m_selectionStart && n == d->m_selectionEnd)
02314           text = str.mid(d->m_startOffset, d->m_endOffset - d->m_startOffset);
02315         else if(n == d->m_selectionStart)
02316           text = str.mid(d->m_startOffset);
02317         else if(n == d->m_selectionEnd)
02318           text += str.left(d->m_endOffset);
02319         else
02320           text += str;
02321       }
02322       else {
02323         // This is our simple HTML -> ASCII transformation:
02324         unsigned short id = n.elementId();
02325         switch(id) {
02326           case ID_BR:
02327             text += "\n";
02328             hasNewLine = true;
02329             break;
02330 
02331           case ID_TD:
02332           case ID_TH:
02333           case ID_HR:
02334           case ID_OL:
02335           case ID_UL:
02336           case ID_LI:
02337           case ID_DD:
02338           case ID_DL:
02339           case ID_DT:
02340           case ID_PRE:
02341           case ID_BLOCKQUOTE:
02342           case ID_DIV:
02343             if (!hasNewLine)
02344                text += "\n";
02345             hasNewLine = true;
02346             break;
02347           case ID_P:
02348           case ID_TR:
02349           case ID_H1:
02350           case ID_H2:
02351           case ID_H3:
02352           case ID_H4:
02353           case ID_H5:
02354           case ID_H6:
02355             if (!hasNewLine)
02356                text += "\n";
02357             text += "\n";
02358             hasNewLine = true;
02359             break;
02360         }
02361       }
02362       if(n == d->m_selectionEnd) break;
02363       DOM::Node next = n.firstChild();
02364       if(next.isNull()) next = n.nextSibling();
02365       while( next.isNull() && !n.parentNode().isNull() ) {
02366         n = n.parentNode();
02367         next = n.nextSibling();
02368         unsigned short id = n.elementId();
02369         switch(id) {
02370           case ID_TD:
02371           case ID_TH:
02372           case ID_HR:
02373           case ID_OL:
02374           case ID_UL:
02375           case ID_LI:
02376           case ID_DD:
02377           case ID_DL:
02378           case ID_DT:
02379           case ID_PRE:
02380           case ID_BLOCKQUOTE:
02381           case ID_DIV:
02382             if (!hasNewLine)
02383                text += "\n";
02384             hasNewLine = true;
02385             break;
02386           case ID_P:
02387           case ID_TR:
02388           case ID_H1:
02389           case ID_H2:
02390           case ID_H3:
02391           case ID_H4:
02392           case ID_H5:
02393           case ID_H6:
02394             if (!hasNewLine)
02395                text += "\n";
02396             text += "\n";
02397             hasNewLine = true;
02398             break;
02399         }
02400       }
02401 
02402       n = next;
02403     }
02404 
02405     if(text.isEmpty())
02406         return QString::null;
02407 
02408     int start = 0;
02409     int end = text.length();
02410 
02411     // Strip leading LFs
02412     while ((start < end) && (text[start] == '\n'))
02413        start++;
02414 
02415     // Strip excessive trailing LFs
02416     while ((start < (end-1)) && (text[end-1] == '\n') && (text[end-2] == '\n'))
02417        end--;
02418 
02419     return text.mid(start, end-start);
02420 }
02421 
02422 bool KHTMLPart::hasSelection() const
02423 {
02424   if ( d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() )
02425       return false;
02426   if ( d->m_selectionStart == d->m_selectionEnd &&
02427        d->m_startOffset == d->m_endOffset )
02428       return false; // empty
02429   return true;
02430 }
02431 
02432 DOM::Range KHTMLPart::selection() const
02433 {
02434     DOM::Range r = document().createRange();DOM::Range();
02435     r.setStart( d->m_selectionStart, d->m_startOffset );
02436     r.setEnd( d->m_selectionEnd, d->m_endOffset );
02437     return r;
02438 }
02439 
02440 
02441 void KHTMLPart::setSelection( const DOM::Range &r )
02442 {
02443     d->m_selectionStart = r.startContainer();
02444     d->m_startOffset = r.startOffset();
02445     d->m_selectionEnd = r.endContainer();
02446     d->m_endOffset = r.endOffset();
02447     d->m_doc->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
02448                            d->m_selectionEnd.handle(),d->m_endOffset);
02449 }
02450 
02451 void KHTMLPart::slotClearSelection()
02452 {
02453     bool hadSelection = hasSelection();
02454     d->m_selectionStart = 0;
02455     d->m_startOffset = 0;
02456     d->m_selectionEnd = 0;
02457     d->m_endOffset = 0;
02458     if ( d->m_doc ) d->m_doc->clearSelection();
02459     if ( hadSelection )
02460       emitSelectionChanged();
02461 }
02462 
02463 void KHTMLPart::overURL( const QString &url, const QString &target, bool /*shiftPressed*/ )
02464 {
02465   KURL u = completeURL(url);
02466 
02467   // special case for <a href="">
02468   if ( url.isEmpty() )
02469     u.setFileName( url );
02470 
02471   emit onURL( url );
02472 
02473   if ( url.isEmpty() ) {
02474     setStatusBarText(u.htmlURL(), BarHoverText);
02475     return;
02476   }
02477 
02478   if (url.find( QString::fromLatin1( "javascript:" ),0, false ) != -1 ) {
02479     QString jscode = KURL::decode_string( url.mid( url.find( "javascript:", 0, false ) ) );
02480     jscode = KStringHandler::rsqueeze( jscode, 80 ); // truncate if too long
02481     setStatusBarText( QStyleSheet::escape( jscode ), BarHoverText );
02482     return;
02483   }
02484 
02485   KFileItem item(u, QString::null, KFileItem::Unknown);
02486   emit d->m_extension->mouseOverInfo(&item);
02487 
02488   QString com;
02489 
02490   KMimeType::Ptr typ = KMimeType::findByURL( u );
02491 
02492   if ( typ )
02493     com = typ->comment( u, false );
02494 
02495   if ( u.isMalformed() ) {
02496     setStatusBarText(u.htmlURL(), BarHoverText);
02497     return;
02498   }
02499 
02500   if ( u.isLocalFile() )
02501   {
02502     // TODO : use KIO::stat() and create a KFileItem out of its result,
02503     // to use KFileItem::statusBarText()
02504     QCString path = QFile::encodeName( u.path() );
02505 
02506     struct stat buff;
02507     bool ok = !stat( path.data(), &buff );
02508 
02509     struct stat lbuff;
02510     if (ok) ok = !lstat( path.data(), &lbuff );
02511 
02512     QString text = u.htmlURL();
02513     QString text2 = text;
02514 
02515     if (ok && S_ISLNK( lbuff.st_mode ) )
02516     {
02517       QString tmp;
02518       if ( com.isNull() )
02519         tmp = i18n( "Symbolic Link");
02520       else
02521         tmp = i18n("%1 (Link)").arg(com);
02522       char buff_two[1024];
02523       text += " -> ";
02524       int n = readlink ( path.data(), buff_two, 1022);
02525       if (n == -1)
02526       {
02527         text2 += "  ";
02528         text2 += tmp;
02529         setStatusBarText(text2, BarHoverText);
02530         return;
02531       }
02532       buff_two[n] = 0;
02533 
02534       text += buff_two;
02535       text += "  ";
02536       text += tmp;
02537     }
02538     else if ( ok && S_ISREG( buff.st_mode ) )
02539     {
02540       if (buff.st_size < 1024)
02541         text = i18n("%2 (%1 bytes)").arg((long) buff.st_size).arg(text2); // always put the URL last, in case it contains '%'
02542       else
02543       {
02544         float d = (float) buff.st_size/1024.0;
02545         text = i18n("%1 (%2 K)").arg(text2).arg(KGlobal::locale()->formatNumber(d, 2)); // was %.2f
02546       }
02547       text += "  ";
02548       text += com;
02549     }
02550     else if ( ok && S_ISDIR( buff.st_mode ) )
02551     {
02552       text += "  ";
02553       text += com;
02554     }
02555     else
02556     {
02557       text += "  ";
02558       text += com;
02559     }
02560     setStatusBarText(text, BarHoverText);
02561   }
02562   else
02563   {
02564     QString extra;
02565     if (target.lower() == "_blank")
02566     {
02567       extra = i18n(" (In new window)");
02568     }
02569     else if (!target.isEmpty() &&
02570              (target.lower() != "_top") &&
02571              (target.lower() != "_self") &&
02572              (target.lower() != "_parent"))
02573     {
02574       extra = i18n(" (In other frame)");
02575     }
02576 
02577     if (u.protocol() == QString::fromLatin1("mailto")) {
02578       QString mailtoMsg /* = QString::fromLatin1("<img src=%1>").arg(locate("icon", QString::fromLatin1("locolor/16x16/actions/mail_send.png")))*/;
02579       mailtoMsg += i18n("Email to: ") + KURL::decode_string(u.path());
02580       QStringList queries = QStringList::split('&', u.query().mid(1));
02581       for (QStringList::Iterator it = queries.begin(); it != queries.end(); ++it)
02582         if ((*it).startsWith(QString::fromLatin1("subject=")))
02583           mailtoMsg += i18n(" - Subject: ") + KURL::decode_string((*it).mid(8));
02584         else if ((*it).startsWith(QString::fromLatin1("cc=")))
02585           mailtoMsg += i18n(" - CC: ") + KURL::decode_string((*it).mid(3));
02586         else if ((*it).startsWith(QString::fromLatin1("bcc=")))
02587           mailtoMsg += i18n(" - BCC: ") + KURL::decode_string((*it).mid(4));
02588       mailtoMsg.replace(QRegExp("&"), QString("&amp;"));
02589       mailtoMsg.replace(QRegExp("<"), QString("&lt;"));
02590       mailtoMsg.replace(QRegExp(">"), QString("&gt;"));
02591       mailtoMsg.replace(QRegExp("([\n\r\t]|[ ]{10})"), "");
02592       setStatusBarText("<qt>"+mailtoMsg, BarHoverText);
02593       return;
02594     }
02595    // Is this check neccessary at all? (Frerich)
02596 #if 0
02597     else if (u.protocol() == QString::fromLatin1("http")) {
02598         DOM::Node hrefNode = nodeUnderMouse().parentNode();
02599         while (hrefNode.nodeName().string() != QString::fromLatin1("A") && !hrefNode.isNull())
02600           hrefNode = hrefNode.parentNode();
02601 
02602         if (!hrefNode.isNull()) {
02603           DOM::Node hreflangNode = hrefNode.attributes().getNamedItem("HREFLANG");
02604           if (!hreflangNode.isNull()) {
02605             QString countryCode = hreflangNode.nodeValue().string().lower();
02606             // Map the language code to an appropriate country code.
02607             if (countryCode == QString::fromLatin1("en"))
02608               countryCode = QString::fromLatin1("gb");
02609             QString flagImg = QString::fromLatin1("<img src=%1>").arg(
02610                 locate("locale", QString::fromLatin1("l10n/")
02611                 + countryCode
02612                 + QString::fromLatin1("/flag.png")));
02613             emit setStatusBarText(flagImg + u.prettyURL() + extra);
02614           }
02615         }
02616       }
02617 #endif
02618     setStatusBarText(u.htmlURL() + extra, BarHoverText);
02619   }
02620 }
02621 
02622 void KHTMLPart::urlSelected( const QString &url, int button, int state, const QString &_target,
02623                              KParts::URLArgs args )
02624 {
02625   bool hasTarget = false;
02626 
02627   QString target = _target;
02628   if ( target.isEmpty() && d->m_doc )
02629     target = d->m_doc->baseTarget();
02630   if ( !target.isEmpty() )
02631       hasTarget = true;
02632 
02633   if ( url.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 )
02634   {
02635     executeScript( KURL::decode_string( url.right( url.length() - 11 ) ) );
02636     return;
02637   }
02638 
02639   KURL cURL = completeURL(url);
02640   // special case for <a href="">  (IE removes filename, mozilla doesn't)
02641   if ( url.isEmpty() )
02642     cURL.setFileName( url ); // removes filename
02643 
02644   if ( !cURL.isValid() )
02645     // ### ERROR HANDLING
02646     return;
02647 
02648   //kdDebug( 6000 ) << "urlSelected: complete URL:" << cURL.url() << " target = " << target << endl;
02649 
02650   if ( button == LeftButton && ( state & ShiftButton ) )
02651   {
02652     KIO::MetaData metaData;
02653     metaData["referrer"] = d->m_referrer;
02654     KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As..." ), cURL, metaData );
02655     return;
02656   }
02657 
02658   if (!checkLinkSecurity(cURL,
02659              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?" ),
02660              i18n( "Follow" )))
02661     return;
02662 
02663   args.frameName = target;
02664 
02665   if ( d->m_bHTTPRefresh )
02666   {
02667     d->m_bHTTPRefresh = false;
02668     args.metaData()["cache"] = "refresh";
02669   }
02670 
02671   args.metaData().insert("main_frame_request",
02672                          parentPart() == 0 ? "TRUE":"FALSE");
02673   args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
02674   args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
02675   args.metaData().insert("PropagateHttpHeader", "true");
02676   args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE");
02677   args.metaData().insert("ssl_activate_warnings", "TRUE");
02678 
02679   if ( hasTarget )
02680   {
02681     // unknown frame names should open in a new window.
02682     khtml::ChildFrame *frame = recursiveFrameRequest( this, cURL, args, false );
02683     if ( frame )
02684     {
02685       args.metaData()["referrer"] = d->m_referrer;
02686       requestObject( frame, cURL, args );
02687       return;
02688     }
02689   }
02690 
02691   if ( !d->m_bComplete && !hasTarget )
02692     closeURL();
02693 
02694   if (!d->m_referrer.isEmpty())
02695     args.metaData()["referrer"] = d->m_referrer;
02696 
02697   if ( button == MidButton && (state & ShiftButton) )
02698   {
02699     KParts::WindowArgs winArgs;
02700     winArgs.lowerWindow = true;
02701     KParts::ReadOnlyPart *newPart = 0;
02702     emit d->m_extension->createNewWindow( cURL, args, winArgs, newPart );
02703     return;
02704   }
02705 
02706   if ( button == LeftButton && (state & ControlButton) )
02707   {
02708     args.setNewTab(true);
02709     emit d->m_extension->createNewWindow( cURL, args );
02710     return;
02711   }
02712 
02713   view()->viewport()->unsetCursor();
02714   emit d->m_extension->openURLRequest( cURL, args );
02715 }
02716 
02717 void KHTMLPart::slotViewDocumentSource()
02718 {
02719   KURL url(m_url);
02720   if (!(url.isLocalFile()) && KHTMLPageCache::self()->isValid(d->m_cacheId))
02721   {
02722      KTempFile sourceFile(QString::null, QString::fromLatin1(".html"));
02723      if (sourceFile.status() == 0)
02724      {
02725         KHTMLPageCache::self()->saveData(d->m_cacheId, sourceFile.dataStream());
02726         url = KURL();
02727         url.setPath(sourceFile.name());
02728      }
02729   }
02730 
02731   //  emit d->m_extension->openURLRequest( m_url, KParts::URLArgs( false, 0, 0, QString::fromLatin1( "text/plain" ) ) );
02732   (void) KRun::runURL( url, QString::fromLatin1("text/plain") );
02733 }
02734 
02735 void KHTMLPart::slotViewPageInfo()
02736 {
02737   KHTMLInfoDlg *dlg = new KHTMLInfoDlg(NULL, "KHTML Page Info Dialog", false, WDestructiveClose);
02738 
02739   if (d->m_doc)
02740      dlg->_title->setText(d->m_doc->title().string());
02741 
02742   // If it's a frame, set the caption to "Frame Information"
02743   if ( parentPart() && d->m_doc && d->m_doc->isHTMLDocument() ) {
02744      dlg->setCaption(i18n("Frame Information"));
02745   }
02746 
02747   QString editStr = QString::null;
02748 
02749   if (!d->m_pageServices.isEmpty())
02750     editStr = i18n("   <a href=\"%1\">[Properties]</a>").arg(d->m_pageServices);
02751 
02752   dlg->_url->setText(QString("<a href=\"%1\">%2</a>%3").arg(url().url()).arg(url().prettyURL()).arg(editStr));
02753   dlg->_lastModified->setText(lastModified());
02754 
02755   /* populate the list view now */
02756   QStringList headers = QStringList::split("\n", d->m_httpHeaders);
02757 
02758   for (QStringList::Iterator it = headers.begin(); it != headers.end(); ++it) {
02759     QStringList header = QStringList::split(QRegExp(":[ ]+"), *it);
02760     if (header.count() != 2)
02761        continue;
02762     new QListViewItem(dlg->_headers, header[0], header[1]);
02763   }
02764 
02765   dlg->show();
02766   /* put no code here */
02767 }
02768 
02769 
02770 void KHTMLPart::slotViewFrameSource()
02771 {
02772   KParts::ReadOnlyPart *frame = currentFrame();
02773   if ( !frame )
02774     return;
02775 
02776   KURL url = frame->url();
02777   if (!(url.isLocalFile()) && frame->inherits("KHTMLPart"))
02778   {
02779        long cacheId = static_cast<KHTMLPart *>(frame)->d->m_cacheId;
02780 
02781        if (KHTMLPageCache::self()->isValid(cacheId))
02782        {
02783            KTempFile sourceFile(QString::null, QString::fromLatin1(".html"));
02784            if (sourceFile.status() == 0)
02785            {
02786                KHTMLPageCache::self()->saveData(cacheId, sourceFile.dataStream());
02787                url = KURL();
02788                url.setPath(sourceFile.name());
02789            }
02790      }
02791   }
02792 
02793   (void) KRun::runURL( url, QString::fromLatin1("text/plain") );
02794 }
02795 
02796 KURL KHTMLPart::backgroundURL() const
02797 {
02798   // ### what about XML documents? get from CSS?
02799   if (!d->m_doc || !d->m_doc->isHTMLDocument())
02800     return KURL();
02801 
02802   QString relURL = static_cast<HTMLDocumentImpl*>(d->m_doc)->body()->getAttribute( ATTR_BACKGROUND ).string();
02803 
02804   return KURL( m_url, relURL );
02805 }
02806 
02807 void KHTMLPart::slotSaveBackground()
02808 {
02809   KIO::MetaData metaData;
02810   metaData["referrer"] = d->m_referrer;
02811   KHTMLPopupGUIClient::saveURL( d->m_view, i18n("Save background image as"), backgroundURL(), metaData );
02812 }
02813 
02814 void KHTMLPart::slotSaveDocument()
02815 {
02816   KURL srcURL( m_url );
02817 
02818   if ( srcURL.fileName(false).isEmpty() )
02819     srcURL.setFileName( "index.html" );
02820 
02821   KIO::MetaData metaData;
02822   // Referre unknown?
02823   KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), srcURL, metaData, i18n("*.html *.htm|HTML files"), d->m_cacheId );
02824 }
02825 
02826 void KHTMLPart::slotSecurity()
02827 {
02828 //   kdDebug( 6050 ) << "Meta Data:" << endl
02829 //                   << d->m_ssl_peer_cert_subject
02830 //                   << endl
02831 //                   << d->m_ssl_peer_cert_issuer
02832 //                   << endl
02833 //                   << d->m_ssl_cipher
02834 //                   << endl
02835 //                   << d->m_ssl_cipher_desc
02836 //                   << endl
02837 //                   << d->m_ssl_cipher_version
02838 //                   << endl
02839 //                   << d->m_ssl_good_from
02840 //                   << endl
02841 //                   << d->m_ssl_good_until
02842 //                   << endl
02843 //                   << d->m_ssl_cert_state
02844 //                   << endl;
02845 
02846   KSSLInfoDlg *kid = new KSSLInfoDlg(d->m_ssl_in_use, widget(), "kssl_info_dlg", true );
02847 
02848   if (d->m_bSecurityInQuestion)
02849       kid->setSecurityInQuestion(true);
02850 
02851   if (d->m_ssl_in_use) {
02852     KSSLCertificate *x = KSSLCertificate::fromString(d->m_ssl_peer_certificate.local8Bit());
02853     if (x) {
02854        // Set the chain back onto the certificate
02855        QStringList cl = QStringList::split(QString("\n"), d->m_ssl_peer_chain);
02856        QPtrList<KSSLCertificate> ncl;
02857 
02858        ncl.setAutoDelete(true);
02859        for (QStringList::Iterator it = cl.begin(); it != cl.end(); ++it) {
02860           KSSLCertificate *y = KSSLCertificate::fromString((*it).local8Bit());
02861           if (y) ncl.append(y);
02862        }
02863 
02864        if (ncl.count() > 0)
02865           x->chain().setChain(ncl);
02866 
02867        kid->setup(x,
02868                   d->m_ssl_peer_ip,
02869                   m_url.url(),
02870                   d->m_ssl_cipher,
02871                   d->m_ssl_cipher_desc,
02872                   d->m_ssl_cipher_version,
02873                   d->m_ssl_cipher_used_bits.toInt(),
02874                   d->m_ssl_cipher_bits.toInt(),
02875                   (KSSLCertificate::KSSLValidation) d->m_ssl_cert_state.toInt()
02876                   );
02877         kid->exec();
02878         delete x;
02879      } else kid->exec();
02880   } else kid->exec();
02881 }
02882 
02883 void KHTMLPart::slotSaveFrame()
02884 {
02885     if ( !d->m_activeFrame )
02886         return; // should never be the case, but one never knows :-)
02887 
02888     KURL srcURL( static_cast<KParts::ReadOnlyPart *>( d->m_activeFrame )->url() );
02889 
02890     if ( srcURL.fileName(false).isEmpty() )
02891         srcURL.setFileName( "index.html" );
02892 
02893     KIO::MetaData metaData;
02894     // Referrer unknown?
02895     KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), srcURL, metaData, i18n("*.html *.htm|HTML files") );
02896 }
02897 
02898 void KHTMLPart::slotSetEncoding()
02899 {
02900     // first Item is always auto
02901     if(d->m_paSetEncoding->currentItem() == 0)
02902         setEncoding(QString::null, false);
02903     else {
02904         // strip of the language to get the raw encoding again.
02905         QString enc = KGlobal::charsets()->encodingForName(d->m_paSetEncoding->currentText());
02906         setEncoding(enc, true);
02907     }
02908 }
02909 
02910 void KHTMLPart::slotUseStylesheet()
02911 {
02912   if (d->m_doc && d->m_paUseStylesheet->currentText() != d->m_sheetUsed) {
02913     d->m_sheetUsed = d->m_paUseStylesheet->currentText();
02914     d->m_doc->updateStyleSelector();
02915   }
02916 }
02917 
02918 void KHTMLPart::updateActions()
02919 {
02920   bool frames = false;
02921 
02922   QValueList<khtml::ChildFrame>::ConstIterator it = d->m_frames.begin();
02923   QValueList<khtml::ChildFrame>::ConstIterator end = d->m_frames.end();
02924   for (; it != end; ++it )
02925       if ( (*it).m_type == khtml::ChildFrame::Frame )
02926       {
02927           frames = true;
02928           break;
02929       }
02930 
02931   d->m_paViewFrame->setEnabled( frames );
02932   d->m_paSaveFrame->setEnabled( frames );
02933 
02934   if ( frames )
02935     d->m_paFind->setText( i18n( "&Find in Frame..." ) );
02936   else
02937     d->m_paFind->setText( i18n( "&Find..." ) );
02938 
02939   KParts::Part *frame = 0;
02940 
02941   if ( frames )
02942     frame = currentFrame();
02943 
02944   bool enableFindAndSelectAll = true;
02945 
02946   if ( frame )
02947     enableFindAndSelectAll = frame->inherits( "KHTMLPart" );
02948 
02949   d->m_paFind->setEnabled( enableFindAndSelectAll );
02950   d->m_paFindNext->setEnabled( false ); // needs a 'find' first
02951   d->m_paSelectAll->setEnabled( enableFindAndSelectAll );
02952 
02953   bool enablePrintFrame = false;
02954 
02955   if ( frame )
02956   {
02957     QObject *ext = KParts::BrowserExtension::childObject( frame );
02958     if ( ext )
02959       enablePrintFrame = ext->metaObject()->slotNames().contains( "print()" );
02960   }
02961 
02962   d->m_paPrintFrame->setEnabled( enablePrintFrame );
02963 
02964   QString bgURL;
02965 
02966   // ### frames
02967   if ( d->m_doc && d->m_doc->isHTMLDocument() && static_cast<HTMLDocumentImpl*>(d->m_doc)->body() && !d->m_bClearing )
02968     bgURL = static_cast<HTMLDocumentImpl*>(d->m_doc)->body()->getAttribute( ATTR_BACKGROUND ).string();
02969 
02970   d->m_paSaveBackground->setEnabled( !bgURL.isEmpty() );
02971 }
02972 
02973 KParts::LiveConnectExtension *KHTMLPart::liveConnectExtension( const khtml::RenderPart *frame) const {
02974     QValueList<khtml::ChildFrame>::ConstIterator it = d->m_objects.begin();
02975     QValueList<khtml::ChildFrame>::ConstIterator end = d->m_objects.end();
02976     for(; it != end; ++it )
02977         if ((*it).m_frame == frame)
02978             return (*it).m_liveconnect;
02979     return 0L;
02980 }
02981 
02982 bool KHTMLPart::requestFrame( khtml::RenderPart *frame, const QString &url, const QString &frameName,
02983                               const QStringList &params, bool isIFrame )
02984 {
02985 //  kdDebug( 6050 ) << "childRequest( ..., " << url << ", " << frameName << " )" << endl;
02986   FrameIt it = d->m_frames.find( frameName );
02987   if ( it == d->m_frames.end() )
02988   {
02989     khtml::ChildFrame child;
02990 //    kdDebug( 6050 ) << "inserting new frame into frame map " << frameName << endl;
02991     child.m_name = frameName;
02992     it = d->m_frames.append( child );
02993   }
02994 
02995   (*it).m_type = isIFrame ? khtml::ChildFrame::IFrame : khtml::ChildFrame::Frame;
02996   (*it).m_frame = frame;
02997   (*it).m_params = params;
02998 
02999   // Support for <frame src="javascript:string">
03000   if ( url.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 )
03001   {
03002       QVariant res = executeScript( DOM::Node(frame->element()), KURL::decode_string( url.right( url.length() - 11) ) );
03003       KURL myurl;
03004       myurl.setProtocol("javascript");
03005       if ( res.type() == QVariant::String )
03006     myurl.setPath(res.asString());
03007       return processObjectRequest(&(*it), myurl, QString("text/html") );
03008   }
03009   KURL u = url.isEmpty() ? KURL() : completeURL( url );
03010   return requestObject( &(*it), u );
03011 }
03012 
03013 QString KHTMLPart::requestFrameName()
03014 {
03015    return QString::fromLatin1("<!--frame %1-->").arg(d->m_frameNameId++);
03016 }
03017 
03018 bool KHTMLPart::requestObject( khtml::RenderPart *frame, const QString &url, const QString &serviceType,
03019                                const QStringList &params )
03020 {
03021   khtml::ChildFrame child;
03022   QValueList<khtml::ChildFrame>::Iterator it = d->m_objects.append( child );
03023   (*it).m_frame = frame;
03024   (*it).m_type = khtml::ChildFrame::Object;
03025   (*it).m_params = params;
03026 
03027   KParts::URLArgs args;
03028   args.serviceType = serviceType;
03029   return requestObject( &(*it), completeURL( url ), args );
03030 }
03031 
03032 bool KHTMLPart::requestObject( khtml::ChildFrame *child, const KURL &url, const KParts::URLArgs &_args )
03033 {
03034   if (!checkLinkSecurity(url))
03035     return false;
03036   if ( child->m_bPreloaded )
03037   {
03038     // kdDebug(6005) << "KHTMLPart::requestObject preload" << endl;
03039     if ( child->m_frame && child->m_part )
03040       child->m_frame->setWidget( child->m_part->widget() );
03041 
03042     child->m_bPreloaded = false;
03043     return true;
03044   }
03045 
03046   KParts::URLArgs args( _args );
03047 
03048   if ( child->m_run )
03049     child->m_run->abort();
03050 
03051   if ( child->m_part && !args.reload && urlcmp( child->m_part->url().url(), url.url(), true, true ) )
03052     args.serviceType = child->m_serviceType;
03053 
03054   child->m_args = args;
03055   child->m_args.reload = (d->m_cachePolicy == KIO::CC_Reload) || (d->m_cachePolicy == KIO::CC_Refresh);
03056   child->m_serviceName = QString::null;
03057   if (!d->m_referrer.isEmpty() && !child->m_args.metaData().contains( "referrer" ))
03058     child->m_args.metaData()["referrer"] = d->m_referrer;
03059 
03060   child->m_args.metaData().insert("PropagateHttpHeader", "true");
03061   child->m_args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
03062   child->m_args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
03063   child->m_args.metaData().insert("main_frame_request",
03064                                   parentPart() == 0 ? "TRUE":"FALSE");
03065   child->m_args.metaData().insert("ssl_was_in_use",
03066                                   d->m_ssl_in_use ? "TRUE":"FALSE");
03067   child->m_args.metaData().insert("ssl_activate_warnings", "TRUE");
03068 
03069   // We want a KHTMLPart if the HTML says <frame src=""> or <frame src="about:blank">
03070   if ((url.isEmpty() || url.url() == "about:blank") && args.serviceType.isEmpty())
03071     args.serviceType = QString::fromLatin1( "text/html" );
03072 
03073   if ( args.serviceType.isEmpty() ) {
03074     child->m_run = new KHTMLRun( this, child, url, child->m_args,
03075                                  child->m_type != khtml::ChildFrame::Frame );
03076     return false;
03077   } else {
03078     return processObjectRequest( child, url, args.serviceType );
03079   }
03080 }
03081 
03082 bool KHTMLPart::processObjectRequest( khtml::ChildFrame *child, const KURL &_url, const QString &mimetype )
03083 {
03084   //kdDebug( 6050 ) << "KHTMLPart::processObjectRequest trying to create part for " << mimetype << endl;
03085 
03086   // IMPORTANT: create a copy of the url here, because it is just a reference, which was likely to be given
03087   // by an emitting frame part (emit openURLRequest( blahurl, ... ) . A few lines below we delete the part
03088   // though -> the reference becomes invalid -> crash is likely
03089   KURL url( _url );
03090 
03091   // khtmlrun called us this way to indicate a loading error
03092   if ( d->m_onlyLocalReferences || ( url.isEmpty() && mimetype.isEmpty() ) )
03093   {
03094       checkEmitLoadEvent();
03095       child->m_bCompleted = true;
03096       return true;
03097   }
03098 
03099   if (child->m_bNotify)
03100   {
03101       child->m_bNotify = false;
03102       if ( !child->m_args.lockHistory() )
03103           emit d->m_extension->openURLNotify();
03104   }
03105 
03106   if ( child->m_serviceType != mimetype )
03107   {
03108     QStringList dummy; // the list of servicetypes handled by the part is now unused.
03109     KParts::ReadOnlyPart *part = createPart( d->m_view->viewport(), child->m_name.ascii(), this, child->m_name.ascii(), mimetype, child->m_serviceName, dummy, child->m_params );
03110 
03111     if ( !part )
03112     {
03113         if ( child->m_frame )
03114           if (child->m_frame->partLoadingErrorNotify( child, url, mimetype ))
03115             return true; // we succeeded after all (a fallback was used)
03116 
03117         checkEmitLoadEvent();
03118         return false;
03119     }
03120 
03121     //CRITICAL STUFF
03122     if ( child->m_part )
03123     {
03124       partManager()->removePart( (KParts::ReadOnlyPart *)child->m_part );
03125       delete (KParts::ReadOnlyPart *)child->m_part;
03126     }
03127 
03128     child->m_serviceType = mimetype;
03129     if ( child->m_frame )
03130       child->m_frame->setWidget( part->widget() );
03131 
03132     if ( child->m_type != khtml::ChildFrame::Object )
03133       partManager()->addPart( part, false );
03134 //  else
03135 //      kdDebug(6005) << "AH! NO FRAME!!!!!" << endl;
03136 
03137     child->m_part = part;
03138     assert( ((void*) child->m_part) != 0);
03139 
03140     if ( child->m_type != khtml::ChildFrame::Object )
03141     {
03142       connect( part, SIGNAL( started( KIO::Job *) ),
03143                this, SLOT( slotChildStarted( KIO::Job *) ) );
03144       connect( part, SIGNAL( completed() ),
03145                this, SLOT( slotChildCompleted() ) );
03146       connect( part, SIGNAL( completed(bool) ),
03147                this, SLOT( slotChildCompleted(bool) ) );
03148       connect( part, SIGNAL( setStatusBarText( const QString & ) ),
03149                this, SIGNAL( setStatusBarText( const QString & ) ) );
03150       if ( part->inherits( "KHTMLPart" ) )
03151       {
03152           connect( this, SIGNAL( completed() ),
03153                    part, SLOT( slotParentCompleted() ) );
03154           connect( this, SIGNAL( completed(bool) ),
03155                    part, SLOT( slotParentCompleted() ) );
03156           // As soon as the child's document is created, we need to set its domain
03157           // (but we do so only once, so it can't be simply done in the child)
03158           connect( part, SIGNAL( docCreated() ),
03159                    this, SLOT( slotChildDocCreated() ) );
03160       }
03161     }
03162 
03163     child->m_extension = KParts::BrowserExtension::childObject( part );
03164 
03165     if ( child->m_extension )
03166     {
03167       connect( child->m_extension, SIGNAL( openURLNotify() ),
03168                d->m_extension, SIGNAL( openURLNotify() ) );
03169 
03170       connect( child->m_extension, SIGNAL( openURLRequestDelayed( const KURL &, const KParts::URLArgs & ) ),
03171                this, SLOT( slotChildURLRequest( const KURL &, const KParts::URLArgs & ) ) );
03172 
03173       connect( child->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ),
03174                d->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ) );
03175       connect( child->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs &, const KParts::WindowArgs &, KParts::ReadOnlyPart *& ) ),
03176                d->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & , const KParts::WindowArgs &, KParts::ReadOnlyPart *&) ) );
03177 
03178       connect( child->m_extension, SIGNAL( popupMenu( const QPoint &, const KFileItemList & ) ),
03179                d->m_extension, SIGNAL( popupMenu( const QPoint &, const KFileItemList & ) ) );
03180       connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList & ) ),
03181                d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList & ) ) );
03182       connect( child->m_extension, SIGNAL( popupMenu( const QPoint &, const KURL &, const QString &, mode_t ) ),
03183                d->m_extension, SIGNAL( popupMenu( const QPoint &, const KURL &, const QString &, mode_t ) ) );
03184       connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const QString &, mode_t ) ),
03185                d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const QString &, mode_t ) ) );
03186 
03187       connect( child->m_extension, SIGNAL( infoMessage( const QString & ) ),
03188                d->m_extension, SIGNAL( infoMessage( const QString & ) ) );
03189 
03190       child->m_extension->setBrowserInterface( d->m_extension->browserInterface() );
03191     }
03192     child->m_liveconnect = KParts::LiveConnectExtension::childObject( part );
03193   }
03194 
03195   checkEmitLoadEvent();
03196   // Some JS code in the load event may have destroyed the part
03197   // In that case, abort
03198   if ( !child->m_part )
03199     return false;
03200 
03201   if ( child->m_bPreloaded )
03202   {
03203     if ( child->m_frame && child->m_part )
03204       child->m_frame->setWidget( child->m_part->widget() );
03205 
03206     child->m_bPreloaded = false;
03207     return true;
03208   }
03209 
03210   child->m_args.reload = (d->m_cachePolicy == KIO::CC_Reload) || (d->m_cachePolicy == KIO::CC_Refresh);
03211 
03212   // make sure the part has a way to find out about the mimetype.
03213   // we actually set it in child->m_args in requestObject already,
03214   // but it's useless if we had to use a KHTMLRun instance, as the
03215   // point the run object is to find out exactly the mimetype.
03216   child->m_args.serviceType = mimetype;
03217 
03218   child->m_bCompleted = false;
03219   if ( child->m_extension )
03220     child->m_extension->setURLArgs( child->m_args );
03221 
03222   if(url.protocol() == "javascript" || url.url() == "about:blank") {
03223       if (!child->m_part->inherits("KHTMLPart"))
03224           return false;
03225 
03226       KHTMLPart* p = static_cast<KHTMLPart*>(static_cast<KParts::ReadOnlyPart *>(child->m_part));
03227 
03228       p->begin();
03229       if (d->m_doc && p->d->m_doc)
03230         p->d->m_doc->setBaseURL(d->m_doc->baseURL());
03231       if (!url.url().startsWith("about:")) {
03232         p->write(url.path());
03233       } else {
03234     p->m_url = url;
03235         // we need a body element. testcase: <iframe id="a"></iframe><script>alert(a.document.body);</script>
03236         p->write("<HTML><BODY></BODY></HTML>");
03237       }
03238       p->end();
03239       return true;
03240   }
03241   else if ( !url.isEmpty() )
03242   {
03243       //kdDebug( 6050 ) << "opening " << url.url() << " in frame " << child->m_part << endl;
03244       return child->m_part->openURL( url );
03245   }
03246   else
03247       return true;
03248 }
03249 
03250 KParts::ReadOnlyPart *KHTMLPart::createPart( QWidget *parentWidget, const char *widgetName,
03251                                              QObject *parent, const char *name, const QString &mimetype,
03252                                              QString &serviceName, QStringList &serviceTypes,
03253                                              const QStringList &params )
03254 {
03255   QString constr;
03256   if ( !serviceName.isEmpty() )
03257     constr.append( QString::fromLatin1( "Name == '%1'" ).arg( serviceName ) );
03258 
03259   KTrader::OfferList offers = KTrader::self()->query( mimetype, "KParts/ReadOnlyPart", constr, QString::null );
03260 
03261   if ( offers.isEmpty() )
03262     return 0L;
03263 
03264   KService::Ptr service = *offers.begin();
03265 
03266   KLibFactory *factory = KLibLoader::self()->factory( QFile::encodeName(service->library()) );
03267 
03268   if ( !factory )
03269     return 0L;
03270 
03271   KParts::ReadOnlyPart *res = 0L;
03272 
03273   const char *className = "KParts::ReadOnlyPart";
03274   if ( service->serviceTypes().contains( "Browser/View" ) )
03275     className = "Browser/View";
03276 
03277   if ( factory->inherits( "KParts::Factory" ) )
03278     res = static_cast<KParts::ReadOnlyPart *>(static_cast<KParts::Factory *>( factory )->createPart( parentWidget, widgetName, parent, name, className, params ));
03279   else
03280   res = static_cast<KParts::ReadOnlyPart *>(factory->create( parentWidget, widgetName, className ));
03281 
03282   if ( !res )
03283     return res;
03284 
03285   serviceTypes = service->serviceTypes();
03286   serviceName = service->name();
03287 
03288   return res;
03289 }
03290 
03291 KParts::PartManager *KHTMLPart::partManager()
03292 {
03293   if ( !d->m_manager )
03294   {
03295     d->m_manager = new KParts::PartManager( d->m_view->topLevelWidget(), this, "khtml part manager" );
03296     d->m_manager->setAllowNestedParts( true );
03297     connect( d->m_manager, SIGNAL( activePartChanged( KParts::Part * ) ),
03298              this, SLOT( slotActiveFrameChanged( KParts::Part * ) ) );
03299     connect( d->m_manager, SIGNAL( partRemoved( KParts::Part * ) ),
03300              this, SLOT( slotPartRemoved( KParts::Part * ) ) );
03301   }
03302 
03303   return d->m_manager;
03304 }
03305 
03306 void KHTMLPart::submitFormAgain()
03307 {
03308   if( d->m_doc && !d->m_doc->parsing() && d->m_submitForm)
03309     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 );
03310 
03311   delete d->m_submitForm;
03312   d->m_submitForm = 0;
03313   disconnect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
03314 }
03315 
03316 void KHTMLPart::submitForm( const char *action, const QString &url, const QByteArray &formData, const QString &_target, const QString& contentType, const QString& boundary )
03317 {
03318   kdDebug(6000) << this << ": KHTMLPart::submitForm target=" << _target << " url=" << url << endl;
03319   KURL u = completeURL( url );
03320 
03321   if ( !u.isValid() )
03322   {
03323     // ### ERROR HANDLING!
03324     return;
03325   }
03326 
03327   // Form security checks
03328   //
03329   /*
03330    * If these form security checks are still in this place in a month or two
03331    * I'm going to simply delete them.
03332    */
03333 
03334   /* This is separate for a reason.  It has to be _before_ all script, etc,
03335    * AND I don't want to break anything that uses checkLinkSecurity() in
03336    * other places.
03337    */
03338 
03339   if (!d->m_submitForm) {
03340     if (u.protocol() != "https" && u.protocol() != "mailto") {
03341       if (d->m_ssl_in_use) {    // Going from SSL -> nonSSL
03342         int rc = KMessageBox::warningContinueCancel(NULL, i18n("Warning:  This is a secure form but it is attempting to send your data back unencrypted."
03343                                                                "\nA third party may be able to intercept and view this information."
03344                                                                "\nAre you sure you wish to continue?"),
03345                                                     i18n("SSL"));
03346         if (rc == KMessageBox::Cancel)
03347           return;
03348       } else {                  // Going from nonSSL -> nonSSL
03349         KSSLSettings kss(true);
03350         if (kss.warnOnUnencrypted()) {
03351           int rc = KMessageBox::warningContinueCancel(NULL,
03352                                                       i18n("Warning: Your data is about to be transmitted across the network unencrypted."
03353                                                            "\nAre you sure you wish to continue?"),
03354                                                       i18n("KDE"),
03355                                                       QString::null,
03356                                                       "WarnOnUnencryptedForm");
03357           // Move this setting into KSSL instead
03358           KConfig *config = kapp->config();
03359           QString grpNotifMsgs = QString::fromLatin1("Notification Messages");
03360           KConfigGroupSaver saver( config, grpNotifMsgs );
03361 
03362           if (!config->readBoolEntry("WarnOnUnencryptedForm", true)) {
03363             config->deleteEntry("WarnOnUnencryptedForm");
03364             config->sync();
03365             kss.setWarnOnUnencrypted(false);
03366             kss.save();
03367           }
03368           if (rc == KMessageBox::Cancel)
03369             return;
03370         }
03371       }
03372     }
03373 
03374     if (u.protocol() == "mailto") {
03375       int rc = KMessageBox::warningContinueCancel(NULL,
03376                                                   i18n("This site is attempting to submit form data via email.\n"
03377                                                        "Do you want to continue?"),
03378                                                   i18n("KDE"),
03379                                                   QString::null,
03380                                                   "WarnTriedEmailSubmit");
03381 
03382       if (rc == KMessageBox::Cancel) {
03383         return;
03384       }
03385     }
03386   }
03387 
03388   // End form security checks
03389   //
03390 
03391   QString urlstring = u.url();
03392 
03393   if ( urlstring.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
03394     urlstring = KURL::decode_string(urlstring);
03395     executeScript( urlstring.right( urlstring.length() - 11) );
03396     return;
03397   }
03398 
03399   if (!checkLinkSecurity(u,
03400              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?" ),
03401              i18n( "Submit" )))
03402     return;
03403 
03404   KParts::URLArgs args;
03405 
03406   if (!d->m_referrer.isEmpty())
03407      args.metaData()["referrer"] = d->m_referrer;
03408 
03409   args.metaData().insert("PropagateHttpHeader", "true");
03410   args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
03411   args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
03412   args.metaData().insert("main_frame_request",
03413                          parentPart() == 0 ? "TRUE":"FALSE");
03414   args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE");
03415   args.metaData().insert("ssl_activate_warnings", "TRUE");
03416   args.frameName = _target.isEmpty() ? d->m_doc->baseTarget() : _target ;
03417 
03418   // Handle mailto: forms
03419   if (u.protocol() == "mailto") {
03420       // 1)  Check for attach= and strip it
03421       QString q = u.query().mid(1);
03422       QStringList nvps = QStringList::split("&", q);
03423       bool triedToAttach = false;
03424 
03425       for (QStringList::Iterator nvp = nvps.begin(); nvp != nvps.end(); ++nvp) {
03426          QStringList pair = QStringList::split("=", *nvp);
03427          if (pair.count() >= 2) {
03428             if (pair.first().lower() == "attach") {
03429                nvp = nvps.remove(nvp);
03430                triedToAttach = true;
03431             }
03432          }
03433       }
03434 
03435       if (triedToAttach)
03436          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");
03437 
03438       // 2)  Append body=
03439       QString bodyEnc;
03440       if (contentType.lower() == "multipart/form-data") {
03441          // FIXME: is this correct?  I suspect not
03442          bodyEnc = KURL::encode_string(QString::fromLatin1(formData.data(),
03443                                                            formData.size()));
03444       } else if (contentType.lower() == "text/plain") {
03445          // Convention seems to be to decode, and s/&/\n/
03446          QString tmpbody = QString::fromLatin1(formData.data(),
03447                                                formData.size());
03448          tmpbody.replace(QRegExp("[&]"), "\n");
03449          tmpbody.replace(QRegExp("[+]"), " ");
03450          tmpbody = KURL::decode_string(tmpbody);  // Decode the rest of it
03451          bodyEnc = KURL::encode_string(tmpbody);  // Recode for the URL
03452       } else {
03453          bodyEnc = KURL::encode_string(QString::fromLatin1(formData.data(),
03454                                                            formData.size()));
03455       }
03456 
03457       nvps.append(QString("body=%1").arg(bodyEnc));
03458       q = nvps.join("&");
03459       u.setQuery(q);
03460   }
03461 
03462   if ( strcmp( action, "get" ) == 0 ) {
03463     if (u.protocol() != "mailto")
03464        u.setQuery( QString::fromLatin1( formData.data(), formData.size() ) );
03465     args.setDoPost( false );
03466   }
03467   else {
03468     args.postData = formData;
03469     args.setDoPost( true );
03470 
03471     // construct some user headers if necessary
03472     if (contentType.isNull() || contentType == "application/x-www-form-urlencoded")
03473       args.setContentType( "Content-Type: application/x-www-form-urlencoded" );
03474     else // contentType must be "multipart/form-data"
03475       args.setContentType( "Content-Type: " + contentType + "; boundary=" + boundary );
03476   }
03477 
03478   if ( d->m_doc->parsing() || d->m_runningScripts > 0 ) {
03479     if( d->m_submitForm ) {
03480       kdDebug(6000) << "KHTMLPart::submitForm ABORTING!" << endl;
03481       return;
03482     }
03483     d->m_submitForm = new KHTMLPartPrivate::SubmitForm;
03484     d->m_submitForm->submitAction = action;
03485     d->m_submitForm->submitUrl = url;
03486     d->m_submitForm->submitFormData = formData;
03487     d->m_submitForm->target = _target;
03488     d->m_submitForm->submitContentType = contentType;
03489     d->m_submitForm->submitBoundary = boundary;
03490     connect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
03491   }
03492   else
03493   {
03494     emit d->m_extension->openURLRequest( u, args );
03495   }
03496 }
03497 
03498 void KHTMLPart::popupMenu( const QString &linkUrl )
03499 {
03500   KURL popupURL;
03501   KURL linkKURL;
03502   if ( linkUrl.isEmpty() ) // click on background
03503     popupURL = this->url();
03504   else {               // click on link
03505     popupURL = completeURL( linkUrl );
03506     linkKURL = popupURL;
03507   }
03508 
03509   KXMLGUIClient *client = new KHTMLPopupGUIClient( this, d->m_popupMenuXML, linkKURL );
03510 
03511   emit d->m_extension->popupMenu( client, QCursor::pos(), popupURL,
03512                                   QString::fromLatin1( "text/html" ), S_IFREG /*always a file*/ );
03513 
03514   delete client;
03515 
03516   emit popupMenu(linkUrl, QCursor::pos());
03517 }
03518 
03519 void KHTMLPart::slotParentCompleted()
03520 {
03521   if ( !d->m_redirectURL.isEmpty() && !d->m_redirectionTimer.isActive() )
03522   {
03523     // kdDebug(6050) << this << ": Child redirection -> " << d->m_redirectURL << endl;
03524     d->m_redirectionTimer.start( 1000 * d->m_delayRedirect, true );
03525   }
03526 }
03527 
03528 void KHTMLPart::slotChildStarted( KIO::Job *job )
03529 {
03530   khtml::ChildFrame *child = frame( sender() );
03531 
03532   assert( child );
03533 
03534   child->m_bCompleted = false;
03535 
03536   if ( d->m_bComplete )
03537   {
03538 #if 0
03539     // WABA: Looks like this belongs somewhere else
03540     if ( !parentPart() ) // "toplevel" html document? if yes, then notify the hosting browser about the document (url) changes
03541     {
03542       emit d->m_extension->openURLNotify();
03543     }
03544 #endif
03545     d->m_bComplete = false;
03546     emit started( job );
03547   }
03548 }
03549 
03550 void KHTMLPart::slotChildCompleted()
03551 {
03552   slotChildCompleted( false );
03553 }
03554 
03555 void KHTMLPart::slotChildCompleted( bool pendingAction )
03556 {
03557   khtml::ChildFrame *child = frame( sender() );
03558 
03559   assert( child );
03560 
03561   child->m_bCompleted = true;
03562   child->m_bPendingRedirection = pendingAction;
03563   child->m_args = KParts::URLArgs();
03564 
03565   checkCompleted();
03566 }
03567 
03568 void KHTMLPart::slotChildDocCreated()
03569 {
03570   const KHTMLPart* htmlFrame = static_cast<const KHTMLPart *>(sender());
03571   // Set domain to the frameset's domain
03572   // This must only be done when loading the frameset initially (#22039),
03573   // not when following a link in a frame (#44162).
03574   if ( d->m_doc && d->m_doc->isHTMLDocument() )
03575   {
03576     if ( sender()->inherits("KHTMLPart") )
03577     {
03578       DOMString domain = static_cast<HTMLDocumentImpl*>(d->m_doc)->domain();
03579       if (htmlFrame->d->m_doc && htmlFrame->d->m_doc->isHTMLDocument() )
03580         //kdDebug(6050) << "KHTMLPart::slotChildDocCreated: url: " << htmlFrame->m_url.url() << endl;
03581         static_cast<HTMLDocumentImpl*>(htmlFrame->d->m_doc)->setDomain( domain );
03582     }
03583   }
03584   // So it only happens once
03585   disconnect( htmlFrame, SIGNAL( docCreated() ), this, SLOT( slotChildDocCreated() ) );
03586 }
03587 
03588 void KHTMLPart::slotChildURLRequest( const KURL &url, const KParts::URLArgs &args )
03589 {
03590   khtml::ChildFrame *child = frame( sender()->parent() );
03591   KHTMLPart *callingHtmlPart = const_cast<KHTMLPart *>(dynamic_cast<const KHTMLPart *>(sender()->parent()));
03592 
03593   // TODO: handle child target correctly! currently the script are always executed fur the parent
03594   QString urlStr = url.url();
03595   if ( urlStr.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
03596       QString script = KURL::decode_string( urlStr.right( urlStr.length() - 11 ) );
03597       executeScript( script );
03598       return;
03599   }
03600 
03601   QString frameName = args.frameName.lower();
03602   if ( !frameName.isEmpty() )
03603   {
03604     if ( frameName == QString::fromLatin1( "_top" ) )
03605     {
03606       emit d->m_extension->openURLRequest( url, args );
03607       return;
03608     }
03609     else if ( frameName == QString::fromLatin1( "_blank" ) )
03610     {
03611       emit d->m_extension->createNewWindow( url, args );
03612       return;
03613     }
03614     else if ( frameName == QString::fromLatin1( "_parent" ) )
03615     {
03616       KParts::URLArgs newArgs( args );
03617       newArgs.frameName = QString::null;
03618 
03619       emit d->m_extension->openURLRequest( url, newArgs );
03620       return;
03621     }
03622     else if ( frameName != QString::fromLatin1( "_self" ) )
03623     {
03624       khtml::ChildFrame *_frame = recursiveFrameRequest( callingHtmlPart, url, args );
03625 
03626       if ( !_frame )
03627       {
03628         emit d->m_extension->openURLRequest( url, args );
03629         return;
03630       }
03631 
03632       child = _frame;
03633     }
03634   }
03635 
03636   if ( child ) {
03637       // Inform someone that we are about to show something else.
03638       child->m_bNotify = true;
03639       requestObject( child, url, args );
03640   }  else if ( frameName== "_self" ) // this is for embedded objects (via <object>) which want to replace the current document
03641   {
03642       KParts::URLArgs newArgs( args );
03643       newArgs.frameName = QString::null;
03644       emit d->m_extension->openURLRequest( url, newArgs );
03645   }
03646 }
03647 
03648 khtml::ChildFrame *KHTMLPart::frame( const QObject *obj )
03649 {
03650     assert( obj->inherits( "KParts::ReadOnlyPart" ) );
03651     const KParts::ReadOnlyPart *part = static_cast<const KParts::ReadOnlyPart *>( obj );
03652 
03653     FrameIt it = d->m_frames.begin();
03654     FrameIt end = d->m_frames.end();
03655     for (; it != end; ++it )
03656       if ( (KParts::ReadOnlyPart *)(*it).m_part == part )
03657         return &(*it);
03658 
03659     return 0L;
03660 }
03661 
03662 //#define DEBUG_FINDFRAME
03663 
03664 bool KHTMLPart::checkFrameAccess(KHTMLPart *callingHtmlPart)
03665 {
03666   if (callingHtmlPart == this)
03667     return true; // trivial
03668 
03669   if (htmlDocument().isNull()) {
03670 #ifdef DEBUG_FINDFRAME
03671     kdDebug(6050) << "KHTMLPart::checkFrameAccess: Empty part " << this << " URL = " << m_url.prettyURL() << endl;
03672 #endif
03673     return false; // we are empty?
03674   }
03675 
03676   // now compare the domains
03677   if (callingHtmlPart && !callingHtmlPart->htmlDocument().isNull() &&
03678       !htmlDocument().isNull())  {
03679     DOM::DOMString actDomain = callingHtmlPart->htmlDocument().domain();
03680     DOM::DOMString destDomain = htmlDocument().domain();
03681 
03682 #ifdef DEBUG_FINDFRAME
03683     kdDebug(6050) << "KHTMLPart::checkFrameAccess: actDomain = '" << actDomain.string() << "' destDomain = '" << destDomain.string() << "'" << endl;
03684 #endif
03685 
03686     if (actDomain == destDomain)
03687       return true;
03688   }
03689 #ifdef DEBUG_FINDFRAME
03690   else
03691   {
03692     kdDebug(6050) << "KHTMLPart::checkFrameAccess: Unknown part/domain " << callingHtmlPart << " tries to access part " << this << endl;
03693   }
03694 #endif
03695   return false;
03696 }
03697 
03698 KHTMLPart *
03699 KHTMLPart::findFrameParent( KParts::ReadOnlyPart *callingPart, const QString &f, khtml::ChildFrame **childFrame )
03700 {
03701 #ifdef DEBUG_FINDFRAME
03702   kdDebug(6050) << "KHTMLPart::findFrameParent: this = " << this << " URL = " << m_url.prettyURL() << " name = " << name() << " findFrameParent( " << f << " )" << endl;
03703 #endif
03704   // Check access
03705   KHTMLPart *callingHtmlPart = dynamic_cast<KHTMLPart *>(callingPart);
03706   
03707   if (!checkFrameAccess(callingHtmlPart))
03708      return 0;
03709 
03710   if (!childFrame && !parentPart() && (name() == f))
03711      return this;
03712 
03713   FrameIt it = d->m_frames.find( f );
03714   FrameIt end = d->m_frames.end();
03715   if ( it != end )
03716   {
03717 #ifdef DEBUG_FINDFRAME
03718      kdDebug(6050) << "KHTMLPart::findFrameParent: FOUND!" << endl;
03719 #endif
03720      if (childFrame)
03721         *childFrame = &(*it);
03722      return this;
03723   }
03724      
03725   it = d->m_frames.begin();
03726   for (; it != end; ++it )
03727   {
03728     KParts::ReadOnlyPart *p = (*it).m_part;
03729     if ( p && p->inherits( "KHTMLPart" ))
03730     {
03731       KHTMLPart *frameParent = static_cast<KHTMLPart*>(p)->findFrameParent(callingPart, f, childFrame);
03732       if (frameParent)
03733          return frameParent;
03734     }
03735   }
03736   return 0;
03737 }
03738 
03739 
03740 KHTMLPart *KHTMLPart::findFrame( const QString &f )
03741 {
03742   khtml::ChildFrame *childFrame;
03743   KHTMLPart *parentFrame = findFrameParent(this, f, &childFrame);
03744   if (parentFrame)
03745   {
03746      KParts::ReadOnlyPart *p = childFrame->m_part;
03747      if ( p && p->inherits( "KHTMLPart" ))
03748         return static_cast<KHTMLPart *>(p);
03749   }
03750   return 0;
03751 }
03752 
03753 KParts::ReadOnlyPart *KHTMLPart::currentFrame() const
03754 {
03755   KParts::ReadOnlyPart* part = (KParts::ReadOnlyPart*)(this);
03756   // Find active part in our frame manager, in case we are a frameset
03757   // and keep doing that (in case of nested framesets).
03758   // Just realized we could also do this recursively, calling part->currentFrame()...
03759   while ( part && part->inherits("KHTMLPart") &&
03760           static_cast<KHTMLPart *>(part)->d->m_frames.count() > 0 ) {
03761     KHTMLPart* frameset = static_cast<KHTMLPart *>(part);
03762     part = static_cast<KParts::ReadOnlyPart *>(frameset->partManager()->activePart());
03763     if ( !part ) return frameset;
03764   }
03765   return part;
03766 }
03767 
03768 bool KHTMLPart::frameExists( const QString &frameName )
03769 {
03770   ConstFrameIt it = d->m_frames.find( frameName );
03771   if ( it == d->m_frames.end() )
03772     return false;
03773 
03774   // WABA: We only return true if the child actually has a frame
03775   // set. Otherwise we might find our preloaded-selve.
03776   // This happens when we restore the frameset.
03777   return (!(*it).m_frame.isNull());
03778 }
03779 
03780 KHTMLPart *KHTMLPart::parentPart()
03781 {
03782   if ( !parent() || !parent()->inherits( "KHTMLPart" ) )
03783     return 0L;
03784 
03785   return (KHTMLPart *)parent();
03786 }
03787 
03788 khtml::ChildFrame *KHTMLPart::recursiveFrameRequest( KHTMLPart *callingHtmlPart, const KURL &url, 
03789                                                      const KParts::URLArgs &args, bool callParent )
03790 {
03791 #ifdef DEBUG_FINDFRAME
03792   kdDebug( 6050 ) << "KHTMLPart::recursiveFrameRequest this = " << this << ", frame = " << args.frameName << ", url = " << url.prettyURL() << endl;
03793 #endif  
03794   khtml::ChildFrame *childFrame;
03795   KHTMLPart *childPart = findFrameParent(callingHtmlPart, args.frameName, &childFrame);
03796   if (childPart)
03797   {
03798      if (childPart == this)
03799         return childFrame;
03800      
03801      childPart->requestObject( childFrame, url, args );
03802      return 0;
03803   }
03804 
03805   if ( parentPart() && callParent )
03806   {
03807      khtml::ChildFrame *res = parentPart()->recursiveFrameRequest( callingHtmlPart, url, args, callParent );
03808 
03809      if ( res )
03810        parentPart()->requestObject( res, url, args );
03811   }
03812 
03813   return 0L;
03814 }
03815 
03816 void KHTMLPart::saveState( QDataStream &stream )
03817 {
03818   kdDebug( 6050 ) << "KHTMLPart::saveState this = " << this << " saving URL " << m_url.url() << endl;
03819 
03820   stream << m_url << (Q_INT32)d->m_view->contentsX() << (Q_INT32)d->m_view->contentsY()
03821          << (Q_INT32) d->m_view->contentsWidth() << (Q_INT32) d->m_view->contentsHeight() << (Q_INT32) d->m_view->marginWidth() << (Q_INT32) d->m_view->marginHeight();
03822 
03823   // save link cursor position
03824   int focusNodeNumber;
03825   if (!d->m_focusNodeRestored)
03826       focusNodeNumber = d->m_focusNodeNumber;
03827   else if (d->m_doc && d->m_doc->focusNode())
03828       focusNodeNumber = d->m_doc->nodeAbsIndex(d->m_doc->focusNode());
03829   else
03830       focusNodeNumber = -1;
03831   stream << focusNodeNumber;
03832 
03833   // Save the doc's cache id.
03834   stream << d->m_cacheId;
03835 
03836   // Save the state of the document (Most notably the state of any forms)
03837   QStringList docState;
03838   if (d->m_doc)
03839   {
03840      docState = d->m_doc->docState();
03841   }
03842   stream << d->m_encoding << d->m_sheetUsed << docState;
03843 
03844   stream << d->m_zoomFactor;
03845 
03846   stream << d->m_httpHeaders;
03847   stream << d->m_pageServices;
03848 
03849   // Save ssl data
03850   stream << d->m_ssl_in_use
03851          << d->m_ssl_peer_certificate
03852          << d->m_ssl_peer_chain
03853          << d->m_ssl_peer_ip
03854          << d->m_ssl_cipher
03855          << d->m_ssl_cipher_desc
03856          << d->m_ssl_cipher_version
03857          << d->m_ssl_cipher_used_bits
03858          << d->m_ssl_cipher_bits
03859          << d->m_ssl_cert_state
03860          << d->m_ssl_parent_ip
03861          << d->m_ssl_parent_cert;
03862 
03863 
03864   QStringList frameNameLst, frameServiceTypeLst, frameServiceNameLst;
03865   KURL::List frameURLLst;
03866   QValueList<QByteArray> frameStateBufferLst;
03867 
03868   ConstFrameIt it = d->m_frames.begin();
03869   ConstFrameIt end = d->m_frames.end();
03870   for (; it != end; ++it )
03871   {
03872     if ( !(*it).m_part )
03873        continue;
03874 
03875     frameNameLst << (*it).m_name;
03876     frameServiceTypeLst << (*it).m_serviceType;
03877     frameServiceNameLst << (*it).m_serviceName;
03878     frameURLLst << (*it).m_part->url();
03879 
03880     QByteArray state;
03881     QDataStream frameStream( state, IO_WriteOnly );
03882 
03883     if ( (*it).m_extension )
03884       (*it).m_extension->saveState( frameStream );
03885 
03886     frameStateBufferLst << state;
03887   }
03888 
03889   // Save frame data
03890   stream << (Q_UINT32) frameNameLst.count();
03891   stream << frameNameLst << frameServiceTypeLst << frameServiceNameLst << frameURLLst << frameStateBufferLst;
03892 }
03893 
03894 void KHTMLPart::restoreState( QDataStream &stream )
03895 {
03896   KURL u;
03897   Q_INT32 xOffset, yOffset, wContents, hContents, mWidth, mHeight;
03898   Q_UINT32 frameCount;
03899   QStringList frameNames, frameServiceTypes, docState, frameServiceNames;
03900   KURL::List frameURLs;
03901   QValueList<QByteArray> frameStateBuffers;
03902   QValueList<int> fSizes;
03903   QString encoding, sheetUsed;
03904   long old_cacheId = d->m_cacheId;
03905 
03906   stream >> u >> xOffset >> yOffset >> wContents >> hContents >> mWidth >> mHeight;
03907 
03908   d->m_view->setMarginWidth( mWidth );
03909   d->m_view->setMarginHeight( mHeight );
03910 
03911   // restore link cursor position
03912   // nth node is active. value is set in checkCompleted()
03913   stream >> d->m_focusNodeNumber;
03914   d->m_focusNodeRestored = false;
03915   kdDebug(6050)<<"new focus Node number is:"<<d->m_focusNodeNumber<<endl;
03916 
03917   stream >> d->m_cacheId;
03918 
03919   stream >> encoding >> sheetUsed >> docState;
03920 
03921   d->m_encoding = encoding;
03922   d->m_sheetUsed = sheetUsed;
03923 
03924   int zoomFactor;
03925   stream >> zoomFactor;
03926   setZoomFactor(zoomFactor);
03927 
03928   stream >> d->m_httpHeaders;
03929   stream >> d->m_pageServices;
03930 
03931   // Restore ssl data
03932   stream >> d->m_ssl_in_use
03933          >> d->m_ssl_peer_certificate
03934          >> d->m_ssl_peer_chain
03935          >> d->m_ssl_peer_ip
03936          >> d->m_ssl_cipher
03937          >> d->m_ssl_cipher_desc
03938          >> d->m_ssl_cipher_version
03939          >> d->m_ssl_cipher_used_bits
03940          >> d->m_ssl_cipher_bits
03941          >> d->m_ssl_cert_state
03942          >> d->m_ssl_parent_ip
03943          >> d->m_ssl_parent_cert;
03944 
03945   d->m_paSecurity->setIcon( d->m_ssl_in_use ? "encrypted" : "decrypted" );
03946 
03947   stream >> frameCount >> frameNames >> frameServiceTypes >> frameServiceNames
03948          >> frameURLs >> frameStateBuffers;
03949 
03950   d->m_bComplete = false;
03951   d->m_bLoadEventEmitted = false;
03952 
03953 //   kdDebug( 6050 ) << "restoreStakte() docState.count() = " << docState.count() << endl;
03954 //   kdDebug( 6050 ) << "m_url " << m_url.url() << " <-> " << u.url() << endl;
03955 //   kdDebug( 6050 ) << "m_frames.count() " << d->m_frames.count() << " <-> " << frameCount << endl;
03956 
03957   if (d->m_cacheId == old_cacheId)
03958   {
03959     // Partial restore
03960     d->m_redirectionTimer.stop();
03961 
03962     FrameIt fIt = d->m_frames.begin();
03963     FrameIt fEnd = d->m_frames.end();
03964 
03965     for (; fIt != fEnd; ++fIt )
03966         (*fIt).m_bCompleted = false;
03967 
03968     fIt = d->m_frames.begin();
03969 
03970     QStringList::ConstIterator fNameIt = frameNames.begin();
03971     QStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin();
03972     QStringList::ConstIterator fServiceNameIt = frameServiceNames.begin();
03973     KURL::List::ConstIterator fURLIt = frameURLs.begin();
03974     QValueList<QByteArray>::ConstIterator fBufferIt = frameStateBuffers.begin();
03975 
03976     for (; fIt != fEnd; ++fIt, ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt )
03977     {
03978       khtml::ChildFrame *child = &(*fIt);
03979 
03980 //      kdDebug( 6050 ) <<  *fNameIt  << " ---- " <<  *fServiceTypeIt << endl;
03981 
03982       if ( child->m_name != *fNameIt || child->m_serviceType != *fServiceTypeIt )
03983       {
03984         child->m_bPreloaded = true;
03985         child->m_name = *fNameIt;
03986         child->m_serviceName = *fServiceNameIt;
03987         processObjectRequest( child, *fURLIt, *fServiceTypeIt );
03988       }
03989 
03990       if ( child->m_part )
03991       {
03992         child->m_bCompleted = false;
03993         if ( child->m_extension && !(*fBufferIt).isEmpty() )
03994         {
03995           QDataStream frameStream( *fBufferIt, IO_ReadOnly );
03996           child->m_extension->restoreState( frameStream );
03997         }
03998         else
03999           child->m_part->openURL( *fURLIt );
04000       }
04001     }
04002 
04003     KParts::URLArgs args( d->m_extension->urlArgs() );
04004     args.xOffset = xOffset;
04005     args.yOffset = yOffset;
04006     args.docState = docState;
04007     d->m_extension->setURLArgs( args );
04008 
04009     d->m_view->resizeContents( wContents,  hContents);
04010     d->m_view->setContentsPos( xOffset, yOffset );
04011   }
04012   else
04013   {
04014     // Full restore.
04015     closeURL();
04016     // We must force a clear because we want to be sure to delete all
04017     // frames.
04018     d->m_bCleared = false;
04019     clear();
04020     d->m_encoding = encoding;
04021     d->m_sheetUsed = sheetUsed;
04022 
04023     QStringList::ConstIterator fNameIt = frameNames.begin();
04024     QStringList::ConstIterator fNameEnd = frameNames.end();
04025 
04026     QStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin();
04027     QStringList::ConstIterator fServiceNameIt = frameServiceNames.begin();
04028     KURL::List::ConstIterator fURLIt = frameURLs.begin();
04029     QValueList<QByteArray>::ConstIterator fBufferIt = frameStateBuffers.begin();
04030 
04031     for (; fNameIt != fNameEnd; ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt )
04032     {
04033       khtml::ChildFrame newChild;
04034       newChild.m_bPreloaded = true;
04035       newChild.m_name = *fNameIt;
04036       newChild.m_serviceName = *fServiceNameIt;
04037 
04038 //      kdDebug( 6050 ) << *fNameIt << " ---- " << *fServiceTypeIt << endl;
04039 
04040       FrameIt childFrame = d->m_frames.append( newChild );
04041 
04042       processObjectRequest( &(*childFrame), *fURLIt, *fServiceTypeIt );
04043 
04044       (*childFrame).m_bPreloaded = true;
04045 
04046       if ( (*childFrame).m_part )
04047       {
04048         if ( (*childFrame).m_extension )
04049         if ( (*childFrame).m_extension && !(*fBufferIt).isEmpty() )
04050         {
04051           QDataStream frameStream( *fBufferIt, IO_ReadOnly );
04052           (*childFrame).m_extension->restoreState( frameStream );
04053         }
04054         else
04055           (*childFrame).m_part->openURL( *fURLIt );
04056       }
04057     }
04058 
04059     KParts::URLArgs args( d->m_extension->urlArgs() );
04060     args.xOffset = xOffset;
04061     args.yOffset = yOffset;
04062     args.docState = docState;
04063     d->m_extension->setURLArgs( args );
04064     if (!KHTMLPageCache::self()->isValid(d->m_cacheId))
04065     {
04066        d->m_restored = true;
04067        openURL( u );
04068        d->m_restored = false;
04069     }
04070     else
04071     {
04072        restoreURL( u );
04073     }
04074   }
04075 
04076 }
04077 
04078 void KHTMLPart::show()
04079 {
04080   if ( d->m_view )
04081     d->m_view->show();
04082 }
04083 
04084 void KHTMLPart::hide()
04085 {
04086   if ( d->m_view )
04087     d->m_view->hide();
04088 }
04089 
04090 DOM::Node KHTMLPart::nodeUnderMouse() const
04091 {
04092     return d->m_view->nodeUnderMouse();
04093 }
04094 
04095 void KHTMLPart::emitSelectionChanged()
04096 {
04097   emit d->m_extension->enableAction( "copy", hasSelection() );
04098   emit d->m_extension->selectionInfo( selectedText() );
04099   emit selectionChanged();
04100 }
04101 
04102 int KHTMLPart::zoomFactor() const
04103 {
04104   return d->m_zoomFactor;
04105 }
04106 
04107 // ### make the list configurable ?
04108 static const int zoomSizes[] = { 20, 40, 60, 80, 90, 95, 100, 105, 110, 120, 140, 160, 180, 200, 250, 300 };
04109 static const int zoomSizeCount = (sizeof(zoomSizes) / sizeof(int));
04110 static const int minZoom = 20;
04111 static const int maxZoom = 300;
04112 
04113 void KHTMLPart::slotIncZoom()
04114 {
04115   int zoomFactor = d->m_zoomFactor;
04116 
04117   if (zoomFactor < maxZoom) {
04118     // find the entry nearest to the given zoomsizes
04119     for (int i = 0; i < zoomSizeCount; ++i)
04120       if (zoomSizes[i] > zoomFactor) {
04121         zoomFactor = zoomSizes[i];
04122         break;
04123       }
04124     setZoomFactor(zoomFactor);
04125   }
04126 }
04127 
04128 void KHTMLPart::slotDecZoom()
04129 {
04130     int zoomFactor = d->m_zoomFactor;
04131     if (zoomFactor > minZoom) {
04132       // find the entry nearest to the given zoomsizes
04133       for (int i = zoomSizeCount-1; i >= 0; --i)
04134         if (zoomSizes[i] < zoomFactor) {
04135           zoomFactor = zoomSizes[i];
04136           break;
04137         }
04138       setZoomFactor(zoomFactor);
04139     }
04140 }
04141 
04142 void KHTMLPart::setZoomFactor (int percent)
04143 {
04144   if (percent < minZoom) percent = minZoom;
04145   if (percent > maxZoom) percent = maxZoom;
04146   if (d->m_zoomFactor == percent) return;
04147   d->m_zoomFactor = percent;
04148 
04149   if(d->m_doc) {
04150       QApplication::setOverrideCursor( waitCursor );
04151     if (d->m_doc->styleSelector())
04152       d->m_doc->styleSelector()->computeFontSizes(d->m_doc->paintDeviceMetrics(), d->m_zoomFactor);
04153     d->m_doc->recalcStyle( NodeImpl::Force );
04154     QApplication::restoreOverrideCursor();
04155   }
04156 
04157   ConstFrameIt it = d->m_frames.begin();
04158   ConstFrameIt end = d->m_frames.end();
04159   for (; it != end; ++it )
04160     if ( !( *it ).m_part.isNull() && ( *it ).m_part->inherits( "KHTMLPart" ) ) {
04161       KParts::ReadOnlyPart* p = ( *it ).m_part;
04162       static_cast<KHTMLPart*>( p )->setZoomFactor(d->m_zoomFactor);
04163     }
04164 
04165   d->m_paDecZoomFactor->setEnabled( d->m_zoomFactor > minZoom );
04166   d->m_paIncZoomFactor->setEnabled( d->m_zoomFactor < maxZoom );
04167 }
04168 
04169 void KHTMLPart::slotZoomView( int delta )
04170 {
04171   if ( delta < 0 )
04172     slotIncZoom();
04173   else
04174     slotDecZoom();
04175 }
04176 
04177 void KHTMLPart::setStatusBarText( const QString& text, StatusBarPriority p)
04178 {
04179   d->m_statusBarText[p] = text;
04180 
04181   // shift handling ?
04182   QString tobe = d->m_statusBarText[BarHoverText];
04183   if (tobe.isEmpty())
04184     tobe = d->m_statusBarText[BarOverrideText];
04185   if (tobe.isEmpty()) {
04186     tobe = d->m_statusBarText[BarDefaultText];
04187     if (!tobe.isEmpty() && d->m_jobspeed)
04188       tobe += " ";
04189     if (d->m_jobspeed)
04190       tobe += i18n( "(%1/s)" ).arg( KIO::convertSize( d->m_jobspeed ) );
04191   }
04192   tobe = "<qt>"+tobe;
04193 
04194   emit ReadOnlyPart::setStatusBarText(tobe);
04195 }
04196 
04197 
04198 void KHTMLPart::setJSStatusBarText( const QString &text )
04199 {
04200   setStatusBarText(text, BarOverrideText);
04201 }
04202 
04203 void KHTMLPart::setJSDefaultStatusBarText( const QString &text )
04204 {
04205   setStatusBarText(text, BarDefaultText);
04206 }
04207 
04208 QString KHTMLPart::jsStatusBarText() const
04209 {
04210     return d->m_statusBarText[BarOverrideText];
04211 }
04212 
04213 QString KHTMLPart::jsDefaultStatusBarText() const
04214 {
04215    return d->m_statusBarText[BarDefaultText];
04216 }
04217 
04218 QString KHTMLPart::referrer() const
04219 {
04220    return d->m_referrer;
04221 }
04222 
04223 QString KHTMLPart::pageReferrer() const
04224 {
04225    KURL referrerURL = d->m_pageReferrer;
04226    if (referrerURL.isValid())
04227    {
04228       QString protocol = referrerURL.protocol();
04229 
04230       if ((protocol == "http") ||
04231          ((protocol == "https") && (m_url.protocol() == "https")))
04232       {
04233           referrerURL.setRef(QString::null);
04234           referrerURL.setUser(QString::null);
04235           referrerURL.setPass(QString::null);
04236           return referrerURL.url();
04237       }
04238    }
04239    
04240    return QString::null;
04241 }
04242 
04243 QString KHTMLPart::lastModified() const
04244 {
04245   if ( d->m_lastModified.isEmpty() && m_url.isLocalFile() ) {
04246     // Local file: set last-modified from the file's mtime.
04247     // Done on demand to save time when this isn't needed - but can lead
04248     // to slightly wrong results if updating the file on disk w/o reloading.
04249     QDateTime lastModif = QFileInfo( m_url.path() ).lastModified();
04250     d->m_lastModified = lastModif.toString( Qt::LocalDate );
04251   }
04252   //kdDebug(6050) << "KHTMLPart::lastModified: " << d->m_lastModified << endl;
04253   return d->m_lastModified;
04254 }
04255 
04256 void KHTMLPart::slotLoadImages()
04257 {
04258   if (d->m_doc )
04259     d->m_doc->docLoader()->setAutoloadImages( !d->m_doc->docLoader()->autoloadImages() );
04260 
04261   ConstFrameIt it = d->m_frames.begin();
04262   ConstFrameIt end = d->m_frames.end();
04263   for (; it != end; ++it )
04264     if ( !( *it ).m_part.isNull() && ( *it ).m_part->inherits( "KHTMLPart" ) ) {
04265       KParts::ReadOnlyPart* p = ( *it ).m_part;
04266       static_cast<KHTMLPart*>( p )->slotLoadImages();
04267     }
04268 }
04269 
04270 void KHTMLPart::reparseConfiguration()
04271 {
04272   KHTMLSettings *settings = KHTMLFactory::defaultHTMLSettings();
04273   settings->init();
04274 
04275   setAutoloadImages( settings->autoLoadImages() );
04276   if (d->m_doc)
04277      d->m_doc->docLoader()->setShowAnimations( settings->showAnimations() );
04278 
04279   d->m_bBackRightClick = settings->isBackRightClickEnabled();
04280   d->m_bJScriptEnabled = settings->isJavaScriptEnabled(m_url.host());
04281   d->m_bJScriptDebugEnabled = settings->isJavaScriptDebugEnabled();
04282   d->m_bJavaEnabled = settings->isJavaEnabled(m_url.host());
04283   d->m_bPluginsEnabled = settings->isPluginsEnabled(m_url.host());
04284   d->m_metaRefreshEnabled = settings->isAutoDelayedActionsEnabled ();
04285 
04286   delete d->m_settings;
04287   d->m_settings = new KHTMLSettings(*KHTMLFactory::defaultHTMLSettings());
04288 
04289   QApplication::setOverrideCursor( waitCursor );
04290   if(d->m_doc) d->m_doc->updateStyleSelector();
04291   QApplication::restoreOverrideCursor();
04292 }
04293 
04294 QStringList KHTMLPart::frameNames() const
04295 {
04296   QStringList res;
04297 
04298   ConstFrameIt it = d->m_frames.begin();
04299   ConstFrameIt end = d->m_frames.end();
04300   for (; it != end; ++it )
04301     if (!(*it).m_bPreloaded)
04302       res += (*it).m_name;
04303 
04304   return res;
04305 }
04306 
04307 QPtrList<KParts::ReadOnlyPart> KHTMLPart::frames() const
04308 {
04309   QPtrList<KParts::ReadOnlyPart> res;
04310 
04311   ConstFrameIt it = d->m_frames.begin();
04312   ConstFrameIt end = d->m_frames.end();
04313   for (; it != end; ++it )
04314     if (!(*it).m_bPreloaded)
04315       res.append( (*it).m_part );
04316 
04317   return res;
04318 }
04319 
04320 bool KHTMLPart::openURLInFrame( const KURL &url, const KParts::URLArgs &urlArgs )
04321 {
04322   FrameIt it = d->m_frames.find( urlArgs.frameName );
04323 
04324   if ( it == d->m_frames.end() )
04325     return false;
04326 
04327   // Inform someone that we are about to show something else.
04328   if ( !urlArgs.lockHistory() )
04329       emit d->m_extension->openURLNotify();
04330 
04331   requestObject( &(*it), url, urlArgs );
04332 
04333   return true;
04334 }
04335 
04336 void KHTMLPart::setDNDEnabled( bool b )
04337 {
04338   d->m_bDnd = b;
04339 }
04340 
04341 bool KHTMLPart::dndEnabled() const
04342 {
04343   return d->m_bDnd;
04344 }
04345 
04346 void KHTMLPart::customEvent( QCustomEvent *event )
04347 {
04348   if ( khtml::MousePressEvent::test( event ) )
04349   {
04350     khtmlMousePressEvent( static_cast<khtml::MousePressEvent *>( event ) );
04351     return;
04352   }
04353 
04354   if ( khtml::MouseDoubleClickEvent::test( event ) )
04355   {
04356     khtmlMouseDoubleClickEvent( static_cast<khtml::MouseDoubleClickEvent *>( event ) );
04357     return;
04358   }
04359 
04360   if ( khtml::MouseMoveEvent::test( event ) )
04361   {
04362     khtmlMouseMoveEvent( static_cast<khtml::MouseMoveEvent *>( event ) );
04363     return;
04364   }
04365 
04366   if ( khtml::MouseReleaseEvent::test( event ) )
04367   {
04368     khtmlMouseReleaseEvent( static_cast<khtml::MouseReleaseEvent *>( event ) );
04369     return;
04370   }
04371 
04372   if ( khtml::DrawContentsEvent::test( event ) )
04373   {
04374     khtmlDrawContentsEvent( static_cast<khtml::DrawContentsEvent *>( event ) );
04375     return;
04376   }
04377 
04378   KParts::ReadOnlyPart::customEvent( event );
04379 }
04380 
04381 void KHTMLPart::khtmlMousePressEvent( khtml::MousePressEvent *event )
04382 {
04383   DOM::DOMString url = event->url();
04384   QMouseEvent *_mouse = event->qmouseEvent();
04385   DOM::Node innerNode = event->innerNode();
04386   d->m_mousePressNode = innerNode;
04387 
04388    d->m_dragStartPos = _mouse->pos();
04389 
04390    if ( !event->url().isNull() ) {
04391      d->m_strSelectedURL = event->url().string();
04392      d->m_strSelectedURLTarget = event->target().string();
04393    }
04394    else
04395      d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
04396 
04397   if ( _mouse->button() == LeftButton ||
04398        _mouse->button() == MidButton )
04399   {
04400     d->m_bMousePressed = true;
04401 
04402 #ifndef KHTML_NO_SELECTION
04403     if ( _mouse->button() == LeftButton )
04404     {
04405       if ( !innerNode.isNull()  && innerNode.handle()->renderer()) {
04406           int offset = 0;
04407           DOM::NodeImpl* node = 0;
04408           innerNode.handle()->renderer()->checkSelectionPoint( event->x(), event->y(),
04409                                                                event->absX()-innerNode.handle()->renderer()->xPos(),
04410                                                                event->absY()-innerNode.handle()->renderer()->yPos(), node, offset);
04411 
04412           d->m_selectionStart = node;
04413           d->m_startOffset = offset;
04414           //if ( node )
04415           //  kdDebug(6005) << "KHTMLPart::khtmlMousePressEvent selectionStart=" << d->m_selectionStart.handle()->renderer()
04416           //                << " offset=" << d->m_startOffset << endl;
04417           //else
04418           //  kdDebug(6005) << "KHTML::khtmlMousePressEvent selectionStart=(nil)" << endl;
04419           d->m_selectionEnd = d->m_selectionStart;
04420           d->m_endOffset = d->m_startOffset;
04421           d->m_doc->clearSelection();
04422       }
04423       else
04424       {
04425         d->m_selectionStart = DOM::Node();
04426         d->m_selectionEnd = DOM::Node();
04427       }
04428       emitSelectionChanged();
04429       startAutoScroll();
04430     }
04431 #else
04432     d->m_dragLastPos = _mouse->globalPos();
04433 #endif
04434   }
04435 
04436   if ( _mouse->button() == RightButton && parentPart() != 0 && d->m_bBackRightClick )
04437   {
04438     d->m_bRightMousePressed = true;
04439   } else if ( _mouse->button() == RightButton )
04440   {
04441     popupMenu( d->m_strSelectedURL );
04442     d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
04443   }
04444 }
04445 
04446 void KHTMLPart::khtmlMouseDoubleClickEvent( khtml::MouseDoubleClickEvent *event )
04447 {
04448   QMouseEvent *_mouse = event->qmouseEvent();
04449   if ( _mouse->button() == LeftButton )
04450   {
04451     d->m_bMousePressed = true;
04452     DOM::Node innerNode = event->innerNode();
04453     // Find selectionStart again, khtmlMouseReleaseEvent lost it
04454     if ( !innerNode.isNull() && innerNode.handle()->renderer()) {
04455       int offset = 0;
04456       DOM::NodeImpl* node = 0;
04457       innerNode.handle()->renderer()->checkSelectionPoint( event->x(), event->y(),
04458                                                            event->absX()-innerNode.handle()->renderer()->xPos(),
04459                                                            event->absY()-innerNode.handle()->renderer()->yPos(), node, offset);
04460 
04461       //kdDebug() << k_funcinfo << "checkSelectionPoint returned node=" << node << " offset=" << offset << endl;
04462 
04463       if ( node && node->renderer() )
04464       {
04465         // Extend selection to a complete word (double-click) or paragraph (triple-click)
04466         bool selectParagraph = (event->clickCount() == 3);
04467 
04468         // Extend to the left
04469         extendSelection( node, offset, d->m_selectionStart, d->m_startOffset, false, selectParagraph );
04470         // Extend to the right
04471         extendSelection( node, offset, d->m_selectionEnd, d->m_endOffset, true, selectParagraph );
04472 
04473         d->m_endOffset++; // the last char must be in
04474         //kdDebug() << d->m_selectionStart.handle() << " " << d->m_startOffset << "  -  " <<
04475         //  d->m_selectionEnd.handle() << " " << d->m_endOffset << endl;
04476 
04477         d->m_startBeforeEnd = true;
04478         emitSelectionChanged();
04479         d->m_doc
04480           ->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
04481                          d->m_selectionEnd.handle(),d->m_endOffset);
04482       }
04483     }
04484   }
04485 }
04486 
04487 void KHTMLPart::extendSelection( DOM::NodeImpl* node, long offset, DOM::Node& selectionNode, long& selectionOffset, bool right, bool selectParagraph )
04488 {
04489   khtml::RenderObject* obj = node->renderer();
04490   QString str;
04491   int len = 0;
04492   if ( obj->isText() ) { // can be false e.g. when double-clicking on a disabled submit button
04493     str = static_cast<khtml::RenderText *>(obj)->data().string();
04494     len = str.length();
04495   }
04496   //kdDebug() << "extendSelection right=" << right << " offset=" << offset << " len=" << len << " Starting at obj=" << obj << endl;
04497   QChar ch;
04498   do {
04499     // Last char was ok, point to it
04500     if ( node ) {
04501       selectionNode = node;
04502       selectionOffset = offset;
04503     }
04504 
04505     // Get another char
04506     while ( obj && ( (right && offset >= len-1) || (!right && offset <= 0) ) )
04507     {
04508       obj = right ? obj->objectBelow() : obj->objectAbove();
04509       //kdDebug() << "obj=" << obj << endl;
04510       if ( obj ) {
04511         //kdDebug() << "isText=" << obj->isText() << endl;
04512         str = QString::null;
04513         if ( obj->isText() )
04514           str = static_cast<khtml::RenderText *>(obj)->data().string();
04515         else if ( obj->isBR() )
04516           str = '\n';
04517         else if ( !obj->isInline() ) {
04518           obj = 0L; // parag limit -> done
04519           break;
04520         }
04521         len = str.length();
04522         //kdDebug() << "str=" << str << " length=" << len << endl;
04523         // set offset - note that the first thing will be a ++ or -- on it.
04524         if ( right )
04525           offset = -1;
04526         else
04527           offset = len;
04528       }
04529     }
04530     if ( !obj ) // end of parag or document
04531       break;
04532     node = obj->element();
04533     if ( right )
04534     {
04535       Q_ASSERT( offset < len-1 );
04536       offset++;
04537     }
04538     else
04539     {
04540       Q_ASSERT( offset > 0 );
04541       offset--;
04542     }
04543 
04544     // Test that char
04545     ch = str[ offset ];
04546     //kdDebug() << " offset=" << offset << " ch=" << QString(ch) << endl;
04547   } while ( selectParagraph || (!ch.isSpace() && !ch.isPunct()) );
04548 }
04549 
04550 void KHTMLPart::khtmlMouseMoveEvent( khtml::MouseMoveEvent *event )
04551 {
04552   QMouseEvent *_mouse = event->qmouseEvent();
04553 
04554   if( d->m_bRightMousePressed && parentPart() != 0 && d->m_bBackRightClick )
04555   {
04556     popupMenu( d->m_strSelectedURL );
04557     d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
04558     d->m_bRightMousePressed = false;
04559   }
04560 #ifndef QT_NO_DRAGANDDROP
04561   if( d->m_bDnd && d->m_bMousePressed &&
04562       (!d->m_strSelectedURL.isEmpty() || (!d->m_mousePressNode.isNull() && d->m_mousePressNode.elementId() == ID_IMG) ) &&
04563       ( d->m_dragStartPos - _mouse->pos() ).manhattanLength() > KGlobalSettings::dndEventDelay()) {
04564 
04565       QPixmap p;
04566       QDragObject *drag = 0;
04567       if( !d->m_strSelectedURL.isEmpty() ) {
04568           KURL u( completeURL( d->m_strSelectedURL) );
04569           KURLDrag* urlDrag = KURLDrag::newDrag( u, d->m_view->viewport() );
04570           if ( !d->m_referrer.isEmpty() )
04571             urlDrag->metaData()["referrer"] = d->m_referrer;
04572           drag = urlDrag;
04573           p = KMimeType::pixmapForURL(u, 0, KIcon::Desktop, KIcon::SizeMedium);
04574       } else {
04575           HTMLImageElementImpl *i = static_cast<HTMLImageElementImpl *>(d->m_mousePressNode.handle());
04576           if( i ) {
04577             KMultipleDrag *mdrag = new KMultipleDrag( d->m_view->viewport() );
04578             mdrag->addDragObject( new QImageDrag( i->currentImage(), 0L ) );
04579             KURL u( completeURL( khtml::parseURL(i->getAttribute(ATTR_SRC)).string() ) );
04580             KURLDrag* urlDrag = KURLDrag::newDrag( u, 0L );
04581             if ( !d->m_referrer.isEmpty() )
04582               urlDrag->metaData()["referrer"] = d->m_referrer;
04583             mdrag->addDragObject( urlDrag );
04584             drag = mdrag;
04585             p = KMimeType::mimeType("image/png")->pixmap(KIcon::Desktop);
04586           }
04587       }
04588 
04589     if ( !p.isNull() )
04590       drag->setPixmap(p);
04591 
04592     stopAutoScroll();
04593     if(drag)
04594         drag->drag();
04595 
04596     // when we finish our drag, we need to undo our mouse press
04597     d->m_bMousePressed = false;
04598     d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
04599     return;
04600   }
04601 #endif
04602 
04603   DOM::DOMString url = event->url();
04604   DOM::DOMString target = event->target();
04605   DOM::Node innerNode = event->innerNode();
04606 
04607   // Not clicked -> mouse over stuff
04608   if ( !d->m_bMousePressed )
04609   {
04610     // The mouse is over something
04611     if ( url.length() )
04612     {
04613       bool shiftPressed = ( _mouse->state() & ShiftButton );
04614 
04615       // Image map
04616       if ( !innerNode.isNull() && innerNode.elementId() == ID_IMG )
04617       {
04618         HTMLImageElementImpl *i = static_cast<HTMLImageElementImpl *>(innerNode.handle());
04619         if ( i && i->isServerMap() )
04620         {
04621           khtml::RenderObject *r = i->renderer();
04622           if(r)
04623           {
04624             int absx, absy, vx, vy;
04625             r->absolutePosition(absx, absy);
04626             view()->contentsToViewport( absx, absy, vx, vy );
04627 
04628             int x(_mouse->x() - vx), y(_mouse->y() - vy);
04629 
04630             d->m_overURL = url.string() + QString("?%1,%2").arg(x).arg(y);
04631             d->m_overURLTarget = target.string();
04632             overURL( d->m_overURL, target.string(), shiftPressed );
04633             return;
04634           }
04635         }
04636       }
04637 
04638       // normal link
04639       if ( d->m_overURL.isEmpty() || d->m_overURL != url || d->m_overURLTarget != target )
04640       {
04641         d->m_overURL = url.string();
04642         d->m_overURLTarget = target.string();
04643         overURL( d->m_overURL, target.string(), shiftPressed );
04644       }
04645     }
04646     else  // Not over a link...
04647     {
04648       if( !d->m_overURL.isEmpty() ) // and we were over a link  -> reset to "default statusbar text"
04649       {
04650         d->m_overURL = d->m_overURLTarget = QString::null;
04651         emit onURL( QString::null );
04652         // revert to default statusbar text
04653         setStatusBarText(QString::null, BarHoverText);
04654         emit d->m_extension->mouseOverInfo(0);
04655      }
04656     }
04657   }
04658   else {
04659 #ifndef KHTML_NO_SELECTION
04660     // selection stuff
04661     if( d->m_bMousePressed && innerNode.handle() && innerNode.handle()->renderer() &&
04662         ( _mouse->state() == LeftButton )) {
04663       int offset;
04664       //kdDebug(6000) << "KHTMLPart::khtmlMouseMoveEvent x=" << event->x() << " y=" << event->y() << endl;
04665       DOM::NodeImpl* node=0;
04666       innerNode.handle()->renderer()->checkSelectionPoint( event->x(), event->y(),
04667                                                            event->absX()-innerNode.handle()->renderer()->xPos(),
04668                                                            event->absY()-innerNode.handle()->renderer()->yPos(), node, offset);
04669       d->m_selectionEnd = node;
04670       d->m_endOffset = offset;
04671       //kdDebug( 6000 ) << "setting end of selection to " << d->m_selectionEnd.handle() << "/" << d->m_endOffset << endl;
04672 
04673       // we have to get to know if end is before start or not...
04674       DOM::Node n = d->m_selectionStart;
04675       d->m_startBeforeEnd = false;
04676       while(!n.isNull()) {
04677         if(n == d->m_selectionEnd) {
04678           d->m_startBeforeEnd = true;
04679           break;
04680         }
04681         DOM::Node next = n.firstChild();
04682         if(next.isNull()) next = n.nextSibling();
04683         while( next.isNull() && !n.parentNode().isNull() ) {
04684           n = n.parentNode();
04685           next = n.nextSibling();
04686         }
04687         n = next;
04688         //d->m_view->viewport()->repaint(false);
04689       }
04690 
04691       if ( !d->m_selectionStart.isNull() && !d->m_selectionEnd.isNull() )
04692       {
04693         if (d->m_selectionEnd == d->m_selectionStart && d->m_endOffset < d->m_startOffset)
04694           d->m_doc
04695             ->setSelection(d->m_selectionStart.handle(),d->m_endOffset,
04696                            d->m_selectionEnd.handle(),d->m_startOffset);
04697         else if (d->m_startBeforeEnd)
04698           d->m_doc
04699             ->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
04700                            d->m_selectionEnd.handle(),d->m_endOffset);
04701         else
04702           d->m_doc
04703             ->setSelection(d->m_selectionEnd.handle(),d->m_endOffset,
04704                            d->m_selectionStart.handle(),d->m_startOffset);
04705       }
04706 #else
04707       if ( d->m_doc && d->m_view ) {
04708         QPoint diff( _mouse->globalPos() - d->m_dragLastPos );
04709 
04710         if ( abs( diff.x() ) > 64 || abs( diff.y() ) > 64 ) {
04711           d->m_view->scrollBy( -diff.x(), -diff.y() );
04712           d->m_dragLastPos = _mouse->globalPos();
04713         }
04714 #endif
04715     }
04716   }
04717 
04718 }
04719 
04720 void KHTMLPart::khtmlMouseReleaseEvent( khtml::MouseReleaseEvent *event )
04721 {
04722   DOM::Node innerNode = event->innerNode();
04723   d->m_mousePressNode = DOM::Node();
04724 
04725   if ( d->m_bMousePressed ) {
04726     setStatusBarText(QString::null, BarHoverText);
04727     stopAutoScroll();
04728   }
04729 
04730   // Used to prevent mouseMoveEvent from initiating a drag before
04731   // the mouse is pressed again.
04732   d->m_bMousePressed = false;
04733 
04734   QMouseEvent *_mouse = event->qmouseEvent();
04735   if ( _mouse->button() == RightButton && parentPart() != 0 && d->m_bBackRightClick )
04736   {
04737     d->m_bRightMousePressed = false;
04738     KParts::BrowserInterface *tmp_iface = d->m_extension->browserInterface();
04739     if( tmp_iface ) {
04740       tmp_iface->callMethod( "goHistory(int)", -1 );
04741     }
04742   }
04743 #ifndef QT_NO_CLIPBOARD
04744   if ((d->m_guiProfile == BrowserViewGUI) && (_mouse->button() == MidButton) && (event->url().isNull()))
04745   {
04746     QClipboard *cb = QApplication::clipboard();
04747     cb->setSelectionMode( true );
04748     QCString plain("plain");
04749     QString url = cb->text(plain).stripWhiteSpace();
04750 
04751     // Check if it's a URL
04752     KURIFilterData m_filterData;
04753     m_filterData.setData( url );
04754     if (KURIFilter::self()->filterURI(m_filterData))
04755     {
04756       int uriType = m_filterData.uriType();
04757       if ( uriType == KURIFilterData::LOCAL_FILE
04758            || uriType == KURIFilterData::LOCAL_DIR
04759            || uriType == KURIFilterData::NET_PROTOCOL )
04760         emit d->m_extension->openURLRequest( m_filterData.uri().url() );
04761     }
04762   }
04763 #endif
04764 
04765 #ifndef KHTML_NO_SELECTION
04766   // delete selection in case start and end position are at the same point
04767   if(d->m_selectionStart == d->m_selectionEnd && d->m_startOffset == d->m_endOffset) {
04768     d->m_selectionStart = 0;
04769     d->m_selectionEnd = 0;
04770     d->m_startOffset = 0;
04771     d->m_endOffset = 0;
04772     emitSelectionChanged();
04773   } else {
04774     // we have to get to know if end is before start or not...
04775     DOM::Node n = d->m_selectionStart;
04776     d->m_startBeforeEnd = false;
04777     if( d->m_selectionStart == d->m_selectionEnd ) {
04778       if( d->m_startOffset < d->m_endOffset )
04779         d->m_startBeforeEnd = true;
04780     } else {
04781       while(!n.isNull()) {
04782         if(n == d->m_selectionEnd) {
04783           d->m_startBeforeEnd = true;
04784           break;
04785         }
04786         DOM::Node next = n.firstChild();
04787         if(next.isNull()) next = n.nextSibling();
04788         while( next.isNull() && !n.parentNode().isNull() ) {
04789           n = n.parentNode();
04790           next = n.nextSibling();
04791         }
04792         n = next;
04793       }
04794     }
04795     if(!d->m_startBeforeEnd)
04796     {
04797       DOM::Node tmpNode = d->m_selectionStart;
04798       int tmpOffset = d->m_startOffset;
04799       d->m_selectionStart = d->m_selectionEnd;
04800       d->m_startOffset = d->m_endOffset;
04801       d->m_selectionEnd = tmpNode;
04802       d->m_endOffset = tmpOffset;
04803       d->m_startBeforeEnd = true;
04804     }
04805     // get selected text and paste to the clipboard
04806 #ifndef QT_NO_CLIPBOARD
04807     QString text = selectedText();
04808     text.replace(QRegExp(QChar(0xa0)), " ");
04809     QClipboard *cb = QApplication::clipboard();
04810     cb->setSelectionMode( true );
04811     disconnect( kapp->clipboard(), SIGNAL( selectionChanged()), this, SLOT( slotClearSelection()));
04812     cb->setText(text);
04813     connect( kapp->clipboard(), SIGNAL( selectionChanged()), SLOT( slotClearSelection()));
04814     cb->setSelectionMode( false );
04815 #endif
04816     //kdDebug( 6000 ) << "selectedText = " << text << endl;
04817     emitSelectionChanged();
04818   }
04819 #endif
04820 
04821 }
04822 
04823 void KHTMLPart::khtmlDrawContentsEvent( khtml::DrawContentsEvent * )
04824 {
04825 }
04826 
04827 void KHTMLPart::guiActivateEvent( KParts::GUIActivateEvent *event )
04828 {
04829   if ( event->activated() )
04830   {
04831     emitSelectionChanged();
04832     emit d->m_extension->enableAction( "print", d->m_doc != 0 );
04833 
04834     if ( !d->m_settings->autoLoadImages() && d->m_paLoadImages )
04835     {
04836         QPtrList<KAction> lst;
04837         lst.append( d->m_paLoadImages );
04838         plugActionList( "loadImages", lst );
04839     }
04840   }
04841 }
04842 
04843 void KHTMLPart::slotPrintFrame()
04844 {
04845   if ( d->m_frames.count() == 0 )
04846     return;
04847 
04848   KParts::ReadOnlyPart *frame = currentFrame();
04849   if (!frame)
04850     return;
04851 
04852   KParts::BrowserExtension *ext = KParts::BrowserExtension::childObject( frame );
04853 
04854   if ( !ext )
04855     return;
04856 
04857   QMetaObject *mo = ext->metaObject();
04858 
04859   int idx = mo->findSlot( "print()", TRUE );
04860   if ( idx >= 0 ) {
04861     QUObject o[ 1 ];
04862     ext->qt_invoke( idx, o );
04863   }
04864 }
04865 
04866 void KHTMLPart::slotSelectAll()
04867 {
04868   KParts::ReadOnlyPart *part = currentFrame();
04869   if (part && part->inherits("KHTMLPart"))
04870     static_cast<KHTMLPart *>(part)->selectAll();
04871 }
04872 
04873 void KHTMLPart::startAutoScroll()
04874 {
04875    connect(&d->m_scrollTimer, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() ));
04876    d->m_scrollTimer.start(100, false);
04877 }
04878 
04879 void KHTMLPart::stopAutoScroll()
04880 {
04881    disconnect(&d->m_scrollTimer, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() ));
04882    if (d->m_scrollTimer.isActive())
04883        d->m_scrollTimer.stop();
04884 }
04885 
04886 
04887 void KHTMLPart::slotAutoScroll()
04888 {
04889     if (d->m_view)
04890       d->m_view->doAutoScroll();
04891     else
04892       stopAutoScroll(); // Safety
04893 }
04894 
04895 void KHTMLPart::selectAll()
04896 {
04897   if (!d->m_doc) return;
04898 
04899   NodeImpl *first;
04900   if (d->m_doc->isHTMLDocument())
04901     first = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
04902   else
04903     first = d->m_doc;
04904   NodeImpl *next;
04905 
04906   // Look for first text/cdata node that has a renderer
04907   while ( first && !((first->nodeType() == Node::TEXT_NODE || first->nodeType() == Node::CDATA_SECTION_NODE) && first->renderer()) )
04908   {
04909     next = first->firstChild();
04910     if ( !next ) next = first->nextSibling();
04911     while( first && !next )
04912     {
04913       first = first->parentNode();
04914       if ( first )
04915         next = first->nextSibling();
04916     }
04917     first = next;
04918   }
04919 
04920   NodeImpl *last;
04921   if (d->m_doc->isHTMLDocument())
04922     last = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
04923   else
04924     last = d->m_doc;
04925   // Look for last text/cdata node that has a renderer
04926   while ( last && !((last->nodeType() == Node::TEXT_NODE || last->nodeType() == Node::CDATA_SECTION_NODE) && last->renderer()) )
04927   {
04928     next = last->lastChild();
04929     if ( !next ) next = last->previousSibling();
04930     while ( last && !next )
04931     {
04932       last = last->parentNode();
04933       if ( last )
04934         next = last->previousSibling();
04935     }
04936     last = next;
04937   }
04938 
04939   if ( !first || !last )
04940     return;
04941   Q_ASSERT(first->renderer());
04942   Q_ASSERT(last->renderer());
04943   d->m_selectionStart = first;
04944   d->m_startOffset = 0;
04945   d->m_selectionEnd = last;
04946   d->m_endOffset = last->nodeValue().length();
04947   d->m_startBeforeEnd = true;
04948 
04949   d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset,
04950                           d->m_selectionEnd.handle(), d->m_endOffset );
04951 
04952   emitSelectionChanged();
04953 }
04954 
04955 bool KHTMLPart::checkLinkSecurity(const KURL &linkURL,const QString &message, const QString &button)
04956 {
04957   // Security check on the link.
04958   // KURL u( url ); Wrong!! Relative URL could be mis-interpreted!!! (DA)
04959   QString linkProto = linkURL.protocol().lower();
04960   QString proto = m_url.protocol().lower();
04961 
04962   if ( !linkProto.isEmpty() && !proto.isEmpty() &&
04963        ( linkProto == "cgi" || linkProto == "file" ) &&
04964        proto != "file" && proto != "cgi" && proto != "man" && proto != "about")
04965   {
04966     Tokenizer *tokenizer = d->m_doc->tokenizer();
04967     if (tokenizer)
04968       tokenizer->setOnHold(true);
04969 
04970     int response = KMessageBox::Cancel;
04971     if (!message.isEmpty())
04972     {
04973         response = KMessageBox::warningContinueCancel( 0,
04974                                message.arg(linkURL.url()),
04975                                i18n( "Security Warning" ),
04976                                button);
04977     }
04978     else
04979     {
04980         KMessageBox::error( 0,
04981                 i18n( "<qt>This untrusted page contains a link<BR><B>%1</B><BR>to your local file system.").arg(linkURL.url()),
04982                 i18n( "Security Alert" ));
04983     }
04984 
04985     if (tokenizer)
04986        tokenizer->setOnHold(false);
04987     return (response==KMessageBox::Continue);
04988   }
04989   return true;
04990 }
04991 
04992 QVariant KHTMLPart::executeScript(QString filename, int baseLine, const DOM::Node &n, const QString &script)
04993 {
04994 #ifdef KJS_VERBOSE
04995   kdDebug(6070) << "executeScript: filename=" << filename << " baseLine=" << baseLine << " script=" << script << endl;
04996 #endif
04997   KJSProxy *proxy = jScript();
04998 
04999   if (!proxy || proxy->paused())
05000     return QVariant();
05001   QVariant ret = proxy->evaluate(filename,baseLine,script, n );
05002   return ret;
05003 }
05004 
05005 void KHTMLPart::slotPartRemoved( KParts::Part *part )
05006 {
05007 //    kdDebug(6050) << "KHTMLPart::slotPartRemoved " << part << endl;
05008     if ( part == d->m_activeFrame )
05009     {
05010         d->m_activeFrame = 0L;
05011         if ( !part->inherits( "KHTMLPart" ) )
05012         {
05013             if (factory()) {
05014                 factory()->removeClient( part );
05015             }
05016             removeChildClient( part );
05017         }
05018     }
05019 }
05020 
05021 void KHTMLPart::slotActiveFrameChanged( KParts::Part *part )
05022 {
05023 //    kdDebug(6050) << "KHTMLPart::slotActiveFrameChanged part=" << part << endl;
05024     if ( part == this )
05025     {
05026         kdError(6050) << "strange error! we activated ourselves" << endl;
05027         assert( false );
05028         return;
05029     }
05030 //    kdDebug(6050) << "KHTMLPart::slotActiveFrameChanged d->m_activeFrame=" << d->m_activeFrame << endl;
05031     if ( d->m_activeFrame && d->m_activeFrame->widget() && d->m_activeFrame->widget()->inherits( "QFrame" ) )
05032     {
05033         QFrame *frame = static_cast<QFrame *>( d->m_activeFrame->widget() );
05034         if (frame->frameStyle() != QFrame::NoFrame)
05035         {
05036            frame->setFrameStyle( QFrame::StyledPanel | QFrame::Sunken);
05037            frame->repaint();
05038         }
05039     }
05040 
05041     if( d->m_activeFrame && !d->m_activeFrame->inherits( "KHTMLPart" ) )
05042     {
05043         if (factory()) {
05044             factory()->removeClient( d->m_activeFrame );
05045         }
05046         removeChildClient( d->m_activeFrame );
05047     }
05048     if( part && !part->inherits( "KHTMLPart" ) )
05049     {
05050         if (factory()) {
05051             factory()->addClient( part );
05052         }
05053         insertChildClient( part );
05054     }
05055 
05056 
05057     d->m_activeFrame = part;
05058 
05059     if ( d->m_activeFrame && d->m_activeFrame->widget()->inherits( "QFrame" ) )
05060     {
05061         QFrame *frame = static_cast<QFrame *>( d->m_activeFrame->widget() );
05062         if (frame->frameStyle() != QFrame::NoFrame)
05063         {
05064            frame->setFrameStyle( QFrame::StyledPanel | QFrame::Plain);
05065            frame->repaint();
05066         }
05067         kdDebug(6050) << "new active frame " << d->m_activeFrame << endl;
05068     }
05069 
05070     updateActions();
05071 
05072     // (note: childObject returns 0 if the argument is 0)
05073     d->m_extension->setExtensionProxy( KParts::BrowserExtension::childObject( d->m_activeFrame ) );
05074 }
05075 
05076 void KHTMLPart::setActiveNode(const DOM::Node &node)
05077 {
05078     if (!d->m_doc || !d->m_view)
05079         return;
05080 
05081     // Set the document's active node
05082     d->m_doc->setFocusNode(node.handle());
05083 
05084     // Scroll the view if necessary to ensure that the new focus node is visible
05085     QRect rect  = node.handle()->getRect();
05086     d->m_view->ensureVisible(rect.right(), rect.bottom());
05087     d->m_view->ensureVisible(rect.left(), rect.top());
05088 }
05089 
05090 DOM::Node KHTMLPart::activeNode() const
05091 {
05092     return DOM::Node(d->m_doc?d->m_doc->focusNode():0);
05093 }
05094 
05095 DOM::EventListener *KHTMLPart::createHTMLEventListener( QString code )
05096 {
05097   KJSProxy *proxy = jScript();
05098 
05099   if (!proxy)
05100     return 0;
05101 
05102   return proxy->createHTMLEventHandler( m_url.url(), code );
05103 }
05104 
05105 KHTMLPart *KHTMLPart::opener()
05106 {
05107     return d->m_opener;
05108 }
05109 
05110 void KHTMLPart::setOpener(KHTMLPart *_opener)
05111 {
05112     d->m_opener = _opener;
05113 }
05114 
05115 bool KHTMLPart::openedByJS()
05116 {
05117     return d->m_openedByJS;
05118 }
05119 
05120 void KHTMLPart::setOpenedByJS(bool _openedByJS)
05121 {
05122     d->m_openedByJS = _openedByJS;
05123 }
05124 
05125 void KHTMLPart::preloadStyleSheet(const QString &url, const QString &stylesheet)
05126 {
05127     khtml::Cache::preloadStyleSheet(url, stylesheet);
05128 }
05129 
05130 void KHTMLPart::preloadScript(const QString &url, const QString &script)
05131 {
05132     khtml::Cache::preloadScript(url, script);
05133 }
05134 
05135 QCString KHTMLPart::dcopObjectId() const
05136 {
05137   QCString id;
05138   id.sprintf("html-widget%d", d->m_dcop_counter);
05139   return id;
05140 }
05141 
05142 long KHTMLPart::cacheId() const
05143 {
05144   return d->m_cacheId;
05145 }
05146 
05147 bool KHTMLPart::restored() const
05148 {
05149   return d->m_restored;
05150 }
05151 
05152 bool KHTMLPart::pluginPageQuestionAsked(const QString& mimetype) const
05153 {
05154   // parentPart() should be const!
05155   KHTMLPart* parent = const_cast<KHTMLPart *>(this)->parentPart();
05156   if ( parent )
05157     return parent->pluginPageQuestionAsked(mimetype);
05158 
05159   return d->m_pluginPageQuestionAsked.contains(mimetype);
05160 }
05161 
05162 void KHTMLPart::setPluginPageQuestionAsked(const QString& mimetype)
05163 {
05164   if ( parentPart() )
05165     parentPart()->setPluginPageQuestionAsked(mimetype);
05166 
05167   d->m_pluginPageQuestionAsked.append(mimetype);
05168 }
05169 
05170 using namespace KParts;
05171 #include "khtml_part.moc"
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.4.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Sun Feb 27 22:16:37 2005 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001