khtml Library API Documentation

khtml_part.cpp

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