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