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