khtml Library API Documentation

khtml_part.cpp

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