khtml Library API Documentation

khtml_part.cpp

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